/** * Mark the request as completed without exception. * <p> * This method may take significant time acquiring the leader lock and * updating the Ketch state machine with results from this replica. * * @param repo * local repository reference used by the push attempt. */ public void done(Repository repo) { if (KetchReplica.log.isDebugEnabled()) { KetchReplica.log.debug(describe("completed")); //$NON-NLS-1$ } if (!notified) { notified = true; replica.afterPush(repo, this); } }
Collections.<ObjectId> emptySet()); try { replica.blockingFetch(repo, fetch); } catch (IOException fetchErr) { KetchReplica.log.error(String.format( "Cannot fetch %s (%s) from %s", //$NON-NLS-1$ remoteId.abbreviate(8).name(), refName, replica.describeForLog()), fetchErr); throw new MissingObjectException(remoteId, OBJ_COMMIT);
/** * Schedule a proposal round with the replica. * <p> * Called with {@link KetchLeader#lock} held by caller. * * @param round * current round being run by the leader. */ void pushTxnAcceptedAsync(Round round) { List<ReceiveCommand> cmds = new ArrayList<>(); if (commitSpeed == BATCHED) { LogIndex committedIndex = leader.getCommitted(); if (equals(txnAccepted, committedIndex) && !equals(txnCommitted, committedIndex)) { prepareTxnCommitted(cmds, committedIndex); } } // TODO(sop) Lagging replicas should build accept on the fly. if (round.stageCommands != null) { for (ReceiveCommand cmd : round.stageCommands) { // TODO(sop): Do not send certain object graphs to replica. cmds.add(copy(cmd)); } } cmds.add(new ReceiveCommand( round.acceptedOldIndex, round.acceptedNewIndex, getSystem().getTxnAccepted())); pushAsync(new ReplicaPushRequest(this, cmds)); }
/** * Update the leader's view of the replica after a poll. * <p> * Called with {@link KetchLeader#lock} held by caller. * * @param refs * map of refs from the replica. */ void initialize(Map<String, Ref> refs) { if (txnAccepted == null) { txnAccepted = getId(refs.get(getSystem().getTxnAccepted())); } if (txnCommitted == null) { txnCommitted = getId(refs.get(getSystem().getTxnCommitted())); } }
private void updateView(ReplicaPushRequest req, @Nullable ObjectId acceptId, ReceiveCommand commitCmd) { if (acceptId != null) { txnAccepted = acceptId; } ObjectId committed = readId(req, commitCmd); if (committed != null) { txnCommitted = committed; } else if (acceptId != null && txnCommitted == null) { // Initialize during first conversation. Map<String, Ref> adv = req.getRefs(); if (adv != null) { Ref refs = adv.get(getSystem().getTxnCommitted()); txnCommitted = getId(refs); } } }
if (!equals(txnCommitted, committed) && shouldPushUnbatchedCommit(committed, leader.isIdle())) { pushCommitAsync(committed); if (queued.isEmpty() || !running.isEmpty() || waitingForRetry()) { return; running.put(cmd.getRefName(), cmd); startPush(new ReplicaPushRequest(this, next));
private void retryLater(ReplicaPushRequest req) { Collection<ReceiveCommand> cmds = req.getCommands(); for (ReceiveCommand cmd : cmds) { cmd.setResult(NOT_ATTEMPTED, null); if (!waiting.containsKey(cmd.getRefName())) { waiting.put(cmd.getRefName(), cmd); } } queued.add(0, new ReplicaPushRequest(this, cmds)); if (!waitingForRetry()) { long delay = KetchSystem.delay( lastRetryMillis, minRetryMillis, maxRetryMillis); if (log.isDebugEnabled()) { log.debug("Retrying {} after {} ms", //$NON-NLS-1$ describeForLog(), Long.valueOf(delay)); } lastRetryMillis = delay; retryAtMillis = SystemReader.getInstance().getCurrentTime() + delay; retryFuture = getSystem().getExecutor() .schedule(new WeakRetryPush(this), delay, MILLISECONDS); } }
if (log.isDebugEnabled()) { log.debug("Replica {} finished:\n{}", //$NON-NLS-1$ replica.describeForLog(), snapshot()); if (replica.getParticipation() == FOLLOWER_ONLY) { int matching = 0; for (KetchReplica r : voters) { if (r.hasAccepted(headIndex)) { matching++;
private void pushAsync(ReplicaPushRequest req) { if (defer(req)) { // TODO(sop) Collapse during long retry outage. for (ReceiveCommand cmd : req.getCommands()) { waiting.put(cmd.getRefName(), cmd); } queued.add(req); } else { for (ReceiveCommand cmd : req.getCommands()) { running.put(cmd.getRefName(), cmd); } startPush(req); } }
/** * Get system configuration. * * @return system configuration. */ public KetchSystem getSystem() { return getLeader().getSystem(); }
@Nullable private static ObjectId readId(ReplicaPushRequest req, @Nullable ReceiveCommand cmd) { if (cmd == null) { // Ref was not in the command list, do not trust advertisement. return null; } else if (cmd.getResult() == OK) { // Currently at newId. return cmd.getNewId(); } Map<String, Ref> refs = req.getRefs(); return refs != null ? getId(refs.get(cmd.getRefName())) : null; }
boolean hasAccepted(LogIndex id) { return equals(txnAccepted, id); }
private String describe(String heading) { StringBuilder b = new StringBuilder(); b.append("push to "); //$NON-NLS-1$ b.append(replica.describeForLog()); b.append(' ').append(heading).append(":\n"); //$NON-NLS-1$ for (ReceiveCommand cmd : commands) { b.append(String.format( " %-12s %-12s %s %s", //$NON-NLS-1$ LeaderSnapshot.str(cmd.getOldId()), LeaderSnapshot.str(cmd.getNewId()), cmd.getRefName(), cmd.getResult())); if (cmd.getMessage() != null) { b.append(' ').append(cmd.getMessage()); } b.append('\n'); } return b.toString(); } }
private void removeStaged(List<ReceiveCommand> cmds, ObjectId committed) { List<ReceiveCommand> a = staged.remove(committed); if (a != null) { delete(cmds, a); } if (staged.isEmpty() || !(committed instanceof LogIndex)) { return; } LogIndex committedIndex = (LogIndex) committed; Iterator<Map.Entry<ObjectId, List<ReceiveCommand>>> itr = staged .entrySet().iterator(); while (itr.hasNext()) { Map.Entry<ObjectId, List<ReceiveCommand>> e = itr.next(); if (e.getKey() instanceof LogIndex) { LogIndex stagedIndex = (LogIndex) e.getKey(); if (stagedIndex.isBefore(committedIndex)) { delete(cmds, e.getValue()); itr.remove(); } } } }
if (!equals(txnCommitted, committed) && shouldPushUnbatchedCommit(committed, leader.isIdle())) { pushCommitAsync(committed); if (queued.isEmpty() || !running.isEmpty() || waitingForRetry()) { return; running.put(cmd.getRefName(), cmd); startPush(new ReplicaPushRequest(this, next));
private void updateView(ReplicaPushRequest req, @Nullable ObjectId acceptId, ReceiveCommand commitCmd) { if (acceptId != null) { txnAccepted = acceptId; } ObjectId committed = readId(req, commitCmd); if (committed != null) { txnCommitted = committed; } else if (acceptId != null && txnCommitted == null) { // Initialize during first conversation. Map<String, Ref> adv = req.getRefs(); if (adv != null) { Ref refs = adv.get(getSystem().getTxnCommitted()); txnCommitted = getId(refs); } } }
private void retryLater(ReplicaPushRequest req) { Collection<ReceiveCommand> cmds = req.getCommands(); for (ReceiveCommand cmd : cmds) { cmd.setResult(NOT_ATTEMPTED, null); if (!waiting.containsKey(cmd.getRefName())) { waiting.put(cmd.getRefName(), cmd); } } queued.add(0, new ReplicaPushRequest(this, cmds)); if (!waitingForRetry()) { long delay = KetchSystem.delay( lastRetryMillis, minRetryMillis, maxRetryMillis); if (log.isDebugEnabled()) { log.debug("Retrying {} after {} ms", //$NON-NLS-1$ describeForLog(), Long.valueOf(delay)); } lastRetryMillis = delay; retryAtMillis = SystemReader.getInstance().getCurrentTime() + delay; retryFuture = getSystem().getExecutor() .schedule(new WeakRetryPush(this), delay, MILLISECONDS); } }
if (log.isDebugEnabled()) { log.debug("Replica {} finished:\n{}", //$NON-NLS-1$ replica.describeForLog(), snapshot()); if (replica.getParticipation() == FOLLOWER_ONLY) { int matching = 0; for (KetchReplica r : voters) { if (r.hasAccepted(headIndex)) { matching++;
private void pushAsync(ReplicaPushRequest req) { if (defer(req)) { // TODO(sop) Collapse during long retry outage. for (ReceiveCommand cmd : req.getCommands()) { waiting.put(cmd.getRefName(), cmd); } queued.add(req); } else { for (ReceiveCommand cmd : req.getCommands()) { running.put(cmd.getRefName(), cmd); } startPush(req); } }