github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/account_level/level_store.go (about)

     1  package account_level
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"bytes"
     7  
     8  	"fmt"
     9  
    10  	"github.com/syndtr/goleveldb/leveldb/util"
    11  	"github.com/sixexorg/magnetic-ring/common"
    12  	"github.com/sixexorg/magnetic-ring/common/serialization"
    13  	"github.com/sixexorg/magnetic-ring/common/sink"
    14  	"github.com/sixexorg/magnetic-ring/store/db"
    15  	mcom "github.com/sixexorg/magnetic-ring/store/mainchain/common"
    16  )
    17  
    18  //prototype pattern
    19  type LevelStore struct {
    20  	dbDir string
    21  	store *db.LevelDBStore
    22  	//cache *AccountCache
    23  }
    24  
    25  func NewLevelStore(dbDir string) (*LevelStore, error) {
    26  	var err error
    27  	store, err := db.NewLevelDBStore(dbDir)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	levelStore := &LevelStore{
    32  		dbDir: dbDir,
    33  		store: store,
    34  	}
    35  	return levelStore, nil
    36  }
    37  
    38  func (this *LevelStore) SaveLevels(height uint64, lvls map[common.Address]EasyLevel) error {
    39  	this.store.NewBatch()
    40  	for k, v := range lvls {
    41  		fmt.Printf("📈 📈 📈 levelUp account:%s level:%d\n", k.ToString(), v)
    42  		key := this.getKey(height, k)
    43  		sk := sink.NewZeroCopySink(nil)
    44  		sk.WriteUint8(uint8(v))
    45  		this.store.BatchPut(key, sk.Bytes())
    46  	}
    47  	err := this.store.BatchCommit()
    48  	return err
    49  }
    50  func (this *LevelStore) GetAccountLvlRange(start, end uint64, account common.Address) []common.FTreer {
    51  	s := this.getKey(start, account)
    52  	l := this.getKey(end, account)
    53  	iter := this.store.NewSeniorIterator(&util.Range{Start: s, Limit: l})
    54  	lvls := []common.FTreer{}
    55  	for iter.Next() {
    56  		key := iter.Key()
    57  		val := iter.Value()
    58  
    59  		height := binary.LittleEndian.Uint64(key[1+common.AddrLength:])
    60  		lvl := EasyLevel(val[0])
    61  		lvls = append(lvls, &HeightLevel{Height: height, Lv: lvl})
    62  	}
    63  	iter.Release()
    64  	return lvls
    65  }
    66  func (this *LevelStore) GetAccountLevel(height uint64, account common.Address) EasyLevel {
    67  	key := this.getKey(height, account)
    68  	iter := this.store.NewIterator(nil)
    69  	buff := bytes.NewBuffer(nil)
    70  	flag := true
    71  	if iter.Seek(key) {
    72  		if bytes.Compare(iter.Key(), key) == 0 {
    73  			buff.Write(iter.Key())
    74  			buff.Write(iter.Value())
    75  			flag = false
    76  		}
    77  	}
    78  	if flag && iter.Prev() {
    79  		buff.Write(iter.Key())
    80  		buff.Write(iter.Value())
    81  	}
    82  	iter.Release()
    83  	err := iter.Error()
    84  	if err != nil {
    85  		return lv0
    86  	}
    87  	if buff.Len() == 0 {
    88  		return lv0
    89  	}
    90  
    91  	buff.Next(1)
    92  	accBytes, err := serialization.ReadBytes(buff, common.AddrLength)
    93  	if err != nil {
    94  		return lv0
    95  	}
    96  	if !bytes.Equal(accBytes, account[:]) {
    97  		return lv0
    98  	}
    99  	buff.Next(8)
   100  	lvl, err := serialization.ReadUint8(buff)
   101  	if err != nil {
   102  		return lv0
   103  	}
   104  	return EasyLevel(lvl)
   105  }
   106  func (this *LevelStore) getKey(height uint64, account common.Address) []byte {
   107  	buff := make([]byte, 1+common.AddrLength+8)
   108  	buff[0] = byte(mcom.ST_ACCOUNT)
   109  	copy(buff[1:common.AddrLength+1], account[:])
   110  	binary.LittleEndian.PutUint64(buff[common.AddrLength+1:], height)
   111  	return buff
   112  }