Class PackedBatchRefUpdate


  • class PackedBatchRefUpdate
    extends BatchRefUpdate
    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.
    • Constructor Detail

      • PackedBatchRefUpdate

        PackedBatchRefUpdate​(RefDirectory refdb)
    • Method Detail

      • execute

        public void execute​(RevWalk walk,
                            ProgressMonitor monitor,
                            java.util.List<java.lang.String> options)
                     throws java.io.IOException
        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 BatchRefUpdate.setAtomic(boolean) and RefDatabase.performsAtomicTransactions().

        Overrides:
        execute in class BatchRefUpdate
        Parameters:
        walk - a RevWalk to parse tags in case the storage system wants to store them pre-peeled, a common performance optimization.
        monitor - progress monitor to receive update status on.
        options - a list of option strings; set null to execute without
        Throws:
        java.io.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.
      • containsSymrefs

        private static boolean containsSymrefs​(java.util.List<ReceiveCommand> commands)
      • checkConflictingNames

        private boolean checkConflictingNames​(java.util.List<ReceiveCommand> commands)
                                       throws java.io.IOException
        Throws:
        java.io.IOException
      • checkObjectExistence

        private boolean checkObjectExistence​(RevWalk walk,
                                             java.util.List<ReceiveCommand> commands)
                                      throws java.io.IOException
        Throws:
        java.io.IOException
      • checkNonFastForwards

        private boolean checkNonFastForwards​(RevWalk walk,
                                             java.util.List<ReceiveCommand> commands)
                                      throws java.io.IOException
        Throws:
        java.io.IOException
      • lockLooseRefs

        @Nullable
        private java.util.Map<java.lang.String,​LockFile> lockLooseRefs​(java.util.List<ReceiveCommand> commands)
                                                                      throws java.io.IOException
        Lock loose refs corresponding to a list of commands.
        Parameters:
        commands - commands that we intend to execute.
        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.
        Throws:
        java.io.IOException - an error occurred other than a failure to acquire; no locks are held if this exception is thrown.
      • writeReflog

        private void writeReflog​(java.util.List<ReceiveCommand> commands)
      • toResultString

        private java.lang.String toResultString​(ReceiveCommand cmd)
      • peeledRef

        private static Ref peeledRef​(RevWalk walk,
                                     ReceiveCommand cmd)
                              throws java.io.IOException
        Throws:
        java.io.IOException
      • unlockAll

        private static void unlockAll​(@Nullable
                                      java.util.Map<?,​LockFile> locks)