All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.geode.internal.cache.wan.parallel.WaitUntilParallelGatewaySenderFlushedCoordinator Maven / Gradle / Ivy

Go to download

Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing

There is a newer version: 1.15.1
Show newest version
/*
 * 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.wan.parallel;

import org.apache.geode.DataSerializer;
import org.apache.geode.cache.Cache;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.*;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.cache.*;
import org.apache.geode.internal.cache.wan.AbstractGatewaySender;
import org.apache.geode.internal.cache.wan.WaitUntilGatewaySenderFlushedCoordinator;
import org.apache.geode.internal.cache.wan.parallel.ConcurrentParallelGatewaySenderQueue;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;

public class WaitUntilParallelGatewaySenderFlushedCoordinator
    extends WaitUntilGatewaySenderFlushedCoordinator {

  public WaitUntilParallelGatewaySenderFlushedCoordinator(AbstractGatewaySender sender,
      long timeout, TimeUnit unit, boolean initiator) {
    super(sender, timeout, unit, initiator);
  }

  public boolean waitUntilFlushed() throws Throwable {
    boolean remoteResult = true, localResult = true;
    Throwable exceptionToThrow = null;
    ConcurrentParallelGatewaySenderQueue prq =
        (ConcurrentParallelGatewaySenderQueue) this.sender.getQueue();
    PartitionedRegion pr = (PartitionedRegion) prq.getRegion();

    // Create callables for local buckets
    List callables =
        buildWaitUntilBucketRegionQueueFlushedCallables(pr);

    // Submit local callables for execution
    ExecutorService service = this.sender.getDistributionManager().getWaitingThreadPool();
    List> callableFutures = new ArrayList<>();
    for (Callable callable : callables) {
      callableFutures.add(service.submit(callable));
    }
    if (logger.isDebugEnabled()) {
      logger.debug("WaitUntilParallelGatewaySenderFlushedCoordinator: Created and submitted "
          + callables.size() + " callables=" + callables);
    }

    // Send message to remote buckets
    if (this.initiator) {
      remoteResult = false;
      try {
        remoteResult = waitUntilFlushedOnRemoteMembers(pr);
      } catch (Throwable t) {
        exceptionToThrow = t;
      }
      if (logger.isDebugEnabled()) {
        logger.debug("WaitUntilParallelGatewaySenderFlushedCoordinator: Processed remote result="
            + remoteResult + "; exceptionToThrow=" + exceptionToThrow);
      }
    }

    // Process local future results
    for (Future future : callableFutures) {
      boolean singleBucketResult = false;
      try {
        singleBucketResult = future.get();
      } catch (ExecutionException e) {
        exceptionToThrow = e.getCause();
      }
      localResult = localResult && singleBucketResult;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("WaitUntilParallelGatewaySenderFlushedCoordinator: Processed local result="
          + localResult + "; exceptionToThrow=" + exceptionToThrow);
    }

    // Return the full result
    if (exceptionToThrow == null) {
      if (logger.isDebugEnabled()) {
        logger.debug("WaitUntilParallelGatewaySenderFlushedCoordinator: Returning full result="
            + (remoteResult && localResult));
      }
      return remoteResult && localResult;
    } else {
      throw exceptionToThrow;
    }
  }

  protected List buildWaitUntilBucketRegionQueueFlushedCallables(
      PartitionedRegion pr) {
    List callables = new ArrayList<>();
    if (pr.isDataStore()) {
      for (BucketRegion br : pr.getDataStore().getAllLocalBucketRegions()) {
        callables.add(new WaitUntilBucketRegionQueueFlushedCallable((BucketRegionQueue) br,
            this.timeout, this.unit));
      }
    }
    return callables;
  }

  protected boolean waitUntilFlushedOnRemoteMembers(PartitionedRegion pr) throws Throwable {
    boolean result = true;
    DM dm = this.sender.getDistributionManager();
    Set recipients = pr.getRegionAdvisor().adviseDataStore();
    if (!recipients.isEmpty()) {
      if (logger.isDebugEnabled()) {
        logger.debug(
            "WaitUntilParallelGatewaySenderFlushedCoordinator: About to send message recipients="
                + recipients);
      }
      WaitUntilGatewaySenderFlushedReplyProcessor processor =
          new WaitUntilGatewaySenderFlushedReplyProcessor(dm, recipients);
      WaitUntilGatewaySenderFlushedMessage message = new WaitUntilGatewaySenderFlushedMessage(
          recipients, processor.getProcessorId(), this.sender.getId(), this.timeout, this.unit);
      dm.putOutgoing(message);
      if (logger.isDebugEnabled()) {
        logger.debug("WaitUntilParallelGatewaySenderFlushedCoordinator: Sent message recipients="
            + recipients);
      }
      try {
        processor.waitForReplies();
        result = processor.getCombinedResult();
      } catch (ReplyException e) {
        if (logger.isDebugEnabled()) {
          logger.debug("WaitUntilParallelGatewaySenderFlushedCoordinator: Caught e=" + e
              + "; cause=" + e.getCause());
        }
        throw e.getCause();
      } catch (InterruptedException e) {
        dm.getCancelCriterion().checkCancelInProgress(e);
        Thread.currentThread().interrupt();
        result = false;
      }
    }
    return result;
  }

  public static class WaitUntilBucketRegionQueueFlushedCallable implements Callable {

    private BucketRegionQueue brq;

    private long timeout;

    private TimeUnit unit;

    public WaitUntilBucketRegionQueueFlushedCallable(BucketRegionQueue brq, long timeout,
        TimeUnit unit) {
      this.brq = brq;
      this.timeout = timeout;
      this.unit = unit;
    }

    @Override
    public Boolean call() throws Exception {
      return this.brq.waitUntilFlushed(this.timeout, this.unit);
    }

    @Override
    public String toString() {
      return new StringBuilder().append(getClass().getSimpleName()).append("[").append("brq=")
          .append(this.brq.getId()).append("]").toString();
    }
  }

  public static class WaitUntilGatewaySenderFlushedReplyProcessor extends ReplyProcessor21 {

    private Map responses;

    public WaitUntilGatewaySenderFlushedReplyProcessor(DM dm, Collection initMembers) {
      super(dm, initMembers);
      initializeResponses();
    }

    private void initializeResponses() {
      this.responses = new ConcurrentHashMap<>();
      for (InternalDistributedMember member : getMembers()) {
        this.responses.put(member, false);
      }
    }

    @Override
    public void process(DistributionMessage msg) {
      try {
        if (msg instanceof ReplyMessage) {
          ReplyMessage reply = (ReplyMessage) msg;
          if (logger.isDebugEnabled()) {
            logger
                .debug("WaitUntilGatewaySenderFlushedReplyProcessor: Processing reply from sender="
                    + reply.getSender() + "; returnValue=" + reply.getReturnValue() + "; exception="
                    + reply.getException());
          }
          if (reply.getException() == null) {
            this.responses.put(reply.getSender(), (Boolean) reply.getReturnValue());
          } else {
            reply.getException().printStackTrace();
          }
        }
      } finally {
        super.process(msg);
      }
    }

    public boolean getCombinedResult() {
      boolean combinedResult = true;
      for (boolean singleMemberResult : this.responses.values()) {
        combinedResult = combinedResult && singleMemberResult;
      }
      if (logger.isDebugEnabled()) {
        logger.debug("WaitUntilGatewaySenderFlushedReplyProcessor: Returning combinedResult="
            + combinedResult);
      }
      return combinedResult;
    }
  }

  public static class WaitUntilGatewaySenderFlushedMessage extends PooledDistributionMessage
      implements MessageWithReply {

    private int processorId;

    private String gatewaySenderId;

    private long timeout;

    private TimeUnit unit;

    /* For serialization */
    public WaitUntilGatewaySenderFlushedMessage() {}

    protected WaitUntilGatewaySenderFlushedMessage(Collection recipients, int processorId,
        String gatewaySenderId, long timeout, TimeUnit unit) {
      super();
      setRecipients(recipients);
      this.processorId = processorId;
      this.gatewaySenderId = gatewaySenderId;
      this.timeout = timeout;
      this.unit = unit;
    }

    @Override
    protected void process(DistributionManager dm) {
      boolean result = false;
      ReplyException replyException = null;
      try {
        if (logger.isDebugEnabled()) {
          logger.debug("WaitUntilGatewaySenderFlushedMessage: Processing gatewaySenderId="
              + this.gatewaySenderId + "; timeout=" + this.timeout + "; unit=" + this.unit);
        }
        Cache cache = GemFireCacheImpl.getInstance();
        if (cache != null) {
          AbstractGatewaySender sender =
              (AbstractGatewaySender) cache.getGatewaySender(this.gatewaySenderId);
          if (sender != null) {
            try {
              WaitUntilParallelGatewaySenderFlushedCoordinator coordinator =
                  new WaitUntilParallelGatewaySenderFlushedCoordinator(sender, this.timeout,
                      this.unit, false);
              result = coordinator.waitUntilFlushed();
            } catch (Throwable e) {
              replyException = new ReplyException(e);
            }
          }
        }
      } finally {
        ReplyMessage replyMsg = new ReplyMessage();
        replyMsg.setRecipient(getSender());
        replyMsg.setProcessorId(this.processorId);
        if (replyException == null) {
          replyMsg.setReturnValue(result);
        } else {
          replyMsg.setException(replyException);
        }
        if (logger.isDebugEnabled()) {
          logger.debug("WaitUntilGatewaySenderFlushedMessage: Sending reply returnValue="
              + replyMsg.getReturnValue() + "; exception=" + replyMsg.getException());
        }
        dm.putOutgoing(replyMsg);
      }
    }

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

    @Override
    public void toData(DataOutput out) throws IOException {
      super.toData(out);
      out.writeInt(this.processorId);
      DataSerializer.writeString(this.gatewaySenderId, out);
      out.writeLong(this.timeout);
      DataSerializer.writeEnum(this.unit, out);
    }

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.processorId = in.readInt();
      this.gatewaySenderId = DataSerializer.readString(in);
      this.timeout = in.readLong();
      this.unit = DataSerializer.readEnum(TimeUnit.class, in);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy