diff options
author | Matthias Sohn <matthias.sohn@sap.com> | 2024-11-15 08:37:10 +0100 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2025-03-03 20:50:40 +0100 |
commit | 1ff9c2a1cbd5ac718559eef152d954755f257bc8 (patch) | |
tree | c748f6d95d82344549733ec6d75044c06a320e23 /org.eclipse.jgit/src/org | |
parent | 5db57fe2a932fc05d28e057df9ff9d6a0bd6abe3 (diff) | |
download | jgit-1ff9c2a1cbd5ac718559eef152d954755f257bc8.tar.gz jgit-1ff9c2a1cbd5ac718559eef152d954755f257bc8.zip |
FileReftableDatabase: consider ref updates by another process
FileReftableDatabase didn't consider that refs might be changed by
another process e.g. using git (which started supporting reftable with
version 2.45).
Add a test creating a light-weight tag which is updated using git
running in another process and assert that FileReftableDatabase
recognizes the tag modification.
FileReftableStack#addReftable checks if the stack is up-to-date while it
holds the FileLock for tables.list, if it is not up-to-date the
RefUpdate fails with a LOCK_FAILURE to protect against lost ref updates
if another instance of FileReftableDatabase or another thread or process
updated the reftable stack since we last read it.
If option `reftable.autoRefresh = true` or `setAutoRefresh(true)` was
called check before each ref resolution if the reftable stack is
up-to-date and, if necessary, reload the reftable stack automatically.
Calling `setAutoRefresh(true)` takes precedence over the configured
value for option `reftable.autoRefresh`.
Add a testConcurrentRacyReload which tests that updates still abort ref
updates if the reftable stack the update is based on was outdated.
Bug: jgit-102
Change-Id: I1f9faa2afdbfff27e83ff295aef6d572babed4fe
Diffstat (limited to 'org.eclipse.jgit/src/org')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java | 54 | ||||
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java | 14 |
2 files changed, 68 insertions, 0 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java index 6040ad554d..d70fa839e9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/FileReftableDatabase.java @@ -16,6 +16,7 @@ import static org.eclipse.jgit.lib.Ref.Storage.PACKED; import java.io.File; import java.io.IOException; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -37,6 +38,7 @@ import org.eclipse.jgit.internal.storage.reftable.ReftableBatchRefUpdate; import org.eclipse.jgit.internal.storage.reftable.ReftableDatabase; import org.eclipse.jgit.internal.storage.reftable.ReftableWriter; import org.eclipse.jgit.lib.BatchRefUpdate; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdRef; @@ -70,6 +72,8 @@ public class FileReftableDatabase extends RefDatabase { private final FileReftableStack reftableStack; + private boolean autoRefresh; + FileReftableDatabase(FileRepository repo) throws IOException { this(repo, new File(new File(repo.getCommonDirectory(), Constants.REFTABLE), Constants.TABLES_LIST)); @@ -77,6 +81,9 @@ public class FileReftableDatabase extends RefDatabase { FileReftableDatabase(FileRepository repo, File refstackName) throws IOException { this.fileRepository = repo; + this.autoRefresh = repo.getConfig().getBoolean( + ConfigConstants.CONFIG_REFTABLE_SECTION, + ConfigConstants.CONFIG_KEY_AUTOREFRESH, false); this.reftableStack = new FileReftableStack(refstackName, new File(fileRepository.getCommonDirectory(), Constants.REFTABLE), () -> fileRepository.fireEvent(new RefsChangedEvent()), @@ -183,6 +190,7 @@ public class FileReftableDatabase extends RefDatabase { @Override public Ref exactRef(String name) throws IOException { + autoRefresh(); return reftableDatabase.exactRef(name); } @@ -193,6 +201,7 @@ public class FileReftableDatabase extends RefDatabase { @Override public Map<String, Ref> getRefs(String prefix) throws IOException { + autoRefresh(); List<Ref> refs = reftableDatabase.getRefsByPrefix(prefix); RefList.Builder<Ref> builder = new RefList.Builder<>(refs.size()); for (Ref r : refs) { @@ -205,6 +214,7 @@ public class FileReftableDatabase extends RefDatabase { @Override public List<Ref> getRefsByPrefixWithExclusions(String include, Set<String> excludes) throws IOException { + autoRefresh(); return reftableDatabase.getRefsByPrefixWithExclusions(include, excludes); } @@ -223,6 +233,50 @@ public class FileReftableDatabase extends RefDatabase { } + /** + * Whether to auto-refresh the reftable stack if it is out of date. + * + * @param autoRefresh + * whether to auto-refresh the reftable stack if it is out of + * date. + */ + public void setAutoRefresh(boolean autoRefresh) { + this.autoRefresh = autoRefresh; + } + + /** + * Whether the reftable stack is auto-refreshed if it is out of date. + * + * @return whether the reftable stack is auto-refreshed if it is out of + * date. + */ + public boolean isAutoRefresh() { + return autoRefresh; + } + + private void autoRefresh() { + if (autoRefresh) { + refresh(); + } + } + + /** + * Check if the reftable stack is up to date, and if not, reload it. + * <p> + * {@inheritDoc} + */ + @Override + public void refresh() { + try { + if (!reftableStack.isUpToDate()) { + reftableDatabase.clearCache(); + reftableStack.reload(); + } + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + private Ref doPeel(Ref leaf) throws IOException { try (RevWalk rw = new RevWalk(fileRepository)) { RevObject obj = rw.parseAny(leaf.getObjectId()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java index 30e7de47c3..f62bf161a7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java @@ -1093,4 +1093,18 @@ public final class ConfigConstants { * @since 7.1 */ public static final String CONFIG_KEY_LOAD_REV_INDEX_IN_PARALLEL = "loadRevIndexInParallel"; + + /** + * The "reftable" section + * + * @since 7.2 + */ + public static final String CONFIG_REFTABLE_SECTION = "reftable"; + + /** + * The "autorefresh" key + * + * @since 7.2 + */ + public static final String CONFIG_KEY_AUTOREFRESH = "autorefresh"; } |