View Javadoc
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  }