...

Source file src/go.etcd.io/bbolt/bolt_unix_solaris.go

Documentation: go.etcd.io/bbolt

     1  package bbolt
     2  
     3  import (
     4  	"fmt"
     5  	"syscall"
     6  	"time"
     7  	"unsafe"
     8  
     9  	"golang.org/x/sys/unix"
    10  )
    11  
    12  // flock acquires an advisory lock on a file descriptor.
    13  func flock(db *DB, exclusive bool, timeout time.Duration) error {
    14  	var t time.Time
    15  	if timeout != 0 {
    16  		t = time.Now()
    17  	}
    18  	fd := db.file.Fd()
    19  	var lockType int16
    20  	if exclusive {
    21  		lockType = syscall.F_WRLCK
    22  	} else {
    23  		lockType = syscall.F_RDLCK
    24  	}
    25  	for {
    26  		// Attempt to obtain an exclusive lock.
    27  		lock := syscall.Flock_t{Type: lockType}
    28  		err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
    29  		if err == nil {
    30  			return nil
    31  		} else if err != syscall.EAGAIN {
    32  			return err
    33  		}
    34  
    35  		// If we timed out then return an error.
    36  		if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
    37  			return ErrTimeout
    38  		}
    39  
    40  		// Wait for a bit and try again.
    41  		time.Sleep(flockRetryTimeout)
    42  	}
    43  }
    44  
    45  // funlock releases an advisory lock on a file descriptor.
    46  func funlock(db *DB) error {
    47  	var lock syscall.Flock_t
    48  	lock.Start = 0
    49  	lock.Len = 0
    50  	lock.Type = syscall.F_UNLCK
    51  	lock.Whence = 0
    52  	return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock)
    53  }
    54  
    55  // mmap memory maps a DB's data file.
    56  func mmap(db *DB, sz int) error {
    57  	// Map the data file to memory.
    58  	b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	// Advise the kernel that the mmap is accessed randomly.
    64  	if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil {
    65  		return fmt.Errorf("madvise: %s", err)
    66  	}
    67  
    68  	// Save the original byte slice and convert to a byte array pointer.
    69  	db.dataref = b
    70  	db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
    71  	db.datasz = sz
    72  	return nil
    73  }
    74  
    75  // munmap unmaps a DB's data file from memory.
    76  func munmap(db *DB) error {
    77  	// Ignore the unmap if we have no mapped data.
    78  	if db.dataref == nil {
    79  		return nil
    80  	}
    81  
    82  	// Unmap using the original byte slice.
    83  	err := unix.Munmap(db.dataref)
    84  	db.dataref = nil
    85  	db.data = nil
    86  	db.datasz = 0
    87  	return err
    88  }
    89  

View as plain text