github.com/tendermint/tmlibs@v0.9.0/db/remotedb/remotedb.go (about)

     1  package remotedb
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/tendermint/tmlibs/db"
     8  	"github.com/tendermint/tmlibs/db/remotedb/grpcdb"
     9  	protodb "github.com/tendermint/tmlibs/db/remotedb/proto"
    10  )
    11  
    12  type RemoteDB struct {
    13  	ctx context.Context
    14  	dc  protodb.DBClient
    15  }
    16  
    17  func NewRemoteDB(serverAddr string, serverKey string) (*RemoteDB, error) {
    18  	return newRemoteDB(grpcdb.NewClient(serverAddr, serverKey))
    19  }
    20  
    21  func newRemoteDB(gdc protodb.DBClient, err error) (*RemoteDB, error) {
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  	return &RemoteDB{dc: gdc, ctx: context.Background()}, nil
    26  }
    27  
    28  type Init struct {
    29  	Dir  string
    30  	Name string
    31  	Type string
    32  }
    33  
    34  func (rd *RemoteDB) InitRemote(in *Init) error {
    35  	_, err := rd.dc.Init(rd.ctx, &protodb.Init{Dir: in.Dir, Type: in.Type, Name: in.Name})
    36  	return err
    37  }
    38  
    39  var _ db.DB = (*RemoteDB)(nil)
    40  
    41  // Close is a noop currently
    42  func (rd *RemoteDB) Close() {
    43  }
    44  
    45  func (rd *RemoteDB) Delete(key []byte) {
    46  	if _, err := rd.dc.Delete(rd.ctx, &protodb.Entity{Key: key}); err != nil {
    47  		panic(fmt.Sprintf("RemoteDB.Delete: %v", err))
    48  	}
    49  }
    50  
    51  func (rd *RemoteDB) DeleteSync(key []byte) {
    52  	if _, err := rd.dc.DeleteSync(rd.ctx, &protodb.Entity{Key: key}); err != nil {
    53  		panic(fmt.Sprintf("RemoteDB.DeleteSync: %v", err))
    54  	}
    55  }
    56  
    57  func (rd *RemoteDB) Set(key, value []byte) {
    58  	if _, err := rd.dc.Set(rd.ctx, &protodb.Entity{Key: key, Value: value}); err != nil {
    59  		panic(fmt.Sprintf("RemoteDB.Set: %v", err))
    60  	}
    61  }
    62  
    63  func (rd *RemoteDB) SetSync(key, value []byte) {
    64  	if _, err := rd.dc.SetSync(rd.ctx, &protodb.Entity{Key: key, Value: value}); err != nil {
    65  		panic(fmt.Sprintf("RemoteDB.SetSync: %v", err))
    66  	}
    67  }
    68  
    69  func (rd *RemoteDB) Get(key []byte) []byte {
    70  	res, err := rd.dc.Get(rd.ctx, &protodb.Entity{Key: key})
    71  	if err != nil {
    72  		panic(fmt.Sprintf("RemoteDB.Get error: %v", err))
    73  	}
    74  	return res.Value
    75  }
    76  
    77  func (rd *RemoteDB) Has(key []byte) bool {
    78  	res, err := rd.dc.Has(rd.ctx, &protodb.Entity{Key: key})
    79  	if err != nil {
    80  		panic(fmt.Sprintf("RemoteDB.Has error: %v", err))
    81  	}
    82  	return res.Exists
    83  }
    84  
    85  func (rd *RemoteDB) ReverseIterator(start, end []byte) db.Iterator {
    86  	dic, err := rd.dc.ReverseIterator(rd.ctx, &protodb.Entity{Start: start, End: end})
    87  	if err != nil {
    88  		panic(fmt.Sprintf("RemoteDB.Iterator error: %v", err))
    89  	}
    90  	return makeReverseIterator(dic)
    91  }
    92  
    93  func (rd *RemoteDB) NewBatch() db.Batch {
    94  	return &batch{
    95  		db:  rd,
    96  		ops: nil,
    97  	}
    98  }
    99  
   100  // TODO: Implement Print when db.DB implements a method
   101  // to print to a string and not db.Print to stdout.
   102  func (rd *RemoteDB) Print() {
   103  	panic("Unimplemented")
   104  }
   105  
   106  func (rd *RemoteDB) Stats() map[string]string {
   107  	stats, err := rd.dc.Stats(rd.ctx, &protodb.Nothing{})
   108  	if err != nil {
   109  		panic(fmt.Sprintf("RemoteDB.Stats error: %v", err))
   110  	}
   111  	if stats == nil {
   112  		return nil
   113  	}
   114  	return stats.Data
   115  }
   116  
   117  func (rd *RemoteDB) Iterator(start, end []byte) db.Iterator {
   118  	dic, err := rd.dc.Iterator(rd.ctx, &protodb.Entity{Start: start, End: end})
   119  	if err != nil {
   120  		panic(fmt.Sprintf("RemoteDB.Iterator error: %v", err))
   121  	}
   122  	return makeIterator(dic)
   123  }
   124  
   125  func makeIterator(dic protodb.DB_IteratorClient) db.Iterator {
   126  	return &iterator{dic: dic}
   127  }
   128  
   129  func makeReverseIterator(dric protodb.DB_ReverseIteratorClient) db.Iterator {
   130  	return &reverseIterator{dric: dric}
   131  }
   132  
   133  type reverseIterator struct {
   134  	dric protodb.DB_ReverseIteratorClient
   135  	cur  *protodb.Iterator
   136  }
   137  
   138  var _ db.Iterator = (*iterator)(nil)
   139  
   140  func (rItr *reverseIterator) Valid() bool {
   141  	return rItr.cur != nil && rItr.cur.Valid
   142  }
   143  
   144  func (rItr *reverseIterator) Domain() (start, end []byte) {
   145  	if rItr.cur == nil || rItr.cur.Domain == nil {
   146  		return nil, nil
   147  	}
   148  	return rItr.cur.Domain.Start, rItr.cur.Domain.End
   149  }
   150  
   151  // Next advances the current reverseIterator
   152  func (rItr *reverseIterator) Next() {
   153  	var err error
   154  	rItr.cur, err = rItr.dric.Recv()
   155  	if err != nil {
   156  		panic(fmt.Sprintf("RemoteDB.ReverseIterator.Next error: %v", err))
   157  	}
   158  }
   159  
   160  func (rItr *reverseIterator) Key() []byte {
   161  	if rItr.cur == nil {
   162  		return nil
   163  	}
   164  	return rItr.cur.Key
   165  }
   166  
   167  func (rItr *reverseIterator) Value() []byte {
   168  	if rItr.cur == nil {
   169  		return nil
   170  	}
   171  	return rItr.cur.Value
   172  }
   173  
   174  func (rItr *reverseIterator) Close() {
   175  }
   176  
   177  // iterator implements the db.Iterator by retrieving
   178  // streamed iterators from the remote backend as
   179  // needed. It is NOT safe for concurrent usage,
   180  // matching the behavior of other iterators.
   181  type iterator struct {
   182  	dic protodb.DB_IteratorClient
   183  	cur *protodb.Iterator
   184  }
   185  
   186  var _ db.Iterator = (*iterator)(nil)
   187  
   188  func (itr *iterator) Valid() bool {
   189  	return itr.cur != nil && itr.cur.Valid
   190  }
   191  
   192  func (itr *iterator) Domain() (start, end []byte) {
   193  	if itr.cur == nil || itr.cur.Domain == nil {
   194  		return nil, nil
   195  	}
   196  	return itr.cur.Domain.Start, itr.cur.Domain.End
   197  }
   198  
   199  // Next advances the current iterator
   200  func (itr *iterator) Next() {
   201  	var err error
   202  	itr.cur, err = itr.dic.Recv()
   203  	if err != nil {
   204  		panic(fmt.Sprintf("RemoteDB.Iterator.Next error: %v", err))
   205  	}
   206  }
   207  
   208  func (itr *iterator) Key() []byte {
   209  	if itr.cur == nil {
   210  		return nil
   211  	}
   212  	return itr.cur.Key
   213  }
   214  
   215  func (itr *iterator) Value() []byte {
   216  	if itr.cur == nil {
   217  		return nil
   218  	}
   219  	return itr.cur.Value
   220  }
   221  
   222  func (itr *iterator) Close() {
   223  	err := itr.dic.CloseSend()
   224  	if err != nil {
   225  		panic(fmt.Sprintf("Error closing iterator: %v", err))
   226  	}
   227  }
   228  
   229  type batch struct {
   230  	db  *RemoteDB
   231  	ops []*protodb.Operation
   232  }
   233  
   234  var _ db.Batch = (*batch)(nil)
   235  
   236  func (bat *batch) Set(key, value []byte) {
   237  	op := &protodb.Operation{
   238  		Entity: &protodb.Entity{Key: key, Value: value},
   239  		Type:   protodb.Operation_SET,
   240  	}
   241  	bat.ops = append(bat.ops, op)
   242  }
   243  
   244  func (bat *batch) Delete(key []byte) {
   245  	op := &protodb.Operation{
   246  		Entity: &protodb.Entity{Key: key},
   247  		Type:   protodb.Operation_DELETE,
   248  	}
   249  	bat.ops = append(bat.ops, op)
   250  }
   251  
   252  func (bat *batch) Write() {
   253  	if _, err := bat.db.dc.BatchWrite(bat.db.ctx, &protodb.Batch{Ops: bat.ops}); err != nil {
   254  		panic(fmt.Sprintf("RemoteDB.BatchWrite: %v", err))
   255  	}
   256  }
   257  
   258  func (bat *batch) WriteSync() {
   259  	if _, err := bat.db.dc.BatchWriteSync(bat.db.ctx, &protodb.Batch{Ops: bat.ops}); err != nil {
   260  		panic(fmt.Sprintf("RemoteDB.BatchWriteSync: %v", err))
   261  	}
   262  }