github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/vfs/os_linux.go (about) 1 //go:build !(sqlite3_flock || sqlite3_nosys) 2 3 package vfs 4 5 import ( 6 "math/rand" 7 "os" 8 "time" 9 10 "golang.org/x/sys/unix" 11 ) 12 13 func osSync(file *os.File, _ /*fullsync*/, _ /*dataonly*/ bool) error { 14 // SQLite trusts Linux's fdatasync for all fsync's. 15 return unix.Fdatasync(int(file.Fd())) 16 } 17 18 func osAllocate(file *os.File, size int64) error { 19 if size == 0 { 20 return nil 21 } 22 return unix.Fallocate(int(file.Fd()), 0, 0, size) 23 } 24 25 func osUnlock(file *os.File, start, len int64) _ErrorCode { 26 err := unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &unix.Flock_t{ 27 Type: unix.F_UNLCK, 28 Start: start, 29 Len: len, 30 }) 31 if err != nil { 32 return _IOERR_UNLOCK 33 } 34 return _OK 35 } 36 37 func osLock(file *os.File, typ int16, start, len int64, timeout time.Duration, def _ErrorCode) _ErrorCode { 38 lock := unix.Flock_t{ 39 Type: typ, 40 Start: start, 41 Len: len, 42 } 43 var err error 44 switch { 45 case timeout == 0: 46 err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) 47 case timeout < 0: 48 err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLKW, &lock) 49 default: 50 before := time.Now() 51 for { 52 err = unix.FcntlFlock(file.Fd(), unix.F_OFD_SETLK, &lock) 53 if errno, _ := err.(unix.Errno); errno != unix.EAGAIN { 54 break 55 } 56 if timeout < time.Since(before) { 57 break 58 } 59 osSleep(time.Duration(rand.Int63n(int64(time.Millisecond)))) 60 } 61 } 62 return osLockErrorCode(err, def) 63 } 64 65 func osReadLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { 66 return osLock(file, unix.F_RDLCK, start, len, timeout, _IOERR_RDLOCK) 67 } 68 69 func osWriteLock(file *os.File, start, len int64, timeout time.Duration) _ErrorCode { 70 return osLock(file, unix.F_WRLCK, start, len, timeout, _IOERR_LOCK) 71 }