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 }