github.com/turingchain2020/turingchain@v1.1.21/executor/localdb.go (about)

     1  package executor
     2  
     3  import (
     4  	"github.com/turingchain2020/turingchain/client"
     5  	"github.com/turingchain2020/turingchain/common/db"
     6  	"github.com/turingchain2020/turingchain/queue"
     7  	"github.com/turingchain2020/turingchain/types"
     8  )
     9  
    10  //LocalDB 本地数据库,类似localdb,不加入区块链的状态。
    11  //数据库只读,不能落盘
    12  //数据的get set 主要经过 cache
    13  //如果需要进行list, 那么把get set 的内容加入到 后端数据库
    14  type LocalDB struct {
    15  	cache        map[string][]byte
    16  	txcache      map[string][]byte
    17  	keys         []string
    18  	intx         bool
    19  	hasbegin     bool
    20  	kvs          []*types.KeyValue
    21  	txid         *types.Int64
    22  	client       queue.Client
    23  	api          client.QueueProtocolAPI
    24  	disableread  bool
    25  	disablewrite bool
    26  }
    27  
    28  //NewLocalDB 创建一个新的LocalDB
    29  func NewLocalDB(cli queue.Client, readOnly bool) db.KVDB {
    30  	api, err := client.New(cli, nil)
    31  	if err != nil {
    32  		panic(err)
    33  	}
    34  	txid, err := api.LocalNew(readOnly)
    35  	if err != nil {
    36  		panic(err)
    37  	}
    38  	return &LocalDB{
    39  		cache:  make(map[string][]byte),
    40  		txid:   txid,
    41  		client: cli,
    42  		api:    api,
    43  	}
    44  }
    45  
    46  //DisableRead 禁止读取LocalDB数据库
    47  func (l *LocalDB) DisableRead() {
    48  	l.disableread = true
    49  }
    50  
    51  //DisableWrite 禁止写LocalDB数据库
    52  func (l *LocalDB) DisableWrite() {
    53  	l.disablewrite = true
    54  }
    55  
    56  //EnableRead 启动读取LocalDB数据库
    57  func (l *LocalDB) EnableRead() {
    58  	l.disableread = false
    59  }
    60  
    61  //EnableWrite 启动写LocalDB数据库
    62  func (l *LocalDB) EnableWrite() {
    63  	l.disablewrite = false
    64  }
    65  
    66  func (l *LocalDB) resetTx() {
    67  	l.intx = false
    68  	l.txcache = nil
    69  	l.keys = nil
    70  	l.hasbegin = false
    71  }
    72  
    73  // StartTx reset state db keys
    74  func (l *LocalDB) StartTx() {
    75  	l.keys = nil
    76  }
    77  
    78  // GetSetKeys  get state db set keys
    79  func (l *LocalDB) GetSetKeys() (keys []string) {
    80  	return l.keys
    81  }
    82  
    83  //Begin 开始一个事务
    84  func (l *LocalDB) Begin() {
    85  	l.intx = true
    86  	l.keys = nil
    87  	l.txcache = nil
    88  	l.hasbegin = false
    89  }
    90  
    91  func (l *LocalDB) begin() {
    92  	err := l.api.LocalBegin(l.txid)
    93  	if err != nil {
    94  		panic(err)
    95  	}
    96  }
    97  
    98  //第一次save 的时候,远程做一个 begin 操作,开始事务
    99  func (l *LocalDB) save() error {
   100  	if l.kvs != nil {
   101  		if !l.hasbegin {
   102  			l.begin()
   103  			l.hasbegin = true
   104  		}
   105  		param := &types.LocalDBSet{Txid: l.txid.Data}
   106  		param.KV = l.kvs
   107  		err := l.api.LocalSet(param)
   108  		if err != nil {
   109  			return err
   110  		}
   111  		l.kvs = nil
   112  	}
   113  	return nil
   114  }
   115  
   116  //Commit 提交一个事务
   117  func (l *LocalDB) Commit() error {
   118  	for k, v := range l.txcache {
   119  		l.cache[k] = v
   120  	}
   121  	err := l.save()
   122  	if err != nil {
   123  		return err
   124  	}
   125  	if l.hasbegin {
   126  		err = l.api.LocalCommit(l.txid)
   127  	}
   128  	l.resetTx()
   129  	return err
   130  }
   131  
   132  //Close 提交一个事务
   133  func (l *LocalDB) Close() error {
   134  	l.cache = nil
   135  	l.resetTx()
   136  	err := l.api.LocalClose(l.txid)
   137  	return err
   138  }
   139  
   140  //Rollback 回滚修改
   141  func (l *LocalDB) Rollback() {
   142  	if l.hasbegin {
   143  		err := l.api.LocalRollback(l.txid)
   144  		if err != nil {
   145  			panic(err)
   146  		}
   147  	}
   148  	l.resetTx()
   149  }
   150  
   151  //Get 获取key
   152  func (l *LocalDB) Get(key []byte) ([]byte, error) {
   153  	if l.disableread {
   154  		return nil, types.ErrDisableRead
   155  	}
   156  	skey := string(key)
   157  	if l.intx && l.txcache != nil {
   158  		if value, ok := l.txcache[skey]; ok {
   159  			return value, nil
   160  		}
   161  	}
   162  	if value, ok := l.cache[skey]; ok {
   163  		if value == nil {
   164  			return nil, types.ErrNotFound
   165  		}
   166  		return value, nil
   167  	}
   168  	query := &types.LocalDBGet{Txid: l.txid.Data, Keys: [][]byte{key}}
   169  	resp, err := l.api.LocalGet(query)
   170  	if err != nil {
   171  		panic(err) //no happen for ever
   172  	}
   173  	if nil == resp.Values {
   174  		l.cache[skey] = nil
   175  		return nil, types.ErrNotFound
   176  	}
   177  	value := resp.Values[0]
   178  	if value == nil {
   179  		l.cache[skey] = nil
   180  		return nil, types.ErrNotFound
   181  	}
   182  	l.cache[skey] = value
   183  	return value, nil
   184  }
   185  
   186  //Set 获取key
   187  func (l *LocalDB) Set(key []byte, value []byte) error {
   188  	if l.disablewrite {
   189  		return types.ErrDisableWrite
   190  	}
   191  	skey := string(key)
   192  	if l.intx {
   193  		if l.txcache == nil {
   194  			l.txcache = make(map[string][]byte)
   195  		}
   196  		l.keys = append(l.keys, skey)
   197  		setmap(l.txcache, skey, value)
   198  	} else {
   199  		setmap(l.cache, skey, value)
   200  	}
   201  	l.kvs = append(l.kvs, &types.KeyValue{Key: key, Value: value})
   202  	return nil
   203  }
   204  
   205  // List 从数据库中查询数据列表
   206  func (l *LocalDB) List(prefix, key []byte, count, direction int32) ([][]byte, error) {
   207  	if l.disableread {
   208  		return nil, types.ErrDisableRead
   209  	}
   210  	err := l.save()
   211  	if err != nil {
   212  		return nil, err
   213  	}
   214  	query := &types.LocalDBList{Txid: l.txid.Data, Prefix: prefix, Key: key, Count: count, Direction: direction}
   215  	resp, err := l.api.LocalList(query)
   216  	if err != nil {
   217  		panic(err) //no happen for ever
   218  	}
   219  	values := resp.Values
   220  	if values == nil {
   221  		//panic(string(key))
   222  		return nil, types.ErrNotFound
   223  	}
   224  	return values, nil
   225  }
   226  
   227  // PrefixCount 从数据库中查询指定前缀的key的数量
   228  func (l *LocalDB) PrefixCount(prefix []byte) (count int64) {
   229  	panic("localdb not support PrefixCount")
   230  }