001/*
002 * Copyright 2009-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.LinkedHashMap;
027import java.util.Map;
028
029import com.unboundid.ldap.sdk.Entry;
030import com.unboundid.util.Debug;
031import com.unboundid.util.NotMutable;
032import com.unboundid.util.ThreadSafety;
033import com.unboundid.util.ThreadSafetyLevel;
034
035import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
036
037
038
039/**
040 * This class defines a monitor entry that provides information about the state
041 * of a replica, including the base DN, replica ID, and generation ID, as well
042 * as information about its communication with the replication server
043 * <BR>
044 * <BLOCKQUOTE>
045 *   <B>NOTE:</B>  This class, and other classes within the
046 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
047 *   supported for use against Ping Identity, UnboundID, and
048 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
049 *   for proprietary functionality or for external specifications that are not
050 *   considered stable or mature enough to be guaranteed to work in an
051 *   interoperable way with other types of LDAP servers.
052 * </BLOCKQUOTE>
053 * <BR>
054 * The server should present a replica monitor entry for each replicated base
055 * DN.  They can be retrieved using the
056 * {@link MonitorManager#getReplicaMonitorEntries} method.  These entries
057 * provide specific methods for accessing information about the replica.
058 * Alternately, this information may be accessed using the generic API.  See the
059 * {@link MonitorManager} class documentation for an example that demonstrates
060 * the use of the generic API for accessing monitor data.
061 */
062@NotMutable()
063@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
064public final class ReplicaMonitorEntry
065       extends MonitorEntry
066{
067  /**
068   * The structural object class used in replica monitor entries.
069   */
070  static final String REPLICA_MONITOR_OC =
071       "ds-replica-monitor-entry";
072
073
074
075  /**
076   * The name of the attribute that contains the base DNs for the replicated
077   * data.
078   */
079  private static final String ATTR_BASE_DN = "base-dn";
080
081
082
083  /**
084   * The name of the attribute that contains the address and port of the
085   * replication server to which the replica is connected.
086   */
087  private static final String ATTR_CONNECTED_TO =
088       "connected-to";
089
090
091
092  /**
093   * The name of the attribute that provides information about the current
094   * receive window size.
095   */
096  private static final String ATTR_CURRENT_RECEIVE_WINDOW_SIZE =
097       "current-rcv-window";
098
099
100
101  /**
102   * The name of the attribute that provides information about the current send
103   * window size.
104   */
105  private static final String ATTR_CURRENT_SEND_WINDOW_SIZE =
106       "current-send-window";
107
108
109
110  /**
111   * The name of the attribute that provides the generation ID for the replica.
112   */
113  private static final String ATTR_GENERATION_ID = "generation-id";
114
115
116
117  /**
118   * The name of the attribute that provides information about the number of
119   * times the connection to the replication server has been lost.
120   */
121  private static final String ATTR_LOST_CONNECTIONS = "lost-connections";
122
123
124
125  /**
126   * The name of the attribute that provides information about the maximum
127   * receive window size.
128   */
129  private static final String ATTR_MAX_RECEIVE_WINDOW_SIZE =
130       "max-rcv-window";
131
132
133
134  /**
135   * The name of the attribute that provides information about the maximum send
136   * window size.
137   */
138  private static final String ATTR_MAX_SEND_WINDOW_SIZE =
139       "max-send-window";
140
141
142
143  /**
144   * The name of the attribute that provides information about the number of
145   * pending updates which are currently being processed by the Directory Server
146   * and have not yet been sent to the replication server.
147   */
148  private static final String ATTR_PENDING_UPDATES = "pending-updates";
149
150
151
152  /**
153   * The name of the attribute that provides information about the number of
154   * updates received from the replication server for this replica.
155   */
156  private static final String ATTR_RECEIVED_UPDATES = "received-updates";
157
158
159
160  /**
161   * The name of the attribute that provides the replica ID for this replica.
162   */
163  private static final String ATTR_REPLICA_ID = "replica-id";
164
165
166
167  /**
168   * The name of the attribute that provides information about the number of
169   * updates that were replayed after resolving a modify conflict.
170   */
171  private static final String ATTR_RESOLVED_MODIFY_CONFLICTS =
172       "resolved-modify-conflicts";
173
174
175
176  /**
177   * The name of the attribute that provides information about the number of
178   * updates that were replayed after resolving a naming conflict.
179   */
180  private static final String ATTR_RESOLVED_NAMING_CONFLICTS =
181       "resolved-naming-conflicts";
182
183
184
185  /**
186   * The name of the attribute that provides information about the number of
187   * updates sent to the replication server from this replica.
188   */
189  private static final String ATTR_SENT_UPDATES = "sent-updates";
190
191
192
193  /**
194   * The name of the attribute that indicates whether SSL is used when
195   * communicating with the replication server.
196   */
197  private static final String ATTR_SSL_ENCRYPTION = "ssl-encryption";
198
199
200
201  /**
202   * The name of the attribute that provides information about the number of
203   * updates that have been successfully replayed with no problems.
204   */
205  private static final String ATTR_SUCCESSFUL_REPLAYED = "replayed-updates-ok";
206
207
208
209  /**
210   * The name of the attribute that provides information about the total number
211   * of updates that have been replayed in some form.
212   */
213  private static final String ATTR_TOTAL_REPLAYED = "replayed-updates";
214
215
216
217  /**
218   * The name of the attribute that provides information about the number of
219   * updates that could not be replayed because of an unresolved naming
220   * conflict.
221   */
222  private static final String ATTR_UNRESOLVED_NAMING_CONFLICTS =
223       "unresolved-naming-conflicts";
224
225
226
227  /**
228   * The serial version UID for this serializable class.
229   */
230  private static final long serialVersionUID = -9164207693317460579L;
231
232
233
234  // Indicates whether the replica uses SSL when communicating with the
235  // replication server.
236  private final Boolean useSSL;
237
238  // The current receive window size.
239  private final Long currentReceiveWindowSize;
240
241  // The current send window size.
242  private final Long currentSendWindowSize;
243
244  // The number of lost connections.
245  private final Long lostConnections;
246
247  // The maximum receive window size.
248  private final Long maxReceiveWindowSize;
249
250  // The maximum send window size.
251  private final Long maxSendWindowSize;
252
253  // The number of pending updates that haven't been sent to the replication
254  // server.
255  private final Long pendingUpdates;
256
257  // The number of updates received from the replication server.
258  private final Long receivedUpdates;
259
260  // The number of updates replayed after resolving a modify conflict.
261  private final Long replayedAfterModifyConflict;
262
263  // The number of updates replayed after resolving a naming conflict.
264  private final Long replayedAfterNamingConflict;
265
266  // The port number of the replication server.
267  private final Long replicationServerPort;
268
269  // The number of updates sent to the replication server.
270  private final Long sentUpdates;
271
272  // The number of updates replayed successfully.
273  private final Long successfullyReplayed;
274
275  // The total number of updates replayed.
276  private final Long totalReplayed;
277
278  // The number of unresolved naming conflicts that could not be successfully
279  // replayed.
280  private final Long unresolvedNamingConflicts;
281
282  // The base DN for the replicated data.
283  private final String baseDN;
284
285  // The generation ID for the replicated data.
286  private final String generationID;
287
288  // The replica ID for the replica.
289  private final String replicaID;
290
291  // The address of the replication server.
292  private final String replicationServerAddress;
293
294
295
296  /**
297   * Creates a new replica monitor entry from the provided entry.
298   *
299   * @param  entry  The entry to be parsed as a replica monitor entry.  It must
300   *                not be {@code null}.
301   */
302  public ReplicaMonitorEntry(final Entry entry)
303  {
304    super(entry);
305
306    useSSL                      = getBoolean(ATTR_SSL_ENCRYPTION);
307    lostConnections             = getLong(ATTR_LOST_CONNECTIONS);
308    receivedUpdates             = getLong(ATTR_RECEIVED_UPDATES);
309    sentUpdates                 = getLong(ATTR_SENT_UPDATES);
310    pendingUpdates              = getLong(ATTR_PENDING_UPDATES);
311    totalReplayed               = getLong(ATTR_TOTAL_REPLAYED);
312    successfullyReplayed        = getLong(ATTR_SUCCESSFUL_REPLAYED);
313    replayedAfterModifyConflict = getLong(ATTR_RESOLVED_MODIFY_CONFLICTS);
314    replayedAfterNamingConflict = getLong(ATTR_RESOLVED_NAMING_CONFLICTS);
315    unresolvedNamingConflicts   = getLong(ATTR_UNRESOLVED_NAMING_CONFLICTS);
316    currentReceiveWindowSize    = getLong(ATTR_CURRENT_RECEIVE_WINDOW_SIZE);
317    currentSendWindowSize       = getLong(ATTR_CURRENT_SEND_WINDOW_SIZE);
318    maxReceiveWindowSize        = getLong(ATTR_MAX_RECEIVE_WINDOW_SIZE);
319    maxSendWindowSize           = getLong(ATTR_MAX_SEND_WINDOW_SIZE);
320    baseDN                      = getString(ATTR_BASE_DN);
321    generationID                = getString(ATTR_GENERATION_ID);
322    replicaID                   = getString(ATTR_REPLICA_ID);
323
324    String addr = null;
325    Long   port = null;
326    final String connectedTo = getString(ATTR_CONNECTED_TO);
327    if (connectedTo != null)
328    {
329      try
330      {
331        final int colonPos = connectedTo.indexOf(':');
332        if (colonPos > 0)
333        {
334          addr = connectedTo.substring(0, colonPos);
335          port = Long.parseLong(connectedTo.substring(colonPos+1));
336        }
337      }
338      catch (final Exception e)
339      {
340        Debug.debugException(e);
341        addr = null;
342        port = null;
343      }
344    }
345
346    replicationServerAddress = addr;
347    replicationServerPort    = port;
348  }
349
350
351
352  /**
353   * Retrieves the base DN for this replica.
354   *
355   * @return  The base DN for this replica, or {@code null} if it was not
356   *          included in the monitor entry.
357   */
358  public String getBaseDN()
359  {
360    return baseDN;
361  }
362
363
364
365  /**
366   * Retrieves the replica ID for this replica.
367   *
368   * @return  The replica ID for this replica, or {@code null} if it was not
369   *          included in the monitor entry.
370   */
371  public String getReplicaID()
372  {
373    return replicaID;
374  }
375
376
377
378  /**
379   * Retrieves the generation ID for this replica.
380   *
381   * @return  The generation ID for this replica, or {@code null} if it was not
382   *          included in the monitor entry.
383   */
384  public String getGenerationID()
385  {
386    return generationID;
387  }
388
389
390
391  /**
392   * Retrieves the address of the replication server to which this replica is
393   * connected.
394   *
395   * @return  The address of the replication server to which this replica is
396   *          connected, or {@code null} if it was not included in the monitor
397   *          entry.
398   */
399  public String getReplicationServerAddress()
400  {
401    return replicationServerAddress;
402  }
403
404
405
406  /**
407   * Retrieves the port number of the replication server to which this replica
408   * is connected.
409   *
410   * @return  The port number of the replication server to which this replica is
411   *          connected, or {@code null} if it was not included in the monitor
412   *          entry.
413   */
414  public Long getReplicationServerPort()
415  {
416    return replicationServerPort;
417  }
418
419
420
421  /**
422   * Indicates whether this replica uses SSL when communicating with the
423   * replication server.
424   *
425   * @return  {@code Boolean.TRUE} if this replica uses SSL when communicating
426   *          with the replication server, {@code Boolean.FALSE} if it does not
427   *          use SSL, or {@code null} if it was not included in the monitor
428   *          entry.
429   */
430  public Boolean useSSL()
431  {
432    return useSSL;
433  }
434
435
436
437  /**
438   * Retrieves the number of times this replica has lost the connection to a
439   * replication server.
440   *
441   * @return  The number of times this replica has lost the connection to a
442   *          replication server, or {@code null} if it was not included in the
443   *          monitor entry.
444   */
445  public Long getLostConnections()
446  {
447    return lostConnections;
448  }
449
450
451
452  /**
453   * Retrieves the number of updates that this replica has received from the
454   * replication server.
455   *
456   * @return  The number of updates that this replica has received from the
457   *          replication server, or {@code null} if it was not included in the
458   *          monitor entry.
459   */
460  public Long getReceivedUpdates()
461  {
462    return receivedUpdates;
463  }
464
465
466
467  /**
468   * Retrieves the number of updates that this replica has sent to the
469   * replication server.
470   *
471   * @return  The number of updates that this replica has sent to the
472   *          replication server, or {@code null} if it was not included in the
473   *          monitor entry.
474   */
475  public Long getSentUpdates()
476  {
477    return sentUpdates;
478  }
479
480
481
482  /**
483   * Retrieves the number of updates that are currently in progress in the
484   * Directory Server and have not yet been sent to the replication server.
485   *
486   * @return  The number of updates that are currently in progress in the
487   *          Directory Server and have not yet been sent to the replication
488   *          server, or {@code null} if it was not included in the monitor
489   *          entry.
490   */
491  public Long getPendingUpdates()
492  {
493    return pendingUpdates;
494  }
495
496
497
498  /**
499   * Retrieves the total number of updates that have been replayed in this
500   * replica.
501   *
502   * @return  The total number of updates that have been replayed in this
503   *          replica, or {@code null} if it was not included in the monitor
504   *          entry.
505   */
506  public Long getTotalUpdatesReplayed()
507  {
508    return totalReplayed;
509  }
510
511
512
513  /**
514   * Retrieves the number of updates that have been successfully replayed in
515   * this replica without conflicts.
516   *
517   * @return  The number of updates that have been successfully replayed in this
518   *          replica without conflicts, or {@code null} if it was not included
519   *          in the monitor entry.
520   */
521  public Long getUpdatesSuccessfullyReplayed()
522  {
523    return successfullyReplayed;
524  }
525
526
527
528  /**
529   * Retrieves the number of updates that have been replayed in this replica
530   * after automatically resolving a modify conflict.
531   *
532   * @return  The number of updates that have been replayed in this replica
533   *          after automatically resolving a modify conflict, or {@code null}
534   *          if it was not included in the monitor entry.
535   */
536  public Long getUpdatesReplayedAfterModifyConflict()
537  {
538    return replayedAfterModifyConflict;
539  }
540
541
542
543  /**
544   * Retrieves the number of updates that have been replayed in this replica
545   * after automatically resolving a naming conflict.
546   *
547   * @return  The number of updates that have been replayed in this replica
548   *          after automatically resolving a naming conflict, or {@code null}
549   *          if it was not included in the monitor entry.
550   */
551  public Long getUpdatesReplayedAfterNamingConflict()
552  {
553    return replayedAfterNamingConflict;
554  }
555
556
557
558  /**
559   * Retrieves the number of updates that could not be replayed as a result of a
560   * naming conflict that could not be automatically resolved.
561   *
562   * @return  The number of updates that could not be replayed as a result of a
563   *          naming conflict that could not be automatically resolved, or
564   *          {@code null} if it was not included in the monitor entry.
565   */
566  public Long getUnresolvedNamingConflicts()
567  {
568    return unresolvedNamingConflicts;
569  }
570
571
572
573  /**
574   * Retrieves the current receive window size for this replica.
575   *
576   * @return  The current receive window size for this replica, or {@code null}
577   *          if it was not included in the monitor entry.
578   */
579  public Long getCurrentReceiveWindowSize()
580  {
581    return currentReceiveWindowSize;
582  }
583
584
585
586  /**
587   * Retrieves the current send window size for this replica.
588   *
589   * @return  The current send window size for this replica, or {@code null} if
590   *          it was not included in the monitor entry.
591   */
592  public Long getCurrentSendWindowSize()
593  {
594    return currentSendWindowSize;
595  }
596
597
598
599  /**
600   * Retrieves the maximum receive window size for this replica.
601   *
602   * @return  The maximum receive window size for this replica, or {@code null}
603   *          if it was not included in the monitor entry.
604   */
605  public Long getMaximumReceiveWindowSize()
606  {
607    return maxReceiveWindowSize;
608  }
609
610
611
612  /**
613   * Retrieves the maximum send window size for this replica.
614   *
615   * @return  The maximum send window size for this replica, or {@code null} if
616   *          it was not included in the monitor entry.
617   */
618  public Long getMaximumSendWindowSize()
619  {
620    return maxSendWindowSize;
621  }
622
623
624
625  /**
626   * {@inheritDoc}
627   */
628  @Override()
629  public String getMonitorDisplayName()
630  {
631    return INFO_REPLICA_MONITOR_DISPNAME.get();
632  }
633
634
635
636  /**
637   * {@inheritDoc}
638   */
639  @Override()
640  public String getMonitorDescription()
641  {
642    return INFO_REPLICA_MONITOR_DESC.get();
643  }
644
645
646
647  /**
648   * {@inheritDoc}
649   */
650  @Override()
651  public Map<String,MonitorAttribute> getMonitorAttributes()
652  {
653    final LinkedHashMap<String,MonitorAttribute> attrs =
654         new LinkedHashMap<>(30);
655
656    if (baseDN != null)
657    {
658      addMonitorAttribute(attrs,
659           ATTR_BASE_DN,
660           INFO_REPLICA_DISPNAME_BASE_DN.get(),
661           INFO_REPLICA_DESC_BASE_DN.get(),
662           baseDN);
663    }
664
665    if (replicaID != null)
666    {
667      addMonitorAttribute(attrs,
668           ATTR_REPLICA_ID,
669           INFO_REPLICA_DISPNAME_REPLICA_ID.get(),
670           INFO_REPLICA_DESC_REPLICA_ID.get(),
671           replicaID);
672    }
673
674    if (generationID != null)
675    {
676      addMonitorAttribute(attrs,
677           ATTR_GENERATION_ID,
678           INFO_REPLICA_DISPNAME_GENERATION_ID.get(),
679           INFO_REPLICA_DESC_GENERATION_ID.get(),
680           generationID);
681    }
682
683    if (replicationServerAddress != null)
684    {
685      addMonitorAttribute(attrs,
686           ATTR_CONNECTED_TO,
687           INFO_REPLICA_DISPNAME_CONNECTED_TO.get(),
688           INFO_REPLICA_DESC_CONNECTED_TO.get(),
689           replicationServerAddress + ':' + replicationServerPort);
690    }
691
692    if (useSSL != null)
693    {
694      addMonitorAttribute(attrs,
695           ATTR_SSL_ENCRYPTION,
696           INFO_REPLICA_DISPNAME_USE_SSL.get(),
697           INFO_REPLICA_DESC_USE_SSL.get(),
698           useSSL);
699    }
700
701    if (lostConnections != null)
702    {
703      addMonitorAttribute(attrs,
704           ATTR_LOST_CONNECTIONS,
705           INFO_REPLICA_DISPNAME_LOST_CONNECTIONS.get(),
706           INFO_REPLICA_DESC_LOST_CONNECTIONS.get(),
707           lostConnections);
708    }
709
710    if (receivedUpdates != null)
711    {
712      addMonitorAttribute(attrs,
713           ATTR_RECEIVED_UPDATES,
714           INFO_REPLICA_DISPNAME_RECEIVED_UPDATES.get(),
715           INFO_REPLICA_DESC_RECEIVED_UPDATES.get(),
716           receivedUpdates);
717    }
718
719    if (sentUpdates != null)
720    {
721      addMonitorAttribute(attrs,
722           ATTR_SENT_UPDATES,
723           INFO_REPLICA_DISPNAME_SENT_UPDATES.get(),
724           INFO_REPLICA_DESC_SENT_UPDATES.get(),
725           sentUpdates);
726    }
727
728    if (pendingUpdates != null)
729    {
730      addMonitorAttribute(attrs,
731           ATTR_PENDING_UPDATES,
732           INFO_REPLICA_DISPNAME_PENDING_UPDATES.get(),
733           INFO_REPLICA_DESC_PENDING_UPDATES.get(),
734           pendingUpdates);
735    }
736
737    if (totalReplayed != null)
738    {
739      addMonitorAttribute(attrs,
740           ATTR_TOTAL_REPLAYED,
741           INFO_REPLICA_DISPNAME_TOTAL_REPLAYED.get(),
742           INFO_REPLICA_DESC_TOTAL_REPLAYED.get(),
743           totalReplayed);
744    }
745
746    if (successfullyReplayed != null)
747    {
748      addMonitorAttribute(attrs,
749           ATTR_SUCCESSFUL_REPLAYED,
750           INFO_REPLICA_DISPNAME_SUCCESSFUL_REPLAYED.get(),
751           INFO_REPLICA_DESC_SUCCESSFUL_REPLAYED.get(),
752           successfullyReplayed);
753    }
754
755    if (replayedAfterModifyConflict != null)
756    {
757      addMonitorAttribute(attrs,
758           ATTR_RESOLVED_MODIFY_CONFLICTS,
759           INFO_REPLICA_DISPNAME_RESOLVED_MODIFY_CONFLICTS.get(),
760           INFO_REPLICA_DESC_RESOLVED_MODIFY_CONFLICTS.get(),
761           replayedAfterModifyConflict);
762    }
763
764    if (replayedAfterNamingConflict != null)
765    {
766      addMonitorAttribute(attrs,
767           ATTR_RESOLVED_NAMING_CONFLICTS,
768           INFO_REPLICA_DISPNAME_RESOLVED_NAMING_CONFLICTS.get(),
769           INFO_REPLICA_DESC_RESOLVED_NAMING_CONFLICTS.get(),
770           replayedAfterNamingConflict);
771    }
772
773    if (unresolvedNamingConflicts != null)
774    {
775      addMonitorAttribute(attrs,
776           ATTR_UNRESOLVED_NAMING_CONFLICTS,
777           INFO_REPLICA_DISPNAME_UNRESOLVED_NAMING_CONFLICTS.get(),
778           INFO_REPLICA_DESC_UNRESOLVED_NAMING_CONFLICTS.get(),
779           unresolvedNamingConflicts);
780    }
781
782    if (currentReceiveWindowSize != null)
783    {
784      addMonitorAttribute(attrs,
785           ATTR_CURRENT_RECEIVE_WINDOW_SIZE,
786           INFO_REPLICA_DISPNAME_CURRENT_RECEIVE_WINDOW_SIZE.get(),
787           INFO_REPLICA_DESC_CURRENT_RECEIVE_WINDOW_SIZE.get(),
788           currentReceiveWindowSize);
789    }
790
791    if (currentSendWindowSize != null)
792    {
793      addMonitorAttribute(attrs,
794           ATTR_CURRENT_SEND_WINDOW_SIZE,
795           INFO_REPLICA_DISPNAME_CURRENT_SEND_WINDOW_SIZE.get(),
796           INFO_REPLICA_DESC_CURRENT_SEND_WINDOW_SIZE.get(),
797           currentSendWindowSize);
798    }
799
800    if (maxReceiveWindowSize != null)
801    {
802      addMonitorAttribute(attrs,
803           ATTR_MAX_RECEIVE_WINDOW_SIZE,
804           INFO_REPLICA_DISPNAME_MAX_RECEIVE_WINDOW_SIZE.get(),
805           INFO_REPLICA_DESC_MAX_RECEIVE_WINDOW_SIZE.get(),
806           maxReceiveWindowSize);
807    }
808
809    if (maxSendWindowSize != null)
810    {
811      addMonitorAttribute(attrs,
812           ATTR_MAX_SEND_WINDOW_SIZE,
813           INFO_REPLICA_DISPNAME_MAX_SEND_WINDOW_SIZE.get(),
814           INFO_REPLICA_DESC_MAX_SEND_WINDOW_SIZE.get(),
815           maxSendWindowSize);
816    }
817
818    return Collections.unmodifiableMap(attrs);
819  }
820}