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