OSDN Git Service

fix lru bug (#469)
[bytom/vapor.git] / database / store.go
index ea947a1..1970543 100644 (file)
@@ -9,13 +9,13 @@ import (
        "github.com/golang/protobuf/proto"
        log "github.com/sirupsen/logrus"
 
-       dbm "github.com/vapor/database/leveldb"
-       "github.com/vapor/database/storage"
-       "github.com/vapor/errors"
-       "github.com/vapor/protocol"
-       "github.com/vapor/protocol/bc"
-       "github.com/vapor/protocol/bc/types"
-       "github.com/vapor/protocol/state"
+       dbm "github.com/bytom/vapor/database/leveldb"
+       "github.com/bytom/vapor/database/storage"
+       "github.com/bytom/vapor/errors"
+       "github.com/bytom/vapor/protocol"
+       "github.com/bytom/vapor/protocol/bc"
+       "github.com/bytom/vapor/protocol/bc/types"
+       "github.com/bytom/vapor/protocol/state"
 )
 
 const (
@@ -32,21 +32,11 @@ const (
        blockTransactons
        mainChainIndex
        txStatus
-       voteResult
-)
-
-var (
-       blockStoreKey          = []byte{blockStore}
-       blockHashesPrefix      = []byte{blockHashes, colon}
-       blockHeaderPrefix      = []byte{blockHeader, colon}
-       blockTransactonsPrefix = []byte{blockTransactons, colon}
-       mainChainIndexPrefix   = []byte{mainChainIndex, colon}
-       txStatusPrefix         = []byte{txStatus, colon}
-       voteResultPrefix       = []byte{voteResult, colon}
+       consensusResult
 )
 
 func loadBlockStoreStateJSON(db dbm.DB) *protocol.BlockStoreState {
-       bytes := db.Get(blockStoreKey)
+       bytes := db.Get([]byte{blockStore})
        if bytes == nil {
                return nil
        }
@@ -63,37 +53,37 @@ func loadBlockStoreStateJSON(db dbm.DB) *protocol.BlockStoreState {
 // methods for querying current data.
 type Store struct {
        db    dbm.DB
-       cache cache
+       cache *cache
 }
 
 func calcMainChainIndexPrefix(height uint64) []byte {
        buf := [8]byte{}
        binary.BigEndian.PutUint64(buf[:], height)
-       return append(mainChainIndexPrefix, buf[:]...)
+       return append([]byte{mainChainIndex, colon}, buf[:]...)
 }
 
 func calcBlockHashesPrefix(height uint64) []byte {
        buf := [8]byte{}
        binary.BigEndian.PutUint64(buf[:], height)
-       return append(blockHashesPrefix, buf[:]...)
+       return append([]byte{blockHashes, colon}, buf[:]...)
 }
 
 func calcBlockHeaderKey(hash *bc.Hash) []byte {
-       return append(blockHeaderPrefix, hash.Bytes()...)
+       return append([]byte{blockHeader, colon}, hash.Bytes()...)
 }
 
 func calcBlockTransactionsKey(hash *bc.Hash) []byte {
-       return append(blockTransactonsPrefix, hash.Bytes()...)
+       return append([]byte{blockTransactons, colon}, hash.Bytes()...)
 }
 
 func calcTxStatusKey(hash *bc.Hash) []byte {
-       return append(txStatusPrefix, hash.Bytes()...)
+       return append([]byte{txStatus, colon}, hash.Bytes()...)
 }
 
-func calcVoteResultKey(seq uint64) []byte {
+func calcConsensusResultKey(seq uint64) []byte {
        buf := [8]byte{}
        binary.BigEndian.PutUint64(buf[:], seq)
-       return append(voteResultPrefix, buf[:]...)
+       return append([]byte{consensusResult, colon}, buf[:]...)
 }
 
 // GetBlockHeader return the block header by given hash
@@ -152,18 +142,18 @@ func GetMainChainHash(db dbm.DB, height uint64) (*bc.Hash, error) {
        return hash, nil
 }
 
-// GetVoteResult return the vote result by given sequence
-func GetVoteResult(db dbm.DB, seq uint64) (*state.VoteResult, error) {
-       data := db.Get(calcVoteResultKey(seq))
+// GetConsensusResult return the vote result by given sequence
+func GetConsensusResult(db dbm.DB, seq uint64) (*state.ConsensusResult, error) {
+       data := db.Get(calcConsensusResultKey(seq))
        if data == nil {
-               return nil, protocol.ErrNotFoundVoteResult
+               return nil, protocol.ErrNotFoundConsensusResult
        }
 
-       voteResult := new(state.VoteResult)
-       if err := json.Unmarshal(data, voteResult); err != nil {
+       consensusResult := new(state.ConsensusResult)
+       if err := json.Unmarshal(data, consensusResult); err != nil {
                return nil, errors.Wrap(err, "unmarshaling vote result")
        }
-       return voteResult, nil
+       return consensusResult, nil
 }
 
 // NewStore creates and returns a new Store object.
@@ -183,11 +173,11 @@ func NewStore(db dbm.DB) *Store {
                return GetMainChainHash(db, height)
        }
 
-       fillVoteResultFn := func(seq uint64) (*state.VoteResult, error) {
-               return GetVoteResult(db, seq)
+       fillConsensusResultFn := func(seq uint64) (*state.ConsensusResult, error) {
+               return GetConsensusResult(db, seq)
        }
 
-       cache := newCache(fillBlockHeaderFn, fillBlockTxsFn, fillBlockHashesFn, fillMainChainHashFn, fillVoteResultFn)
+       cache := newCache(fillBlockHeaderFn, fillBlockTxsFn, fillBlockHashesFn, fillMainChainHashFn, fillConsensusResultFn)
        return &Store{
                db:    db,
                cache: cache,
@@ -267,9 +257,9 @@ func (s *Store) GetUtxo(hash *bc.Hash) (*storage.UtxoEntry, error) {
        return getUtxo(s.db, hash)
 }
 
-// GetVoteResult retrive the voting result in specified vote sequence
-func (s *Store) GetVoteResult(seq uint64) (*state.VoteResult, error) {
-       return s.cache.lookupVoteResult(seq)
+// GetConsensusResult retrive the voting result in specified vote sequence
+func (s *Store) GetConsensusResult(seq uint64) (*state.ConsensusResult, error) {
+       return s.cache.lookupConsensusResult(seq)
 }
 
 // SaveBlock persists a new block in the protocol.
@@ -334,20 +324,25 @@ func (s *Store) SaveBlockHeader(blockHeader *types.BlockHeader) error {
 }
 
 // SaveChainStatus save the core's newest status && delete old status
-func (s *Store) SaveChainStatus(blockHeader, irrBlockHeader *types.BlockHeader, mainBlockHeaders []*types.BlockHeader, view *state.UtxoViewpoint, voteResults []*state.VoteResult) error {
+func (s *Store) SaveChainStatus(blockHeader, irrBlockHeader *types.BlockHeader, mainBlockHeaders []*types.BlockHeader, view *state.UtxoViewpoint, consensusResults []*state.ConsensusResult) error {
+       currentStatus := loadBlockStoreStateJSON(s.db)
        batch := s.db.NewBatch()
        if err := saveUtxoView(batch, view); err != nil {
                return err
        }
 
-       for _, vote := range voteResults {
-               bytes, err := json.Marshal(vote)
+       var clearCacheFuncs []func()
+       for _, consensusResult := range consensusResults {
+               result := consensusResult
+               bytes, err := json.Marshal(result)
                if err != nil {
                        return err
                }
 
-               batch.Set(calcVoteResultKey(vote.Seq), bytes)
-               s.cache.removeVoteResult(vote)
+               batch.Set(calcConsensusResultKey(result.Seq), bytes)
+               clearCacheFuncs = append(clearCacheFuncs, func() {
+                       s.cache.removeConsensusResult(result)
+               })
        }
 
        blockHash := blockHeader.Hash()
@@ -361,10 +356,11 @@ func (s *Store) SaveChainStatus(blockHeader, irrBlockHeader *types.BlockHeader,
        if err != nil {
                return err
        }
-       batch.Set(blockStoreKey, bytes)
+       batch.Set([]byte{blockStore}, bytes)
 
        // save main chain blockHeaders
-       for _, bh := range mainBlockHeaders {
+       for _, blockHeader := range mainBlockHeaders {
+               bh := blockHeader
                blockHash := bh.Hash()
                binaryBlockHash, err := blockHash.MarshalText()
                if err != nil {
@@ -372,8 +368,24 @@ func (s *Store) SaveChainStatus(blockHeader, irrBlockHeader *types.BlockHeader,
                }
 
                batch.Set(calcMainChainIndexPrefix(bh.Height), binaryBlockHash)
-               s.cache.removeMainChainHash(bh.Height)
+               clearCacheFuncs = append(clearCacheFuncs, func() {
+                       s.cache.removeMainChainHash(bh.Height)
+               })
+       }
+
+       if currentStatus != nil {
+               for i := blockHeader.Height + 1; i <= currentStatus.Height; i++ {
+                       index := i
+                       batch.Delete(calcMainChainIndexPrefix(index))
+                       clearCacheFuncs = append(clearCacheFuncs, func() {
+                               s.cache.removeMainChainHash(index)
+                       })
+               }
        }
        batch.Write()
+
+       for _, clearCacheFunc := range clearCacheFuncs {
+               clearCacheFunc()
+       }
        return nil
 }