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  }