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  }