Skip to content

Instantly share code, notes, and snippets.

@rightfold
Last active August 29, 2015 14:19
Show Gist options
  • Save rightfold/fb67cc32fb86fc25ad71 to your computer and use it in GitHub Desktop.
Save rightfold/fb67cc32fb86fc25ad71 to your computer and use it in GitHub Desktop.
package storage
import (
"golang.org/x/sys/unix"
"os"
"path/filepath"
)
// UserdirLock maintains a lock on a user directory.
type UserdirLock struct {
file *os.File
}
// NewUserdirLock creates a new unlocked user directory lock.
func NewUserdirLock(userdir string) (*UserdirLock, error) {
path := filepath.Join(userdir, "lock")
file, err := os.OpenFile(path, os.O_CREATE, 0644)
if err != nil {
return nil, err
}
return &UserdirLock{file: file}, nil
}
// NewLockedUserdirLock creates a new locked user directory lock.
func NewLockedUserdirLock(userdir string) (*UserdirLock, error) {
lock, err := NewUserdirLock(userdir)
if err != nil {
return nil, err
}
if err := lock.Lock(); err != nil {
lock.Close()
return nil, err
}
return lock, nil
}
// Close closes the user directory lock, but does not unlock it.
func (lock *UserdirLock) Close() error {
return lock.file.Close()
}
// Lock locks the user directory. If the user directory is already locked, Lock
// will wait until it is unlocked.
func (lock *UserdirLock) Lock() error {
return unix.Flock(int(lock.file.Fd()), unix.LOCK_EX)
}
// Unlock unlocks the user directory. If the user directory is already unlocked
// the behavior is undefined.
func (lock *UserdirLock) Unlock() error {
return unix.Flock(int(lock.file.Fd()), unix.LOCK_UN)
}
// Unlock unlocks the user directory and closes the lock. If the user directory
// is already unlocked the behavior is undefined.
func (lock *UserdirLock) UnlockAndClose() error {
if err := lock.Unlock(); err != nil {
return err
}
return lock.Close()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment