github.com/turingchain2020/turingchain@v1.1.21/system/store/mavl/db/memmavl.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package mavl
     6  
     7  import (
     8  	"fmt"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/turingchain2020/turingchain/common"
    13  	dbm "github.com/turingchain2020/turingchain/common/db"
    14  	farm "github.com/dgryski/go-farm"
    15  	lru "github.com/hashicorp/golang-lru"
    16  )
    17  
    18  // MemTreeOpera memtree操作接口
    19  type MemTreeOpera interface {
    20  	Add(key, value interface{})
    21  	Get(key interface{}) (value interface{}, ok bool)
    22  	Delete(key interface{})
    23  	Contains(key interface{}) bool
    24  	Len() int
    25  }
    26  
    27  // TreeMap map形式memtree
    28  type TreeMap struct {
    29  	mpCache map[interface{}]interface{}
    30  	lock    sync.RWMutex
    31  }
    32  
    33  // NewTreeMap new mem tree
    34  func NewTreeMap(size int) *TreeMap {
    35  	mp := &TreeMap{}
    36  	mp.mpCache = make(map[interface{}]interface{}, size)
    37  	return mp
    38  }
    39  
    40  // Add 添加元素
    41  func (tm *TreeMap) Add(key, value interface{}) {
    42  	tm.lock.Lock()
    43  	defer tm.lock.Unlock()
    44  	if _, ok := tm.mpCache[key]; ok {
    45  		delete(tm.mpCache, key)
    46  		return
    47  	}
    48  	tm.mpCache[key] = value
    49  }
    50  
    51  // Get 获取元素
    52  func (tm *TreeMap) Get(key interface{}) (value interface{}, ok bool) {
    53  	tm.lock.Lock()
    54  	defer tm.lock.Unlock()
    55  	if value, ok := tm.mpCache[key]; ok {
    56  		return value, ok
    57  	}
    58  	return nil, false
    59  }
    60  
    61  // Delete 删除元素
    62  func (tm *TreeMap) Delete(key interface{}) {
    63  	tm.lock.Lock()
    64  	defer tm.lock.Unlock()
    65  	if _, ok := tm.mpCache[key]; ok {
    66  		delete(tm.mpCache, key)
    67  	}
    68  }
    69  
    70  // Contains 查看是否包含元素
    71  func (tm *TreeMap) Contains(key interface{}) bool {
    72  	tm.lock.Lock()
    73  	defer tm.lock.Unlock()
    74  	if _, ok := tm.mpCache[key]; ok {
    75  		return true
    76  	}
    77  	return false
    78  }
    79  
    80  // Len 元素长度
    81  func (tm *TreeMap) Len() int {
    82  	tm.lock.Lock()
    83  	defer tm.lock.Unlock()
    84  	return len(tm.mpCache)
    85  }
    86  
    87  // TreeARC lru的mem tree
    88  type TreeARC struct {
    89  	arcCache *lru.ARCCache
    90  }
    91  
    92  // NewTreeARC new lru mem tree
    93  func NewTreeARC(size int) *TreeARC {
    94  	ma := &TreeARC{}
    95  	var err error
    96  	ma.arcCache, err = lru.NewARC(size)
    97  	if err != nil {
    98  		panic("New tree lru fail")
    99  	}
   100  	return ma
   101  }
   102  
   103  // Add 添加元素
   104  func (ta *TreeARC) Add(key, value interface{}) {
   105  	if ta.arcCache.Contains(key) {
   106  		ta.arcCache.Remove(key)
   107  		return
   108  	}
   109  	ta.arcCache.Add(key, value)
   110  }
   111  
   112  // Get 获取元素
   113  func (ta *TreeARC) Get(key interface{}) (value interface{}, ok bool) {
   114  	return ta.arcCache.Get(key)
   115  }
   116  
   117  // Delete 删除元素
   118  func (ta *TreeARC) Delete(key interface{}) {
   119  	ta.arcCache.Remove(key)
   120  }
   121  
   122  // Contains 查看是否包含元素
   123  func (ta *TreeARC) Contains(key interface{}) bool {
   124  	return ta.arcCache.Contains(key)
   125  }
   126  
   127  // Len 元素长度
   128  func (ta *TreeARC) Len() int {
   129  	return ta.arcCache.Len()
   130  }
   131  
   132  // LoadTree2MemDb 从数据库中载入mem tree
   133  func LoadTree2MemDb(db dbm.DB, hash []byte, mp map[uint64]struct{}) {
   134  	nDb := newNodeDB(db, true)
   135  	node, err := nDb.getLightNode(nil, hash)
   136  	if err != nil {
   137  		fmt.Println("err", err)
   138  		return
   139  	}
   140  	pri := ""
   141  	if len(node.hash) > 32 {
   142  		pri = string(node.hash[:16])
   143  	}
   144  	treelog.Info("hash node", "hash pri", pri, "hash", common.ToHex(node.hash), "height", node.height)
   145  	start := time.Now()
   146  	leftHash := make([]byte, len(node.leftHash))
   147  	copy(leftHash, node.leftHash)
   148  	rightHash := make([]byte, len(node.rightHash))
   149  	copy(rightHash, node.rightHash)
   150  	mp[farm.Hash64(node.hash)] = struct{}{}
   151  	node.loadNodeInfo(nDb, mp)
   152  	end := time.Now()
   153  	treelog.Info("hash node", "cost time", end.Sub(start), "node count", len(mp))
   154  	PrintMemStats(1)
   155  }
   156  
   157  func (node *Node) loadNodeInfo(db *nodeDB, mp map[uint64]struct{}) {
   158  	if node.height == 0 {
   159  		//trMem.Add(Hash64(node.hash), &hashNode{leftHash: node.leftHash, rightHash: node.rightHash})
   160  		leftHash := make([]byte, len(node.leftHash))
   161  		copy(leftHash, node.leftHash)
   162  		rightHash := make([]byte, len(node.rightHash))
   163  		copy(rightHash, node.rightHash)
   164  		mp[farm.Hash64(node.hash)] = struct{}{}
   165  		return
   166  	}
   167  	if node.leftHash != nil {
   168  		left, err := db.getLightNode(nil, node.leftHash)
   169  		if err != nil {
   170  			return
   171  		}
   172  		//trMem.Add(Hash64(left.hash), &hashNode{leftHash: left.leftHash, rightHash: left.rightHash})
   173  		leftHash := make([]byte, len(left.leftHash))
   174  		copy(leftHash, left.leftHash)
   175  		rightHash := make([]byte, len(left.rightHash))
   176  		copy(rightHash, left.rightHash)
   177  		mp[farm.Hash64(left.hash)] = struct{}{}
   178  		left.loadNodeInfo(db, mp)
   179  	}
   180  	if node.rightHash != nil {
   181  		right, err := db.getLightNode(nil, node.rightHash)
   182  		if err != nil {
   183  			return
   184  		}
   185  		//trMem.Add(Hash64(right.hash), &hashNode{leftHash: right.leftHash, rightHash: right.rightHash})
   186  		leftHash := make([]byte, len(right.leftHash))
   187  		copy(leftHash, right.leftHash)
   188  		rightHash := make([]byte, len(right.rightHash))
   189  		copy(rightHash, right.rightHash)
   190  		mp[farm.Hash64(right.hash)] = struct{}{}
   191  		right.loadNodeInfo(db, mp)
   192  	}
   193  }
   194  
   195  func (ndb *nodeDB) getLightNode(t *Tree, hash []byte) (*Node, error) {
   196  	// Doesn't exist, load from db.
   197  	var buf []byte
   198  	buf, err := ndb.db.Get(hash)
   199  
   200  	if len(buf) == 0 || err != nil {
   201  		return nil, ErrNodeNotExist
   202  	}
   203  	node, err := MakeNode(buf, t)
   204  	if err != nil {
   205  		panic(fmt.Sprintf("Error reading IAVLNode. bytes: %X  error: %v", buf, err))
   206  	}
   207  	node.hash = hash
   208  	node.key = nil
   209  	node.value = nil
   210  	return node, nil
   211  }
   212  
   213  func copyBytes(b []byte) (copiedBytes []byte) {
   214  	if b == nil {
   215  		return nil
   216  	}
   217  	copiedBytes = make([]byte, len(b))
   218  	copy(copiedBytes, b)
   219  	return copiedBytes
   220  }