github.com/bhojpur/cache@v0.0.4/pkg/memory/storage_unix_aix.go (about)

     1  //go:build aix
     2  // +build aix
     3  
     4  package memory
     5  
     6  // Copyright (c) 2018 Bhojpur Consulting Private Limited, India. All rights reserved.
     7  
     8  // Permission is hereby granted, free of charge, to any person obtaining a copy
     9  // of this software and associated documentation files (the "Software"), to deal
    10  // in the Software without restriction, including without limitation the rights
    11  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    12  // copies of the Software, and to permit persons to whom the Software is
    13  // furnished to do so, subject to the following conditions:
    14  
    15  // The above copyright notice and this permission notice shall be included in
    16  // all copies or substantial portions of the Software.
    17  
    18  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    19  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    20  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    21  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    22  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    23  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    24  // THE SOFTWARE.
    25  
    26  import (
    27  	"fmt"
    28  	"syscall"
    29  	"time"
    30  	"unsafe"
    31  
    32  	"golang.org/x/sys/unix"
    33  )
    34  
    35  // flock acquires an advisory lock on a file descriptor.
    36  func flock(db *DB, exclusive bool, timeout time.Duration) error {
    37  	var t time.Time
    38  	if timeout != 0 {
    39  		t = time.Now()
    40  	}
    41  	fd := db.file.Fd()
    42  	var lockType int16
    43  	if exclusive {
    44  		lockType = syscall.F_WRLCK
    45  	} else {
    46  		lockType = syscall.F_RDLCK
    47  	}
    48  	for {
    49  		// Attempt to obtain an exclusive lock.
    50  		lock := syscall.Flock_t{Type: lockType}
    51  		err := syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
    52  		if err == nil {
    53  			return nil
    54  		} else if err != syscall.EAGAIN {
    55  			return err
    56  		}
    57  
    58  		// If we timed out then return an error.
    59  		if timeout != 0 && time.Since(t) > timeout-flockRetryTimeout {
    60  			return ErrTimeout
    61  		}
    62  
    63  		// Wait for a bit and try again.
    64  		time.Sleep(flockRetryTimeout)
    65  	}
    66  }
    67  
    68  // funlock releases an advisory lock on a file descriptor.
    69  func funlock(db *DB) error {
    70  	var lock syscall.Flock_t
    71  	lock.Start = 0
    72  	lock.Len = 0
    73  	lock.Type = syscall.F_UNLCK
    74  	lock.Whence = 0
    75  	return syscall.FcntlFlock(uintptr(db.file.Fd()), syscall.F_SETLK, &lock)
    76  }
    77  
    78  // mmap memory maps a DB's data file.
    79  func mmap(db *DB, sz int) error {
    80  	// Map the data file to memory.
    81  	b, err := unix.Mmap(int(db.file.Fd()), 0, sz, syscall.PROT_READ, syscall.MAP_SHARED|db.MmapFlags)
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	// Advise the kernel that the mmap is accessed randomly.
    87  	if err := unix.Madvise(b, syscall.MADV_RANDOM); err != nil {
    88  		return fmt.Errorf("madvise: %s", err)
    89  	}
    90  
    91  	// Save the original byte slice and convert to a byte array pointer.
    92  	db.dataref = b
    93  	db.data = (*[maxMapSize]byte)(unsafe.Pointer(&b[0]))
    94  	db.datasz = sz
    95  	return nil
    96  }
    97  
    98  // munmap unmaps a DB's data file from memory.
    99  func munmap(db *DB) error {
   100  	// Ignore the unmap if we have no mapped data.
   101  	if db.dataref == nil {
   102  		return nil
   103  	}
   104  
   105  	// Unmap using the original byte slice.
   106  	err := unix.Munmap(db.dataref)
   107  	db.dataref = nil
   108  	db.data = nil
   109  	db.datasz = 0
   110  	return err
   111  }