fslock

package
v0.0.0-...-d899e02 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 12, 2024 License: BSD-3-Clause Imports: 6 Imported by: 32

Documentation

Overview

Package fslock is a cross-platform filesystem locking implementation.

fslock aims to implement workable filesystem-based locking semantics. Each implementation offers its own nuances, and not all of those nuances are addressed by this package.

Locks can either be exclusive (default) or shared. For a given file, exactly one of the following circumstances may be true at a given moment:

  • No locks are held.
  • A single exclusive lock may be held.
  • Multiple shared locks may be held.

Notably, an exclusive lock may not be held on a file that has shared locks, and a shared lock may not be held on a file that has an exclusive lock.

fslock will work as long as you don't do anything particularly weird, such as:

  • Manually forking your Go process.
  • Circumventing the fslock package and opening and/or manipulating the lock file directly.

An attempt to take a filesystem lock is non-blocking, and will return ErrLockHeld if the lock is already held elsewhere.

Index

Constants

This section is empty.

Variables

View Source
var ErrLockHeld = errors.New("fslock: lock is held")

ErrLockHeld is a sentinel error returned when the lock could not be acquired.

Functions

func With

func With(path string, fn func() error) error

With is a convenience function to create a lock, execute a function while holding that lock, and then release the lock on completion.

See L's With method for details.

func WithBlocking

func WithBlocking(path string, b Blocker, fn func() error) error

WithBlocking is a convenience function to create a lock, execute a function while holding that lock, and then release the lock on completion. The supplied block function is used to retry (see L's Block field).

See L's With method for details.

func WithShared

func WithShared(path string, fn func() error) error

WithShared is a convenience function to create a lock, execute a function while holding that lock, and then release the lock on completion.

See L's With method for details.

func WithSharedBlocking

func WithSharedBlocking(path string, b Blocker, fn func() error) error

WithSharedBlocking is a convenience function to create a lock, execute a function while holding that lock, and then release the lock on completion. The supplied block function is used to retry (see L's Block field).

See L's With method for details.

Types

type Blocker

type Blocker func() error

Blocker is used for the Delay field in a Lock.

type Handle

type Handle interface {
	// Unlock releases the held lock.
	//
	// This can error if the underlying filesystem operations fail. This should
	// not happen unless something has gone externally wrong, or the lock was
	// mishandled.
	Unlock() error

	// LockFile returns the underlying lock File. This is not generally useful,
	// and should be used circumstantially. Operating on the file occurs outside
	// of the scope of this package, and can result in unintended consequences.
	//
	// The file should NOT be directly closed or modified.
	//
	// The file will be valid for the duration of the Handle. Once the Handle is
	// closed with Unlock, the file's state is implementation-specific and
	// unspecified.
	LockFile() *os.File

	// PreserveExec preserves the lock across execve syscall.
	//
	// The lock will be held even after call execve. It is not possible to
	// acquire a handle for the lock unless manually passing the fd as an
	// argument.
	//
	// On Windows, the behaviour is not promised unless CreateProcess with
	// bInheritHandles.
	PreserveExec() error
}

Handle is a reference to a held lock. It must be released via Unlock when finished. Multiple calls to Unlock will panic.

Handle is NOT safe for concurrent use.

func Lock

func Lock(path string) (Handle, error)

Lock acquires a filesystem lock for the given path.

If the lock could not be acquired because it is held by another entity, ErrLockHeld will be returned. If an error is encountered while locking, that error will be returned.

Lock is a convenience method for L's Lock.

func LockBlocking

func LockBlocking(path string, b Blocker) (Handle, error)

LockBlocking acquires an exclusive filesystem lock for the given path. If the lock is already held, LockBlocking will repeatedly attempt to acquire it using the supplied Blocker in between attempts.

If no Blocker is provided and the lock could not be acquired because it is held by another entity, ErrLockHeld will be returned. If an error is encountered while locking, or an error is returned by b, that error will be returned.

LockBlocking is a convenience method for L's Lock.

func LockShared

func LockShared(path string) (Handle, error)

Lock acquires a filesystem lock for the given path.

If the lock could not be acquired because it is held by another entity, ErrLockHeld will be returned. If an error is encountered while locking, that error will be returned.

Lock is a convenience method for L's Lock.

func LockSharedBlocking

func LockSharedBlocking(path string, b Blocker) (Handle, error)

LockSharedBlocking acquires a shared filesystem lock for the given path. If the lock is already held, LockSharedBlocking will repeatedly attempt to acquire it using the supplied Blocker in between attempts.

If no Blocker is provided and the lock could not be acquired because it is held by another entity, ErrLockHeld will be returned. If an error is encountered while locking, or an error is returned by b, that error will be returned.

LockSharedBlocking is a convenience method for L's Lock.

type L

type L struct {
	// Path is the path of the file to lock.
	Path string

	// Shared, if true, indicates that this should be a shared lock rather than
	// an exclusive lock.
	//
	// See package documentation for details.
	Shared bool

	// Content, if populated, is the lock file content. Content is written to the
	// file when the lock call creates it, and only if the lock call actually
	// creates the file. Failure to write Content is non-fatal.
	//
	// Content should be used only as a convenience hint for users who want to
	// know what the lock file is, and not for actual programmatic management.
	// Several code paths can result in successful file locking and still fail to
	// write Content to that file.
	//
	// Content is not synchronized with the actual locking. Failure to write
	// Content to the lock file is considered non-fatal.
	Content []byte

	// Block is the configured blocking function.
	//
	// If not nil, an attempt to acquire the lock will loop indefinitely until an
	// error other than ErrLockHeld is encountered (fatal) or the lock is
	// acquired. Block will be called each time a lock attempt returns
	// ErrLockHeld, and should delay and/or cancel the acquisition by returning
	// nil or an error code respectively.
	//
	// If Block returns an error, it will be propagated as the error result of the
	// locking attempt.
	Block Blocker
}

L describes a filesystem lock.

L's fields should not be modified concurrently, but L's methods are safe for concurrent use.

func (*L) Lock

func (l *L) Lock() (Handle, error)

Lock attempts to acquire the configured lock.

func (*L) With

func (l *L) With(fn func() error) (err error)

With is a convenience method to acquire a lock via Lock, call fn, and release the lock on completion (via defer).

If an error is encountered, it will be returned. Otherwise, the return value from fn will be returned.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL