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

org.apache.geode.internal.cache.FindVersionTagOperation 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;

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

import org.apache.logging.log4j.Logger;

import org.apache.geode.CancelException;
import org.apache.geode.DataSerializer;
import org.apache.geode.distributed.internal.DM;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.DistributionMessage;
import org.apache.geode.distributed.internal.HighPriorityDistributionMessage;
import org.apache.geode.distributed.internal.MessageWithReply;
import org.apache.geode.distributed.internal.ReplyMessage;
import org.apache.geode.distributed.internal.ReplyProcessor21;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.logging.LogService;

/**
 *
 */
public class FindVersionTagOperation {
  private static final Logger logger = LogService.getLogger();

  public static VersionTag findVersionTag(LocalRegion r, EventID eventId, boolean isBulkOp) {
    DM dm = r.getDistributionManager();
    Set recipients;
    if (r instanceof DistributedRegion) {
      recipients = ((DistributedRegion) r).getDistributionAdvisor().adviseCacheOp();
    } else {
      recipients = ((PartitionedRegion) r).getRegionAdvisor().adviseDataStore();
    }
    ResultReplyProcessor processor = new ResultReplyProcessor(dm, recipients);
    FindVersionTagMessage msg = new FindVersionTagMessage(recipients, processor.getProcessorId(),
        r.getFullPath(), eventId, isBulkOp);
    dm.putOutgoing(msg);
    try {
      processor.waitForReplies();
    } catch (InterruptedException e) {
      dm.getCancelCriterion().checkCancelInProgress(e);
      Thread.currentThread().interrupt();
      return null;
    }
    return processor.getVersionTag();
  }

  public static class ResultReplyProcessor extends ReplyProcessor21 {

    VersionTag versionTag;

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

    @Override
    public void process(DistributionMessage msg) {
      if (msg instanceof VersionTagReply) {
        VersionTagReply reply = (VersionTagReply) msg;
        if (reply.versionTag != null) {
          this.versionTag = reply.versionTag;
          this.versionTag.replaceNullIDs(reply.getSender());
        }
      }
      super.process(msg);
    }

    public VersionTag getVersionTag() {
      return versionTag;
    }

    @Override
    public boolean stillWaiting() {
      return this.versionTag == null && super.stillWaiting();
    }

  }

  /**
   * FindVersionTagOperation searches other members for version information for a replayed
   * operation. If we don't have version information the op may be applied by this cache as a new
   * event. When the event is then propagated to other servers that have already seen the event it
   * will be ignored, causing an inconsistency.
   */
  public static class FindVersionTagMessage extends HighPriorityDistributionMessage
      implements MessageWithReply {

    int processorId;
    String regionName;
    EventID eventId;
    private boolean isBulkOp;

    protected FindVersionTagMessage(Collection recipients, int processorId, String regionName,
        EventID eventId, boolean isBulkOp) {
      super();
      setRecipients(recipients);
      this.processorId = processorId;
      this.regionName = regionName;
      this.eventId = eventId;
      this.isBulkOp = isBulkOp;
    }

    /** for deserialization */
    public FindVersionTagMessage() {}

    /*
     * (non-Javadoc)
     * 
     * @see org.apache.geode.distributed.internal.DistributionMessage#process(org.apache.geode.
     * distributed.internal.DistributionManager)
     */
    @Override
    protected void process(DistributionManager dm) {
      VersionTag result = null;
      try {
        LocalRegion r = findRegion();
        if (r == null) {
          if (logger.isDebugEnabled()) {
            logger.debug("Region not found, so ignoring version tag request: {}", this);
          }
          return;
        }
        if (isBulkOp) {
          result = r.findVersionTagForClientBulkOp(eventId);

        } else {
          result = r.findVersionTagForClientEvent(eventId);
        }
        if (result != null) {
          result.replaceNullIDs(r.getVersionMember());
        }
        if (logger.isDebugEnabled()) {
          logger.debug("Found version tag {}", result);
        }

      } catch (RuntimeException e) {
        logger.warn("Exception thrown while searching for a version tag", e);
      } finally {
        VersionTagReply reply = new VersionTagReply(result);
        reply.setProcessorId(this.processorId);
        reply.setRecipient(getSender());
        try {
          dm.putOutgoing(reply);
        } catch (CancelException e) {
          // can't send a reply, so ignore the exception
        }
      }
    }

    private LocalRegion findRegion() {
      GemFireCacheImpl cache = null;
      try {
        cache = GemFireCacheImpl.getInstance();
        if (cache != null) {
          return cache.getRegionByPathForProcessing(regionName);
        }
      } catch (CancelException e) {
        // nothing to do
      }
      return null;
    }

    public int getDSFID() {
      return FIND_VERSION_TAG;
    }

    @Override
    public void toData(DataOutput out) throws IOException {
      super.toData(out);
      out.writeInt(this.processorId);
      out.writeUTF(this.regionName);
      InternalDataSerializer.invokeToData(this.eventId, out);
      out.writeBoolean(this.isBulkOp);
    }

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.processorId = in.readInt();
      this.regionName = in.readUTF();
      this.eventId = new EventID();
      InternalDataSerializer.invokeFromData(this.eventId, in);
      this.isBulkOp = in.readBoolean();
    }

    @Override
    public String toString() {
      return this.getShortClassName() + "(processorId=" + this.processorId + ";region="
          + this.regionName + ";eventId=" + this.eventId + ";isBulkOp=" + this.isBulkOp + ")";
    }
  }

  public static class VersionTagReply extends ReplyMessage {
    VersionTag versionTag;

    VersionTagReply(VersionTag result) {
      this.versionTag = result;
    }

    /** for deserialization */
    public VersionTagReply() {}

    @Override
    public String toString() {
      return "VersionTagReply(" + this.versionTag + ")";
    }

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

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.versionTag = (VersionTag) DataSerializer.readObject(in);
    }

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

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy