/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package org.apache.geode.distributed.internal.locks;

import java.util.HashMap;

import org.apache.logging.log4j.Logger;

import org.apache.geode.InternalGemFireError;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.logging.log4j.LogMarker;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * Keeps track of all the information kept by the elder.
 *
 * @since GemFire 4.0
 */
public class ElderState {
  private static final Logger logger = LogService.getLogger();

  /**
   * Maps service name keys to GrantorInfo values.
   */
  private final HashMap<String, GrantorInfo> nameToInfo;
  private final DistributionManager dm;

  /**
   * Constructs the EdlerState for the given dm. Note that this constructor does not complete until
   * elder recovery is complete.
   */
  public ElderState(DistributionManager dm) {
    Assert.assertTrue(dm != null);
    this.dm = dm;
    this.nameToInfo = new HashMap<>();
    try {
      this.dm.getStats().incElders(1);
      ElderInitProcessor.init(this.dm, this.nameToInfo);
    } catch (NullPointerException | InternalGemFireError e) {
      try {
        checkForProblem(dm);
      } finally {
        throw e;
      }
    } finally {
      if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
        StringBuilder sb = new StringBuilder("ElderState initialized with:");
        for (String key : this.nameToInfo.keySet()) {
          sb.append("\n\t").append(key).append(": ").append(this.nameToInfo.get(key));
        }
        logger.trace(LogMarker.DLS_VERBOSE, sb.toString());
      }
    }
  }

  private void checkForProblem(DistributionManager checkDM) {
    if (checkDM.getSystem() == null) {
      logger.warn(LogMarker.DLS_MARKER, "ElderState problem: system={}", checkDM.getSystem());
      return;
    }
    if (checkDM.getSystem().getDistributionManager() == null) {
      logger.warn(LogMarker.DLS_MARKER,
          "ElderState problem: system DistributionManager={}",
          checkDM.getSystem().getDistributionManager());
    }
    if (checkDM != checkDM.getSystem().getDistributionManager()) {
      logger.warn(LogMarker.DLS_MARKER,
          "ElderState problem: dm={}, but system DistributionManager={}",
          new Object[] {checkDM, checkDM.getSystem().getDistributionManager()});
    }
  }

  /**
   * Atomically determine who is the current grantor of the given service. If no current grantor
   * exists then the caller is made the grantor.
   *
   * @param serviceName the name of the lock service we want the grantor of
   * @param requestor the id of the member who is making this request
   * @return the current grantor of <code>serviceName</code> and recoveryNeeded will be true if
   *         requestor has become the grantor and needs to recover lock info.
   */
  public GrantorInfo getGrantor(String serviceName, InternalDistributedMember requestor,
      int dlsSerialNumberRequestor) {
    synchronized (this) {
      GrantorInfo gi = (GrantorInfo) this.nameToInfo.get(serviceName);
      if (gi != null) {
        waitWhileInitiatingTransfer(gi);
        InternalDistributedMember currentGrantor = gi.getId();
        // Note that elder recovery may put GrantorInfo instances in
        // the map whose id is null and whose needRecovery is true
        if (currentGrantor != null
            && this.dm.getDistributionManagerIds().contains(currentGrantor)) {
          return gi;
        } else {
          if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
            logger.trace(LogMarker.DLS_VERBOSE, "Elder setting grantor for {} to {} because {} ",
                serviceName, requestor, (currentGrantor != null ? "current grantor crashed"
                    : "of unclean grantor shutdown"));
          }
          // current grantor crashed; make new member grantor and force recovery
          long myVersion = gi.getVersionId() + 1;
          this.nameToInfo.put(serviceName,
              new GrantorInfo(requestor, myVersion, dlsSerialNumberRequestor, false));
          return new GrantorInfo(requestor, myVersion, dlsSerialNumberRequestor, true);
        }
      } else {
        if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
          logger.trace(LogMarker.DLS_VERBOSE,
              "Elder setting grantor for {} to {} because of clean grantor shutdown", serviceName,
              requestor);
        }
        gi = new GrantorInfo(requestor, 1, dlsSerialNumberRequestor, false);
        this.nameToInfo.put(serviceName, gi);
        return gi;
      }
    }
  }

  /**
   * Atomically determine who is the current grantor of the given service.
   *
   * @param serviceName the name of the lock service we want the grantor of
   * @return the current grantor of <code>serviceName</code> and recoveryNeeded will be true if
   *         requestor has become the grantor and needs to recover lock info.
   */
  public GrantorInfo peekGrantor(String serviceName) {
    synchronized (this) {
      GrantorInfo gi = (GrantorInfo) this.nameToInfo.get(serviceName);
      if (gi != null) {
        waitWhileInitiatingTransfer(gi);
        InternalDistributedMember currentGrantor = gi.getId();
        // Note that elder recovery may put GrantorInfo instances in
        // the map whose id is null and whose needRecovery is true
        if (currentGrantor != null
            && this.dm.getDistributionManagerIds().contains(currentGrantor)) {
          return gi;
        } else {
          return new GrantorInfo(null, 0, 0, true);
        }
      } else {
        return new GrantorInfo(null, 0, 0, false);
      }
    }
  }

  /**
   * Atomically sets the current grantor of the given service to <code>newGrantor</code>.
   *
   * @param serviceName the name of the lock service we want the grantor of
   * @param newGrantor the id of the member who is making this request
   * @param oldTurk if non-null then only do the become if the current grantor is the oldTurk
   * @return the previous grantor, which may be null, of <code>serviceName</code> and recoveryNeeded
   *         will be true if new grantor needs to recover lock info
   */
  public GrantorInfo becomeGrantor(String serviceName, InternalDistributedMember newGrantor,
      int newGrantorSerialNumber, InternalDistributedMember oldTurk) {
    GrantorInfo newInfo = null;
    InternalDistributedMember previousGrantor = null;
    long newGrantorVersion = -1;
    try {
      synchronized (this) {
        GrantorInfo gi = (GrantorInfo) this.nameToInfo.get(serviceName);
        while (gi != null && gi.isInitiatingTransfer()) {
          waitWhileInitiatingTransfer(gi);
          gi = (GrantorInfo) this.nameToInfo.get(serviceName);
        }
        if (gi != null) {
          previousGrantor = gi.getId();
          // Note that elder recovery may put GrantorInfo instances in
          // the map whose id is null and whose needRecovery is true

          // if previousGrantor still exists...
          if (previousGrantor != null
              && this.dm.getDistributionManagerIds().contains(previousGrantor)) {

            // if newGrantor is not previousGrantor...
            if (!newGrantor.equals(previousGrantor)) {

              // problem: specified oldTurk is not previousGrantor...
              if (oldTurk != null && !oldTurk.equals(previousGrantor)) {
                if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
                  logger.trace(LogMarker.DLS_VERBOSE,
                      "Elder did not become grantor for {} to {} because oldT was {} and the current grantor is {}",
                      serviceName, newGrantor, oldTurk, previousGrantor);
                }
              }

              // no oldTurk or oldTurk matches previousGrantor... transfer might occur
              else {
                // install new grantor
                if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
                  logger.trace(LogMarker.DLS_VERBOSE, "Elder forced to set grantor for {} to {}",
                      serviceName, newGrantor);
                }
                long myVersion = gi.getVersionId() + 1;
                newGrantorVersion = myVersion;
                newInfo = new GrantorInfo(newGrantor, myVersion, newGrantorSerialNumber, false);
                this.nameToInfo.put(serviceName, newInfo);

                if (gi.getId() != null && (oldTurk == null || gi.getId().equals(oldTurk))
                    && !gi.getId().equals(newGrantor)) {
                  beginInitiatingTransfer(newInfo);
                }

              }
            }
            // return previous grantor
            return new GrantorInfo(gi.getId(), gi.getVersionId(), gi.getSerialNumber(), true);
          }

          // no previousGrantor in existence...
          else {
            long myVersion = gi.getVersionId() + 1;

            // problem: oldTurk was specified but there is no previousGrantor...
            if (oldTurk != null) {
              if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
                logger.trace(LogMarker.DLS_VERBOSE,
                    "Elder did not become grantor for {} to {} because oldT was {} and the current grantor {} had crashed",
                    serviceName, newGrantor, oldTurk, previousGrantor);
              }
            }

            // no oldTurk was specified...
            else {
              if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
                logger.trace(LogMarker.DLS_VERBOSE,
                    "Elder forced to set grantor for {} to {} and noticed previous grantor had crashed",
                    serviceName, newGrantor);
              }
              // current grantor crashed; make new member grantor and force recovery
              this.nameToInfo.put(serviceName,
                  new GrantorInfo(newGrantor, myVersion, newGrantorSerialNumber, false));
            }

            return new GrantorInfo(null, myVersion - 1, gi.getSerialNumber(), true);
          }
        }

        // GrantorInfo was null...
        else {
          // problem: no oldTurk was specified
          if (oldTurk != null) {
            if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
              logger.trace(LogMarker.DLS_VERBOSE,
                  "Elder did not become grantor for {} to {} because oldT was {} and elder had no current grantor",
                  serviceName, newGrantor, oldTurk);
            }
          }

          // no oldTurk was specified
          else {
            if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
              logger.trace(LogMarker.DLS_VERBOSE,
                  "Elder forced to set grantor for {} to {} because of clean grantor shutdown",
                  serviceName, newGrantor);
            }
            // no current grantor; last one shutdown cleanly
            gi = new GrantorInfo(newGrantor, 1, newGrantorSerialNumber, false);
            this.nameToInfo.put(serviceName, gi);
          }
          return new GrantorInfo(null, 0, 0, false);
        }
      }
    } finally {
      if (isInitiatingTransfer(newInfo)) {
        Assert.assertTrue(newGrantorVersion > -1);
        DeposeGrantorProcessor.send(serviceName, previousGrantor, newGrantor, newGrantorVersion,
            newGrantorSerialNumber, dm);
        finishInitiatingTransfer(newInfo);
      }
    }
  }

  /**
   * Atomically clears the current grantor of the given service if the current grantor is
   * <code>oldGrantor</code>. The next grantor for this service will not need to recover unless
   * <code>locksHeld</code> is true.
   *
   * @param locksHeld true if old grantor had held locks
   */
  public void clearGrantor(long grantorVersion, String serviceName, int dlsSerialNumber,
      InternalDistributedMember oldGrantor, boolean locksHeld) {
    synchronized (this) {
      if (grantorVersion == -1) {
        // not possible to clear grantor of non-initialized grantorVersion
        return;
      }

      GrantorInfo currentGI = (GrantorInfo) this.nameToInfo.get(serviceName);
      if (currentGI == null) {
        // added null check because becomeGrantor may not have talked to elder before destroy dls
        return;
      }
      if (currentGI.getVersionId() != grantorVersion
          || currentGI.getSerialNumber() != dlsSerialNumber) {
        // not possible to clear mismatched grantorVersion
        return;
      }

      GrantorInfo gi;
      if (locksHeld) {
        gi = (GrantorInfo) this.nameToInfo.put(serviceName,
            new GrantorInfo(null, currentGI.getVersionId(), 0, true));
      } else {
        gi = (GrantorInfo) this.nameToInfo.remove(serviceName);
      }
      if (gi != null) {
        InternalDistributedMember currentGrantor = gi.getId();
        if (!oldGrantor.equals(currentGrantor)) { // fix for 32603
          this.nameToInfo.put(serviceName, gi);
          if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
            logger.trace(LogMarker.DLS_VERBOSE,
                "Elder not making {} grantor shutdown for {} by {} because the current grantor is {}",
                (locksHeld ? "unclean" : "clean"), serviceName, oldGrantor, currentGrantor);
          }
        } else {
          if (logger.isTraceEnabled(LogMarker.DLS_VERBOSE)) {
            logger.trace(LogMarker.DLS_VERBOSE, "Elder making {} grantor shutdown for {} by {}",
                (locksHeld ? "unclean" : "clean"), serviceName, oldGrantor);
          }
        }
      }
    }
  }

  private boolean isInitiatingTransfer(GrantorInfo gi) {
    if (gi == null)
      return false;
    synchronized (this) {
      return gi.isInitiatingTransfer();
    }
  }

  private void beginInitiatingTransfer(GrantorInfo gi) {
    synchronized (this) {
      gi.setInitiatingTransfer(true);
    }
  }

  private void finishInitiatingTransfer(GrantorInfo gi) {
    synchronized (this) {
      gi.setInitiatingTransfer(false);
      notifyAll();
    }
  }

  private void waitWhileInitiatingTransfer(GrantorInfo gi) {
    synchronized (this) {
      boolean interrupted = false;
      try {
        while (gi.isInitiatingTransfer()) {
          try {
            wait();
          } catch (InterruptedException e) {
            interrupted = true;
            dm.getCancelCriterion().checkCancelInProgress(e);
          }
        }
      } finally {
        if (interrupted)
          Thread.currentThread().interrupt();
      }
    }
  }

  /** Testing method to force grantor recovery state for named service */
  public void forceGrantorRecovery(String serviceName) {
    synchronized (this) {
      GrantorInfo gi = (GrantorInfo) this.nameToInfo.get(serviceName);
      if (gi.isInitiatingTransfer()) {
        throw new IllegalStateException(
            "Cannot force grantor recovery for grantor that is transferring");
      }
      this.nameToInfo.put(serviceName,
          new GrantorInfo(gi.getId(), gi.getVersionId(), gi.getSerialNumber(), true));
    }
  }

}
