github.com/blong14/gache@v0.0.0-20240124023949-89416fd8bbfa/internal/db/sstable/table.go (about)

     1  package sstable
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"log"
     7  	"os"
     8  	"sync"
     9  
    10  	garena "github.com/blong14/gache/internal/arena"
    11  	gfile "github.com/blong14/gache/internal/io/file"
    12  	gmap "github.com/blong14/gache/internal/map/tablemap"
    13  )
    14  
    15  type SSTable struct {
    16  	mtx   sync.Mutex
    17  	buf   *bufio.Writer
    18  	xindx *gmap.TableMap[[]byte, *indexValue]
    19  	data  gfile.Map
    20  	ptr   int
    21  }
    22  
    23  func New(f *os.File) *SSTable {
    24  	s, err := f.Stat()
    25  	if err != nil {
    26  		panic(err)
    27  	}
    28  	len_ := s.Size() + gfile.DataEndIndex
    29  	mmap, err := gfile.NewMap(
    30  		f,
    31  		gfile.Prot(gfile.Read),
    32  		gfile.Prot(gfile.Write),
    33  		gfile.Flag(gfile.Shared),
    34  		gfile.Length(int(len_)),
    35  	)
    36  	if err != nil {
    37  		panic(err)
    38  	}
    39  	_, err = mmap.Seek(gfile.DataStartIndex, 0)
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  	_, err = f.Seek(gfile.DataStartIndex, 0)
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  	return &SSTable{
    48  		xindx: gmap.New[[]byte, *indexValue](bytes.Compare),
    49  		data:  mmap,
    50  		buf:   bufio.NewWriter(f),
    51  	}
    52  }
    53  
    54  type indexValue struct {
    55  	length int64
    56  	offset int64
    57  }
    58  
    59  func (ss *SSTable) Get(k []byte) ([]byte, bool) {
    60  	raw, ok := ss.xindx.Get(k)
    61  	if !ok {
    62  		return nil, false
    63  	}
    64  	kv := byteArena.Allocate(int(raw.length))
    65  	_, err := ss.data.Peek(kv, raw.offset, raw.length)
    66  	if err != nil {
    67  		return nil, false
    68  	}
    69  	line, err := gfile.DecodeLine(string(kv))
    70  	if err != nil {
    71  		return nil, false
    72  	}
    73  	klen := line[1]
    74  	value := line[klen:]
    75  	return value, true
    76  }
    77  
    78  var byteArena = make(garena.ByteArena, 0)
    79  
    80  func (ss *SSTable) Set(k, v []byte) error {
    81  	klen := len(k)
    82  	vlen := len(v)
    83  	encoded := byteArena.Allocate(klen + vlen + 1)
    84  	encoded[0] = byte(klen)
    85  	copy(encoded[1:klen+1], k)
    86  	copy(encoded[klen+1:], v)
    87  	row, err := gfile.EncodeBlock(encoded)
    88  	if err != nil {
    89  		return err
    90  	}
    91  	ss.mtx.Lock()
    92  	offset := ss.ptr
    93  	_len, _ := ss.buf.Write(row)
    94  	_ = ss.buf.Flush()
    95  	ss.ptr += _len
    96  	ss.mtx.Unlock()
    97  	ss.xindx.Set(k, &indexValue{offset: int64(offset), length: int64(_len)})
    98  	return nil
    99  }
   100  
   101  func (ss *SSTable) Free() {
   102  	if err := ss.data.Close(); err != nil {
   103  		log.Println(err)
   104  	}
   105  }