github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/flock/flock_unix.go (about) 1 // +build !windows,!plan9 2 3 package flock 4 5 import ( 6 "fmt" 7 "os" 8 "syscall" 9 ) 10 11 // FileLockGuard holds a lock of file on a directory. 12 type FileLockGuard struct { 13 // file descriptor on directory. 14 fd *os.File 15 } 16 17 // AcquireFileLock acquire the lock on the directory by syscall.Flock. 18 // Return a FileLockGuard or an error, if any. 19 func AcquireFileLock(path string, readOnly bool) (*FileLockGuard, error) { 20 var flag = os.O_RDWR 21 if readOnly { 22 flag = os.O_RDONLY 23 } 24 file, err := os.OpenFile(path, flag, 0) 25 if os.IsNotExist(err) { 26 file, err = os.OpenFile(path, flag|os.O_CREATE, 0644) 27 } 28 if err != nil { 29 return nil, err 30 } 31 32 var how = syscall.LOCK_EX | syscall.LOCK_NB 33 if readOnly { 34 how = syscall.LOCK_SH | syscall.LOCK_NB 35 } 36 if err := syscall.Flock(int(file.Fd()), how); err != nil { 37 return nil, err 38 } 39 return &FileLockGuard{fd: file}, nil 40 } 41 42 // SyncDir commits the current contents of the directory to stable storage. 43 func SyncDir(path string) error { 44 fd, err := os.Open(path) 45 if err != nil { 46 return err 47 } 48 err = fd.Sync() 49 closeErr := fd.Close() 50 if err != nil { 51 return fmt.Errorf("sync dir err: %+v", err) 52 } 53 if closeErr != nil { 54 return fmt.Errorf("close dir err: %+v", err) 55 } 56 return nil 57 } 58 59 // Release release the file lock. 60 func (fl *FileLockGuard) Release() error { 61 how := syscall.LOCK_UN | syscall.LOCK_NB 62 if err := syscall.Flock(int(fl.fd.Fd()), how); err != nil { 63 return err 64 } 65 return fl.fd.Close() 66 }