github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/syndtr/goleveldb/leveldb/session_record.go (about) 1 // Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com> 2 // All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 7 package leveldb 8 9 import ( 10 "bufio" 11 "encoding/binary" 12 "io" 13 "strings" 14 15 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/errors" 16 "github.com/insionng/yougam/libraries/syndtr/goleveldb/leveldb/storage" 17 ) 18 19 type byteReader interface { 20 io.Reader 21 io.ByteReader 22 } 23 24 // These numbers are written to disk and should not be changed. 25 const ( 26 recComparer = 1 27 recJournalNum = 2 28 recNextFileNum = 3 29 recSeqNum = 4 30 recCompPtr = 5 31 recDelTable = 6 32 recAddTable = 7 33 // 8 was used for large value refs 34 recPrevJournalNum = 9 35 ) 36 37 type cpRecord struct { 38 level int 39 ikey internalKey 40 } 41 42 type atRecord struct { 43 level int 44 num int64 45 size int64 46 imin internalKey 47 imax internalKey 48 } 49 50 type dtRecord struct { 51 level int 52 num int64 53 } 54 55 type sessionRecord struct { 56 hasRec int 57 comparer string 58 journalNum int64 59 prevJournalNum int64 60 nextFileNum int64 61 seqNum uint64 62 compPtrs []cpRecord 63 addedTables []atRecord 64 deletedTables []dtRecord 65 66 scratch [binary.MaxVarintLen64]byte 67 err error 68 } 69 70 func (p *sessionRecord) has(rec int) bool { 71 return p.hasRec&(1<<uint(rec)) != 0 72 } 73 74 func (p *sessionRecord) setComparer(name string) { 75 p.hasRec |= 1 << recComparer 76 p.comparer = name 77 } 78 79 func (p *sessionRecord) setJournalNum(num int64) { 80 p.hasRec |= 1 << recJournalNum 81 p.journalNum = num 82 } 83 84 func (p *sessionRecord) setPrevJournalNum(num int64) { 85 p.hasRec |= 1 << recPrevJournalNum 86 p.prevJournalNum = num 87 } 88 89 func (p *sessionRecord) setNextFileNum(num int64) { 90 p.hasRec |= 1 << recNextFileNum 91 p.nextFileNum = num 92 } 93 94 func (p *sessionRecord) setSeqNum(num uint64) { 95 p.hasRec |= 1 << recSeqNum 96 p.seqNum = num 97 } 98 99 func (p *sessionRecord) addCompPtr(level int, ikey internalKey) { 100 p.hasRec |= 1 << recCompPtr 101 p.compPtrs = append(p.compPtrs, cpRecord{level, ikey}) 102 } 103 104 func (p *sessionRecord) resetCompPtrs() { 105 p.hasRec &= ^(1 << recCompPtr) 106 p.compPtrs = p.compPtrs[:0] 107 } 108 109 func (p *sessionRecord) addTable(level int, num, size int64, imin, imax internalKey) { 110 p.hasRec |= 1 << recAddTable 111 p.addedTables = append(p.addedTables, atRecord{level, num, size, imin, imax}) 112 } 113 114 func (p *sessionRecord) addTableFile(level int, t *tFile) { 115 p.addTable(level, t.fd.Num, t.size, t.imin, t.imax) 116 } 117 118 func (p *sessionRecord) resetAddedTables() { 119 p.hasRec &= ^(1 << recAddTable) 120 p.addedTables = p.addedTables[:0] 121 } 122 123 func (p *sessionRecord) delTable(level int, num int64) { 124 p.hasRec |= 1 << recDelTable 125 p.deletedTables = append(p.deletedTables, dtRecord{level, num}) 126 } 127 128 func (p *sessionRecord) resetDeletedTables() { 129 p.hasRec &= ^(1 << recDelTable) 130 p.deletedTables = p.deletedTables[:0] 131 } 132 133 func (p *sessionRecord) putUvarint(w io.Writer, x uint64) { 134 if p.err != nil { 135 return 136 } 137 n := binary.PutUvarint(p.scratch[:], x) 138 _, p.err = w.Write(p.scratch[:n]) 139 } 140 141 func (p *sessionRecord) putVarint(w io.Writer, x int64) { 142 if x < 0 { 143 panic("invalid negative value") 144 } 145 p.putUvarint(w, uint64(x)) 146 } 147 148 func (p *sessionRecord) putBytes(w io.Writer, x []byte) { 149 if p.err != nil { 150 return 151 } 152 p.putUvarint(w, uint64(len(x))) 153 if p.err != nil { 154 return 155 } 156 _, p.err = w.Write(x) 157 } 158 159 func (p *sessionRecord) encode(w io.Writer) error { 160 p.err = nil 161 if p.has(recComparer) { 162 p.putUvarint(w, recComparer) 163 p.putBytes(w, []byte(p.comparer)) 164 } 165 if p.has(recJournalNum) { 166 p.putUvarint(w, recJournalNum) 167 p.putVarint(w, p.journalNum) 168 } 169 if p.has(recNextFileNum) { 170 p.putUvarint(w, recNextFileNum) 171 p.putVarint(w, p.nextFileNum) 172 } 173 if p.has(recSeqNum) { 174 p.putUvarint(w, recSeqNum) 175 p.putUvarint(w, p.seqNum) 176 } 177 for _, r := range p.compPtrs { 178 p.putUvarint(w, recCompPtr) 179 p.putUvarint(w, uint64(r.level)) 180 p.putBytes(w, r.ikey) 181 } 182 for _, r := range p.deletedTables { 183 p.putUvarint(w, recDelTable) 184 p.putUvarint(w, uint64(r.level)) 185 p.putVarint(w, r.num) 186 } 187 for _, r := range p.addedTables { 188 p.putUvarint(w, recAddTable) 189 p.putUvarint(w, uint64(r.level)) 190 p.putVarint(w, r.num) 191 p.putVarint(w, r.size) 192 p.putBytes(w, r.imin) 193 p.putBytes(w, r.imax) 194 } 195 return p.err 196 } 197 198 func (p *sessionRecord) readUvarintMayEOF(field string, r io.ByteReader, mayEOF bool) uint64 { 199 if p.err != nil { 200 return 0 201 } 202 x, err := binary.ReadUvarint(r) 203 if err != nil { 204 if err == io.ErrUnexpectedEOF || (mayEOF == false && err == io.EOF) { 205 p.err = errors.NewErrCorrupted(storage.FileDesc{}, &ErrManifestCorrupted{field, "short read"}) 206 } else if strings.HasPrefix(err.Error(), "binary:") { 207 p.err = errors.NewErrCorrupted(storage.FileDesc{}, &ErrManifestCorrupted{field, err.Error()}) 208 } else { 209 p.err = err 210 } 211 return 0 212 } 213 return x 214 } 215 216 func (p *sessionRecord) readUvarint(field string, r io.ByteReader) uint64 { 217 return p.readUvarintMayEOF(field, r, false) 218 } 219 220 func (p *sessionRecord) readVarint(field string, r io.ByteReader) int64 { 221 x := int64(p.readUvarintMayEOF(field, r, false)) 222 if x < 0 { 223 p.err = errors.NewErrCorrupted(storage.FileDesc{}, &ErrManifestCorrupted{field, "invalid negative value"}) 224 } 225 return x 226 } 227 228 func (p *sessionRecord) readBytes(field string, r byteReader) []byte { 229 if p.err != nil { 230 return nil 231 } 232 n := p.readUvarint(field, r) 233 if p.err != nil { 234 return nil 235 } 236 x := make([]byte, n) 237 _, p.err = io.ReadFull(r, x) 238 if p.err != nil { 239 if p.err == io.ErrUnexpectedEOF { 240 p.err = errors.NewErrCorrupted(storage.FileDesc{}, &ErrManifestCorrupted{field, "short read"}) 241 } 242 return nil 243 } 244 return x 245 } 246 247 func (p *sessionRecord) readLevel(field string, r io.ByteReader) int { 248 if p.err != nil { 249 return 0 250 } 251 x := p.readUvarint(field, r) 252 if p.err != nil { 253 return 0 254 } 255 return int(x) 256 } 257 258 func (p *sessionRecord) decode(r io.Reader) error { 259 br, ok := r.(byteReader) 260 if !ok { 261 br = bufio.NewReader(r) 262 } 263 p.err = nil 264 for p.err == nil { 265 rec := p.readUvarintMayEOF("field-header", br, true) 266 if p.err != nil { 267 if p.err == io.EOF { 268 return nil 269 } 270 return p.err 271 } 272 switch rec { 273 case recComparer: 274 x := p.readBytes("comparer", br) 275 if p.err == nil { 276 p.setComparer(string(x)) 277 } 278 case recJournalNum: 279 x := p.readVarint("journal-num", br) 280 if p.err == nil { 281 p.setJournalNum(x) 282 } 283 case recPrevJournalNum: 284 x := p.readVarint("prev-journal-num", br) 285 if p.err == nil { 286 p.setPrevJournalNum(x) 287 } 288 case recNextFileNum: 289 x := p.readVarint("next-file-num", br) 290 if p.err == nil { 291 p.setNextFileNum(x) 292 } 293 case recSeqNum: 294 x := p.readUvarint("seq-num", br) 295 if p.err == nil { 296 p.setSeqNum(x) 297 } 298 case recCompPtr: 299 level := p.readLevel("comp-ptr.level", br) 300 ikey := p.readBytes("comp-ptr.ikey", br) 301 if p.err == nil { 302 p.addCompPtr(level, internalKey(ikey)) 303 } 304 case recAddTable: 305 level := p.readLevel("add-table.level", br) 306 num := p.readVarint("add-table.num", br) 307 size := p.readVarint("add-table.size", br) 308 imin := p.readBytes("add-table.imin", br) 309 imax := p.readBytes("add-table.imax", br) 310 if p.err == nil { 311 p.addTable(level, num, size, imin, imax) 312 } 313 case recDelTable: 314 level := p.readLevel("del-table.level", br) 315 num := p.readVarint("del-table.num", br) 316 if p.err == nil { 317 p.delTable(level, num) 318 } 319 } 320 } 321 322 return p.err 323 }