github.com/containers/podman/v4@v4.9.4/libpod/lock/lock.go (about)

     1  package lock
     2  
     3  // Manager provides an interface for allocating multiprocess locks.
     4  // Locks returned by Manager MUST be multiprocess - allocating a lock in
     5  // process A and retrieving that lock's ID in process B must return handles for
     6  // the same lock, and locking the lock in A should exclude B from the lock until
     7  // it is unlocked in A.
     8  // All locks must be identified by a UUID (retrieved with Locker's ID() method).
     9  // All locks with a given UUID must refer to the same underlying lock, and it
    10  // must be possible to retrieve the lock given its UUID.
    11  // Each UUID should refer to a unique underlying lock.
    12  // Calls to AllocateLock() must return a unique, unallocated UUID.
    13  // AllocateLock() must fail once all available locks have been allocated.
    14  // Locks are returned to use by calls to Free(), and can subsequently be
    15  // reallocated.
    16  type Manager interface {
    17  	// AllocateLock returns an unallocated lock.
    18  	// It is guaranteed that the same lock will not be returned again by
    19  	// AllocateLock until the returned lock has Free() called on it.
    20  	// If all available locks are allocated, AllocateLock will return an
    21  	// error.
    22  	AllocateLock() (Locker, error)
    23  	// RetrieveLock retrieves a lock given its UUID.
    24  	// The underlying lock MUST be the same as another other lock with the
    25  	// same UUID.
    26  	RetrieveLock(id uint32) (Locker, error)
    27  	// AllocateAndRetrieveLock marks the lock with the given UUID as in use
    28  	// and retrieves it.
    29  	// RetrieveAndAllocateLock will error if the lock in question has
    30  	// already been allocated.
    31  	// This is mostly used after a system restart to repopulate the list of
    32  	// locks in use.
    33  	AllocateAndRetrieveLock(id uint32) (Locker, error)
    34  	// PLEASE READ FULL DESCRIPTION BEFORE USING.
    35  	// FreeAllLocks frees all allocated locks, in preparation for lock
    36  	// reallocation.
    37  	// As this deallocates all presently-held locks, this can be very
    38  	// dangerous - if there are other processes running that might be
    39  	// attempting to allocate new locks and free existing locks, we may
    40  	// encounter races leading to an inconsistent state.
    41  	// (This is in addition to the fact that FreeAllLocks instantly makes
    42  	// the state inconsistent simply by using it, and requires a full
    43  	// lock renumbering to restore consistency!).
    44  	// In short, this should only be used as part of unit tests, or lock
    45  	// renumbering, where reasonable guarantees about other processes can be
    46  	// made.
    47  	FreeAllLocks() error
    48  	// NumAvailableLocks gets the number of remaining locks available to be
    49  	// allocated.
    50  	// Some lock managers do not have a maximum number of locks, and can
    51  	// allocate an unlimited number. These implementations should return
    52  	// a nil uin32.
    53  	AvailableLocks() (*uint32, error)
    54  	// Get a list of locks that are currently locked.
    55  	// This may not be supported by some drivers, depending on the exact
    56  	// backend implementation in use.
    57  	LocksHeld() ([]uint32, error)
    58  }
    59  
    60  // Locker is similar to sync.Locker, but provides a method for freeing the lock
    61  // to allow its reuse.
    62  // All Locker implementations must maintain mutex semantics - the lock only
    63  // allows one caller in the critical section at a time.
    64  // All locks with the same ID must refer to the same underlying lock, even
    65  // if they are within multiple processes.
    66  type Locker interface {
    67  	// ID retrieves the lock's ID.
    68  	// ID is guaranteed to uniquely identify the lock within the
    69  	// Manager - that is, calling RetrieveLock with this ID will return
    70  	// another instance of the same lock.
    71  	ID() uint32
    72  	// Lock locks the lock.
    73  	// This call MUST block until it successfully acquires the lock or
    74  	// encounters a fatal error.
    75  	// All errors must be handled internally, as they are not returned. For
    76  	// the most part, panicking should be appropriate.
    77  	// Some lock implementations may require that Lock() and Unlock() occur
    78  	// within the same goroutine (SHM locking, for example). The usual Go
    79  	// Lock()/defer Unlock() pattern will still work fine in these cases.
    80  	Lock()
    81  	// Unlock unlocks the lock.
    82  	// All errors must be handled internally, as they are not returned. For
    83  	// the most part, panicking should be appropriate.
    84  	// This includes unlocking locks which are already unlocked.
    85  	Unlock()
    86  	// Free deallocates the underlying lock, allowing its reuse by other
    87  	// pods and containers.
    88  	// The lock MUST still be usable after a Free() - some libpod instances
    89  	// may still retain Container structs with the old lock. This simply
    90  	// advises the manager that the lock may be reallocated.
    91  	Free() error
    92  }