* @param key the key the operation is operating upon
* @param o the operation
*/
@Override
public void addOperation(final String key, final Operation o) {
MemcachedNode placeIn = null;
MemcachedNode primary;
if(o instanceof ReplicaGetOperation
&& locator instanceof VBucketNodeLocator) {
primary = ((VBucketNodeLocator) locator).getReplica(key,
((ReplicaGetOperation) o).getReplicaIndex());
} else if(o instanceof ReplicaGetsOperation
&& locator instanceof VBucketNodeLocator) {
primary = ((VBucketNodeLocator) locator).getReplica(key,
((ReplicaGetsOperation) o).getReplicaIndex());
} else {
primary = locator.getPrimary(key);
}
if (primary == null) {
o.cancel();
cf.checkConfigUpdate();
return;
}
boolean needsRecheckConfigUpdate = false;
if (primary.isActive() || failureMode == FailureMode.Retry) {
placeIn = primary;
needsRecheckConfigUpdate = !primary.isActive();
} else if (failureMode == FailureMode.Cancel) {
o.cancel();
needsRecheckConfigUpdate = true;
} else {
// Look for another node in sequence that is ready.
for (Iterator<MemcachedNode> i = locator.getSequence(key); placeIn == null
&& i.hasNext();) {
MemcachedNode n = i.next();
if (n.isActive()) {
placeIn = n;
}
}
if (placeIn == null) {
placeIn = primary;
needsRecheckConfigUpdate = true;
}
}
// If we didn't find an active node, queue it in the primary node
// and wait for it to come back online.
if (needsRecheckConfigUpdate) {
getLogger().info("Node for key \"%s\" is not active (yet). Queueing "
+ "up for retry and checking for stale configuration.", key);
cf.checkConfigUpdate();
}
assert o.isCancelled() || placeIn != null : "No node found for key " + key;
if (placeIn != null) {
// add the vbucketIndex to the operation
if (locator instanceof VBucketNodeLocator) {
VBucketNodeLocator vbucketLocator = (VBucketNodeLocator) locator;
short vbucketIndex = (short) vbucketLocator.getVBucketIndex(key);
if (o instanceof VBucketAware) {
VBucketAware vbucketAwareOp = (VBucketAware) o;
vbucketAwareOp.setVBucket(key, vbucketIndex);
Collection<MemcachedNode> notMyVbucketNodes =
vbucketAwareOp.getNotMyVbucketNodes();
if (!notMyVbucketNodes.isEmpty()) {
cf.checkConfigUpdate();
MemcachedNode alternative = vbucketLocator.getAlternative(key,
notMyVbucketNodes);
if (alternative == null) {
notMyVbucketNodes.clear();
} else {
placeIn = alternative;