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