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

org.jgroups.raft.util.CommitTable Maven / Gradle / Ivy

There is a newer version: 1.0.13.Final
Show newest version
package org.jgroups.raft.util;

import org.jgroups.Address;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * Keeps track of next_index and match_index for each cluster member (excluding this leader).
 * Used to (1) compute the commit_index and (2) to resend log entries to members which haven't yet seen them.

* Only created on the leader * @author Bela Ban * @since 0.1 */ public class CommitTable { protected final ConcurrentMap map=new ConcurrentHashMap<>(); public CommitTable(List

members, long next_index) { adjust(members, next_index); } public Set
keys() {return map.keySet();} public Entry get(Address a) {return map.get(a);} public void adjust(List
members, long next_index) { map.keySet().retainAll(members); // entry is only created if mbr is not in map, reducing unneeded creations members.forEach(mbr -> map.computeIfAbsent(mbr, k -> new Entry(next_index))); } public CommitTable update(Address member, long match_index, long next_index, long commit_index, boolean single_resend) { return update(member, match_index, next_index, commit_index, single_resend, false); } public CommitTable update(Address member, long match_index, long next_index, long commit_index, boolean single_resend, boolean overwrite) { Entry e=map.get(member); if(e == null) return this; e.match_index=overwrite? match_index : Math.max(match_index, e.match_index); e.next_index=Math.max(1, next_index); e.commit_index=Math.max(e.commit_index, commit_index); e.send_single_msg=single_resend; e.assertInvariant(); return this; } /** Applies a function to all elements of the commit table */ public void forEach(BiConsumer function) { for(Map.Entry entry: map.entrySet()) { Entry val=entry.getValue(); function.accept(entry.getKey(), val); } } @Override public String toString() { return map.entrySet().stream().map(e -> String.format("%s: %s", e.getKey(), e.getValue())) .collect(Collectors.joining("\n")); } public static class Entry { protected long commit_index; // the commit index of the given member protected long match_index; // the index of the highest entry known to be replicated to the member protected long next_index; // the next index to send; initialized to last_appended +1 // set to true when next_index was decremented, so we only send a single entry on the next resend interval; // set to false when we receive an AppendEntries(true) response protected boolean send_single_msg; public Entry(long next_index) {this.next_index=next_index;} public long commitIndex() {return commit_index;} public Entry commitIndex(long idx) {this.commit_index=idx; return this;} public long matchIndex() {return match_index;} public Entry matchIndex(long idx) {this.match_index=idx; return this;} public long nextIndex() {return next_index;} public Entry nextIndex(long idx) {next_index=idx; return this;} public boolean sendSingleMessage() {return send_single_msg;} public Entry sendSingleMessage(boolean flag) {this.send_single_msg=flag; return this;} public void assertInvariant() { assert commit_index <= match_index && match_index <= next_index : this; } @Override public String toString() { StringBuilder sb=new StringBuilder("commit-index=").append(commit_index) .append(", match-index=").append(match_index).append(", next-index=").append(next_index); if(send_single_msg) sb.append(" [send-single-msg]"); return sb.toString(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy