Browse Source

DHT: Add sequence RefData

RefData now uses a sequence number as part of the field, ensuring
that updates always increase the sequence number by one whenever
a reference is modified.

Attaching a sequence number to RefData will help with storing
reference log entries during updates. As the sequence number should
be unique within the reference name space, log entries can be keyed
by the sequence number and remain unique.  Making this work over
reference delete-create cycles will require an additional RefTable
API to return the oldest sequence number previously used in the
reference log to seed the recreated reference.

Change-Id: I11cfff2a96ef962e57f29925a3eef41bdbf9f9bb
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
stable-1.0
Shawn O. Pearce 14 years ago committed by Chris Aniszczyk
parent
commit
b8c508e54d
  1. 5
      org.eclipse.jgit.generated.storage.dht.proto/resources/org/eclipse/jgit/storage/dht/git_store.proto
  2. 254
      org.eclipse.jgit.generated.storage.dht.proto/src/org/eclipse/jgit/generated/storage/dht/proto/GitStore.java
  3. 216
      org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtRefDatabase.java
  4. 52
      org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtRefUpdate.java
  5. 58
      org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RefDataUtil.java
  6. 11
      org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java

5
org.eclipse.jgit.generated.storage.dht.proto/resources/org/eclipse/jgit/storage/dht/git_store.proto

@ -56,6 +56,11 @@ option java_package = "org.eclipse.jgit.generated.storage.dht.proto";
// Either symref *OR* target must be populated, but never both.
//
message RefData {
// Incrementing counter updated each time the RefData changes.
// Should always start at 1.
//
required uint32 sequence = 5 [default = 0];
// An ObjectId with an optional hint about where it can be found.
//
message Id {

254
org.eclipse.jgit.generated.storage.dht.proto/src/org/eclipse/jgit/generated/storage/dht/proto/GitStore.java

@ -11,6 +11,10 @@ public final class GitStore {
public interface RefDataOrBuilder
extends com.google.protobuf.MessageOrBuilder {
// required uint32 sequence = 5 [default = 0];
boolean hasSequence();
int getSequence();
// optional string symref = 1;
boolean hasSymref();
String getSymref();
@ -575,11 +579,21 @@ public final class GitStore {
}
private int bitField0_;
// required uint32 sequence = 5 [default = 0];
public static final int SEQUENCE_FIELD_NUMBER = 5;
private int sequence_;
public boolean hasSequence() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
public int getSequence() {
return sequence_;
}
// optional string symref = 1;
public static final int SYMREF_FIELD_NUMBER = 1;
private Object symref_;
public boolean hasSymref() {
return ((bitField0_ & 0x00000001) == 0x00000001);
return ((bitField0_ & 0x00000002) == 0x00000002);
}
public String getSymref() {
Object ref = symref_;
@ -611,7 +625,7 @@ public final class GitStore {
public static final int TARGET_FIELD_NUMBER = 2;
private org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id target_;
public boolean hasTarget() {
return ((bitField0_ & 0x00000002) == 0x00000002);
return ((bitField0_ & 0x00000004) == 0x00000004);
}
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getTarget() {
return target_;
@ -624,7 +638,7 @@ public final class GitStore {
public static final int IS_PEELED_FIELD_NUMBER = 3;
private boolean isPeeled_;
public boolean hasIsPeeled() {
return ((bitField0_ & 0x00000004) == 0x00000004);
return ((bitField0_ & 0x00000008) == 0x00000008);
}
public boolean getIsPeeled() {
return isPeeled_;
@ -634,7 +648,7 @@ public final class GitStore {
public static final int PEELED_FIELD_NUMBER = 4;
private org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id peeled_;
public boolean hasPeeled() {
return ((bitField0_ & 0x00000008) == 0x00000008);
return ((bitField0_ & 0x00000010) == 0x00000010);
}
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getPeeled() {
return peeled_;
@ -644,6 +658,7 @@ public final class GitStore {
}
private void initFields() {
sequence_ = 0;
symref_ = "";
target_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance();
isPeeled_ = false;
@ -654,6 +669,10 @@ public final class GitStore {
byte isInitialized = memoizedIsInitialized;
if (isInitialized != -1) return isInitialized == 1;
if (!hasSequence()) {
memoizedIsInitialized = 0;
return false;
}
if (hasTarget()) {
if (!getTarget().isInitialized()) {
memoizedIsInitialized = 0;
@ -673,18 +692,21 @@ public final class GitStore {
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBytes(1, getSymrefBytes());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeMessage(2, target_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeBool(3, isPeeled_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeMessage(4, peeled_);
}
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeUInt32(5, sequence_);
}
getUnknownFields().writeTo(output);
}
@ -694,22 +716,26 @@ public final class GitStore {
if (size != -1) return size;
size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, getSymrefBytes());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(2, target_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream
.computeBoolSize(3, isPeeled_);
}
if (((bitField0_ & 0x00000008) == 0x00000008)) {
if (((bitField0_ & 0x00000010) == 0x00000010)) {
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(4, peeled_);
}
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(5, sequence_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -731,6 +757,11 @@ public final class GitStore {
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData other = (org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData) obj;
boolean result = true;
result = result && (hasSequence() == other.hasSequence());
if (hasSequence()) {
result = result && (getSequence()
== other.getSequence());
}
result = result && (hasSymref() == other.hasSymref());
if (hasSymref()) {
result = result && getSymref()
@ -760,6 +791,10 @@ public final class GitStore {
public int hashCode() {
int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode();
if (hasSequence()) {
hash = (37 * hash) + SEQUENCE_FIELD_NUMBER;
hash = (53 * hash) + getSequence();
}
if (hasSymref()) {
hash = (37 * hash) + SYMREF_FIELD_NUMBER;
hash = (53 * hash) + getSymref().hashCode();
@ -894,22 +929,24 @@ public final class GitStore {
public Builder clear() {
super.clear();
symref_ = "";
sequence_ = 0;
bitField0_ = (bitField0_ & ~0x00000001);
symref_ = "";
bitField0_ = (bitField0_ & ~0x00000002);
if (targetBuilder_ == null) {
target_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance();
} else {
targetBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000002);
isPeeled_ = false;
bitField0_ = (bitField0_ & ~0x00000004);
isPeeled_ = false;
bitField0_ = (bitField0_ & ~0x00000008);
if (peeledBuilder_ == null) {
peeled_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance();
} else {
peeledBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000008);
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
@ -951,22 +988,26 @@ public final class GitStore {
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001;
}
result.symref_ = symref_;
result.sequence_ = sequence_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002;
}
result.symref_ = symref_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
if (targetBuilder_ == null) {
result.target_ = target_;
} else {
result.target_ = targetBuilder_.build();
}
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
result.isPeeled_ = isPeeled_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008;
}
result.isPeeled_ = isPeeled_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000010;
}
if (peeledBuilder_ == null) {
result.peeled_ = peeled_;
} else {
@ -988,6 +1029,9 @@ public final class GitStore {
public Builder mergeFrom(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData other) {
if (other == org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.getDefaultInstance()) return this;
if (other.hasSequence()) {
setSequence(other.getSequence());
}
if (other.hasSymref()) {
setSymref(other.getSymref());
}
@ -1005,6 +1049,10 @@ public final class GitStore {
}
public final boolean isInitialized() {
if (!hasSequence()) {
return false;
}
if (hasTarget()) {
if (!getTarget().isInitialized()) {
@ -1044,7 +1092,7 @@ public final class GitStore {
break;
}
case 10: {
bitField0_ |= 0x00000001;
bitField0_ |= 0x00000002;
symref_ = input.readBytes();
break;
}
@ -1058,7 +1106,7 @@ public final class GitStore {
break;
}
case 24: {
bitField0_ |= 0x00000004;
bitField0_ |= 0x00000008;
isPeeled_ = input.readBool();
break;
}
@ -1071,16 +1119,42 @@ public final class GitStore {
setPeeled(subBuilder.buildPartial());
break;
}
case 40: {
bitField0_ |= 0x00000001;
sequence_ = input.readUInt32();
break;
}
}
}
}
private int bitField0_;
// required uint32 sequence = 5 [default = 0];
private int sequence_ ;
public boolean hasSequence() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
public int getSequence() {
return sequence_;
}
public Builder setSequence(int value) {
bitField0_ |= 0x00000001;
sequence_ = value;
onChanged();
return this;
}
public Builder clearSequence() {
bitField0_ = (bitField0_ & ~0x00000001);
sequence_ = 0;
onChanged();
return this;
}
// optional string symref = 1;
private Object symref_ = "";
public boolean hasSymref() {
return ((bitField0_ & 0x00000001) == 0x00000001);
return ((bitField0_ & 0x00000002) == 0x00000002);
}
public String getSymref() {
Object ref = symref_;
@ -1096,19 +1170,19 @@ public final class GitStore {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
bitField0_ |= 0x00000002;
symref_ = value;
onChanged();
return this;
}
public Builder clearSymref() {
bitField0_ = (bitField0_ & ~0x00000001);
bitField0_ = (bitField0_ & ~0x00000002);
symref_ = getDefaultInstance().getSymref();
onChanged();
return this;
}
void setSymref(com.google.protobuf.ByteString value) {
bitField0_ |= 0x00000001;
bitField0_ |= 0x00000002;
symref_ = value;
onChanged();
}
@ -1118,7 +1192,7 @@ public final class GitStore {
private com.google.protobuf.SingleFieldBuilder<
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id, org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder, org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.IdOrBuilder> targetBuilder_;
public boolean hasTarget() {
return ((bitField0_ & 0x00000002) == 0x00000002);
return ((bitField0_ & 0x00000004) == 0x00000004);
}
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getTarget() {
if (targetBuilder_ == null) {
@ -1137,7 +1211,7 @@ public final class GitStore {
} else {
targetBuilder_.setMessage(value);
}
bitField0_ |= 0x00000002;
bitField0_ |= 0x00000004;
return this;
}
public Builder setTarget(
@ -1148,12 +1222,12 @@ public final class GitStore {
} else {
targetBuilder_.setMessage(builderForValue.build());
}
bitField0_ |= 0x00000002;
bitField0_ |= 0x00000004;
return this;
}
public Builder mergeTarget(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id value) {
if (targetBuilder_ == null) {
if (((bitField0_ & 0x00000002) == 0x00000002) &&
if (((bitField0_ & 0x00000004) == 0x00000004) &&
target_ != org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance()) {
target_ =
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.newBuilder(target_).mergeFrom(value).buildPartial();
@ -1164,7 +1238,7 @@ public final class GitStore {
} else {
targetBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000002;
bitField0_ |= 0x00000004;
return this;
}
public Builder clearTarget() {
@ -1174,11 +1248,11 @@ public final class GitStore {
} else {
targetBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000002);
bitField0_ = (bitField0_ & ~0x00000004);
return this;
}
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder getTargetBuilder() {
bitField0_ |= 0x00000002;
bitField0_ |= 0x00000004;
onChanged();
return getTargetFieldBuilder().getBuilder();
}
@ -1206,19 +1280,19 @@ public final class GitStore {
// optional bool is_peeled = 3;
private boolean isPeeled_ ;
public boolean hasIsPeeled() {
return ((bitField0_ & 0x00000004) == 0x00000004);
return ((bitField0_ & 0x00000008) == 0x00000008);
}
public boolean getIsPeeled() {
return isPeeled_;
}
public Builder setIsPeeled(boolean value) {
bitField0_ |= 0x00000004;
bitField0_ |= 0x00000008;
isPeeled_ = value;
onChanged();
return this;
}
public Builder clearIsPeeled() {
bitField0_ = (bitField0_ & ~0x00000004);
bitField0_ = (bitField0_ & ~0x00000008);
isPeeled_ = false;
onChanged();
return this;
@ -1229,7 +1303,7 @@ public final class GitStore {
private com.google.protobuf.SingleFieldBuilder<
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id, org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder, org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.IdOrBuilder> peeledBuilder_;
public boolean hasPeeled() {
return ((bitField0_ & 0x00000008) == 0x00000008);
return ((bitField0_ & 0x00000010) == 0x00000010);
}
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getPeeled() {
if (peeledBuilder_ == null) {
@ -1248,7 +1322,7 @@ public final class GitStore {
} else {
peeledBuilder_.setMessage(value);
}
bitField0_ |= 0x00000008;
bitField0_ |= 0x00000010;
return this;
}
public Builder setPeeled(
@ -1259,12 +1333,12 @@ public final class GitStore {
} else {
peeledBuilder_.setMessage(builderForValue.build());
}
bitField0_ |= 0x00000008;
bitField0_ |= 0x00000010;
return this;
}
public Builder mergePeeled(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id value) {
if (peeledBuilder_ == null) {
if (((bitField0_ & 0x00000008) == 0x00000008) &&
if (((bitField0_ & 0x00000010) == 0x00000010) &&
peeled_ != org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance()) {
peeled_ =
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.newBuilder(peeled_).mergeFrom(value).buildPartial();
@ -1275,7 +1349,7 @@ public final class GitStore {
} else {
peeledBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000008;
bitField0_ |= 0x00000010;
return this;
}
public Builder clearPeeled() {
@ -1285,11 +1359,11 @@ public final class GitStore {
} else {
peeledBuilder_.clear();
}
bitField0_ = (bitField0_ & ~0x00000008);
bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder getPeeledBuilder() {
bitField0_ |= 0x00000008;
bitField0_ |= 0x00000010;
onChanged();
return getPeeledFieldBuilder().getBuilder();
}
@ -7811,51 +7885,51 @@ public final class GitStore {
static {
java.lang.String[] descriptorData = {
"\n,org/eclipse/jgit/storage/dht/git_store" +
".proto\022\034org.eclipse.jgit.storage.dht\"\316\001\n" +
"\007RefData\022\016\n\006symref\030\001 \001(\t\0228\n\006target\030\002 \001(\013" +
"2(.org.eclipse.jgit.storage.dht.RefData." +
"Id\022\021\n\tis_peeled\030\003 \001(\010\0228\n\006peeled\030\004 \001(\0132(." +
"org.eclipse.jgit.storage.dht.RefData.Id\032" +
",\n\002Id\022\023\n\013object_name\030\001 \002(\t\022\021\n\tchunk_key\030" +
"\002 \001(\t\"\364\001\n\nObjectInfo\022H\n\013object_type\030\001 \001(" +
"\01623.org.eclipse.jgit.storage.dht.ObjectI" +
"nfo.ObjectType\022\016\n\006offset\030\002 \002(\005\022\023\n\013packed",
"_size\030\003 \002(\003\022\025\n\rinflated_size\030\004 \002(\003\022\022\n\nde" +
"lta_base\030\005 \001(\014\022\025\n\ris_fragmented\030\006 \001(\010\"5\n" +
"\nObjectType\022\n\n\006COMMIT\020\001\022\010\n\004TREE\020\002\022\010\n\004BLO" +
"B\020\003\022\007\n\003TAG\020\004\"\217\004\n\tChunkInfo\022>\n\006source\030\001 \001" +
"(\0162..org.eclipse.jgit.storage.dht.ChunkI" +
"nfo.Source\022G\n\013object_type\030\002 \001(\01622.org.ec" +
"lipse.jgit.storage.dht.ChunkInfo.ObjectT" +
"ype\022\023\n\013is_fragment\030\003 \001(\010\022\027\n\017cached_pack_" +
"key\030\004 \001(\t\022K\n\robject_counts\030\005 \001(\01324.org.e" +
"clipse.jgit.storage.dht.ChunkInfo.Object",
"Counts\022\022\n\nchunk_size\030\006 \001(\005\022\022\n\nindex_size" +
"\030\007 \001(\005\022\021\n\tmeta_size\030\010 \001(\005\032R\n\014ObjectCount" +
"s\022\r\n\005total\030\001 \001(\005\022\r\n\005whole\030\002 \001(\005\022\021\n\tofs_d" +
"elta\030\003 \001(\005\022\021\n\tref_delta\030\004 \001(\005\"-\n\006Source\022" +
"\013\n\007RECEIVE\020\001\022\n\n\006INSERT\020\002\022\n\n\006REPACK\020\003\"@\n\n" +
"ObjectType\022\t\n\005MIXED\020\000\022\n\n\006COMMIT\020\001\022\010\n\004TRE" +
"E\020\002\022\010\n\004BLOB\020\003\022\007\n\003TAG\020\004\"\352\002\n\tChunkMeta\022E\n\n" +
"base_chunk\030\001 \003(\01321.org.eclipse.jgit.stor" +
"age.dht.ChunkMeta.BaseChunk\022\020\n\010fragment\030" +
"\002 \003(\t\022M\n\017commit_prefetch\0303 \001(\01324.org.ecl",
"ipse.jgit.storage.dht.ChunkMeta.Prefetch" +
"Hint\022K\n\rtree_prefetch\0304 \001(\01324.org.eclips" +
"e.jgit.storage.dht.ChunkMeta.PrefetchHin" +
"t\0326\n\tBaseChunk\022\026\n\016relative_start\030\001 \002(\003\022\021" +
"\n\tchunk_key\030\002 \002(\t\0320\n\014PrefetchHint\022\014\n\004edg" +
"e\030\001 \003(\t\022\022\n\nsequential\030\002 \003(\t\"\322\002\n\016CachedPa" +
"ckInfo\022\014\n\004name\030\001 \002(\t\022\017\n\007version\030\002 \002(\t\022\025\n" +
"\robjects_total\030\003 \002(\003\022\025\n\robjects_delta\030\004 " +
"\001(\003\022\023\n\013bytes_total\030\005 \001(\003\022L\n\010tip_list\030\006 \002" +
"(\0132:.org.eclipse.jgit.storage.dht.Cached",
"PackInfo.TipObjectList\022J\n\nchunk_list\030\007 \002" +
"(\01326.org.eclipse.jgit.storage.dht.Cached" +
"PackInfo.ChunkList\032$\n\rTipObjectList\022\023\n\013o" +
"bject_name\030\001 \003(\t\032\036\n\tChunkList\022\021\n\tchunk_k" +
"ey\030\001 \003(\tB1\n,org.eclipse.jgit.generated.s" +
"torage.dht.proto\240\001\001"
".proto\022\034org.eclipse.jgit.storage.dht\"\343\001\n" +
"\007RefData\022\023\n\010sequence\030\005 \002(\r:\0010\022\016\n\006symref\030" +
"\001 \001(\t\0228\n\006target\030\002 \001(\0132(.org.eclipse.jgit" +
".storage.dht.RefData.Id\022\021\n\tis_peeled\030\003 \001" +
"(\010\0228\n\006peeled\030\004 \001(\0132(.org.eclipse.jgit.st" +
"orage.dht.RefData.Id\032,\n\002Id\022\023\n\013object_nam" +
"e\030\001 \002(\t\022\021\n\tchunk_key\030\002 \001(\t\"\364\001\n\nObjectInf" +
"o\022H\n\013object_type\030\001 \001(\01623.org.eclipse.jgi" +
"t.storage.dht.ObjectInfo.ObjectType\022\016\n\006o",
"ffset\030\002 \002(\005\022\023\n\013packed_size\030\003 \002(\003\022\025\n\rinfl" +
"ated_size\030\004 \002(\003\022\022\n\ndelta_base\030\005 \001(\014\022\025\n\ri" +
"s_fragmented\030\006 \001(\010\"5\n\nObjectType\022\n\n\006COMM" +
"IT\020\001\022\010\n\004TREE\020\002\022\010\n\004BLOB\020\003\022\007\n\003TAG\020\004\"\217\004\n\tCh" +
"unkInfo\022>\n\006source\030\001 \001(\0162..org.eclipse.jg" +
"it.storage.dht.ChunkInfo.Source\022G\n\013objec" +
"t_type\030\002 \001(\01622.org.eclipse.jgit.storage." +
"dht.ChunkInfo.ObjectType\022\023\n\013is_fragment\030" +
"\003 \001(\010\022\027\n\017cached_pack_key\030\004 \001(\t\022K\n\robject" +
"_counts\030\005 \001(\01324.org.eclipse.jgit.storage",
".dht.ChunkInfo.ObjectCounts\022\022\n\nchunk_siz" +
"e\030\006 \001(\005\022\022\n\nindex_size\030\007 \001(\005\022\021\n\tmeta_size" +
"\030\010 \001(\005\032R\n\014ObjectCounts\022\r\n\005total\030\001 \001(\005\022\r\n" +
"\005whole\030\002 \001(\005\022\021\n\tofs_delta\030\003 \001(\005\022\021\n\tref_d" +
"elta\030\004 \001(\005\"-\n\006Source\022\013\n\007RECEIVE\020\001\022\n\n\006INS" +
"ERT\020\002\022\n\n\006REPACK\020\003\"@\n\nObjectType\022\t\n\005MIXED" +
"\020\000\022\n\n\006COMMIT\020\001\022\010\n\004TREE\020\002\022\010\n\004BLOB\020\003\022\007\n\003TA" +
"G\020\004\"\352\002\n\tChunkMeta\022E\n\nbase_chunk\030\001 \003(\01321." +
"org.eclipse.jgit.storage.dht.ChunkMeta.B" +
"aseChunk\022\020\n\010fragment\030\002 \003(\t\022M\n\017commit_pre",
"fetch\0303 \001(\01324.org.eclipse.jgit.storage.d" +
"ht.ChunkMeta.PrefetchHint\022K\n\rtree_prefet" +
"ch\0304 \001(\01324.org.eclipse.jgit.storage.dht." +
"ChunkMeta.PrefetchHint\0326\n\tBaseChunk\022\026\n\016r" +
"elative_start\030\001 \002(\003\022\021\n\tchunk_key\030\002 \002(\t\0320" +
"\n\014PrefetchHint\022\014\n\004edge\030\001 \003(\t\022\022\n\nsequenti" +
"al\030\002 \003(\t\"\322\002\n\016CachedPackInfo\022\014\n\004name\030\001 \002(" +
"\t\022\017\n\007version\030\002 \002(\t\022\025\n\robjects_total\030\003 \002(" +
"\003\022\025\n\robjects_delta\030\004 \001(\003\022\023\n\013bytes_total\030" +
"\005 \001(\003\022L\n\010tip_list\030\006 \002(\0132:.org.eclipse.jg",
"it.storage.dht.CachedPackInfo.TipObjectL" +
"ist\022J\n\nchunk_list\030\007 \002(\01326.org.eclipse.jg" +
"it.storage.dht.CachedPackInfo.ChunkList\032" +
"$\n\rTipObjectList\022\023\n\013object_name\030\001 \003(\t\032\036\n" +
"\tChunkList\022\021\n\tchunk_key\030\001 \003(\tB1\n,org.ecl" +
"ipse.jgit.generated.storage.dht.proto\240\001\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
@ -7867,7 +7941,7 @@ public final class GitStore {
internal_static_org_eclipse_jgit_storage_dht_RefData_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_org_eclipse_jgit_storage_dht_RefData_descriptor,
new java.lang.String[] { "Symref", "Target", "IsPeeled", "Peeled", },
new java.lang.String[] { "Sequence", "Symref", "Target", "IsPeeled", "Peeled", },
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.class,
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Builder.class);
internal_static_org_eclipse_jgit_storage_dht_RefData_Id_descriptor =

216
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtRefDatabase.java

@ -45,6 +45,7 @@ package org.eclipse.jgit.storage.dht;
import static org.eclipse.jgit.lib.Ref.Storage.LOOSE;
import static org.eclipse.jgit.lib.Ref.Storage.NEW;
import static org.eclipse.jgit.storage.dht.RefDataUtil.NONE;
import java.io.IOException;
import java.util.Collections;
@ -58,9 +59,6 @@ import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef.PeeledNonTag;
import org.eclipse.jgit.lib.ObjectIdRef.PeeledTag;
import org.eclipse.jgit.lib.ObjectIdRef.Unpeeled;
import org.eclipse.jgit.lib.ObjectIdSubclassMap;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
@ -107,7 +105,7 @@ public class DhtRefDatabase extends RefDatabase {
public Ref getRef(String needle) throws IOException {
RefCache curr = readRefs();
for (String prefix : SEARCH_PATH) {
Ref ref = curr.ids.get(prefix + needle);
DhtRef ref = curr.ids.get(prefix + needle);
if (ref != null) {
ref = resolve(ref, 0, curr.ids);
return ref;
@ -116,6 +114,14 @@ public class DhtRefDatabase extends RefDatabase {
return null;
}
private DhtRef getOneRef(String refName) throws IOException {
RefCache curr = readRefs();
DhtRef ref = curr.ids.get(refName);
if (ref != null)
return resolve(ref, 0, curr.ids);
return ref;
}
@Override
public List<Ref> getAdditionalRefs() {
return Collections.emptyList();
@ -124,12 +130,12 @@ public class DhtRefDatabase extends RefDatabase {
@Override
public Map<String, Ref> getRefs(String prefix) throws IOException {
RefCache curr = readRefs();
RefList<Ref> packed = RefList.emptyList();
RefList<Ref> loose = curr.ids;
RefList.Builder<Ref> sym = new RefList.Builder<Ref>(curr.sym.size());
RefList<DhtRef> packed = RefList.emptyList();
RefList<DhtRef> loose = curr.ids;
RefList.Builder<DhtRef> sym = new RefList.Builder<DhtRef>(curr.sym.size());
for (int idx = 0; idx < curr.sym.size(); idx++) {
Ref ref = curr.sym.get(idx);
DhtRef ref = curr.sym.get(idx);
String name = ref.getName();
ref = resolve(ref, 0, loose);
if (ref != null && ref.getObjectId() != null) {
@ -147,12 +153,12 @@ public class DhtRefDatabase extends RefDatabase {
return new RefMap(prefix, packed, loose, sym.toRefList());
}
private Ref resolve(Ref ref, int depth, RefList<Ref> loose)
private DhtRef resolve(DhtRef ref, int depth, RefList<DhtRef> loose)
throws IOException {
if (!ref.isSymbolic())
return ref;
Ref dst = ref.getTarget();
DhtRef dst = (DhtRef) ref.getTarget();
if (MAX_SYMBOLIC_REF_DEPTH <= depth)
return null; // claim it doesn't exist
@ -165,7 +171,10 @@ public class DhtRefDatabase extends RefDatabase {
if (dst == null)
return null;
return new SymbolicRef(ref.getName(), dst);
return new DhtSymbolicRef(
ref.getName(),
dst,
((DhtSymbolicRef) ref).getRefData());
}
@Override
@ -174,12 +183,12 @@ public class DhtRefDatabase extends RefDatabase {
if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null)
return ref;
Ref newLeaf = doPeel(oldLeaf);
DhtRef newLeaf = doPeel(oldLeaf);
RefCache cur = readRefs();
int idx = cur.ids.find(oldLeaf.getName());
if (0 <= idx && cur.ids.get(idx) == oldLeaf) {
RefList<Ref> newList = cur.ids.set(idx, newLeaf);
RefList<DhtRef> newList = cur.ids.set(idx, newLeaf);
if (cache.compareAndSet(cur, new RefCache(newList, cur)))
cachePeeledState(oldLeaf, newLeaf);
}
@ -192,8 +201,8 @@ public class DhtRefDatabase extends RefDatabase {
try {
RepositoryKey repo = repository.getRepositoryKey();
RefKey key = RefKey.create(repo, newLeaf.getName());
RefData oldData = RefDataUtil.fromRef(oldLeaf);
RefData newData = RefDataUtil.fromRef(newLeaf);
RefData oldData = ((DhtRef) oldLeaf).getRefData();
RefData newData = ((DhtRef) newLeaf).getRefData();
db.ref().compareAndPut(key, oldData, newData);
} catch (TimeoutException e) {
// Ignore a timeout here, we were only trying to update
@ -205,27 +214,36 @@ public class DhtRefDatabase extends RefDatabase {
}
}
private Ref doPeel(final Ref leaf) throws MissingObjectException,
private DhtRef doPeel(final Ref leaf) throws MissingObjectException,
IOException {
RevWalk rw = new RevWalk(getRepository());
try {
String name = leaf.getName();
ObjectId oId = leaf.getObjectId();
RevObject obj = rw.parseAny(oId);
DhtReader ctx = (DhtReader) rw.getObjectReader();
RevObject obj = rw.parseAny(leaf.getObjectId());
RefData.Builder d = RefData.newBuilder(((DhtRef) leaf).getRefData());
ChunkKey key = ctx.findChunk(oId);
if (key != null)
oId = new IdWithChunk(oId, key);
ChunkKey oKey = ctx.findChunk(leaf.getObjectId());
if (oKey != null)
d.getTargetBuilder().setChunkKey(oKey.asString());
else
d.getTargetBuilder().clearChunkKey();
if (obj instanceof RevTag) {
ObjectId pId = rw.peel(obj);
key = ctx.findChunk(pId);
pId = key != null ? new IdWithChunk(pId, key) : pId.copy();
return new PeeledTag(leaf.getStorage(), name, oId, pId);
d.getPeeledBuilder().setObjectName(pId.name());
ChunkKey pKey = ctx.findChunk(pId);
if (pKey != null)
d.getPeeledBuilder().setChunkKey(pKey.asString());
else
d.getPeeledBuilder().clearChunkKey();
} else {
return new PeeledNonTag(leaf.getStorage(), name, oId);
d.clearPeeled();
}
d.setIsPeeled(true);
d.setSequence(d.getSequence() + 1);
return new DhtObjectIdRef(leaf.getName(), d.build());
} finally {
rw.release();
}
@ -242,11 +260,26 @@ public class DhtRefDatabase extends RefDatabase {
@Override
public DhtRefUpdate newUpdate(String refName, boolean detach)
throws IOException {
Ref ref = getRefs(ALL).get(refName);
boolean detachingSymbolicRef = false;
DhtRef ref = getOneRef(refName);
if (ref == null)
ref = new Unpeeled(NEW, refName, null);
ref = new DhtObjectIdRef(refName, NONE);
else
detachingSymbolicRef = detach && ref.isSymbolic();
if (detachingSymbolicRef) {
RefData src = ((DhtRef) ref.getLeaf()).getRefData();
RefData.Builder b = RefData.newBuilder(ref.getRefData());
b.clearSymref();
b.setTarget(src.getTarget());
ref = new DhtObjectIdRef(refName, b.build());
}
RepositoryKey repo = repository.getRepositoryKey();
return new DhtRefUpdate(this, repo, db, ref);
DhtRefUpdate update = new DhtRefUpdate(this, repo, db, ref);
if (detachingSymbolicRef)
update.setDetachingSymbolicRef();
return update;
}
@Override
@ -259,7 +292,7 @@ public class DhtRefDatabase extends RefDatabase {
@Override
public boolean isNameConflicting(String refName) throws IOException {
RefList<Ref> all = readRefs().ids;
RefList<DhtRef> all = readRefs().ids;
// Cannot be nested within an existing reference.
int lastSlash = refName.lastIndexOf('/');
@ -293,15 +326,15 @@ public class DhtRefDatabase extends RefDatabase {
}
void stored(String refName, RefData newData) {
Ref ref = fromData(refName, newData);
DhtRef ref = fromData(refName, newData);
RefCache oldCache, newCache;
do {
oldCache = cache.get();
if (oldCache == null)
return;
RefList<Ref> ids = oldCache.ids.put(ref);
RefList<Ref> sym = oldCache.sym;
RefList<DhtRef> ids = oldCache.ids.put(ref);
RefList<DhtRef> sym = oldCache.sym;
if (ref.isSymbolic()) {
sym.put(ref);
@ -324,12 +357,12 @@ public class DhtRefDatabase extends RefDatabase {
int p;
RefList<Ref> ids = oldCache.ids;
RefList<DhtRef> ids = oldCache.ids;
p = ids.find(refName);
if (0 <= p)
ids = ids.remove(p);
RefList<Ref> sym = oldCache.sym;
RefList<DhtRef> sym = oldCache.sym;
p = sym.find(refName);
if (0 <= p)
sym = sym.remove(p);
@ -352,12 +385,12 @@ public class DhtRefDatabase extends RefDatabase {
}
private RefCache read() throws DhtException, TimeoutException {
RefList.Builder<Ref> id = new RefList.Builder<Ref>();
RefList.Builder<Ref> sym = new RefList.Builder<Ref>();
RefList.Builder<DhtRef> id = new RefList.Builder<DhtRef>();
RefList.Builder<DhtRef> sym = new RefList.Builder<DhtRef>();
ObjectIdSubclassMap<IdWithChunk> hints = new ObjectIdSubclassMap<IdWithChunk>();
for (Map.Entry<RefKey, RefData> e : scan()) {
Ref ref = fromData(e.getKey().getName(), e.getValue());
DhtRef ref = fromData(e.getKey().getName(), e.getValue());
if (ref.isSymbolic())
sym.add(ref);
@ -377,23 +410,18 @@ public class DhtRefDatabase extends RefDatabase {
return new RefCache(id.toRefList(), sym.toRefList(), hints);
}
private static Ref fromData(String name, RefData data) {
if (data.hasSymref()) {
Ref leaf = new Unpeeled(NEW, data.getSymref(), null);
return new SymbolicRef(name, leaf);
}
if (!data.hasTarget())
return new Unpeeled(LOOSE, name, null);
static DhtRef fromData(String name, RefData data) {
if (data.hasSymref())
return new DhtSymbolicRef(name, data);
else
return new DhtObjectIdRef(name, data);
}
ObjectId oId = IdWithChunk.create(data.getTarget());
if (data.getIsPeeled() && data.hasPeeled()) {
ObjectId pId = IdWithChunk.create(data.getPeeled());
return new PeeledTag(LOOSE, name, oId, pId);
}
if (data.getIsPeeled())
return new PeeledNonTag(LOOSE, name, oId);
return new Unpeeled(LOOSE, name, oId);
private static ObjectId idFrom(RefData.Id src) {
ObjectId id = ObjectId.fromString(src.getObjectName());
if (!src.hasChunkKey())
return id;
return new IdWithChunk(id, ChunkKey.fromString(src.getChunkKey()));
}
private Set<Map.Entry<RefKey, RefData>> scan() throws DhtException,
@ -404,21 +432,93 @@ public class DhtRefDatabase extends RefDatabase {
}
private static class RefCache {
final RefList<Ref> ids;
final RefList<DhtRef> ids;
final RefList<Ref> sym;
final RefList<DhtRef> sym;
final ObjectIdSubclassMap<IdWithChunk> hints;
RefCache(RefList<Ref> ids, RefList<Ref> sym,
RefCache(RefList<DhtRef> ids, RefList<DhtRef> sym,
ObjectIdSubclassMap<IdWithChunk> hints) {
this.ids = ids;
this.sym = sym;
this.hints = hints;
}
RefCache(RefList<Ref> ids, RefCache old) {
RefCache(RefList<DhtRef> ids, RefCache old) {
this(ids, old.sym, old.hints);
}
}
static interface DhtRef extends Ref {
RefData getRefData();
}
private static class DhtSymbolicRef extends SymbolicRef implements DhtRef {
private final RefData data;
DhtSymbolicRef(String refName,RefData data) {
super(refName, new DhtObjectIdRef(data.getSymref(), NONE));
this.data = data;
}
DhtSymbolicRef(String refName, Ref target, RefData data) {
super(refName, target);
this.data = data;
}
public RefData getRefData() {
return data;
}
}
private static class DhtObjectIdRef implements DhtRef {
private final String name;
private final RefData data;
private final ObjectId objectId;
private final ObjectId peeledId;
DhtObjectIdRef(String name, RefData data) {
this.name = name;
this.data = data;
this.objectId = data.hasTarget() ? idFrom(data.getTarget()) : null;
this.peeledId = data.hasPeeled() ? idFrom(data.getPeeled()) : null;
}
public String getName() {
return name;
}
public boolean isSymbolic() {
return false;
}
public Ref getLeaf() {
return this;
}
public Ref getTarget() {
return this;
}
public ObjectId getObjectId() {
return objectId;
}
public Ref.Storage getStorage() {
return data.hasTarget() ? LOOSE : NEW;
}
public boolean isPeeled() {
return data.getIsPeeled();
}
public ObjectId getPeeledObjectId() {
return peeledId;
}
public RefData getRefData() {
return data;
}
}
}

52
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/DhtRefUpdate.java

@ -54,6 +54,7 @@ import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.dht.DhtRefDatabase.DhtRef;
import org.eclipse.jgit.storage.dht.spi.Database;
class DhtRefUpdate extends RefUpdate {
@ -107,7 +108,7 @@ class DhtRefUpdate extends RefUpdate {
dstRef = dstRef.getLeaf();
refKey = RefKey.create(repo, dstRef.getName());
oldData = RefDataUtil.fromRef(dstRef);
oldData = ((DhtRef) dstRef).getRefData();
if (dstRef.isSymbolic())
setOldObjectId(null);
@ -158,7 +159,11 @@ class DhtRefUpdate extends RefUpdate {
@Override
protected Result doLink(String target) throws IOException {
try {
newData = RefDataUtil.symbolic(target);
RefData.Builder d = RefData.newBuilder(oldData);
clearRefData(d);
updateSequence(d);
d.setSymref(target);
newData = d.build();
boolean r = db.ref().compareAndPut(refKey, oldData, newData);
if (r) {
getRefDatabase().stored(dstRef.getName(), newData);
@ -175,26 +180,45 @@ class DhtRefUpdate extends RefUpdate {
}
private RefData newData() throws IOException {
RefData.Builder d = RefData.newBuilder(oldData);
clearRefData(d);
updateSequence(d);
ObjectId newId = getNewObjectId();
d.getTargetBuilder().setObjectName(newId.name());
try {
RevObject obj = rw.parseAny(newId);
DhtReader ctx = (DhtReader) rw.getObjectReader();
RevObject obj = rw.parseAny(newId);
ChunkKey key = ctx.findChunk(newId);
if (key != null)
newId = new RefDataUtil.IdWithChunk(newId, key);
ChunkKey oKey = ctx.findChunk(newId);
if (oKey != null)
d.getTargetBuilder().setChunkKey(oKey.asString());
if (obj instanceof RevTag) {
ObjectId pId = rw.peel(obj);
key = ctx.findChunk(pId);
pId = key != null ? new RefDataUtil.IdWithChunk(pId, key) : pId;
return RefDataUtil.peeled(newId, pId);
} else if (obj != null)
return RefDataUtil.peeled(newId, null);
else
return RefDataUtil.id(newId);
ChunkKey pKey = ctx.findChunk(pId);
if (pKey != null)
d.getPeeledBuilder().setChunkKey(pKey.asString());
d.getPeeledBuilder().setObjectName(pId.name());
}
} catch (MissingObjectException e) {
return RefDataUtil.id(newId);
// Automatic peeling failed. Ignore the problem and deal with it
// during reading later, this is the classical Git behavior on disk.
}
return d.build();
}
private static void clearRefData(RefData.Builder d) {
// Clear fields individually rather than discarding the RefData.
// This way implementation specific extensions are carried
// through from the old version to the new version.
d.clearSymref();
d.clearTarget();
d.clearPeeled();
d.clearIsPeeled();
}
private static void updateSequence(RefData.Builder d) {
d.setSequence(d.getSequence() + 1);
}
}

58
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/RefDataUtil.java

@ -46,69 +46,13 @@ package org.eclipse.jgit.storage.dht;
import org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
/** Tools to work with {@link RefData}. */
public class RefDataUtil {
/** Magic constant meaning does not exist. */
public static final RefData NONE = RefData.newBuilder().build();
static RefData symbolic(String target) {
RefData.Builder b = RefData.newBuilder();
b.setSymref(target);
return b.build();
}
static RefData id(AnyObjectId id) {
RefData.Builder b = RefData.newBuilder();
b.setTarget(toRefData(id));
return b.build();
}
static RefData fromRef(Ref ref) {
if (ref.isSymbolic())
return symbolic(ref.getTarget().getName());
if (ref.getObjectId() == null)
return NONE;
RefData.Builder b = RefData.newBuilder();
b.setTarget(toRefData(ref.getObjectId()));
if (ref.isPeeled()) {
b.setIsPeeled(true);
if (ref.getPeeledObjectId() != null)
b.setPeeled(toRefData(ref.getPeeledObjectId()));
}
return b.build();
}
static RefData peeled(ObjectId targetId, ObjectId peeledId) {
RefData.Builder b = RefData.newBuilder();
b.setTarget(toRefData(targetId));
b.setIsPeeled(true);
if (peeledId != null)
b.setPeeled(toRefData(peeledId));
return b.build();
}
private static RefData.Id toRefData(AnyObjectId id) {
RefData.Id.Builder r = RefData.Id.newBuilder();
r.setObjectName(id.name());
if (id instanceof IdWithChunk)
r.setChunkKey(((IdWithChunk) id).getChunkKey().asString());
return r.build();
}
public static final RefData NONE = RefData.newBuilder().buildPartial();
static class IdWithChunk extends ObjectId {
static ObjectId create(RefData.Id src) {
if (src.hasChunkKey()) {
return new IdWithChunk(
ObjectId.fromString(src.getObjectName()),
ChunkKey.fromString(src.getChunkKey()));
}
return ObjectId.fromString(src.getObjectName());
}
private final ChunkKey chunkKey;
IdWithChunk(AnyObjectId id, ChunkKey key) {

11
org.eclipse.jgit/src/org/eclipse/jgit/util/RefMap.java

@ -136,12 +136,13 @@ public class RefMap extends AbstractMap<String, Ref> {
* list {@code loose}, if an item appears in both. Items in this
* list <b>must</b> also appear in {@code loose}.
*/
public RefMap(String prefix, RefList<Ref> packed, RefList<Ref> loose,
RefList<Ref> resolved) {
@SuppressWarnings("unchecked")
public RefMap(String prefix, RefList<? extends Ref> packed,
RefList<? extends Ref> loose, RefList<? extends Ref> resolved) {
this.prefix = prefix;
this.packed = packed;
this.loose = loose;
this.resolved = resolved;
this.packed = (RefList<Ref>) packed;
this.loose = (RefList<Ref>) loose;
this.resolved = (RefList<Ref>) resolved;
}
@Override

Loading…
Cancel
Save