1 /* 2 * Copyright (C) 2016, Google Inc. and others 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the Eclipse Distribution License v. 1.0 which is available at 6 * https://www.eclipse.org/org/documents/edl-v10.php. 7 * 8 * SPDX-License-Identifier: BSD-3-Clause 9 */ 10 11 package org.eclipse.jgit.internal.ketch; 12 13 import org.eclipse.jgit.lib.AnyObjectId; 14 import org.eclipse.jgit.lib.ObjectId; 15 16 /** 17 * An ObjectId for a commit extended with incrementing log index. 18 * <p> 19 * For any two LogIndex instances, {@code A} is an ancestor of {@code C} 20 * reachable through parent edges in the graph if {@code A.index < C.index}. 21 * LogIndex provides a performance optimization for Ketch, the same information 22 * can be obtained from {@link org.eclipse.jgit.revwalk.RevWalk}. 23 * <p> 24 * Index values are only valid within a single 25 * {@link org.eclipse.jgit.internal.ketch.KetchLeader} instance after it has won 26 * an election. By restricting scope to a single leader new leaders do not need 27 * to traverse the entire history to determine the next {@code index} for new 28 * proposals. This differs from Raft, where leader election uses the log index 29 * and the term number to determine which replica holds a sufficiently 30 * up-to-date log. Since Ketch uses Git objects for storage of its replicated 31 * log, it keeps the term number as Raft does but uses standard Git operations 32 * to imply the log index. 33 * <p> 34 * {@link org.eclipse.jgit.internal.ketch.Round#runAsync(AnyObjectId)} bumps the 35 * index as each new round is constructed. 36 */ 37 public class LogIndex extends ObjectId { 38 static LogIndex unknown(AnyObjectId id) { 39 return new LogIndex(id, 0); 40 } 41 42 private final long index; 43 44 private LogIndex(AnyObjectId id, long index) { 45 super(id); 46 this.index = index; 47 } 48 49 LogIndex nextIndex(AnyObjectId id) { 50 return new LogIndex(id, index + 1); 51 } 52 53 /** 54 * Get index provided by the current leader instance. 55 * 56 * @return index provided by the current leader instance. 57 */ 58 public long getIndex() { 59 return index; 60 } 61 62 /** 63 * Check if this log position committed before another log position. 64 * <p> 65 * Only valid for log positions in memory for the current leader. 66 * 67 * @param c 68 * other (more recent) log position. 69 * @return true if this log position was before {@code c} or equal to c and 70 * therefore any agreement of {@code c} implies agreement on this 71 * log position. 72 */ 73 boolean isBefore(LogIndex c) { 74 return index <= c.index; 75 } 76 77 /** 78 * Create string suitable for debug logging containing the log index and 79 * abbreviated ObjectId. 80 * 81 * @return string suitable for debug logging containing the log index and 82 * abbreviated ObjectId. 83 */ 84 @SuppressWarnings("boxing") 85 public String describeForLog() { 86 return String.format("%5d/%s", index, abbreviate(6).name()); //$NON-NLS-1$ 87 } 88 89 /** {@inheritDoc} */ 90 @SuppressWarnings("boxing") 91 @Override 92 public String toString() { 93 return String.format("LogId[%5d/%s]", index, name()); //$NON-NLS-1$ 94 } 95 }