/** * Apply mutations to the underlying {@link KVStore}. */ void applyMutations(final Iterable<Mutation> mutations) { if (this.kv instanceof AtomicKVStore) { ((AtomicKVStore)this.kv).mutate(new Mutations() { @Override public Iterable<Del> getRemoveRanges() { return Iterables.filter(mutations, Del.class); } @Override public Iterable<Map.Entry<byte[], byte[]>> getPutPairs() { return Iterables.transform(Iterables.filter(mutations, Put.class), Put::toMapEntry); } @Override public Iterable<Map.Entry<byte[], Long>> getAdjustPairs() { return Collections.<Map.Entry<byte[], Long>>emptySet(); } }, true); } else { for (Mutation mutation : mutations) mutation.apply(this.kv); } }
/** * Join the specified cluster and persist the specified cluster ID. * * @param newClusterId cluster ID; must not be zero * @return true if successful, false if an error occurred * @throws IllegalStateException if this node is already part of some cluster * @throws IllegalArgumentException if {@code newClusterId} is zero */ boolean joinCluster(int newClusterId) { // Sanity check assert Thread.holdsLock(this); Preconditions.checkArgument(newClusterId != 0); Preconditions.checkState(this.clusterId == 0); // Persist it this.info("joining cluster with ID " + String.format("0x%08x", newClusterId)); final Writes writes = new Writes(); writes.getPuts().put(CLUSTER_ID_KEY, LongEncoder.encode(newClusterId)); try { this.kv.mutate(writes, true); } catch (Exception e) { this.error("error updating key/value store with new cluster ID", e); return false; } // Done this.clusterId = newClusterId; return true; }
/** * Record the peer voted for in the current term. */ private boolean updateVotedFor(String recipient) { // Sanity check assert Thread.holdsLock(this.raft); assert recipient != null; // Update persistent store final Writes writes = new Writes(); writes.getPuts().put(RaftKVDatabase.VOTED_FOR_KEY, this.raft.encodeString(recipient)); try { this.raft.kv.mutate(writes, true); } catch (Exception e) { this.error("error persisting vote for \"" + recipient + "\"", e); return false; } // Done this.votedFor = recipient; return true; }
/** * Apply the next chunk of key/value pairs. * * @param buf encoded key/value pairs * @throws IllegalArgumentException if {@code buf} contains invalid data * @throws IllegalArgumentException if {@code buf} is null */ public void applyNextChunk(ByteBuffer buf) { // Sanity check Preconditions.checkArgument(buf != null, "null buf"); // Read and apply key/value pairs in a single operation final PutMutations mutations = new PutMutations(buf, this.prefix, this.previousKey); this.kv.mutate(mutations, false); assert mutations.getEndKey() != null || (this.pairIndex == 0 && mutations.getNumPuts() == 0); // Advance our installation frontier this.pairIndex += mutations.getNumPuts(); this.previousKey = mutations.getEndKey(); }
/** * Update and persist a new current term. */ boolean advanceTerm(long newTerm) { // Sanity check assert Thread.holdsLock(this); assert newTerm > this.currentTerm; if (this.logger.isDebugEnabled()) this.debug("advancing current term from " + this.currentTerm + " -> " + newTerm); // Update persistent store final Writes writes = new Writes(); writes.getPuts().put(CURRENT_TERM_KEY, LongEncoder.encode(newTerm)); writes.getRemoves().add(new KeyRange(VOTED_FOR_KEY)); try { this.kv.mutate(writes, true); } catch (Exception e) { this.error("error persisting new term " + newTerm, e); return false; } // Update in-memory copy this.currentTerm = newTerm; this.currentTermStartTime = System.currentTimeMillis(); return true; }
this.kv.mutate(writes, true); } catch (Exception e) { this.error("flip-flop error updating key/value store term/index to " + index + "t" + term, e);
this.debug("applying committed log entry " + logEntry + " to key/value store"); try { this.raft.kv.mutate(mutations, !this.raft.disableSync && this.raft.log.getLastAppliedIndex() == this.raft.commitIndex); } catch (Exception e) {