001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.monitors;
022
023
024
025import java.util.Collections;
026import java.util.List;
027import java.util.LinkedHashMap;
028import java.util.Map;
029
030import com.unboundid.ldap.sdk.Entry;
031import com.unboundid.util.Debug;
032import com.unboundid.util.DebugType;
033import com.unboundid.util.NotMutable;
034import com.unboundid.util.ThreadSafety;
035import com.unboundid.util.ThreadSafetyLevel;
036
037import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
038
039
040
041/**
042 * This class defines a monitor entry that provides general information about a
043 * Directory Server backend.
044 * <BR>
045 * <BLOCKQUOTE>
046 *   <B>NOTE:</B>  This class, and other classes within the
047 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
048 *   supported for use against Ping Identity, UnboundID, and
049 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
050 *   for proprietary functionality or for external specifications that are not
051 *   considered stable or mature enough to be guaranteed to work in an
052 *   interoperable way with other types of LDAP servers.
053 * </BLOCKQUOTE>
054 * <BR>
055 * Information that may be available in a backend monitor entry includes:
056 * <UL>
057 *   <LI>The backend ID for the backend.</LI>
058 *   <LI>The set of base DNs for the backend.</LI>
059 *   <LI>The total number of entries in the backend.</LI>
060 *   <LI>The number of entries in the backend per base DN.</LI>
061 *   <LI>The writability mode for the backend, which indicates whether it will
062 *       accept write operations.</LI>
063 *   <LI>An indication about whether the backend is public (intended to hold
064 *       user data) or private (intended to hold operational data).</LI>
065 * </UL>
066 * The set of backend monitor entries published by the directory server can be
067 * obtained using the {@link MonitorManager#getBackendMonitorEntries} method.
068 * Specific methods are available for accessing the associated monitor data
069 * (e.g., {@link BackendMonitorEntry#getBackendID} to retrieve the backend ID),
070 * and there are also methods for accessing this information in a generic manner
071 * (e.g., {@link BackendMonitorEntry#getMonitorAttributes} to retrieve all of
072 * the monitor attributes).  See the {@link MonitorManager} class documentation
073 * for an example that demonstrates the use of the generic API for accessing
074 * monitor data.
075 */
076@NotMutable()
077@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
078public final class BackendMonitorEntry
079       extends MonitorEntry
080{
081  /**
082   * The structural object class used in backend monitor entries.
083   */
084  static final String BACKEND_MONITOR_OC = "ds-backend-monitor-entry";
085
086
087
088  /**
089   * The name of the attribute that contains the backend ID.
090   */
091  private static final String ATTR_BACKEND_ID = "ds-backend-id";
092
093
094
095  /**
096   * The name of the attribute that specifies the base DN(s) for the backend.
097   */
098  private static final String ATTR_BASE_DN = "ds-backend-base-dn";
099
100
101
102  /**
103   * The name of the attribute that specifies the number of entries per base DN
104   * in the backend.
105   */
106  private static final String ATTR_ENTRIES_PER_BASE_DN =
107       "ds-base-dn-entry-count";
108
109
110
111  /**
112   * The name of the attribute that indicates whether the backend is a private
113   * backend.
114   */
115  private static final String ATTR_IS_PRIVATE = "ds-backend-is-private";
116
117
118
119  /**
120   * The name of the attribute that holds the number of soft deletes processed
121   * since the backend was initialized.
122   */
123  private static final String ATTR_SOFT_DELETE_COUNT =
124       "ds-soft-delete-operations-count";
125
126
127
128  /**
129   * The name of the attribute that specifies the total number of entries in the
130   * backend.
131   */
132  private static final String ATTR_TOTAL_ENTRIES = "ds-backend-entry-count";
133
134
135
136  /**
137   * The name of the attribute that holds the number of undeletes processed
138   * since the backend was initialized.
139   */
140  private static final String ATTR_UNDELETE_COUNT =
141       "ds-undelete-operations-count";
142
143
144
145  /**
146   * The name of the attribute that specifies the writability mode for the
147   * backend.
148   */
149  private static final String ATTR_WRITABILITY_MODE =
150       "ds-backend-writability-mode";
151
152
153
154  /**
155   * The serial version UID for this serializable class.
156   */
157  private static final long serialVersionUID = -4256944695436807547L;
158
159
160
161  // Indicates whether the backend is a private backend.
162  private final Boolean isPrivate;
163
164  // The base DNs for the backend.
165  private final List<String> baseDNs;
166
167  // The number of soft delete operations processed since the backend was
168  // started.
169  private final Long softDeleteCount;
170
171  // The total number of entries in the backend.
172  private final Long totalEntries;
173
174  // The number of undelete operations processed since the backend was started.
175  private final Long undeleteCount;
176
177  // The number of entries per base DN in the backend.
178  private final Map<String,Long> entriesPerBaseDN;
179
180  // The backend ID for the backend.
181  private final String backendID;
182
183  // The writability mode for the backend.
184  private final String writabilityMode;
185
186
187
188  /**
189   * Creates a new backend monitor entry from the provided entry.
190   *
191   * @param  entry  The entry to be parsed as a backend monitor entry.  It must
192   *                not be {@code null}.
193   */
194  public BackendMonitorEntry(final Entry entry)
195  {
196    super(entry);
197
198    backendID       = getString(ATTR_BACKEND_ID);
199    baseDNs         = getStrings(ATTR_BASE_DN);
200    isPrivate       = getBoolean(ATTR_IS_PRIVATE);
201    softDeleteCount = getLong(ATTR_SOFT_DELETE_COUNT);
202    totalEntries    = getLong(ATTR_TOTAL_ENTRIES);
203    undeleteCount   = getLong(ATTR_UNDELETE_COUNT);
204    writabilityMode = getString(ATTR_WRITABILITY_MODE);
205
206    final List<String> entriesPerBase = getStrings(ATTR_ENTRIES_PER_BASE_DN);
207    final LinkedHashMap<String,Long> countMap =
208         new LinkedHashMap<>(entriesPerBase.size());
209    for (final String s : entriesPerBase)
210    {
211      try
212      {
213        final int spacePos = s.indexOf(' ');
214        final Long l = Long.parseLong(s.substring(0, spacePos));
215        final String dn = s.substring(spacePos+1).trim();
216        countMap.put(dn, l);
217      }
218      catch (final Exception e)
219      {
220        Debug.debugException(e);
221
222        if (Debug.debugEnabled(DebugType.MONITOR))
223        {
224          Debug.debugMonitor(entry,
225               "Cannot parse value '" + s + "' for attribute " +
226                    ATTR_ENTRIES_PER_BASE_DN);
227        }
228      }
229    }
230
231    entriesPerBaseDN = Collections.unmodifiableMap(countMap);
232  }
233
234
235
236  /**
237   * Retrieves the backend ID for the associated backend.
238   *
239   * @return  The backend ID for the associated backend, or {@code null} if it
240   *          was not included in the monitor entry.
241   */
242  public String getBackendID()
243  {
244    return backendID;
245  }
246
247
248
249  /**
250   * Retrieves the base DNs for the associated backend.
251   *
252   * @return  The base DNs for the associated backend, or an empty list if it
253   *          was not included in the monitor entry.
254   */
255  public List<String> getBaseDNs()
256  {
257    return baseDNs;
258  }
259
260
261
262  /**
263   * Indicates whether the associated backend is a private backend.
264   *
265   * @return  {@code Boolean.TRUE} if the backend is a private backend,
266   *          {@code Boolean.FALSE} if it is not a private backend, or
267   *          {@code null} if it was not included in the monitor entry.
268   */
269  public Boolean isPrivate()
270  {
271    return isPrivate;
272  }
273
274
275
276  /**
277   * Retrieves the writability mode for the associated backend.
278   *
279   * @return  The writability mode for the associated backend, or {@code null}
280   *          if it was not included in the monitor entry.
281   */
282  public String getWritabilityMode()
283  {
284    return writabilityMode;
285  }
286
287
288
289  /**
290   * Retrieves the total number of entries in the associated backend.
291   *
292   * @return  The total number of entries in the associated backend, or
293   *          {@code null} if it was not included in the monitor entry.
294   */
295  public Long getTotalEntries()
296  {
297    return totalEntries;
298  }
299
300
301
302  /**
303   * Retrieves a count of the number of entries per base DN in the associated
304   * backend.
305   *
306   * @return  A count of the number of entries per base DN in the associated
307   *          backend, or an empty map if it was not included in the monitor
308   *          entry.
309   */
310  public Map<String,Long> getEntriesPerBaseDN()
311  {
312    return entriesPerBaseDN;
313  }
314
315
316
317  /**
318   * Retrieves the number of soft delete operations processed in the backend
319   * since the backend was started.
320   *
321   * @return  The number of soft delete operations processed in the backend
322   *          since the backend was started, or {@code null} if it was not
323   *          included in the monitor entry.
324   */
325  public Long getSoftDeleteCount()
326  {
327    return softDeleteCount;
328  }
329
330
331
332  /**
333   * Retrieves the number of undelete operations processed in the backend since
334   * the backend was started.
335   *
336   * @return  The number of undelete operations processed in the backend since
337   *          the backend was started, or {@code null} if it was not included in
338   *          the monitor entry.
339   */
340  public Long getUndeleteCount()
341  {
342    return undeleteCount;
343  }
344
345
346
347  /**
348   * {@inheritDoc}
349   */
350  @Override()
351  public String getMonitorDisplayName()
352  {
353    return INFO_BACKEND_MONITOR_DISPNAME.get();
354  }
355
356
357
358  /**
359   * {@inheritDoc}
360   */
361  @Override()
362  public String getMonitorDescription()
363  {
364    return INFO_BACKEND_MONITOR_DESC.get();
365  }
366
367
368
369  /**
370   * {@inheritDoc}
371   */
372  @Override()
373  public Map<String,MonitorAttribute> getMonitorAttributes()
374  {
375    final LinkedHashMap<String,MonitorAttribute> attrs =
376         new LinkedHashMap<>(20);
377
378    if (backendID != null)
379    {
380      addMonitorAttribute(attrs,
381           ATTR_BACKEND_ID,
382           INFO_BACKEND_DISPNAME_BACKEND_ID.get(),
383           INFO_BACKEND_DESC_BACKEND_ID.get(),
384           backendID);
385    }
386
387    if (! baseDNs.isEmpty())
388    {
389      addMonitorAttribute(attrs,
390           ATTR_BASE_DN,
391           INFO_BACKEND_DISPNAME_BASE_DN.get(),
392           INFO_BACKEND_DESC_BASE_DN.get(),
393           baseDNs);
394    }
395
396    if (totalEntries != null)
397    {
398      addMonitorAttribute(attrs,
399           ATTR_TOTAL_ENTRIES,
400           INFO_BACKEND_DISPNAME_TOTAL_ENTRIES.get(),
401           INFO_BACKEND_DESC_TOTAL_ENTRIES.get(),
402           totalEntries);
403    }
404
405    for (final String baseDN : entriesPerBaseDN.keySet())
406    {
407      final Long count = entriesPerBaseDN.get(baseDN);
408      addMonitorAttribute(attrs,
409                          ATTR_ENTRIES_PER_BASE_DN + '-' + baseDN,
410                          INFO_BACKEND_DISPNAME_ENTRY_COUNT.get(baseDN),
411                          INFO_BACKEND_DESC_ENTRY_COUNT.get(baseDN),
412                          count);
413
414    }
415
416    if (softDeleteCount != null)
417    {
418      addMonitorAttribute(attrs,
419           ATTR_SOFT_DELETE_COUNT,
420           INFO_BACKEND_DISPNAME_SOFT_DELETE_COUNT.get(),
421           INFO_BACKEND_DESC_SOFT_DELETE_COUNT.get(),
422           softDeleteCount);
423    }
424
425    if (undeleteCount != null)
426    {
427      addMonitorAttribute(attrs,
428           ATTR_UNDELETE_COUNT,
429           INFO_BACKEND_DISPNAME_UNDELETE_COUNT.get(),
430           INFO_BACKEND_DESC_UNDELETE_COUNT.get(),
431           undeleteCount);
432    }
433
434    if (writabilityMode != null)
435    {
436      addMonitorAttribute(attrs,
437           ATTR_WRITABILITY_MODE,
438           INFO_BACKEND_DISPNAME_WRITABILITY_MODE.get(),
439           INFO_BACKEND_DESC_WRITABILITY_MODE.get(),
440           writabilityMode);
441    }
442
443    if (isPrivate != null)
444    {
445      addMonitorAttribute(attrs,
446           ATTR_IS_PRIVATE,
447           INFO_BACKEND_DISPNAME_IS_PRIVATE.get(),
448           INFO_BACKEND_DESC_IS_PRIVATE.get(),
449           isPrivate);
450    }
451
452    return Collections.unmodifiableMap(attrs);
453  }
454}