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 }