/*
 * 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.io.Serializable;
import java.util.ArrayList;
import java.util.List;
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.CacheException;
import org.apache.geode.cache.RegionDestroyedException;
import org.apache.geode.cache.TimeoutException;
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.cache.ForceReattemptException;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.logging.log4j.LogMarker;
import org.apache.geode.internal.serialization.DeserializationContext;
import org.apache.geode.internal.serialization.SerializationContext;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * A message used for debugging purposes. For example if a test fails it can call
 * {@link org.apache.geode.internal.cache.PartitionedRegion#sendDumpB2NRegionForBucket(int)} which
 * sends this message to all VMs that have that PartitionedRegion defined.
 *
 * @see org.apache.geode.internal.cache.PartitionedRegion#sendDumpB2NRegionForBucket(int)
 */
public class DumpB2NRegion extends PartitionMessage {
  private static final Logger logger = LogService.getLogger();

  private int bucketId;
  private boolean onlyReturnPrimaryInfo;


  public DumpB2NRegion() {}

  private DumpB2NRegion(Set recipients, int regionId, ReplyProcessor21 processor, int bId,
      boolean justPrimaryInfo) {
    super(recipients, regionId, processor);
    this.bucketId = bId;
    this.onlyReturnPrimaryInfo = justPrimaryInfo;
  }

  public static DumpB2NResponse send(Set recipients, PartitionedRegion r, int bId,
      boolean justPrimaryInfo) {
    DumpB2NResponse p = new DumpB2NResponse(r.getSystem(), recipients);
    DumpB2NRegion m = new DumpB2NRegion(recipients, r.getPRId(), p, bId, justPrimaryInfo);
    m.setTransactionDistributed(r.getCache().getTxManager().isDistributed());
    r.getDistributionManager().putOutgoing(m);
    return p;
  }

  @Override
  public void process(final ClusterDistributionManager dm) {
    PartitionedRegion pr = null;

    // Get the region, or die trying...
    final long finish = System.currentTimeMillis() + 10 * 1000;
    try {
      for (;;) {
        dm.getCancelCriterion().checkCancelInProgress(null);

        // pr = null; (redundant assignment)
        pr = PartitionedRegion.getPRFromId(this.regionId);

        if (pr != null) {
          break;
        }

        if (System.currentTimeMillis() > finish) {
          ReplyException rex =
              new ReplyException(new TimeoutException("Waited too long for region to initialize"));
          sendReply(getSender(), this.processorId, dm, rex, null, 0);
          return;
        }

        // wait a little
        boolean interrupted = Thread.interrupted();
        try {
          Thread.sleep(2000);
        } catch (InterruptedException e) {
          interrupted = true;
        } finally {
          if (interrupted)
            Thread.currentThread().interrupt();
        }
      }

      // Now, wait for the PR to finish initializing
      pr.waitForData();

      // OK, now it's safe to process this.
      super.process(dm);
    } catch (CancelException e) {
      sendReply(this.sender, this.processorId, dm, new ReplyException(e), pr, 0);
    } catch (PRLocallyDestroyedException e) {
      sendReply(this.sender, this.processorId, dm, new ReplyException(e), pr, 0);
      return;
    } catch (RegionDestroyedException rde) {
      sendReply(this.sender, this.processorId, dm, new ReplyException(rde), pr, 0);
      return;
    }
  }


  @Override
  protected boolean operateOnPartitionedRegion(ClusterDistributionManager dm, PartitionedRegion pr,
      long startTime) throws CacheException {
    PrimaryInfo pinfo = null;
    if (this.onlyReturnPrimaryInfo) {
      pinfo = new PrimaryInfo(pr.getRegionAdvisor().getBucket(this.bucketId).isHosting(),
          pr.getRegionAdvisor().isPrimaryForBucket(this.bucketId), "");
    } else {
      pr.dumpB2NForBucket(this.bucketId);
    }
    DumpB2NReplyMessage.send(getSender(), getProcessorId(), dm, pinfo);

    return false;
  }

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

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

  @Override
  public void toData(DataOutput out,
      SerializationContext context) throws IOException {
    super.toData(out, context);
    out.writeInt(this.bucketId);
    out.writeBoolean(this.onlyReturnPrimaryInfo);
  }



  public static class DumpB2NReplyMessage extends ReplyMessage {
    private PrimaryInfo primaryInfo;

    public DumpB2NReplyMessage() {}

    private DumpB2NReplyMessage(int procid, PrimaryInfo pinfo) {
      super();
      setProcessorId(procid);
      this.primaryInfo = pinfo;
    }

    public static void send(InternalDistributedMember recipient, int processorId,
        DistributionManager dm, PrimaryInfo pinfo) {
      DumpB2NReplyMessage m = new DumpB2NReplyMessage(processorId, pinfo);
      m.setRecipient(recipient);
      dm.putOutgoing(m);
    }


    @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,
            "DumpB2NReplyMessage process invoking reply processor with processorId: {}",
            this.processorId);
      }

      if (processor == null) {
        if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
          logger.trace(LogMarker.DM_VERBOSE, "DumpB2NReplyMessage 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);
    }


    public PrimaryInfo getPrimaryInfo() {
      return this.primaryInfo;
    }

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

    @Override
    public void fromData(DataInput in,
        DeserializationContext context) throws IOException, ClassNotFoundException {
      super.fromData(in, context);
      this.primaryInfo = (PrimaryInfo) DataSerializer.readObject(in);
    }

    @Override
    public void toData(DataOutput out,
        SerializationContext context) throws IOException {
      super.toData(out, context);
      DataSerializer.writeObject(this.primaryInfo, out);
    }

    @Override
    public String toString() {
      StringBuffer sb = new StringBuffer();
      sb.append("DumpB2NReplyMessage ");
      sb.append(this.processorId);
      sb.append(" from ");
      sb.append(this.getSender());
      ReplyException ex = this.getException();
      if (ex != null) {
        sb.append(" with exception ");
        sb.append(ex);
      }
      return sb.toString();
    }
  }

  public static class DumpB2NResponse extends PartitionResponse {
    public final ArrayList primaryInfos = new ArrayList();

    public DumpB2NResponse(InternalDistributedSystem dm, Set initMembers) {
      super(dm, initMembers);
    }

    @Override
    public void process(DistributionMessage msg) {
      if (msg instanceof DumpB2NReplyMessage) {
        DumpB2NReplyMessage reply = (DumpB2NReplyMessage) msg;
        if (reply.getPrimaryInfo() != null && reply.getPrimaryInfo().isHosting) {
          Object[] newBucketHost = new Object[] {reply.getSender(),
              Boolean.valueOf(reply.getPrimaryInfo().isPrimary), reply.getPrimaryInfo().hostToken};
          synchronized (this.primaryInfos) {
            this.primaryInfos.add(newBucketHost);
          }
        }
        if (logger.isTraceEnabled(LogMarker.DM_VERBOSE)) {
          logger.trace(LogMarker.DM_VERBOSE, "DumpB2NResponse got a primaryInfo {} from {}",
              reply.getPrimaryInfo(), reply.getSender());
        }
      }
      super.process(msg);
    }

    public List waitForPrimaryInfos() throws ForceReattemptException {
      try {
        waitForCacheException();
      } catch (ForceReattemptException e) {
        logger.debug("B2NResponse got ForceReattemptException; rethrowing {}", e.getMessage(), e);
        throw e;
      } catch (CacheException e) {
        logger.debug("B2NResponse got remote CacheException, throwing ForceReattemptException. {}",
            e.getMessage(), e);
        throw new ForceReattemptException(
            "B2NResponse got remote CacheException, throwing ForceReattemptException.",
            e);
      }
      synchronized (this.primaryInfos) {
        return this.primaryInfos;
      }
    }
  }

  private static class PrimaryInfo implements Serializable {
    private static final long serialVersionUID = 6334695270795306178L;
    public final boolean isHosting, isPrimary;
    public final String hostToken;

    PrimaryInfo(boolean isHosting, boolean isPrimary, String hToken) {
      this.isHosting = isHosting;
      this.isPrimary = isPrimary;
      this.hostToken = hToken;
      if (this.isPrimary) {
        Assert.assertTrue(this.isHosting);
      }
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.apache.geode.internal.cache.partitioned.PartitionMessage#appendFields(java.lang.
   * StringBuffer)
   */
  @Override
  protected void appendFields(StringBuilder buff) {
    super.appendFields(buff);
    buff.append(" bucketId=").append(this.bucketId).append(" primaryInfoOnly=")
        .append(this.onlyReturnPrimaryInfo);
  }

  /*
   * (non-Javadoc)
   *
   * @see java.lang.Object#clone()
   */
  @Override
  protected Object clone() throws CloneNotSupportedException {
    // TODO Auto-generated method stub
    return super.clone();
  }
}
