mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Valery Kharseko
18 hours ago 69f502abd9219bf113a3b062d30068d699f79403
opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java
@@ -148,8 +148,20 @@
  protected long generationId = -1;
  /** The generation id of the hosting RS. */
  protected long localGenerationId = -1;
  /** The generation id before processing a new start handshake. */
  protected long oldGenerationId = -1;
  /**
   * The domain generation id that this handler replaced during the start
   * handshake, or -100 when this handler has not changed the domain generation
   * id and there is nothing to roll back on {@link #abortStart(LocalizableMessage)}.
   */
  protected long oldGenerationId = -100;
  /**
   * The generation id this handler wrote into the domain during the start
   * handshake, or -100 when it wrote none. Used by
   * {@link #abortStart(LocalizableMessage)} to roll back only this handler's
   * own change: a value concurrently set by another thread must not be
   * overwritten with the stale {@link #oldGenerationId}.
   */
  private long generationIdSetOnStart = -100;
  /** Group id of this remote server. */
  protected byte groupId = -1;
  /** The SSL encryption after the negotiation with the peer. */
@@ -219,15 +231,54 @@
      localSession.close();
    }
    releaseDomainLock();
    // If generation id of domain was changed, set it back to old value
    // We may have changed it as it was -1 and we received a value >0 from peer
    // server and the last topo message sent may have failed being sent: in that
    // case retrieve old value of generation id for replication server domain
    // If this handler changed the domain generation id during the handshake,
    // set it back to the old value. Only undo our own change: another thread
    // may have legitimately changed the generation id in the meantime (e.g.
    // adopted it from a peer topology message) and that value must not be
    // overwritten with our stale snapshot. Do it BEFORE releasing the domain
    // lock, so a handshake queued on the lock cannot read, advertise or arm on
    // the doomed value in between.
    if (oldGenerationId != -100)
    {
      replicationServerDomain.changeGenerationId(oldGenerationId);
      replicationServerDomain.rollbackGenerationIdIfUnchanged(
          generationIdSetOnStart, oldGenerationId);
      oldGenerationId = -100;
      generationIdSetOnStart = -100;
    }
    releaseDomainLock();
  }
  /**
   * Changes the domain generation id during the start handshake, remembering
   * the replaced value so that {@link #abortStart(LocalizableMessage)} can
   * undo this handler's own change (and only it) if the handshake
   * subsequently fails.
   * <p>
   * The change is applied only if the domain generation id still equals
   * {@link #localGenerationId}, the value this handler based its decision on:
   * a generation id concurrently adopted by a lock-free path (an update
   * received from an already connected server) must not be stomped. This also
   * makes a repeated call within one handshake a no-op, preserving the first
   * arming's rollback point. Wire values below -1 are rejected — they can only
   * come from a malformed peer and would collide with the -100 sentinel.
   *
   * @param generationId the generation id to set on the domain
   */
  protected void setDomainGenerationIdOnStart(long generationId)
  {
    if (generationId < -1)
    {
      return;
    }
    if (replicationServerDomain.changeGenerationIdIfUnchanged(
        localGenerationId, generationId))
    {
      if (oldGenerationId == -100)
      {
        oldGenerationId = localGenerationId;
      }
      generationIdSetOnStart = generationId;
    }
  }