dataStore_badger.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // +build BADGER_DB
  2. /*
  3. * Copyright (c) 2018, Psiphon Inc.
  4. * All rights reserved.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. package psiphon
  21. import (
  22. "os"
  23. "path/filepath"
  24. "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
  25. "github.com/dgraph-io/badger"
  26. "github.com/dgraph-io/badger/options"
  27. )
  28. const (
  29. DATA_STORE_DIRECTORY = "psiphon.badgerdb"
  30. )
  31. type datastoreDB struct {
  32. badgerDB *badger.DB
  33. }
  34. type datastoreTx struct {
  35. badgerTx *badger.Txn
  36. }
  37. type datastoreBucket struct {
  38. name []byte
  39. tx *datastoreTx
  40. }
  41. type datastoreCursor struct {
  42. badgerIterator *badger.Iterator
  43. prefix []byte
  44. }
  45. func datastoreOpenDB(rootDataDirectory string) (*datastoreDB, error) {
  46. dbDirectory := filepath.Join(rootDataDirectory, "psiphon.badgerdb")
  47. err := os.MkdirAll(dbDirectory, 0700)
  48. if err != nil {
  49. return nil, errors.Trace(err)
  50. }
  51. opts := badger.DefaultOptions
  52. opts.Dir = dbDirectory
  53. opts.ValueDir = dbDirectory
  54. opts.TableLoadingMode = options.FileIO
  55. opts.ValueLogLoadingMode = options.FileIO
  56. opts.MaxTableSize = 1 << 16
  57. opts.ValueLogFileSize = 1 << 20
  58. opts.NumMemtables = 1
  59. opts.NumLevelZeroTables = 1
  60. opts.NumLevelZeroTablesStall = 2
  61. opts.NumCompactors = 1
  62. db, err := badger.Open(opts)
  63. if err != nil {
  64. return nil, errors.Trace(err)
  65. }
  66. for {
  67. if db.RunValueLogGC(0.5) != nil {
  68. break
  69. }
  70. }
  71. return &datastoreDB{badgerDB: db}, nil
  72. }
  73. func (db *datastoreDB) close() error {
  74. return db.badgerDB.Close()
  75. }
  76. func (db *datastoreDB) view(fn func(tx *datastoreTx) error) error {
  77. return db.badgerDB.View(
  78. func(tx *badger.Txn) error {
  79. err := fn(&datastoreTx{badgerTx: tx})
  80. if err != nil {
  81. return errors.Trace(err)
  82. }
  83. return nil
  84. })
  85. }
  86. func (db *datastoreDB) update(fn func(tx *datastoreTx) error) error {
  87. return db.badgerDB.Update(
  88. func(tx *badger.Txn) error {
  89. err := fn(&datastoreTx{badgerTx: tx})
  90. if err != nil {
  91. return errors.Trace(err)
  92. }
  93. return nil
  94. })
  95. }
  96. func (tx *datastoreTx) bucket(name []byte) *datastoreBucket {
  97. return &datastoreBucket{
  98. name: name,
  99. tx: tx,
  100. }
  101. }
  102. func (tx *datastoreTx) clearBucket(name []byte) error {
  103. b := tx.bucket(name)
  104. c := b.cursor()
  105. for key := c.firstKey(); key != nil; key = c.nextKey() {
  106. err := tx.badgerTx.Delete(key)
  107. if err != nil {
  108. return errors.Trace(err)
  109. }
  110. }
  111. return nil
  112. }
  113. func (b *datastoreBucket) get(key []byte) []byte {
  114. keyWithPrefix := append(b.name, key...)
  115. item, err := b.tx.badgerTx.Get(keyWithPrefix)
  116. if err != nil {
  117. if err != badger.ErrKeyNotFound {
  118. // The original datastore interface does not return an error from
  119. // Get, so emit notice.
  120. NoticeWarning("get failed: %s: %s",
  121. string(keyWithPrefix), errors.Trace(err))
  122. }
  123. return nil
  124. }
  125. value, err := item.Value()
  126. if err != nil {
  127. NoticeWarning("get failed: %s: %s",
  128. string(keyWithPrefix), errors.Trace(err))
  129. return nil
  130. }
  131. return value
  132. }
  133. func (b *datastoreBucket) put(key, value []byte) error {
  134. keyWithPrefix := append(b.name, key...)
  135. err := b.tx.badgerTx.Set(keyWithPrefix, value)
  136. if err != nil {
  137. return errors.Trace(err)
  138. }
  139. return nil
  140. }
  141. func (b *datastoreBucket) delete(key []byte) error {
  142. keyWithPrefix := append(b.name, key...)
  143. err := b.tx.badgerTx.Delete(keyWithPrefix)
  144. if err != nil {
  145. return errors.Trace(err)
  146. }
  147. return nil
  148. }
  149. func (b *datastoreBucket) cursor() *datastoreCursor {
  150. opts := badger.DefaultIteratorOptions
  151. opts.PrefetchValues = false
  152. iterator := b.tx.badgerTx.NewIterator(opts)
  153. return &datastoreCursor{badgerIterator: iterator, prefix: b.name}
  154. }
  155. func (c *datastoreCursor) firstKey() []byte {
  156. c.badgerIterator.Seek(c.prefix)
  157. return c.currentKey()
  158. }
  159. func (c *datastoreCursor) currentKey() []byte {
  160. if !c.badgerIterator.ValidForPrefix(c.prefix) {
  161. return nil
  162. }
  163. item := c.badgerIterator.Item()
  164. return item.Key()[len(c.prefix):]
  165. }
  166. func (c *datastoreCursor) nextKey() []byte {
  167. c.badgerIterator.Next()
  168. return c.currentKey()
  169. }
  170. func (c *datastoreCursor) first() ([]byte, []byte) {
  171. c.badgerIterator.Seek(c.prefix)
  172. return c.current()
  173. }
  174. func (c *datastoreCursor) current() ([]byte, []byte) {
  175. if !c.badgerIterator.ValidForPrefix(c.prefix) {
  176. return nil, nil
  177. }
  178. item := c.badgerIterator.Item()
  179. value, err := item.Value()
  180. if err != nil {
  181. return nil, nil
  182. }
  183. return item.Key()[len(c.prefix):], value
  184. }
  185. func (c *datastoreCursor) next() ([]byte, []byte) {
  186. c.badgerIterator.Next()
  187. return c.current()
  188. }
  189. func (c *datastoreCursor) close() {
  190. c.badgerIterator.Close()
  191. }