You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
5.9 KiB

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