Skip to content

Commit 4189f39

Browse files
committed
Merge branch 'stable-7.3' into stable-7.4
* stable-7.3: Do not always refresh packed-refs during ref updates Change-Id: I9b5afc13f287da2248f2fcfd4be44b691b023843
2 parents b2d3c51 + 85b454b commit 4189f39

File tree

3 files changed

+28
-30
lines changed

3 files changed

+28
-30
lines changed

Documentation/config-options.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ For details on native git options see also the official [git config documentatio
5757
| `core.symlinks` | Auto detect if filesystem supports symlinks| ✅ | If false, symbolic links are checked out as small plain files that contain the link text. |
5858
| ~~`core.trustFolderStat`~~ | `true` | ⃞ | __Deprecated__, use `core.trustStat` instead. If set to `true` translated to `core.trustStat=always`, if `false` translated to `core.trustStat=never`, see below. If both `core.trustFolderStat` and `core.trustStat` are configured then `trustStat` takes precedence and `trustFolderStat` is ignored. |
5959
| `core.trustLooseRefStat` | `inherit` | ⃞ | Whether to trust the file attributes of loose refs and its fan-out parent directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `trustStat`. |
60-
| `core.trustPackedRefsStat` | `inherit` | ⃞ | Whether to trust the file attributes of the packed-refs file. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. |
60+
| `core.trustPackedRefsStat` | `inherit` | ⃞ | Whether to trust the file attributes of the packed-refs file. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. __Note:__ since 6.10.2, this setting applies during both ref reads and ref updates, but previously only applied during reads.|
6161
| `core.trustTablesListStat` | `inherit` | ⃞ | Whether to trust the file attributes of the `tables.list` file used by the reftable ref storage backend to store the list of reftable filenames. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. The reftable backend is used if `extensions.refStorage = reftable`. |
6262
| `core.trustLooseObjectStat` | `inherit` | ⃞ | Whether to trust the file attributes of the loose object file and its fan-out parent directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. |
6363
| `core.trustPackStat` | `inherit` | ⃞ | Whether to trust the file attributes of the `objects/pack` directory. See `core.trustStat` for possible values. If `inherit`, JGit will use the behavior configured in `core.trustStat`. |

org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackedBatchRefUpdate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public void execute(RevWalk walk, ProgressMonitor monitor,
172172
}
173173

174174
packedRefsLock = refdb.lockPackedRefsOrThrow();
175-
PackedRefList oldPackedList = refdb.refreshPackedRefs();
175+
PackedRefList oldPackedList = refdb.getLockedPackedRefs(packedRefsLock);
176176
RefList<Ref> newRefs = applyUpdates(walk, oldPackedList, pending);
177177
if (newRefs == null) {
178178
return;

org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ void delete(RefDirectoryUpdate update) throws IOException {
720720
PackedRefList packed = getPackedRefs();
721721
if (packed.contains(name)) {
722722
// Force update our packed-refs snapshot before writing
723-
packed = refreshPackedRefs();
723+
packed = getLockedPackedRefs(lck);
724724
int idx = packed.find(name);
725725
if (0 <= idx) {
726726
commitPackedRefs(lck, packed.remove(idx), packed, true);
@@ -788,7 +788,7 @@ private void pack(Collection<String> refs,
788788
try {
789789
LockFile lck = lockPackedRefsOrThrow();
790790
try {
791-
PackedRefList oldPacked = refreshPackedRefs();
791+
PackedRefList oldPacked = getLockedPackedRefs(lck);
792792
RefList<Ref> newPacked = oldPacked;
793793

794794
// Iterate over all refs to be packed
@@ -971,6 +971,15 @@ else if (0 <= (idx = packed.find(dst.getName())))
971971
}
972972

973973
PackedRefList getPackedRefs() throws IOException {
974+
return refreshPackedRefsIfNeeded();
975+
}
976+
977+
PackedRefList getLockedPackedRefs(LockFile packedRefsFileLock) throws IOException {
978+
packedRefsFileLock.requireLock();
979+
return refreshPackedRefsIfNeeded();
980+
}
981+
982+
PackedRefList refreshPackedRefsIfNeeded() throws IOException {
974983
PackedRefList curList = packedRefs.get();
975984
if (!curList.shouldRefresh()) {
976985
return curList;
@@ -985,23 +994,29 @@ private PackedRefsRefresher getPackedRefsRefresher(PackedRefList curList)
985994
return refresher;
986995
}
987996
// This synchronized is NOT needed for correctness. Instead it is used
988-
// as a throttling mechanism to ensure that only one "read" thread does
989-
// the work to refresh the file. In order to avoid stalling writes which
990-
// must already be serialized and tend to be a bottleneck,
991-
// the refreshPackedRefs() need not be synchronized.
997+
// as a mechanism to try to avoid parallel reads of the same file content
998+
// since repeating work, even in parallel, hurts performance.
999+
// Unfortunately, this approach can still lead to some unnecessary re-reads
1000+
// during the "racy" window of the snapshot timestamp.
9921001
synchronized (this) {
9931002
if (packedRefsRefresher.get() != refresher) {
9941003
refresher = packedRefsRefresher.get();
9951004
if (refresher != null) {
996-
// Refresher now guaranteed to have been created after the
997-
// current thread entered getPackedRefsRefresher(), even if
998-
// it's currently out of date.
1005+
// Refresher now guaranteed to have not started refreshing until
1006+
// after the current thread entered getPackedRefsRefresher(),
1007+
// even if it's currently out of date. And if the packed-refs
1008+
// lock is held before calling this method, then it is also
1009+
// guaranteed to not be out-of date even during the "racy"
1010+
// window of the snapshot timestamp.
9991011
return refresher;
10001012
}
10011013
}
1002-
refresher = createPackedRefsRefresherAsLatest(curList);
1014+
refresher = new PackedRefsRefresher(curList);
1015+
packedRefsRefresher.set(refresher);
10031016
}
1004-
return runAndClear(refresher);
1017+
refresher.run();
1018+
packedRefsRefresher.compareAndSet(refresher, null);
1019+
return refresher;
10051020
}
10061021

10071022
private boolean shouldRefreshPackedRefs(FileSnapshot snapshot) throws IOException {
@@ -1027,23 +1042,6 @@ private boolean shouldRefreshPackedRefs(FileSnapshot snapshot) throws IOExceptio
10271042
return true;
10281043
}
10291044

1030-
PackedRefList refreshPackedRefs() throws IOException {
1031-
return runAndClear(createPackedRefsRefresherAsLatest(packedRefs.get()))
1032-
.getOrThrowIOException();
1033-
}
1034-
1035-
private PackedRefsRefresher createPackedRefsRefresherAsLatest(PackedRefList curList) {
1036-
PackedRefsRefresher refresher = new PackedRefsRefresher(curList);
1037-
packedRefsRefresher.set(refresher);
1038-
return refresher;
1039-
}
1040-
1041-
private PackedRefsRefresher runAndClear(PackedRefsRefresher refresher) {
1042-
refresher.run();
1043-
packedRefsRefresher.compareAndSet(refresher, null);
1044-
return refresher;
1045-
}
1046-
10471045
private PackedRefList refreshPackedRefs(PackedRefList curList)
10481046
throws IOException {
10491047
final PackedRefList newList = readPackedRefs();

0 commit comments

Comments
 (0)