001/*
002 * Copyright 2009-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2009-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) 2009-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.io.Serializable;
041import java.util.Date;
042
043import com.unboundid.util.Debug;
044import com.unboundid.util.NotMutable;
045import com.unboundid.util.NotNull;
046import com.unboundid.util.Nullable;
047import com.unboundid.util.StaticUtils;
048import com.unboundid.util.ThreadSafety;
049import com.unboundid.util.ThreadSafetyLevel;
050
051
052
053/**
054 * This class provides a data structure that contains information about a
055 * replica contained in a replication summary monitor entry.
056 * <BR>
057 * <BLOCKQUOTE>
058 *   <B>NOTE:</B>  This class, and other classes within the
059 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
060 *   supported for use against Ping Identity, UnboundID, and
061 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
062 *   for proprietary functionality or for external specifications that are not
063 *   considered stable or mature enough to be guaranteed to work in an
064 *   interoperable way with other types of LDAP servers.
065 * </BLOCKQUOTE>
066 */
067@NotMutable()
068@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
069public final class ReplicationSummaryReplica
070       implements Serializable
071{
072  /**
073   * The serial version UID for this serializable class.
074   */
075  private static final long serialVersionUID = 5967001261856109688L;
076
077
078
079  // The date of the oldest backlog change.
080  @Nullable private final Date oldestBacklogChangeDate;
081
082  // The LDAP server port for this replica.
083  @Nullable private final Long ldapServerPort;
084
085  // The replication backlog, presented as the number of missing changes in the
086  // replica.
087  @Nullable private final Long replicationBacklog;
088
089  // The peak update rate in operations per second.
090  @Nullable private final Long peakUpdateRate;
091
092  // The recent update rate in operations per second.
093  @Nullable private final Long recentUpdateRate;
094
095  // The generation ID for the data in the replica.
096  @Nullable private final String generationID;
097
098  // The LDAP server address for this replica.
099  @Nullable private final String ldapServerAddress;
100
101  // The replica ID for this replica.
102  @Nullable private final String replicaID;
103
104  // The replication server ID for the replication server to which this replica
105  // is connected.
106  @Nullable private final String replicationServerID;
107
108  // The value used to create this replication summary replica object.
109  @NotNull private final String stringRepresentation;
110
111
112
113  /**
114   * Creates a new replication summary replica object from the provided string
115   * representation.
116   *
117   * @param  value  The value string to be parsed as a replication summary
118   *                replica object.
119   */
120  public ReplicationSummaryReplica(@NotNull final String value)
121  {
122    stringRepresentation = value;
123
124    replicaID           = getElementValue(value, "replica-id");
125    replicationServerID = getElementValue(value, "connected-to");
126    generationID        = getElementValue(value, "generation-id");
127
128    final String hostPort = getElementValue(value, "ldap-server");
129    if (hostPort == null)
130    {
131      ldapServerAddress = null;
132      ldapServerPort    = null;
133    }
134    else
135    {
136      Long p;
137      String a;
138
139      try
140      {
141        final int colonPos = hostPort.indexOf(':');
142        a = hostPort.substring(0, colonPos);
143        p = Long.parseLong(hostPort.substring(colonPos+1));
144      }
145      catch (final Exception e)
146      {
147        Debug.debugException(e);
148        a = null;
149        p = null;
150      }
151
152      ldapServerAddress = a;
153      ldapServerPort    = p;
154    }
155
156    String replicationBacklogStr =
157            getElementValue(value, "replication-backlog");
158    if (replicationBacklogStr == null)
159    {
160      // missing-changes was renamed to replication-backlog, so we check
161      // for missing-changes to maintain backwards compatibility.
162      replicationBacklogStr = getElementValue(value, "missing-changes");
163    }
164
165    if (replicationBacklogStr == null)
166    {
167      replicationBacklog = null;
168    }
169    else
170    {
171      Long mc;
172
173      try
174      {
175        mc = Long.parseLong(replicationBacklogStr);
176      }
177      catch (final Exception e)
178      {
179        Debug.debugException(e);
180        mc = null;
181      }
182
183      replicationBacklog = mc;
184    }
185
186    String rateStr = getElementValue(value, "recent-update-rate");
187    if (rateStr == null)
188    {
189      recentUpdateRate = null;
190    }
191    else
192    {
193      Long r;
194      try
195      {
196        final int slashPos = rateStr.indexOf('/');
197        r = Long.parseLong(rateStr.substring(0, slashPos));
198      }
199      catch (final Exception e)
200      {
201        Debug.debugException(e);
202        r = null;
203      }
204      recentUpdateRate = r;
205    }
206
207    rateStr = getElementValue(value, "peak-update-rate");
208    if (rateStr == null)
209    {
210      peakUpdateRate = null;
211    }
212    else
213    {
214      Long r;
215      try
216      {
217        final int slashPos = rateStr.indexOf('/');
218        r = Long.parseLong(rateStr.substring(0, slashPos));
219      }
220      catch (final Exception e)
221      {
222        Debug.debugException(e);
223        r = null;
224      }
225      peakUpdateRate = r;
226    }
227
228    String dateStr =
229         getElementValue(value, "age-of-oldest-backlog-change");
230    if (dateStr == null)
231    {
232      // age-of-oldest-missing-change was renamed to
233      // age-of-oldest-backlog-change, so we check
234      // for age-of-oldest-missing-change to maintain backwards compatibility.
235      dateStr = getElementValue(value, "age-of-oldest-missing-change");
236    }
237
238    if (dateStr == null)
239    {
240      oldestBacklogChangeDate = null;
241    }
242    else
243    {
244      Date d;
245
246      try
247      {
248        final int spacePos = dateStr.indexOf(' ');
249        d = StaticUtils.decodeGeneralizedTime(dateStr.substring(0, spacePos));
250      }
251      catch (final Exception e)
252      {
253        Debug.debugException(e);
254        d = null;
255      }
256
257      oldestBacklogChangeDate = d;
258    }
259  }
260
261
262
263  /**
264   * Retrieves the value for the specified element in the replica string.
265   *
266   * @param  s  The string to be parsed.
267   * @param  n  The name of the element for which to retrieve the value.
268   *
269   * @return  The value for the specified element in the replica string, or
270   *          {@code null} if it was not present, could not be determined, or
271   *          was an empty string.
272   */
273  @Nullable()
274  private static String getElementValue(@NotNull final String s,
275                                        @NotNull final String n)
276  {
277    final String nPlusEQ = n + "=\"";
278
279    int pos = s.indexOf(nPlusEQ);
280    if (pos < 0)
281    {
282      return null;
283    }
284    pos += nPlusEQ.length();
285
286    final int closePos = s.indexOf('"', pos);
287    if (closePos <= pos)
288    {
289      return null;
290    }
291
292    return s.substring(pos, closePos);
293  }
294
295
296
297  /**
298   * Retrieves the replica ID for this replica.
299   *
300   * @return  The replica ID for this replica, or {@code null} if that
301   *          information is not available.
302   */
303  @Nullable()
304  public String getReplicaID()
305  {
306    return replicaID;
307  }
308
309
310
311  /**
312   * Retrieves the address used to communicate with this replica via LDAP.
313   *
314   * @return  The address used to communicate with this replica via LDAP, or
315   *          {@code null} if that information is not available.
316   */
317  @Nullable()
318  public String getLDAPServerAddress()
319  {
320    return ldapServerAddress;
321  }
322
323
324
325  /**
326   * Retrieves the port number used to communicate with this replica via LDAP.
327   *
328   * @return  The port number used to communicate with this replica via LDAP, or
329   *          {@code null} if that information is not available.
330   */
331  @Nullable()
332  public Long getLDAPServerPort()
333  {
334    return ldapServerPort;
335  }
336
337
338
339  /**
340   * Retrieves the replication server ID for the replication server to which
341   * this replica is connected.
342   *
343   * @return  The replication server ID for the replication server to which this
344   *          replica is connected, or {@code null} if that information is not
345   *          available.
346   */
347  @Nullable()
348  public String getReplicationServerID()
349  {
350    return replicationServerID;
351  }
352
353
354
355  /**
356   * Retrieves the generation ID for this replica.
357   *
358   * @return  The generation ID for this replica, or {@code null} if that
359   *          information is not available.
360   */
361  @Nullable()
362  public String getGenerationID()
363  {
364    return generationID;
365  }
366
367
368
369  /**
370   * Retrieves the recent update rate for this replica in operations per second.
371   *
372   * @return  The recent update rate for this replica in operations per second,
373   *          or {@code null} if that information is not available.
374   */
375  @Nullable()
376  public Long getRecentUpdateRate()
377  {
378    return recentUpdateRate;
379  }
380
381
382
383  /**
384   * Retrieves the peak update rate for this replica in operations per second.
385   *
386   * @return  The peak update rate for this replica in operations per second, or
387   *          {@code null} if that information is not available.
388   */
389  @Nullable()
390  public Long getPeakUpdateRate()
391  {
392    return peakUpdateRate;
393  }
394
395
396
397  /**
398   * Retrieves the replication backlog, represented as the number of missing
399   * changes, for this replica.
400   *
401   * @return  The replication backlog, represented as the number of missing
402   *          changes, for this replica , or {@code null} if
403   *          that information is not available.
404   *
405   * @deprecated  Use {@link #getReplicationBacklog()} instead.
406   */
407  @Deprecated
408  @Nullable()
409  public Long getMissingChanges()
410  {
411    return getReplicationBacklog();
412  }
413
414
415
416  /**
417   * Retrieves the replication backlog, represented as the number of missing
418   * changes, for this replica.
419   *
420   * @return  The replication backlog, represented as the number of missing
421   *          changes, for this replica , or {@code null} if
422   *          that information is not available.
423   */
424  @Nullable()
425  public Long getReplicationBacklog()
426  {
427    return replicationBacklog;
428  }
429
430
431
432  /**
433   * Retrieves the date of the oldest backlog change for this replica.
434   *
435   * @return  The date of the oldest backlog change for this replica, or
436   *          {@code null} if that information is not available or there are no
437   *          backlog changes.
438   *
439   * @deprecated  Use {@link #getOldestBacklogChangeDate()} instead.
440   */
441  @Deprecated
442  @Nullable()
443  public Date getOldestMissingChangeDate()
444  {
445    return getOldestBacklogChangeDate();
446  }
447
448
449
450  /**
451   * Retrieves the date of the oldest backlog change for this replica.
452   *
453   * @return  The date of the oldest backlog change for this replica, or
454   *          {@code null} if that information is not available or there are no
455   *          backlog changes.
456   */
457  @Nullable()
458  public Date getOldestBacklogChangeDate()
459  {
460    return oldestBacklogChangeDate;
461  }
462
463
464
465  /**
466   * Retrieves a string representation of this replication summary replica.
467   *
468   * @return  A string representation of this replication summary replica.
469   */
470  @Override()
471  @NotNull()
472  public String toString()
473  {
474    return stringRepresentation;
475  }
476}