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>
This commit is contained in:
Shawn O. Pearce 2011-05-13 09:16:58 -07:00 committed by Chris Aniszczyk
parent 6ec6169215
commit b8c508e54d
6 changed files with 375 additions and 227 deletions

View File

@ -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 {

View File

@ -11,6 +11,10 @@ public static void registerAllExtensions(
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 @@ void setChunkKey(com.google.protobuf.ByteString value) {
}
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 @@ private com.google.protobuf.ByteString getSymrefBytes() {
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 org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.IdOrBuilder
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 boolean getIsPeeled() {
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 org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.IdOrBuilder
}
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 boolean isInitialized() {
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 boolean isInitialized() {
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 int getSerializedSize() {
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 boolean equals(final Object obj) {
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 boolean equals(final Object obj) {
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 @@ private static Builder create() {
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 org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData buildPartia
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 Builder mergeFrom(com.google.protobuf.Message other) {
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 Builder mergeFrom(org.eclipse.jgit.generated.storage.dht.proto.GitStore.R
}
public final boolean isInitialized() {
if (!hasSequence()) {
return false;
}
if (hasTarget()) {
if (!getTarget().isInitialized()) {
@ -1044,7 +1092,7 @@ public Builder mergeFrom(
break;
}
case 10: {
bitField0_ |= 0x00000001;
bitField0_ |= 0x00000002;
symref_ = input.readBytes();
break;
}
@ -1058,7 +1106,7 @@ public Builder mergeFrom(
break;
}
case 24: {
bitField0_ |= 0x00000004;
bitField0_ |= 0x00000008;
isPeeled_ = input.readBool();
break;
}
@ -1071,16 +1119,42 @@ public Builder mergeFrom(
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 Builder setSymref(String value) {
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 @@ void setSymref(com.google.protobuf.ByteString value) {
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 Builder setTarget(org.eclipse.jgit.generated.storage.dht.proto.GitStore.R
} else {
targetBuilder_.setMessage(value);
}
bitField0_ |= 0x00000002;
bitField0_ |= 0x00000004;
return this;
}
public Builder setTarget(
@ -1148,12 +1222,12 @@ public Builder setTarget(
} 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 Builder mergeTarget(org.eclipse.jgit.generated.storage.dht.proto.GitStore
} else {
targetBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000002;
bitField0_ |= 0x00000004;
return this;
}
public Builder clearTarget() {
@ -1174,11 +1248,11 @@ public Builder clearTarget() {
} 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 org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.IdOrBuilder
// 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 Builder clearIsPeeled() {
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 Builder setPeeled(org.eclipse.jgit.generated.storage.dht.proto.GitStore.R
} else {
peeledBuilder_.setMessage(value);
}
bitField0_ |= 0x00000008;
bitField0_ |= 0x00000010;
return this;
}
public Builder setPeeled(
@ -1259,12 +1333,12 @@ public Builder setPeeled(
} 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 Builder mergePeeled(org.eclipse.jgit.generated.storage.dht.proto.GitStore
} else {
peeledBuilder_.mergeFrom(value);
}
bitField0_ |= 0x00000008;
bitField0_ |= 0x00000010;
return this;
}
public Builder clearPeeled() {
@ -1285,11 +1359,11 @@ public Builder clearPeeled() {
} 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 org.eclipse.jgit.generated.storage.dht.proto.GitStore.CachedPackInfo.Chun
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 com.google.protobuf.ExtensionRegistry assignDescriptors(
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 =

View File

@ -45,6 +45,7 @@
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.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 @@ ChunkKey findChunk(AnyObjectId id) {
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 Ref getRef(String needle) throws IOException {
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 List<Ref> getAdditionalRefs() {
@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 Map<String, Ref> getRefs(String prefix) throws IOException {
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 @@ private Ref resolve(Ref ref, int depth, RefList<Ref> loose)
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 Ref peel(Ref ref) throws IOException {
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 @@ private void cachePeeledState(Ref oldLeaf, Ref newLeaf) {
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 @@ private void cachePeeledState(Ref oldLeaf, Ref newLeaf) {
}
}
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 @@ private static Ref recreate(final Ref old, final Ref leaf) {
@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 RefRename newRename(String fromName, String toName)
@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 @@ void clearCache() {
}
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 @@ void removed(String refName) {
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 @@ private RefCache readRefs() throws DhtException {
}
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 @@ private RefCache read() throws DhtException, TimeoutException {
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);
}
static DhtRef fromData(String name, RefData data) {
if (data.hasSymref())
return new DhtSymbolicRef(name, data);
else
return new DhtObjectIdRef(name, data);
}
if (!data.hasTarget())
return new Unpeeled(LOOSE, name, null);
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 @@ private Set<Map.Entry<RefKey, RefData>> scan() throws DhtException,
}
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;
}
}
}

View File

@ -54,6 +54,7 @@
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 @@ protected boolean tryLock(boolean deref) throws IOException {
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 @@ protected Result doDelete(Result desiredResult) throws IOException {
@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 @@ protected Result doLink(String target) throws IOException {
}
private RefData newData() throws IOException {
ObjectId newId = getNewObjectId();
try {
RevObject obj = rw.parseAny(newId);
DhtReader ctx = (DhtReader) rw.getObjectReader();
RefData.Builder d = RefData.newBuilder(oldData);
clearRefData(d);
updateSequence(d);
ChunkKey key = ctx.findChunk(newId);
if (key != null)
newId = new RefDataUtil.IdWithChunk(newId, key);
ObjectId newId = getNewObjectId();
d.getTargetBuilder().setObjectName(newId.name());
try {
DhtReader ctx = (DhtReader) rw.getObjectReader();
RevObject obj = rw.parseAny(newId);
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);
}
}

View File

@ -46,69 +46,13 @@
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) {

View File

@ -136,12 +136,13 @@ public RefMap() {
* 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