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

com.gemstone.gemfire.internal.cache.SendQueueOperation Maven / Gradle / Ivy

There is a newer version: 2.0-BETA
Show newest version
/*
 * Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
 *
 * Licensed 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. See accompanying
 * LICENSE file.
 */

package com.gemstone.gemfire.internal.cache;

import java.util.*;
import java.io.*;
import com.gemstone.gemfire.*;
import com.gemstone.gemfire.cache.*;
import com.gemstone.gemfire.distributed.*;
import com.gemstone.gemfire.distributed.internal.*;


/**
 * Sends a chunk of queued messages to everyone currently playing a role.
 *
 * @author Darrel Schneider
 * @since 5.0
 *
 */
public class SendQueueOperation {
  //private ReplyProcessor21 processor = null;
  private final DM dm;
  private final DistributedRegion r;
  private final List l;
  private final Role role;

  SendQueueOperation(DM dm, DistributedRegion r, List l, Role role) {
    this.dm = dm;
    this.r = r;
    this.l = l;
    this.role = role;
  }

  /**
   * Returns true if distribution successful. Also modifies message list by
   * removing messages sent to the required role.
   */
  boolean distribute() {
    CacheDistributionAdvisor advisor = this.r.getCacheDistributionAdvisor();
    Set recipients = advisor.adviseCacheOpRole(this.role);
    if (recipients.isEmpty()) {
      return false;
    }
    ReplyProcessor21 processor = new ReplyProcessor21(this.dm, recipients);
    // @todo darrel: make this a reliable one
    SendQueueMessage msg = new SendQueueMessage();
    msg.setRecipients(recipients);
    msg.setRegionPath(this.r.getFullPath());
    msg.setProcessorId(processor.getProcessorId());
    msg.setOperations(this.l);
    dm.putOutgoing(msg);
    try {
      processor.waitForReplies();
    } catch (InterruptedException ex) {
      Thread.currentThread().interrupt();
      // It's OK to keep going, no significant work below.
    } catch (ReplyException ex) {
      ex.handleAsUnexpected();
    }
    if (msg.getSuccessfulRecipients().isEmpty()) {
      return false;
    }
    // @todo darrel: now remove sent items from the list
    this.r.getCachePerfStats().incReliableQueuedOps(- l.size());
    this.l.clear();
    return true;
  }

  /**
   * A batch of queued messages. Once they are processed on the other side
   * an ack is sent.
   */
  public static final class SendQueueMessage
    extends SerialDistributionMessage
    implements MessageWithReply
  {
    private int processorId;
    private String regionPath;
    /**
     * List of QueuedOperation instances
     */
    private List ops;

    @Override
    public int getProcessorId() {
      return this.processorId;
    }
    public void setProcessorId(int id) {
      this.processorId = id;
    }
    public String getRegionPath() {
      return this.regionPath;
    }
    public void setRegionPath(String rp) {
      this.regionPath = rp;
    }
    public void setOperations(List l) {
      this.ops = l;
    }
    @Override
    protected void process(DistributionManager dm) {
      ReplyException rex = null;
      boolean ignored = false;
      try {
        GemFireCacheImpl gfc = (GemFireCacheImpl)CacheFactory.getInstance(dm.getSystem());
        final LocalRegion lclRgn = gfc.getRegionByPathForProcessing(this.regionPath);
        if (lclRgn != null) {
          lclRgn.waitOnInitialization();
          final long lastMod = gfc.cacheTimeMillis();
          Iterator it = this.ops.iterator();
          while (it.hasNext()) {
            QueuedOperation op = (QueuedOperation)it.next();
            op.process(lclRgn, getSender(), lastMod);
          }
        } else {
          ignored = true;
        }
      } catch (RegionDestroyedException e) {
        ignored = true;
      } catch (CancelException e) {
        ignored = true;
      } finally {
        ReplyMessage.send(getSender(), this.processorId, rex, dm, ignored,
            false, null, false);
      }
    }

    public int getDSFID() {
      return SEND_QUEUE_MESSAGE;
    }

    @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
      super.fromData(in);
      this.regionPath = DataSerializer.readString(in);
      this.processorId = in.readInt();
      {
        int opCount = in.readInt();
        QueuedOperation[] ops = new QueuedOperation[opCount];
        for (int i=0; i < opCount; i++) {
          ops[i] = QueuedOperation.createFromData(in);
        }
        this.ops = Arrays.asList(ops);
      }
    }
    
    @Override
    public void toData(DataOutput out) throws IOException {
      super.toData(out);
      DataSerializer.writeString(this.regionPath, out);
      out.writeInt(this.processorId);
      {
        int opCount = this.ops.size();
        out.writeInt(opCount);
        for (int i=0; i < opCount; i++) {
          QueuedOperation op = (QueuedOperation)this.ops.get(i);
          op.toData(out);
        }
      }
    }

    @Override
    public String toString() {
      StringBuffer buff = new StringBuffer();
      buff.append(getClass().getName());
      buff.append("(region path='"); // make sure this is the first one
      buff.append(this.regionPath);
      buff.append("'");
      buff.append("; processorId=");
      buff.append(this.processorId);
      buff.append("; queuedOps=");
      buff.append(this.ops.size());
      buff.append(")");
      return buff.toString();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy