OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / syndtr / goleveldb / leveldb / session_record.go
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/syndtr/goleveldb/leveldb/errors"
16         "github.com/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 }