github.com/scottcagno/storage@v1.8.0/pkg/mmap/mmfile.go (about)

     1  package mmap
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"reflect"
     7  	"unsafe"
     8  )
     9  
    10  // OpenMappedFile prepares a file, calls the initializer if file was just created
    11  // and returns a new mapping of the prepared file into the memory.
    12  func OpenFileMapping(name string, perm os.FileMode, size uintptr, flags Flag, init func(mf *Mapping) error) (*Mapping, error) {
    13  	mf, created, err := func() (*Mapping, bool, error) {
    14  		created := false
    15  		if _, err := os.Stat(name); err != nil && os.IsNotExist(err) {
    16  			created = true
    17  		}
    18  		f, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR, perm)
    19  		if err != nil {
    20  			return nil, false, err
    21  		}
    22  		defer func() {
    23  			if f != nil {
    24  				_ = f.Close()
    25  			}
    26  		}()
    27  		onFailure := func() {
    28  			_ = f.Close()
    29  			f = nil
    30  			if created {
    31  				_ = os.Remove(name)
    32  			}
    33  		}
    34  		if err := f.Truncate(int64(size)); err != nil {
    35  			onFailure()
    36  			return nil, false, err
    37  		}
    38  		mf, err := Open(f.Fd(), 0, size, ModeReadWrite, flags)
    39  		if err != nil {
    40  			onFailure()
    41  			return nil, false, err
    42  		}
    43  		return mf, created, nil
    44  	}()
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  	if created && init != nil {
    49  		if err := init(mf); err != nil {
    50  			_ = mf.Close()
    51  			_ = os.Remove(name)
    52  			return nil, err
    53  		}
    54  	}
    55  	return mf, nil
    56  }
    57  
    58  func OpenFile(path string) (*os.File, error) {
    59  	_, err := os.Stat(path)
    60  	if os.IsNotExist(err) {
    61  		dir, file := filepath.Split(path)
    62  		err = os.MkdirAll(dir, os.ModeDir)
    63  		if err != nil {
    64  			return nil, err
    65  		}
    66  		fd, err := os.Create(dir + file)
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  		err = fd.Close()
    71  		if err != nil {
    72  			return fd, err
    73  		}
    74  	}
    75  	fd, err := os.OpenFile(path, os.O_RDWR, os.ModeSticky)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return fd, nil
    80  }
    81  
    82  // UnsafeBytesToString converts bytes to string saving allocations
    83  func UnsafeBytesToString(bytes []byte) string {
    84  	sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes))
    85  
    86  	return *(*string)(unsafe.Pointer(&reflect.StringHeader{
    87  		Data: sliceHeader.Data,
    88  		Len:  sliceHeader.Len,
    89  	}))
    90  }
    91  
    92  // UnsafeStringToBytes converts bytes to string saving allocations by re-using
    93  func UnsafeStringToBytes(s string) []byte {
    94  	stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
    95  	return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
    96  		Data: stringHeader.Data,
    97  		Len:  stringHeader.Len,
    98  		Cap:  stringHeader.Len,
    99  	}))
   100  }