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  }