github.com/flower-corp/rosedb@v1.1.2-0.20230117132829-21dc4f7b319a/ioselector/mmap.go (about)

     1  package ioselector
     2  
     3  import (
     4  	"github.com/flower-corp/rosedb/mmap"
     5  	"io"
     6  	"os"
     7  )
     8  
     9  // MMapSelector represents using memory-mapped file I/O.
    10  type MMapSelector struct {
    11  	fd     *os.File
    12  	buf    []byte // a buffer of mmap
    13  	bufLen int64
    14  }
    15  
    16  // NewMMapSelector create a new mmap selector.
    17  func NewMMapSelector(fName string, fsize int64) (IOSelector, error) {
    18  	if fsize <= 0 {
    19  		return nil, ErrInvalidFsize
    20  	}
    21  	file, err := openFile(fName, fsize)
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  	buf, err := mmap.Mmap(file, true, fsize)
    26  	if err != nil {
    27  		return nil, err
    28  	}
    29  
    30  	return &MMapSelector{fd: file, buf: buf, bufLen: int64(len(buf))}, nil
    31  }
    32  
    33  // Write copy slice b into mapped region(buf) at offset.
    34  func (lm *MMapSelector) Write(b []byte, offset int64) (int, error) {
    35  	length := int64(len(b))
    36  	if length <= 0 {
    37  		return 0, nil
    38  	}
    39  	if offset < 0 || length+offset > lm.bufLen {
    40  		return 0, io.EOF
    41  	}
    42  	return copy(lm.buf[offset:], b), nil
    43  }
    44  
    45  // Read copy data from mapped region(buf) into slice b at offset.
    46  func (lm *MMapSelector) Read(b []byte, offset int64) (int, error) {
    47  	if offset < 0 || offset >= lm.bufLen {
    48  		return 0, io.EOF
    49  	}
    50  	if offset+int64(len(b)) >= lm.bufLen {
    51  		return 0, io.EOF
    52  	}
    53  	return copy(b, lm.buf[offset:]), nil
    54  }
    55  
    56  // Sync synchronize the mapped buffer to the file's contents on disk.
    57  func (lm *MMapSelector) Sync() error {
    58  	return mmap.Msync(lm.buf)
    59  }
    60  
    61  // Close sync/unmap mapped buffer and close fd.
    62  func (lm *MMapSelector) Close() error {
    63  	if err := mmap.Msync(lm.buf); err != nil {
    64  		return err
    65  	}
    66  	if err := mmap.Munmap(lm.buf); err != nil {
    67  		return err
    68  	}
    69  	return lm.fd.Close()
    70  }
    71  
    72  // Delete delete mapped buffer and remove file on disk.
    73  func (lm *MMapSelector) Delete() error {
    74  	if err := mmap.Munmap(lm.buf); err != nil {
    75  		return err
    76  	}
    77  	lm.buf = nil
    78  
    79  	if err := lm.fd.Truncate(0); err != nil {
    80  		return err
    81  	}
    82  	if err := lm.fd.Close(); err != nil {
    83  		return err
    84  	}
    85  	return os.Remove(lm.fd.Name())
    86  }