github.com/containers/podman/v4@v4.9.4/libpod/lock/file_lock_manager.go (about) 1 package lock 2 3 import ( 4 "github.com/containers/podman/v4/libpod/define" 5 "github.com/containers/podman/v4/libpod/lock/file" 6 ) 7 8 // FileLockManager manages shared memory locks. 9 type FileLockManager struct { 10 locks *file.FileLocks 11 } 12 13 // NewFileLockManager makes a new FileLockManager at the specified directory. 14 func NewFileLockManager(lockPath string) (Manager, error) { 15 locks, err := file.CreateFileLock(lockPath) 16 if err != nil { 17 return nil, err 18 } 19 20 manager := new(FileLockManager) 21 manager.locks = locks 22 23 return manager, nil 24 } 25 26 // OpenFileLockManager opens an existing FileLockManager at the specified directory. 27 func OpenFileLockManager(path string) (Manager, error) { 28 locks, err := file.OpenFileLock(path) 29 if err != nil { 30 return nil, err 31 } 32 33 manager := new(FileLockManager) 34 manager.locks = locks 35 36 return manager, nil 37 } 38 39 // AllocateLock allocates a new lock from the manager. 40 func (m *FileLockManager) AllocateLock() (Locker, error) { 41 semIndex, err := m.locks.AllocateLock() 42 if err != nil { 43 return nil, err 44 } 45 46 lock := new(FileLock) 47 lock.lockID = semIndex 48 lock.manager = m 49 50 return lock, nil 51 } 52 53 // AllocateAndRetrieveLock allocates the lock with the given ID and returns it. 54 // If the lock is already allocated, error. 55 func (m *FileLockManager) AllocateAndRetrieveLock(id uint32) (Locker, error) { 56 lock := new(FileLock) 57 lock.lockID = id 58 lock.manager = m 59 60 if err := m.locks.AllocateGivenLock(id); err != nil { 61 return nil, err 62 } 63 64 return lock, nil 65 } 66 67 // RetrieveLock retrieves a lock from the manager given its ID. 68 func (m *FileLockManager) RetrieveLock(id uint32) (Locker, error) { 69 lock := new(FileLock) 70 lock.lockID = id 71 lock.manager = m 72 73 return lock, nil 74 } 75 76 // FreeAllLocks frees all locks in the manager. 77 // This function is DANGEROUS. Please read the full comment in locks.go before 78 // trying to use it. 79 func (m *FileLockManager) FreeAllLocks() error { 80 return m.locks.DeallocateAllLocks() 81 } 82 83 // AvailableLocks returns the number of available locks. Since this is not 84 // limited in the file lock implementation, nil is returned. 85 func (m *FileLockManager) AvailableLocks() (*uint32, error) { 86 return nil, nil 87 } 88 89 // LocksHeld returns any locks that are presently locked. 90 // It is not implemented for the file lock backend. 91 // It ought to be possible, but my motivation to dig into c/storage and add 92 // trylock semantics to the filelocker implementation for an uncommonly-used 93 // lock backend is lacking. 94 func (m *FileLockManager) LocksHeld() ([]uint32, error) { 95 return nil, define.ErrNotImplemented 96 } 97 98 // FileLock is an individual shared memory lock. 99 type FileLock struct { 100 lockID uint32 101 manager *FileLockManager 102 } 103 104 // ID returns the ID of the lock. 105 func (l *FileLock) ID() uint32 { 106 return l.lockID 107 } 108 109 // Lock acquires the lock. 110 func (l *FileLock) Lock() { 111 if err := l.manager.locks.LockFileLock(l.lockID); err != nil { 112 panic(err.Error()) 113 } 114 } 115 116 // Unlock releases the lock. 117 func (l *FileLock) Unlock() { 118 if err := l.manager.locks.UnlockFileLock(l.lockID); err != nil { 119 panic(err.Error()) 120 } 121 } 122 123 // Free releases the lock, allowing it to be reused. 124 func (l *FileLock) Free() error { 125 return l.manager.locks.DeallocateLock(l.lockID) 126 }