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