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