github.com/scottcagno/storage@v1.8.0/pkg/lsmtree/commitlog.go (about) 1 package lsmtree 2 3 import ( 4 "io" 5 "os" 6 "path/filepath" 7 ) 8 9 const defaultCommitLogFileName = "wal-backup.log" 10 11 type commitLog struct { 12 baseDir string 13 syncOnWrite bool 14 fd *os.File 15 offsets []int64 16 } 17 18 func openCommitLog(base string, syncOnWrite bool) (*commitLog, error) { 19 // initialize base path 20 base, err := initBasePath(base) 21 if err != nil { 22 return nil, err 23 } 24 // full file path 25 file := filepath.Join(base, defaultCommitLogFileName) 26 // open file 27 fd, err := os.OpenFile(file, os.O_CREATE, 0666) 28 if err != nil { 29 return nil, err 30 } 31 // create commit log instance 32 c := &commitLog{ 33 baseDir: base, 34 syncOnWrite: syncOnWrite, 35 fd: fd, 36 } 37 // load entry index 38 err = c.loadIndex() 39 if err != nil { 40 return nil, err 41 } 42 return c, nil 43 } 44 45 func (c *commitLog) loadIndex() error { 46 for { 47 // get offset of entry 48 offset, err := c.fd.Seek(0, io.SeekCurrent) 49 if err != nil { 50 return err 51 } 52 // read entry 53 _, err = readEntry(c.fd) 54 if err != nil { 55 if err == io.EOF || err == io.ErrUnexpectedEOF { 56 break 57 } 58 return err 59 } 60 // read entry successful, add to index 61 c.offsets = append(c.offsets, offset) 62 } 63 return nil 64 } 65 66 func (c *commitLog) get(offset int64) (*Entry, error) { 67 // read entry at provided offset 68 e, err := readEntryAt(c.fd, offset) 69 if err != nil { 70 return nil, err 71 } 72 // found it 73 return e, nil 74 } 75 76 func (c *commitLog) put(e *Entry) (int64, error) { 77 // write provided entry 78 offset, err := writeEntry(c.fd, e) 79 if err != nil { 80 return -1, err 81 } 82 // return offset 83 return offset, nil 84 } 85 86 func (c *commitLog) scan(iter func(e *Entry) bool) error { 87 for i := range c.offsets { 88 // read entry 89 e, err := readEntryAt(c.fd, c.offsets[i]) 90 if err != nil { 91 if err == io.EOF || err == io.ErrUnexpectedEOF { 92 break 93 } 94 return err 95 } 96 // check entry against iterator boolean function 97 if !iter(e) { 98 // if it returns false, then process next segEntry 99 continue 100 } 101 } 102 return nil 103 } 104 105 func (c *commitLog) cycle() error { 106 // seek to start 107 _, err := c.fd.Seek(0, io.SeekStart) 108 if err != nil { 109 return err 110 } 111 // truncate file 112 err = c.fd.Truncate(0) 113 if err != nil { 114 return err 115 } 116 return nil 117 } 118 119 func (c *commitLog) sync() error { 120 // flush data 121 err := c.fd.Sync() 122 if err != nil { 123 return err 124 } 125 return nil 126 } 127 128 func (c *commitLog) size() int64 { 129 fi, err := c.fd.Stat() 130 if err != nil { 131 return -1 132 } 133 return fi.Size() 134 } 135 136 func (c *commitLog) close() error { 137 // flush data 138 err := c.fd.Sync() 139 if err != nil { 140 return err 141 } 142 // close that thing 143 err = c.fd.Close() 144 if err != nil { 145 return err 146 } 147 return nil 148 }