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. // Either symref *OR* target must be populated, but never both.
// //
message RefData { 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. // An ObjectId with an optional hint about where it can be found.
// //
message Id { 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 public interface RefDataOrBuilder
extends com.google.protobuf.MessageOrBuilder { extends com.google.protobuf.MessageOrBuilder {
// required uint32 sequence = 5 [default = 0];
boolean hasSequence();
int getSequence();
// optional string symref = 1; // optional string symref = 1;
boolean hasSymref(); boolean hasSymref();
String getSymref(); String getSymref();
@ -575,11 +579,21 @@ public final class GitStore {
} }
private int bitField0_; 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; // optional string symref = 1;
public static final int SYMREF_FIELD_NUMBER = 1; public static final int SYMREF_FIELD_NUMBER = 1;
private Object symref_; private Object symref_;
public boolean hasSymref() { public boolean hasSymref() {
return ((bitField0_ & 0x00000001) == 0x00000001); return ((bitField0_ & 0x00000002) == 0x00000002);
} }
public String getSymref() { public String getSymref() {
Object ref = symref_; Object ref = symref_;
@ -611,7 +625,7 @@ public final class GitStore {
public static final int TARGET_FIELD_NUMBER = 2; public static final int TARGET_FIELD_NUMBER = 2;
private org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id target_; private org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id target_;
public boolean hasTarget() { public boolean hasTarget() {
return ((bitField0_ & 0x00000002) == 0x00000002); return ((bitField0_ & 0x00000004) == 0x00000004);
} }
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getTarget() { public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getTarget() {
return target_; return target_;
@ -624,7 +638,7 @@ public final class GitStore {
public static final int IS_PEELED_FIELD_NUMBER = 3; public static final int IS_PEELED_FIELD_NUMBER = 3;
private boolean isPeeled_; private boolean isPeeled_;
public boolean hasIsPeeled() { public boolean hasIsPeeled() {
return ((bitField0_ & 0x00000004) == 0x00000004); return ((bitField0_ & 0x00000008) == 0x00000008);
} }
public boolean getIsPeeled() { public boolean getIsPeeled() {
return isPeeled_; return isPeeled_;
@ -634,7 +648,7 @@ public final class GitStore {
public static final int PEELED_FIELD_NUMBER = 4; public static final int PEELED_FIELD_NUMBER = 4;
private org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id peeled_; private org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id peeled_;
public boolean hasPeeled() { public boolean hasPeeled() {
return ((bitField0_ & 0x00000008) == 0x00000008); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getPeeled() { public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getPeeled() {
return peeled_; return peeled_;
@ -644,6 +658,7 @@ public final class GitStore {
} }
private void initFields() { private void initFields() {
sequence_ = 0;
symref_ = ""; symref_ = "";
target_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance(); target_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance();
isPeeled_ = false; isPeeled_ = false;
@ -654,6 +669,10 @@ public final class GitStore {
byte isInitialized = memoizedIsInitialized; byte isInitialized = memoizedIsInitialized;
if (isInitialized != -1) return isInitialized == 1; if (isInitialized != -1) return isInitialized == 1;
if (!hasSequence()) {
memoizedIsInitialized = 0;
return false;
}
if (hasTarget()) { if (hasTarget()) {
if (!getTarget().isInitialized()) { if (!getTarget().isInitialized()) {
memoizedIsInitialized = 0; memoizedIsInitialized = 0;
@ -673,18 +692,21 @@ public final class GitStore {
public void writeTo(com.google.protobuf.CodedOutputStream output) public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException { throws java.io.IOException {
getSerializedSize(); getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBytes(1, getSymrefBytes()); output.writeBytes(1, getSymrefBytes());
} }
if (((bitField0_ & 0x00000002) == 0x00000002)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeMessage(2, target_); output.writeMessage(2, target_);
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeBool(3, isPeeled_); output.writeBool(3, isPeeled_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000010) == 0x00000010)) {
output.writeMessage(4, peeled_); output.writeMessage(4, peeled_);
} }
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeUInt32(5, sequence_);
}
getUnknownFields().writeTo(output); getUnknownFields().writeTo(output);
} }
@ -694,22 +716,26 @@ public final class GitStore {
if (size != -1) return size; if (size != -1) return size;
size = 0; size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) { if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBytesSize(1, getSymrefBytes()); .computeBytesSize(1, getSymrefBytes());
} }
if (((bitField0_ & 0x00000002) == 0x00000002)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeMessageSize(2, target_); .computeMessageSize(2, target_);
} }
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000008) == 0x00000008)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeBoolSize(3, isPeeled_); .computeBoolSize(3, isPeeled_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { if (((bitField0_ & 0x00000010) == 0x00000010)) {
size += com.google.protobuf.CodedOutputStream size += com.google.protobuf.CodedOutputStream
.computeMessageSize(4, peeled_); .computeMessageSize(4, peeled_);
} }
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(5, sequence_);
}
size += getUnknownFields().getSerializedSize(); size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size; memoizedSerializedSize = size;
return 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; org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData other = (org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData) obj;
boolean result = true; boolean result = true;
result = result && (hasSequence() == other.hasSequence());
if (hasSequence()) {
result = result && (getSequence()
== other.getSequence());
}
result = result && (hasSymref() == other.hasSymref()); result = result && (hasSymref() == other.hasSymref());
if (hasSymref()) { if (hasSymref()) {
result = result && getSymref() result = result && getSymref()
@ -760,6 +791,10 @@ public final class GitStore {
public int hashCode() { public int hashCode() {
int hash = 41; int hash = 41;
hash = (19 * hash) + getDescriptorForType().hashCode(); hash = (19 * hash) + getDescriptorForType().hashCode();
if (hasSequence()) {
hash = (37 * hash) + SEQUENCE_FIELD_NUMBER;
hash = (53 * hash) + getSequence();
}
if (hasSymref()) { if (hasSymref()) {
hash = (37 * hash) + SYMREF_FIELD_NUMBER; hash = (37 * hash) + SYMREF_FIELD_NUMBER;
hash = (53 * hash) + getSymref().hashCode(); hash = (53 * hash) + getSymref().hashCode();
@ -894,22 +929,24 @@ public final class GitStore {
public Builder clear() { public Builder clear() {
super.clear(); super.clear();
symref_ = ""; sequence_ = 0;
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000001);
symref_ = "";
bitField0_ = (bitField0_ & ~0x00000002);
if (targetBuilder_ == null) { if (targetBuilder_ == null) {
target_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance(); target_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance();
} else { } else {
targetBuilder_.clear(); targetBuilder_.clear();
} }
bitField0_ = (bitField0_ & ~0x00000002);
isPeeled_ = false;
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000004);
isPeeled_ = false;
bitField0_ = (bitField0_ & ~0x00000008);
if (peeledBuilder_ == null) { if (peeledBuilder_ == null) {
peeled_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance(); peeled_ = org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.getDefaultInstance();
} else { } else {
peeledBuilder_.clear(); peeledBuilder_.clear();
} }
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000010);
return this; return this;
} }
@ -951,22 +988,26 @@ public final class GitStore {
if (((from_bitField0_ & 0x00000001) == 0x00000001)) { if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
to_bitField0_ |= 0x00000001; to_bitField0_ |= 0x00000001;
} }
result.symref_ = symref_; result.sequence_ = sequence_;
if (((from_bitField0_ & 0x00000002) == 0x00000002)) { if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
to_bitField0_ |= 0x00000002; to_bitField0_ |= 0x00000002;
} }
result.symref_ = symref_;
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
if (targetBuilder_ == null) { if (targetBuilder_ == null) {
result.target_ = target_; result.target_ = target_;
} else { } else {
result.target_ = targetBuilder_.build(); result.target_ = targetBuilder_.build();
} }
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
to_bitField0_ |= 0x00000004;
}
result.isPeeled_ = isPeeled_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) { if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008; to_bitField0_ |= 0x00000008;
} }
result.isPeeled_ = isPeeled_;
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
to_bitField0_ |= 0x00000010;
}
if (peeledBuilder_ == null) { if (peeledBuilder_ == null) {
result.peeled_ = peeled_; result.peeled_ = peeled_;
} else { } else {
@ -988,6 +1029,9 @@ public final class GitStore {
public Builder mergeFrom(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData 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 == org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.getDefaultInstance()) return this;
if (other.hasSequence()) {
setSequence(other.getSequence());
}
if (other.hasSymref()) { if (other.hasSymref()) {
setSymref(other.getSymref()); setSymref(other.getSymref());
} }
@ -1005,6 +1049,10 @@ public final class GitStore {
} }
public final boolean isInitialized() { public final boolean isInitialized() {
if (!hasSequence()) {
return false;
}
if (hasTarget()) { if (hasTarget()) {
if (!getTarget().isInitialized()) { if (!getTarget().isInitialized()) {
@ -1044,7 +1092,7 @@ public final class GitStore {
break; break;
} }
case 10: { case 10: {
bitField0_ |= 0x00000001; bitField0_ |= 0x00000002;
symref_ = input.readBytes(); symref_ = input.readBytes();
break; break;
} }
@ -1058,7 +1106,7 @@ public final class GitStore {
break; break;
} }
case 24: { case 24: {
bitField0_ |= 0x00000004; bitField0_ |= 0x00000008;
isPeeled_ = input.readBool(); isPeeled_ = input.readBool();
break; break;
} }
@ -1071,16 +1119,42 @@ public final class GitStore {
setPeeled(subBuilder.buildPartial()); setPeeled(subBuilder.buildPartial());
break; break;
} }
case 40: {
bitField0_ |= 0x00000001;
sequence_ = input.readUInt32();
break;
}
} }
} }
} }
private int bitField0_; 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; // optional string symref = 1;
private Object symref_ = ""; private Object symref_ = "";
public boolean hasSymref() { public boolean hasSymref() {
return ((bitField0_ & 0x00000001) == 0x00000001); return ((bitField0_ & 0x00000002) == 0x00000002);
} }
public String getSymref() { public String getSymref() {
Object ref = symref_; Object ref = symref_;
@ -1096,19 +1170,19 @@ public final class GitStore {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
bitField0_ |= 0x00000001; bitField0_ |= 0x00000002;
symref_ = value; symref_ = value;
onChanged(); onChanged();
return this; return this;
} }
public Builder clearSymref() { public Builder clearSymref() {
bitField0_ = (bitField0_ & ~0x00000001); bitField0_ = (bitField0_ & ~0x00000002);
symref_ = getDefaultInstance().getSymref(); symref_ = getDefaultInstance().getSymref();
onChanged(); onChanged();
return this; return this;
} }
void setSymref(com.google.protobuf.ByteString value) { void setSymref(com.google.protobuf.ByteString value) {
bitField0_ |= 0x00000001; bitField0_ |= 0x00000002;
symref_ = value; symref_ = value;
onChanged(); onChanged();
} }
@ -1118,7 +1192,7 @@ public final class GitStore {
private com.google.protobuf.SingleFieldBuilder< 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_; 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() { public boolean hasTarget() {
return ((bitField0_ & 0x00000002) == 0x00000002); return ((bitField0_ & 0x00000004) == 0x00000004);
} }
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getTarget() { public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getTarget() {
if (targetBuilder_ == null) { if (targetBuilder_ == null) {
@ -1137,7 +1211,7 @@ public final class GitStore {
} else { } else {
targetBuilder_.setMessage(value); targetBuilder_.setMessage(value);
} }
bitField0_ |= 0x00000002; bitField0_ |= 0x00000004;
return this; return this;
} }
public Builder setTarget( public Builder setTarget(
@ -1148,12 +1222,12 @@ public final class GitStore {
} else { } else {
targetBuilder_.setMessage(builderForValue.build()); targetBuilder_.setMessage(builderForValue.build());
} }
bitField0_ |= 0x00000002; bitField0_ |= 0x00000004;
return this; return this;
} }
public Builder mergeTarget(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id value) { public Builder mergeTarget(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id value) {
if (targetBuilder_ == null) { 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.getDefaultInstance()) {
target_ = target_ =
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.newBuilder(target_).mergeFrom(value).buildPartial(); org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.newBuilder(target_).mergeFrom(value).buildPartial();
@ -1164,7 +1238,7 @@ public final class GitStore {
} else { } else {
targetBuilder_.mergeFrom(value); targetBuilder_.mergeFrom(value);
} }
bitField0_ |= 0x00000002; bitField0_ |= 0x00000004;
return this; return this;
} }
public Builder clearTarget() { public Builder clearTarget() {
@ -1174,11 +1248,11 @@ public final class GitStore {
} else { } else {
targetBuilder_.clear(); targetBuilder_.clear();
} }
bitField0_ = (bitField0_ & ~0x00000002); bitField0_ = (bitField0_ & ~0x00000004);
return this; return this;
} }
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder getTargetBuilder() { public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder getTargetBuilder() {
bitField0_ |= 0x00000002; bitField0_ |= 0x00000004;
onChanged(); onChanged();
return getTargetFieldBuilder().getBuilder(); return getTargetFieldBuilder().getBuilder();
} }
@ -1206,19 +1280,19 @@ public final class GitStore {
// optional bool is_peeled = 3; // optional bool is_peeled = 3;
private boolean isPeeled_ ; private boolean isPeeled_ ;
public boolean hasIsPeeled() { public boolean hasIsPeeled() {
return ((bitField0_ & 0x00000004) == 0x00000004); return ((bitField0_ & 0x00000008) == 0x00000008);
} }
public boolean getIsPeeled() { public boolean getIsPeeled() {
return isPeeled_; return isPeeled_;
} }
public Builder setIsPeeled(boolean value) { public Builder setIsPeeled(boolean value) {
bitField0_ |= 0x00000004; bitField0_ |= 0x00000008;
isPeeled_ = value; isPeeled_ = value;
onChanged(); onChanged();
return this; return this;
} }
public Builder clearIsPeeled() { public Builder clearIsPeeled() {
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000008);
isPeeled_ = false; isPeeled_ = false;
onChanged(); onChanged();
return this; return this;
@ -1229,7 +1303,7 @@ public final class GitStore {
private com.google.protobuf.SingleFieldBuilder< 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_; 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() { public boolean hasPeeled() {
return ((bitField0_ & 0x00000008) == 0x00000008); return ((bitField0_ & 0x00000010) == 0x00000010);
} }
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getPeeled() { public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id getPeeled() {
if (peeledBuilder_ == null) { if (peeledBuilder_ == null) {
@ -1248,7 +1322,7 @@ public final class GitStore {
} else { } else {
peeledBuilder_.setMessage(value); peeledBuilder_.setMessage(value);
} }
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
return this; return this;
} }
public Builder setPeeled( public Builder setPeeled(
@ -1259,12 +1333,12 @@ public final class GitStore {
} else { } else {
peeledBuilder_.setMessage(builderForValue.build()); peeledBuilder_.setMessage(builderForValue.build());
} }
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
return this; return this;
} }
public Builder mergePeeled(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id value) { public Builder mergePeeled(org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id value) {
if (peeledBuilder_ == null) { 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.getDefaultInstance()) {
peeled_ = peeled_ =
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.newBuilder(peeled_).mergeFrom(value).buildPartial(); org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.newBuilder(peeled_).mergeFrom(value).buildPartial();
@ -1275,7 +1349,7 @@ public final class GitStore {
} else { } else {
peeledBuilder_.mergeFrom(value); peeledBuilder_.mergeFrom(value);
} }
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
return this; return this;
} }
public Builder clearPeeled() { public Builder clearPeeled() {
@ -1285,11 +1359,11 @@ public final class GitStore {
} else { } else {
peeledBuilder_.clear(); peeledBuilder_.clear();
} }
bitField0_ = (bitField0_ & ~0x00000008); bitField0_ = (bitField0_ & ~0x00000010);
return this; return this;
} }
public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder getPeeledBuilder() { public org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Id.Builder getPeeledBuilder() {
bitField0_ |= 0x00000008; bitField0_ |= 0x00000010;
onChanged(); onChanged();
return getPeeledFieldBuilder().getBuilder(); return getPeeledFieldBuilder().getBuilder();
} }
@ -7811,51 +7885,51 @@ public final class GitStore {
static { static {
java.lang.String[] descriptorData = { java.lang.String[] descriptorData = {
"\n,org/eclipse/jgit/storage/dht/git_store" + "\n,org/eclipse/jgit/storage/dht/git_store" +
".proto\022\034org.eclipse.jgit.storage.dht\"\316\001\n" + ".proto\022\034org.eclipse.jgit.storage.dht\"\343\001\n" +
"\007RefData\022\016\n\006symref\030\001 \001(\t\0228\n\006target\030\002 \001(\013" + "\007RefData\022\023\n\010sequence\030\005 \002(\r:\0010\022\016\n\006symref\030" +
"2(.org.eclipse.jgit.storage.dht.RefData." + "\001 \001(\t\0228\n\006target\030\002 \001(\0132(.org.eclipse.jgit" +
"Id\022\021\n\tis_peeled\030\003 \001(\010\0228\n\006peeled\030\004 \001(\0132(." + ".storage.dht.RefData.Id\022\021\n\tis_peeled\030\003 \001" +
"org.eclipse.jgit.storage.dht.RefData.Id\032" + "(\010\0228\n\006peeled\030\004 \001(\0132(.org.eclipse.jgit.st" +
",\n\002Id\022\023\n\013object_name\030\001 \002(\t\022\021\n\tchunk_key\030" + "orage.dht.RefData.Id\032,\n\002Id\022\023\n\013object_nam" +
"\002 \001(\t\"\364\001\n\nObjectInfo\022H\n\013object_type\030\001 \001(" + "e\030\001 \002(\t\022\021\n\tchunk_key\030\002 \001(\t\"\364\001\n\nObjectInf" +
"\01623.org.eclipse.jgit.storage.dht.ObjectI" + "o\022H\n\013object_type\030\001 \001(\01623.org.eclipse.jgi" +
"nfo.ObjectType\022\016\n\006offset\030\002 \002(\005\022\023\n\013packed", "t.storage.dht.ObjectInfo.ObjectType\022\016\n\006o",
"_size\030\003 \002(\003\022\025\n\rinflated_size\030\004 \002(\003\022\022\n\nde" + "ffset\030\002 \002(\005\022\023\n\013packed_size\030\003 \002(\003\022\025\n\rinfl" +
"lta_base\030\005 \001(\014\022\025\n\ris_fragmented\030\006 \001(\010\"5\n" + "ated_size\030\004 \002(\003\022\022\n\ndelta_base\030\005 \001(\014\022\025\n\ri" +
"\nObjectType\022\n\n\006COMMIT\020\001\022\010\n\004TREE\020\002\022\010\n\004BLO" + "s_fragmented\030\006 \001(\010\"5\n\nObjectType\022\n\n\006COMM" +
"B\020\003\022\007\n\003TAG\020\004\"\217\004\n\tChunkInfo\022>\n\006source\030\001 \001" + "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" +
"(\0162..org.eclipse.jgit.storage.dht.ChunkI" + "unkInfo\022>\n\006source\030\001 \001(\0162..org.eclipse.jg" +
"nfo.Source\022G\n\013object_type\030\002 \001(\01622.org.ec" + "it.storage.dht.ChunkInfo.Source\022G\n\013objec" +
"lipse.jgit.storage.dht.ChunkInfo.ObjectT" + "t_type\030\002 \001(\01622.org.eclipse.jgit.storage." +
"ype\022\023\n\013is_fragment\030\003 \001(\010\022\027\n\017cached_pack_" + "dht.ChunkInfo.ObjectType\022\023\n\013is_fragment\030" +
"key\030\004 \001(\t\022K\n\robject_counts\030\005 \001(\01324.org.e" + "\003 \001(\010\022\027\n\017cached_pack_key\030\004 \001(\t\022K\n\robject" +
"clipse.jgit.storage.dht.ChunkInfo.Object", "_counts\030\005 \001(\01324.org.eclipse.jgit.storage",
"Counts\022\022\n\nchunk_size\030\006 \001(\005\022\022\n\nindex_size" + ".dht.ChunkInfo.ObjectCounts\022\022\n\nchunk_siz" +
"\030\007 \001(\005\022\021\n\tmeta_size\030\010 \001(\005\032R\n\014ObjectCount" + "e\030\006 \001(\005\022\022\n\nindex_size\030\007 \001(\005\022\021\n\tmeta_size" +
"s\022\r\n\005total\030\001 \001(\005\022\r\n\005whole\030\002 \001(\005\022\021\n\tofs_d" + "\030\010 \001(\005\032R\n\014ObjectCounts\022\r\n\005total\030\001 \001(\005\022\r\n" +
"elta\030\003 \001(\005\022\021\n\tref_delta\030\004 \001(\005\"-\n\006Source\022" + "\005whole\030\002 \001(\005\022\021\n\tofs_delta\030\003 \001(\005\022\021\n\tref_d" +
"\013\n\007RECEIVE\020\001\022\n\n\006INSERT\020\002\022\n\n\006REPACK\020\003\"@\n\n" + "elta\030\004 \001(\005\"-\n\006Source\022\013\n\007RECEIVE\020\001\022\n\n\006INS" +
"ObjectType\022\t\n\005MIXED\020\000\022\n\n\006COMMIT\020\001\022\010\n\004TRE" + "ERT\020\002\022\n\n\006REPACK\020\003\"@\n\nObjectType\022\t\n\005MIXED" +
"E\020\002\022\010\n\004BLOB\020\003\022\007\n\003TAG\020\004\"\352\002\n\tChunkMeta\022E\n\n" + "\020\000\022\n\n\006COMMIT\020\001\022\010\n\004TREE\020\002\022\010\n\004BLOB\020\003\022\007\n\003TA" +
"base_chunk\030\001 \003(\01321.org.eclipse.jgit.stor" + "G\020\004\"\352\002\n\tChunkMeta\022E\n\nbase_chunk\030\001 \003(\01321." +
"age.dht.ChunkMeta.BaseChunk\022\020\n\010fragment\030" + "org.eclipse.jgit.storage.dht.ChunkMeta.B" +
"\002 \003(\t\022M\n\017commit_prefetch\0303 \001(\01324.org.ecl", "aseChunk\022\020\n\010fragment\030\002 \003(\t\022M\n\017commit_pre",
"ipse.jgit.storage.dht.ChunkMeta.Prefetch" + "fetch\0303 \001(\01324.org.eclipse.jgit.storage.d" +
"Hint\022K\n\rtree_prefetch\0304 \001(\01324.org.eclips" + "ht.ChunkMeta.PrefetchHint\022K\n\rtree_prefet" +
"e.jgit.storage.dht.ChunkMeta.PrefetchHin" + "ch\0304 \001(\01324.org.eclipse.jgit.storage.dht." +
"t\0326\n\tBaseChunk\022\026\n\016relative_start\030\001 \002(\003\022\021" + "ChunkMeta.PrefetchHint\0326\n\tBaseChunk\022\026\n\016r" +
"\n\tchunk_key\030\002 \002(\t\0320\n\014PrefetchHint\022\014\n\004edg" + "elative_start\030\001 \002(\003\022\021\n\tchunk_key\030\002 \002(\t\0320" +
"e\030\001 \003(\t\022\022\n\nsequential\030\002 \003(\t\"\322\002\n\016CachedPa" + "\n\014PrefetchHint\022\014\n\004edge\030\001 \003(\t\022\022\n\nsequenti" +
"ckInfo\022\014\n\004name\030\001 \002(\t\022\017\n\007version\030\002 \002(\t\022\025\n" + "al\030\002 \003(\t\"\322\002\n\016CachedPackInfo\022\014\n\004name\030\001 \002(" +
"\robjects_total\030\003 \002(\003\022\025\n\robjects_delta\030\004 " + "\t\022\017\n\007version\030\002 \002(\t\022\025\n\robjects_total\030\003 \002(" +
"\001(\003\022\023\n\013bytes_total\030\005 \001(\003\022L\n\010tip_list\030\006 \002" + "\003\022\025\n\robjects_delta\030\004 \001(\003\022\023\n\013bytes_total\030" +
"(\0132:.org.eclipse.jgit.storage.dht.Cached", "\005 \001(\003\022L\n\010tip_list\030\006 \002(\0132:.org.eclipse.jg",
"PackInfo.TipObjectList\022J\n\nchunk_list\030\007 \002" + "it.storage.dht.CachedPackInfo.TipObjectL" +
"(\01326.org.eclipse.jgit.storage.dht.Cached" + "ist\022J\n\nchunk_list\030\007 \002(\01326.org.eclipse.jg" +
"PackInfo.ChunkList\032$\n\rTipObjectList\022\023\n\013o" + "it.storage.dht.CachedPackInfo.ChunkList\032" +
"bject_name\030\001 \003(\t\032\036\n\tChunkList\022\021\n\tchunk_k" + "$\n\rTipObjectList\022\023\n\013object_name\030\001 \003(\t\032\036\n" +
"ey\030\001 \003(\tB1\n,org.eclipse.jgit.generated.s" + "\tChunkList\022\021\n\tchunk_key\030\001 \003(\tB1\n,org.ecl" +
"torage.dht.proto\240\001\001" "ipse.jgit.generated.storage.dht.proto\240\001\001"
}; };
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { 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 internal_static_org_eclipse_jgit_storage_dht_RefData_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable( com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_org_eclipse_jgit_storage_dht_RefData_descriptor, 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.class,
org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Builder.class); org.eclipse.jgit.generated.storage.dht.proto.GitStore.RefData.Builder.class);
internal_static_org_eclipse_jgit_storage_dht_RefData_Id_descriptor = 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.LOOSE;
import static org.eclipse.jgit.lib.Ref.Storage.NEW; import static org.eclipse.jgit.lib.Ref.Storage.NEW;
import static org.eclipse.jgit.storage.dht.RefDataUtil.NONE;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; 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.generated.storage.dht.proto.GitStore.RefData;
import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId; 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.ObjectIdSubclassMap;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.RefDatabase;
@ -107,7 +105,7 @@ public class DhtRefDatabase extends RefDatabase {
public Ref getRef(String needle) throws IOException { public Ref getRef(String needle) throws IOException {
RefCache curr = readRefs(); RefCache curr = readRefs();
for (String prefix : SEARCH_PATH) { for (String prefix : SEARCH_PATH) {
Ref ref = curr.ids.get(prefix + needle); DhtRef ref = curr.ids.get(prefix + needle);
if (ref != null) { if (ref != null) {
ref = resolve(ref, 0, curr.ids); ref = resolve(ref, 0, curr.ids);
return ref; return ref;
@ -116,6 +114,14 @@ public class DhtRefDatabase extends RefDatabase {
return null; 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 @Override
public List<Ref> getAdditionalRefs() { public List<Ref> getAdditionalRefs() {
return Collections.emptyList(); return Collections.emptyList();
@ -124,12 +130,12 @@ public class DhtRefDatabase extends RefDatabase {
@Override @Override
public Map<String, Ref> getRefs(String prefix) throws IOException { public Map<String, Ref> getRefs(String prefix) throws IOException {
RefCache curr = readRefs(); RefCache curr = readRefs();
RefList<Ref> packed = RefList.emptyList(); RefList<DhtRef> packed = RefList.emptyList();
RefList<Ref> loose = curr.ids; RefList<DhtRef> loose = curr.ids;
RefList.Builder<Ref> sym = new RefList.Builder<Ref>(curr.sym.size()); RefList.Builder<DhtRef> sym = new RefList.Builder<DhtRef>(curr.sym.size());
for (int idx = 0; idx < curr.sym.size(); idx++) { 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(); String name = ref.getName();
ref = resolve(ref, 0, loose); ref = resolve(ref, 0, loose);
if (ref != null && ref.getObjectId() != null) { if (ref != null && ref.getObjectId() != null) {
@ -147,12 +153,12 @@ public class DhtRefDatabase extends RefDatabase {
return new RefMap(prefix, packed, loose, sym.toRefList()); 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 { throws IOException {
if (!ref.isSymbolic()) if (!ref.isSymbolic())
return ref; return ref;
Ref dst = ref.getTarget(); DhtRef dst = (DhtRef) ref.getTarget();
if (MAX_SYMBOLIC_REF_DEPTH <= depth) if (MAX_SYMBOLIC_REF_DEPTH <= depth)
return null; // claim it doesn't exist return null; // claim it doesn't exist
@ -165,7 +171,10 @@ public class DhtRefDatabase extends RefDatabase {
if (dst == null) if (dst == null)
return null; return null;
return new SymbolicRef(ref.getName(), dst); return new DhtSymbolicRef(
ref.getName(),
dst,
((DhtSymbolicRef) ref).getRefData());
} }
@Override @Override
@ -174,12 +183,12 @@ public class DhtRefDatabase extends RefDatabase {
if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null) if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null)
return ref; return ref;
Ref newLeaf = doPeel(oldLeaf); DhtRef newLeaf = doPeel(oldLeaf);
RefCache cur = readRefs(); RefCache cur = readRefs();
int idx = cur.ids.find(oldLeaf.getName()); int idx = cur.ids.find(oldLeaf.getName());
if (0 <= idx && cur.ids.get(idx) == oldLeaf) { 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))) if (cache.compareAndSet(cur, new RefCache(newList, cur)))
cachePeeledState(oldLeaf, newLeaf); cachePeeledState(oldLeaf, newLeaf);
} }
@ -192,8 +201,8 @@ public class DhtRefDatabase extends RefDatabase {
try { try {
RepositoryKey repo = repository.getRepositoryKey(); RepositoryKey repo = repository.getRepositoryKey();
RefKey key = RefKey.create(repo, newLeaf.getName()); RefKey key = RefKey.create(repo, newLeaf.getName());
RefData oldData = RefDataUtil.fromRef(oldLeaf); RefData oldData = ((DhtRef) oldLeaf).getRefData();
RefData newData = RefDataUtil.fromRef(newLeaf); RefData newData = ((DhtRef) newLeaf).getRefData();
db.ref().compareAndPut(key, oldData, newData); db.ref().compareAndPut(key, oldData, newData);
} catch (TimeoutException e) { } catch (TimeoutException e) {
// Ignore a timeout here, we were only trying to update // 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 { IOException {
RevWalk rw = new RevWalk(getRepository()); RevWalk rw = new RevWalk(getRepository());
try { try {
String name = leaf.getName();
ObjectId oId = leaf.getObjectId();
RevObject obj = rw.parseAny(oId);
DhtReader ctx = (DhtReader) rw.getObjectReader(); DhtReader ctx = (DhtReader) rw.getObjectReader();
RevObject obj = rw.parseAny(leaf.getObjectId());
RefData.Builder d = RefData.newBuilder(((DhtRef) leaf).getRefData());
ChunkKey key = ctx.findChunk(oId); ChunkKey oKey = ctx.findChunk(leaf.getObjectId());
if (key != null) if (oKey != null)
oId = new IdWithChunk(oId, key); d.getTargetBuilder().setChunkKey(oKey.asString());
else
d.getTargetBuilder().clearChunkKey();
if (obj instanceof RevTag) { if (obj instanceof RevTag) {
ObjectId pId = rw.peel(obj); ObjectId pId = rw.peel(obj);
key = ctx.findChunk(pId); d.getPeeledBuilder().setObjectName(pId.name());
pId = key != null ? new IdWithChunk(pId, key) : pId.copy();
return new PeeledTag(leaf.getStorage(), name, oId, pId); ChunkKey pKey = ctx.findChunk(pId);
if (pKey != null)
d.getPeeledBuilder().setChunkKey(pKey.asString());
else
d.getPeeledBuilder().clearChunkKey();
} else { } 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 { } finally {
rw.release(); rw.release();
} }
@ -242,11 +260,26 @@ public class DhtRefDatabase extends RefDatabase {
@Override @Override
public DhtRefUpdate newUpdate(String refName, boolean detach) public DhtRefUpdate newUpdate(String refName, boolean detach)
throws IOException { throws IOException {
Ref ref = getRefs(ALL).get(refName); boolean detachingSymbolicRef = false;
DhtRef ref = getOneRef(refName);
if (ref == null) 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(); 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 @Override
@ -259,7 +292,7 @@ public class DhtRefDatabase extends RefDatabase {
@Override @Override
public boolean isNameConflicting(String refName) throws IOException { public boolean isNameConflicting(String refName) throws IOException {
RefList<Ref> all = readRefs().ids; RefList<DhtRef> all = readRefs().ids;
// Cannot be nested within an existing reference. // Cannot be nested within an existing reference.
int lastSlash = refName.lastIndexOf('/'); int lastSlash = refName.lastIndexOf('/');
@ -293,15 +326,15 @@ public class DhtRefDatabase extends RefDatabase {
} }
void stored(String refName, RefData newData) { void stored(String refName, RefData newData) {
Ref ref = fromData(refName, newData); DhtRef ref = fromData(refName, newData);
RefCache oldCache, newCache; RefCache oldCache, newCache;
do { do {
oldCache = cache.get(); oldCache = cache.get();
if (oldCache == null) if (oldCache == null)
return; return;
RefList<Ref> ids = oldCache.ids.put(ref); RefList<DhtRef> ids = oldCache.ids.put(ref);
RefList<Ref> sym = oldCache.sym; RefList<DhtRef> sym = oldCache.sym;
if (ref.isSymbolic()) { if (ref.isSymbolic()) {
sym.put(ref); sym.put(ref);
@ -324,12 +357,12 @@ public class DhtRefDatabase extends RefDatabase {
int p; int p;
RefList<Ref> ids = oldCache.ids; RefList<DhtRef> ids = oldCache.ids;
p = ids.find(refName); p = ids.find(refName);
if (0 <= p) if (0 <= p)
ids = ids.remove(p); ids = ids.remove(p);
RefList<Ref> sym = oldCache.sym; RefList<DhtRef> sym = oldCache.sym;
p = sym.find(refName); p = sym.find(refName);
if (0 <= p) if (0 <= p)
sym = sym.remove(p); sym = sym.remove(p);
@ -352,12 +385,12 @@ public class DhtRefDatabase extends RefDatabase {
} }
private RefCache read() throws DhtException, TimeoutException { private RefCache read() throws DhtException, TimeoutException {
RefList.Builder<Ref> id = new RefList.Builder<Ref>(); RefList.Builder<DhtRef> id = new RefList.Builder<DhtRef>();
RefList.Builder<Ref> sym = new RefList.Builder<Ref>(); RefList.Builder<DhtRef> sym = new RefList.Builder<DhtRef>();
ObjectIdSubclassMap<IdWithChunk> hints = new ObjectIdSubclassMap<IdWithChunk>(); ObjectIdSubclassMap<IdWithChunk> hints = new ObjectIdSubclassMap<IdWithChunk>();
for (Map.Entry<RefKey, RefData> e : scan()) { 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()) if (ref.isSymbolic())
sym.add(ref); sym.add(ref);
@ -377,23 +410,18 @@ public class DhtRefDatabase extends RefDatabase {
return new RefCache(id.toRefList(), sym.toRefList(), hints); return new RefCache(id.toRefList(), sym.toRefList(), hints);
} }
private static Ref fromData(String name, RefData data) { static DhtRef fromData(String name, RefData data) {
if (data.hasSymref()) { if (data.hasSymref())
Ref leaf = new Unpeeled(NEW, data.getSymref(), null); return new DhtSymbolicRef(name, data);
return new SymbolicRef(name, leaf); else
} return new DhtObjectIdRef(name, data);
}
if (!data.hasTarget())
return new Unpeeled(LOOSE, name, null);
ObjectId oId = IdWithChunk.create(data.getTarget()); private static ObjectId idFrom(RefData.Id src) {
if (data.getIsPeeled() && data.hasPeeled()) { ObjectId id = ObjectId.fromString(src.getObjectName());
ObjectId pId = IdWithChunk.create(data.getPeeled()); if (!src.hasChunkKey())
return new PeeledTag(LOOSE, name, oId, pId); return id;
} return new IdWithChunk(id, ChunkKey.fromString(src.getChunkKey()));
if (data.getIsPeeled())
return new PeeledNonTag(LOOSE, name, oId);
return new Unpeeled(LOOSE, name, oId);
} }
private Set<Map.Entry<RefKey, RefData>> scan() throws DhtException, private Set<Map.Entry<RefKey, RefData>> scan() throws DhtException,
@ -404,21 +432,93 @@ public class DhtRefDatabase extends RefDatabase {
} }
private static class RefCache { private static class RefCache {
final RefList<Ref> ids; final RefList<DhtRef> ids;
final RefList<Ref> sym; final RefList<DhtRef> sym;
final ObjectIdSubclassMap<IdWithChunk> hints; final ObjectIdSubclassMap<IdWithChunk> hints;
RefCache(RefList<Ref> ids, RefList<Ref> sym, RefCache(RefList<DhtRef> ids, RefList<DhtRef> sym,
ObjectIdSubclassMap<IdWithChunk> hints) { ObjectIdSubclassMap<IdWithChunk> hints) {
this.ids = ids; this.ids = ids;
this.sym = sym; this.sym = sym;
this.hints = hints; this.hints = hints;
} }
RefCache(RefList<Ref> ids, RefCache old) { RefCache(RefList<DhtRef> ids, RefCache old) {
this(ids, old.sym, old.hints); 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.RevObject;
import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.dht.DhtRefDatabase.DhtRef;
import org.eclipse.jgit.storage.dht.spi.Database; import org.eclipse.jgit.storage.dht.spi.Database;
class DhtRefUpdate extends RefUpdate { class DhtRefUpdate extends RefUpdate {
@ -107,7 +108,7 @@ class DhtRefUpdate extends RefUpdate {
dstRef = dstRef.getLeaf(); dstRef = dstRef.getLeaf();
refKey = RefKey.create(repo, dstRef.getName()); refKey = RefKey.create(repo, dstRef.getName());
oldData = RefDataUtil.fromRef(dstRef); oldData = ((DhtRef) dstRef).getRefData();
if (dstRef.isSymbolic()) if (dstRef.isSymbolic())
setOldObjectId(null); setOldObjectId(null);
@ -158,7 +159,11 @@ class DhtRefUpdate extends RefUpdate {
@Override @Override
protected Result doLink(String target) throws IOException { protected Result doLink(String target) throws IOException {
try { 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); boolean r = db.ref().compareAndPut(refKey, oldData, newData);
if (r) { if (r) {
getRefDatabase().stored(dstRef.getName(), newData); getRefDatabase().stored(dstRef.getName(), newData);
@ -175,26 +180,45 @@ class DhtRefUpdate extends RefUpdate {
} }
private RefData newData() throws IOException { private RefData newData() throws IOException {
RefData.Builder d = RefData.newBuilder(oldData);
clearRefData(d);
updateSequence(d);
ObjectId newId = getNewObjectId(); ObjectId newId = getNewObjectId();
d.getTargetBuilder().setObjectName(newId.name());
try { try {
RevObject obj = rw.parseAny(newId);
DhtReader ctx = (DhtReader) rw.getObjectReader(); DhtReader ctx = (DhtReader) rw.getObjectReader();
RevObject obj = rw.parseAny(newId);
ChunkKey key = ctx.findChunk(newId); ChunkKey oKey = ctx.findChunk(newId);
if (key != null) if (oKey != null)
newId = new RefDataUtil.IdWithChunk(newId, key); d.getTargetBuilder().setChunkKey(oKey.asString());
if (obj instanceof RevTag) { if (obj instanceof RevTag) {
ObjectId pId = rw.peel(obj); ObjectId pId = rw.peel(obj);
key = ctx.findChunk(pId); ChunkKey pKey = ctx.findChunk(pId);
pId = key != null ? new RefDataUtil.IdWithChunk(pId, key) : pId; if (pKey != null)
return RefDataUtil.peeled(newId, pId); d.getPeeledBuilder().setChunkKey(pKey.asString());
} else if (obj != null) d.getPeeledBuilder().setObjectName(pId.name());
return RefDataUtil.peeled(newId, null); }
else
return RefDataUtil.id(newId);
} catch (MissingObjectException e) { } 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.generated.storage.dht.proto.GitStore.RefData;
import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
/** Tools to work with {@link RefData}. */ /** Tools to work with {@link RefData}. */
public class RefDataUtil { public class RefDataUtil {
/** Magic constant meaning does not exist. */ /** Magic constant meaning does not exist. */
public static final RefData NONE = RefData.newBuilder().build(); public static final RefData NONE = RefData.newBuilder().buildPartial();
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();
}
static class IdWithChunk extends ObjectId { 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; private final ChunkKey chunkKey;
IdWithChunk(AnyObjectId id, ChunkKey key) { 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 {@code loose}, if an item appears in both. Items in this
* list <b>must</b> also appear in {@code loose}. * list <b>must</b> also appear in {@code loose}.
*/ */
public RefMap(String prefix, RefList<Ref> packed, RefList<Ref> loose, @SuppressWarnings("unchecked")
RefList<Ref> resolved) { public RefMap(String prefix, RefList<? extends Ref> packed,
RefList<? extends Ref> loose, RefList<? extends Ref> resolved) {
this.prefix = prefix; this.prefix = prefix;
this.packed = packed; this.packed = (RefList<Ref>) packed;
this.loose = loose; this.loose = (RefList<Ref>) loose;
this.resolved = resolved; this.resolved = (RefList<Ref>) resolved;
} }
@Override @Override

Loading…
Cancel
Save