/*
 * 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.internal.cache.partitioned;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Set;

import org.apache.logging.log4j.Logger;

import org.apache.geode.CancelException;
import org.apache.geode.DataSerializer;
import org.apache.geode.cache.PartitionedRegionStorageException;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.DistributionMessage;
import org.apache.geode.distributed.internal.DistributionStats;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.distributed.internal.ReplyException;
import org.apache.geode.distributed.internal.ReplyMessage;
import org.apache.geode.distributed.internal.ReplyProcessor21;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.Assert;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.cache.FixedPartitionAttributesImpl;
import org.apache.geode.internal.cache.ForceReattemptException;
import org.apache.geode.internal.cache.Node;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.cache.PartitionedRegionHelper;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.logging.log4j.LogMarker;

/**
 * A request from an accessor to a datastore telling it to direct the creation of a bucket. This
 * request is somewhat of a hack. With 6.0, we no longer recover redundancy when a member crashes.
 * However, if the member directing the creation of a bucket crashes, that will leave us with low
 * redundancy. We decided it was not good behavior to leave the system with impaired redundancy if
 * an accessor crashes. Hence, by forcing a datastore to direct the creation of the bucket, at least
 * we will expect the redundancy to be impaired if that datastore crashes (even if it never hosted
 * that bucket).
 *
 * @since GemFire 6.0
 *
 */
public class CreateBucketMessage extends PartitionMessage {
  private static final Logger logger = LogService.getLogger();

  /** The key associated with the value that must be sent */
  private int bucketId;

  /** The value associated with the key that must be sent */
  private int bucketSize;

  /**
   * Empty constructor to satisfy {@link DataSerializer} requirements
   */
  public CreateBucketMessage() {}

  private CreateBucketMessage(InternalDistributedMember recipient, int regionId,
      ReplyProcessor21 processor, int bucketId, int bucketSize) {
    super(recipient, regionId, processor);
    this.bucketId = bucketId;
    this.bucketSize = bucketSize;
  }

  public CreateBucketMessage(DataInput in) throws IOException, ClassNotFoundException {
    fromData(in);
  }

  @Override
  public int getProcessorType() {
    return ClusterDistributionManager.WAITING_POOL_EXECUTOR;
  }

  /**
   * Sends a PartitionedRegion manage bucket request to the recipient
   *
   * @param recipient the member to which the bucket manage request is sent
   * @param r the PartitionedRegion to which the bucket belongs
   * @param bucketId the unique identifier of the bucket
   * @param bucketSize the size in bytes of the bucket
   * @return the processor used to fetch the returned Node if any
   * @throws ForceReattemptException if the peer is no longer available
   */
  public static NodeResponse send(InternalDistributedMember recipient, PartitionedRegion r,
      int bucketId, int bucketSize) throws ForceReattemptException {
    Assert.assertTrue(recipient != null, "CreateBucketMessage NULL recipient");
    NodeResponse p = new NodeResponse(r.getSystem(), recipient);
    CreateBucketMessage m =
        new CreateBucketMessage(recipient, r.getPRId(), p, bucketId, bucketSize);
    m.setTransactionDistributed(r.getCache().getTxManager().isDistributed());

    p.enableSevereAlertProcessing();

    Set failures = r.getDistributionManager().putOutgoing(m);
    if (failures != null && failures.size() > 0) {
      throw new ForceReattemptException("Failed sending <" + m + ">");
    }

    return p;
  }


  /**
   * This method is called upon receipt and make the desired changes to the PartitionedRegion Note:
   * It is very important that this message does NOT cause any deadlocks as the sender will wait
   * indefinitely for the acknowledgement
   */
  @Override
  protected boolean operateOnPartitionedRegion(ClusterDistributionManager dm, PartitionedRegion r,
      long startTime) {
    if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
      logger.trace(LogMarker.DM_VERBOSE, "CreateBucketMessage operateOnRegion: {}",
          r.getFullPath());
    }

    // This is to ensure that initialization is complete before bucket creation request is
    // serviced. BUGFIX for 35888
    if (!r.isInitialized()) {
      // This VM is NOT ready to manage a new bucket, refuse operation
      CreateBucketReplyMessage.sendResponse(getSender(), getProcessorId(), dm, null);
      return false;
    }

    // For FPR, for given bucket id find out the partition to which this bucket
    // belongs
    String partitionName = null;
    if (r.isFixedPartitionedRegion()) {
      FixedPartitionAttributesImpl fpa =
          PartitionedRegionHelper.getFixedPartitionAttributesForBucket(r, bucketId);
      partitionName = fpa.getPartitionName();
    }
    r.checkReadiness();
    InternalDistributedMember primary = r.getRedundancyProvider().createBucketAtomically(bucketId,
        bucketSize, false, partitionName);
    r.getPrStats().endPartitionMessagesProcessing(startTime);
    CreateBucketReplyMessage.sendResponse(getSender(), getProcessorId(), dm, primary);
    return false;
  }

  @Override
  public int getDSFID() {
    return PR_CREATE_BUCKET_MESSAGE;
  }

  @Override
  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
    super.fromData(in);
    this.bucketId = in.readInt();
    this.bucketSize = in.readInt();
  }

  @Override
  public void toData(DataOutput out) throws IOException {
    super.toData(out);
    out.writeInt(this.bucketId);
    out.writeInt(this.bucketSize);
  }


  /**
   * Assists the toString method in reporting the contents of this message
   *
   * @see PartitionMessage#toString()
   */
  @Override
  protected void appendFields(StringBuilder buff) {
    super.appendFields(buff);
    buff.append("; bucketId=").append(this.bucketId).append("; bucketSize=")
        .append(this.bucketSize);
  }

  @Override
  public boolean isSevereAlertCompatible() {
    // since bucket management happens during entry operations, it
    // must be severe-alert compatible
    return true;
  }

  /**
   * A class that contains the reply to a {@link CreateBucketMessage} message which contains the
   * {@link Node} that has accepted to manage the bucket.
   *
   * @since GemFire 5.0
   */
  public static class CreateBucketReplyMessage extends ReplyMessage {
    private InternalDistributedMember primary;

    /**
     * Empty constructor to conform to DataSerializable interface
     */
    public CreateBucketReplyMessage() {}

    public CreateBucketReplyMessage(DataInput in) throws IOException, ClassNotFoundException {
      fromData(in);
    }

    private CreateBucketReplyMessage(int processorId, InternalDistributedMember primary) {
      setProcessorId(processorId);
      this.primary = primary;
    }

    /**
     * Accept the request to manage the bucket
     *
     * @param recipient the requesting node
     * @param processorId the identity of the processor the requesting node is waiting on
     * @param dm the distribution manager used to send the acceptance message
     */
    public static void sendResponse(InternalDistributedMember recipient, int processorId,
        DistributionManager dm, InternalDistributedMember primary) {
      Assert.assertTrue(recipient != null, "CreateBucketReplyMessage NULL reply message");
      CreateBucketReplyMessage m = new CreateBucketReplyMessage(processorId, primary);
      m.setRecipient(recipient);
      dm.putOutgoing(m);
    }

    /**
     * Processes this message. This method is invoked by the receiver of the message.
     *
     * @param dm the distribution manager that is processing the message.
     */
    @Override
    public void process(final DistributionManager dm, final ReplyProcessor21 processor) {
      final long startTime = getTimestamp();
      if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
        logger.trace(LogMarker.DM_VERBOSE,
            "CreateBucketReplyMessage process invoking reply processor with processorId:"
                + this.processorId);
      }

      if (processor == null) {
        if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
          logger.trace(LogMarker.DM_VERBOSE, "CreateBucketReplyMessage processor not found");
        }
        return;
      }
      processor.process(this);

      if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
        logger.trace(LogMarker.DM_VERBOSE, "{} processed {}", processor, this);
      }
      dm.getStats().incReplyMessageTime(DistributionStats.getStatTime() - startTime);
    }

    @Override
    public void toData(DataOutput out) throws IOException {
      super.toData(out);
      out.writeBoolean(primary != null);
      if (primary != null) {
        InternalDataSerializer.invokeToData(primary, out);
      }
    }

    @Override
    public int getDSFID() {
      return PR_CREATE_BUCKET_REPLY_MESSAGE;
    }

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      boolean hasPrimary = in.readBoolean();
      if (hasPrimary) {
        primary = new InternalDistributedMember();
        InternalDataSerializer.invokeFromData(primary, in);
      }
    }

    @Override
    public String toString() {
      return new StringBuffer().append("CreateBucketReplyMessage ").append("processorid=")
          .append(this.processorId).toString();
    }
  }

  /**
   * A processor to capture the {@link Node} returned by {@link CreateBucketMessage}
   *
   * @since GemFire 5.0
   */
  public static class NodeResponse extends ReplyProcessor21 {
    /**
     * the message that triggers return from waitForAcceptance. This will be null if the target
     * member exited
     */
    private volatile CreateBucketReplyMessage msg;

    public NodeResponse(InternalDistributedSystem ds, InternalDistributedMember recipient) {
      super(ds, recipient);
    }

    @Override
    public void process(DistributionMessage msg) {
      try {
        if (msg instanceof CreateBucketReplyMessage) {
          CreateBucketReplyMessage reply = (CreateBucketReplyMessage) msg;
          this.msg = reply;
          if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
            logger.trace(LogMarker.DM_VERBOSE, "NodeResponse return value is ");
          }
        } else {
          Assert.assertTrue(msg instanceof ReplyMessage);
        }
      } finally {
        super.process(msg);
      }
    }


    /**
     * Wait for the response to a {@link CreateBucketMessage} request.
     *
     * @return true if the node sent the request is managing the bucket
     * @throws ForceReattemptException if the peer is no longer available
     */
    public InternalDistributedMember waitForResponse() throws ForceReattemptException {
      try {
        waitForRepliesUninterruptibly();
      } catch (ReplyException e) {
        Throwable t = e.getCause();
        if (t instanceof CancelException) {
          logger.debug(
              "NodeResponse got remote cancellation, throwing PartitionedRegionCommunication Exception {}",
              t.getMessage(), t);
          return null;
        }
        if (t instanceof PRLocallyDestroyedException) {
          logger.debug(
              "NodeResponse got local destroy on the PartitionRegion , throwing ForceReattemptException {}",
              t.getMessage(), t);
          return null;
        }
        if (t instanceof ForceReattemptException) {
          logger.debug(
              "NodeResponse got ForceReattemptException due to local destroy on the PartitionRegion {}",
              t.getMessage(), t);
          return null;
        }
        if (t instanceof PartitionedRegionStorageException) {
          throw new PartitionedRegionStorageException(t.getMessage(), t);
        }
        e.handleCause();
      }
      CreateBucketReplyMessage message = this.msg;
      if (message == null) {
        return null;
      } else {
        return (message.primary);
      }
    }
  }
}
