Top Description Fields Constructors Methods
org.eclipse.jgit.internal.storage.file

pack-priv Class PackedBatchRefUpdate

extends BatchRefUpdate
Class Inheritance
Known Direct Subclasses
org.eclipse.jgit.internal.storage.file.SnapshottingRefDirectory.SnapshotPackedBatchRefUpdate
Static Imports
java.util.stream.Collectors.toList, org.eclipse.jgit.transport.ReceiveCommand.Result.LOCK_FAILURE, .ReceiveCommand.Result.NOT_ATTEMPTED, .ReceiveCommand.Result.REJECTED_NONFASTFORWARD, .ReceiveCommand.Result.REJECTED_OTHER_REASON

Implementation of BatchRefUpdate that uses the packed-refs file to support atomically updating multiple refs.

The algorithm is designed to be compatible with traditional single ref updates operating on single refs only. Regardless of success or failure, the results are atomic: from the perspective of any reader, either all updates in the batch will be visible, or none will. In the case of process failure during any of the following steps, removal of stale lock files is always safe, and will never result in an inconsistent state, although the update may or may not have been applied.

The algorithm is:

  1. Pack loose refs involved in the transaction using the normal pack-refs operation. This ensures that creating lock files in the following step succeeds even if a batch contains both a delete of refs/x (loose) and a create of refs/x/y.
  2. Create locks for all loose refs involved in the transaction, even if they are not currently loose.
  3. Pack loose refs again, this time while holding all lock files (see RefDirectory#pack(Map)), without deleting them afterwards. This covers a potential race where new loose refs were created after the initial packing step. If no new loose refs were created during this race, this step does not modify any files on disk. Keep the merged state in memory.
  4. Update the in-memory packed refs with the commands in the batch, possibly failing the whole batch if any old ref values do not match.
  5. If the update succeeds, lock packed-refs and commit by atomically renaming the lock file.
  6. Delete loose ref lock files.
Because the packed-refs file format is a sorted list, this algorithm is linear in the total number of refs, regardless of the batch size. This can be a significant slowdown on repositories with large numbers of refs; callers that prefer speed over atomicity should use setAtomic(false). As an optimization, an update containing a single ref update does not use the packed-refs protocol.

Field Summary

Modifier and TypeField and Description
private RefDirectory
private boolean
Inherited from org.eclipse.jgit.lib.BatchRefUpdate:
MAX_WAIT

Constructor Summary

AccessConstructor and Description
pack-priv
pack-priv
PackedBatchRefUpdate(RefDirectory refdb, boolean shouldLockLooseRefs)

Method Summary

Modifier and TypeMethod and Description
private static RefList<Ref>
private boolean
private boolean
private boolean
private static boolean
public void
execute(RevWalk
a RevWalk to parse tags in case the storage system wants to store them pre-peeled, a common performance optimization.
walk
,
ProgressMonitor
progress monitor to receive update status on.
monitor
,
List<String>
a list of option strings; set null to execute without
options
)

Overrides org.eclipse.jgit.lib.BatchRefUpdate.execute.

Execute this batch update.

private static void
private Map<String, LockFile>

Returns:

map of ref name in the input commands to lock file. Always contains one entry for each ref in the input list. All locks are acquired before returning. If any lock was not able to be acquired: the return value is null; no locks are held; and all commands that were pending are set to fail with LOCK_FAILURE.
lockLooseRefs
(List<ReceiveCommand>
commands that we intend to execute.
commands
)

Lock loose refs corresponding to a list of commands.

private static Ref
private static void
private static void
private String
private static void
unlockAll(Map<?, LockFile> locks)

private void
Inherited from org.eclipse.jgit.lib.BatchRefUpdate:
addCommandaddCommandaddCommandaddPrefixesToaddProposedTimestampblockUntilTimestampsdisableRefLogexecutegetCommandsgetPrefixesgetProposedTimestampsgetPushCertificategetPushOptionsgetRefDatabasegetRefLogIdentgetRefLogMessagegetRefLogMessageisAllowNonFastForwardsisAtomicisForceRefLogisForceRefLogisRefLogDisabledisRefLogDisabledisRefLogIncludingResultisRefLogIncludingResultnewUpdatesetAllowNonFastForwardssetAtomicsetForceRefLogsetPushCertificatesetPushOptionssetRefLogIdentsetRefLogMessagetoString

Field Detail

refdbback to summary
private RefDirectory refdb

Hides org.eclipse.jgit.lib.BatchRefUpdate.refdb.

shouldLockLooseRefsback to summary
private boolean shouldLockLooseRefs

Constructor Detail

PackedBatchRefUpdateback to summary
pack-priv PackedBatchRefUpdate(RefDirectory refdb)
PackedBatchRefUpdateback to summary
pack-priv PackedBatchRefUpdate(RefDirectory refdb, boolean shouldLockLooseRefs)

Method Detail

applyUpdatesback to summary
private static RefList<Ref> applyUpdates(RevWalk walk, RefList<Ref> refs, List<ReceiveCommand> commands) throws IOException
checkConflictingNamesback to summary
private boolean checkConflictingNames(List<ReceiveCommand> commands) throws IOException
checkNonFastForwardsback to summary
private boolean checkNonFastForwards(RevWalk walk, List<ReceiveCommand> commands) throws IOException
checkObjectExistenceback to summary
private boolean checkObjectExistence(RevWalk walk, List<ReceiveCommand> commands) throws IOException
containsSymrefsback to summary
private static boolean containsSymrefs(List<ReceiveCommand> commands)
executeback to summary
public void execute(RevWalk walk, ProgressMonitor monitor, List<String> options) throws IOException

Overrides org.eclipse.jgit.lib.BatchRefUpdate.execute.

Doc from org.eclipse.jgit.lib.BatchRefUpdate.execute.

Execute this batch update.

The default implementation of this method performs a sequential reference update over each reference.

Implementations must respect the atomicity requirements of the underlying database as described in setAtomic(boolean) and org.eclipse.jgit.lib.RefDatabase#performsAtomicTransactions().

Parameters
walk:RevWalk

a RevWalk to parse tags in case the storage system wants to store them pre-peeled, a common performance optimization.

monitor:ProgressMonitor

progress monitor to receive update status on.

options:List<String>

a list of option strings; set null to execute without

Annotations
@Override
Exceptions
IOException:
the database is unable to accept the update. Individual command status must be tested to determine if there is a partial failure, or a total failure.
lockFailureback to summary
private static void lockFailure(ReceiveCommand cmd, List<ReceiveCommand> commands)
lockLooseRefsback to summary
private Map<String, LockFile> lockLooseRefs(List<ReceiveCommand> commands) throws IOException

Lock loose refs corresponding to a list of commands.

Parameters
commands:List<ReceiveCommand>

commands that we intend to execute.

Returns:Map<String, LockFile>

map of ref name in the input commands to lock file. Always contains one entry for each ref in the input list. All locks are acquired before returning. If any lock was not able to be acquired: the return value is null; no locks are held; and all commands that were pending are set to fail with LOCK_FAILURE.

Annotations
@Nullable
Exceptions
IOException:
an error occurred other than a failure to acquire; no locks are held if this exception is thrown.
peeledRefback to summary
private static Ref peeledRef(RevWalk walk, ReceiveCommand cmd) throws IOException
rejectback to summary
private static void reject(ReceiveCommand cmd, ReceiveCommand.Result result, List<ReceiveCommand> commands)
rejectback to summary
private static void reject(ReceiveCommand cmd, ReceiveCommand.Result result, String why, List<ReceiveCommand> commands)
toResultStringback to summary
private String toResultString(ReceiveCommand cmd)
unlockAllback to summary
private static void unlockAll(Map<?, LockFile> locks)
writeReflogback to summary
private void writeReflog(List<ReceiveCommand> commands)