dataStore_badger.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. // +build PSIPHON_USE_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(
  46. rootDataDirectory string, _ bool) (*datastoreDB, error) {
  47. dbDirectory := filepath.Join(rootDataDirectory, "psiphon.badgerdb")
  48. err := os.MkdirAll(dbDirectory, 0700)
  49. if err != nil {
  50. return nil, errors.Trace(err)
  51. }
  52. opts := badger.DefaultOptions
  53. opts.Dir = dbDirectory
  54. opts.ValueDir = dbDirectory
  55. opts.TableLoadingMode = options.FileIO
  56. opts.ValueLogLoadingMode = options.FileIO
  57. opts.MaxTableSize = 1 << 16
  58. opts.ValueLogFileSize = 1 << 20
  59. opts.NumMemtables = 1
  60. opts.NumLevelZeroTables = 1
  61. opts.NumLevelZeroTablesStall = 2
  62. opts.NumCompactors = 1
  63. db, err := badger.Open(opts)
  64. if err != nil {
  65. return nil, errors.Trace(err)
  66. }
  67. for {
  68. if db.RunValueLogGC(0.5) != nil {
  69. break
  70. }
  71. }
  72. return &datastoreDB{badgerDB: db}, nil
  73. }
  74. func (db *datastoreDB) close() error {
  75. return db.badgerDB.Close()
  76. }
  77. func (db *datastoreDB) view(fn func(tx *datastoreTx) error) error {
  78. return db.badgerDB.View(
  79. func(tx *badger.Txn) error {
  80. err := fn(&datastoreTx{badgerTx: tx})
  81. if err != nil {
  82. return errors.Trace(err)
  83. }
  84. return nil
  85. })
  86. }
  87. func (db *datastoreDB) update(fn func(tx *datastoreTx) error) error {
  88. return db.badgerDB.Update(
  89. func(tx *badger.Txn) error {
  90. err := fn(&datastoreTx{badgerTx: tx})
  91. if err != nil {
  92. return errors.Trace(err)
  93. }
  94. return nil
  95. })
  96. }
  97. func (tx *datastoreTx) bucket(name []byte) *datastoreBucket {
  98. return &datastoreBucket{
  99. name: name,
  100. tx: tx,
  101. }
  102. }
  103. func (tx *datastoreTx) clearBucket(name []byte) error {
  104. b := tx.bucket(name)
  105. c := b.cursor()
  106. for key := c.firstKey(); key != nil; key = c.nextKey() {
  107. err := tx.badgerTx.Delete(key)
  108. if err != nil {
  109. return errors.Trace(err)
  110. }
  111. }
  112. return nil
  113. }
  114. func (b *datastoreBucket) get(key []byte) []byte {
  115. keyWithPrefix := append(b.name, key...)
  116. item, err := b.tx.badgerTx.Get(keyWithPrefix)
  117. if err != nil {
  118. if err != badger.ErrKeyNotFound {
  119. // The original datastore interface does not return an error from
  120. // Get, so emit notice.
  121. NoticeWarning("get failed: %s: %s",
  122. string(keyWithPrefix), errors.Trace(err))
  123. }
  124. return nil
  125. }
  126. value, err := item.Value()
  127. if err != nil {
  128. NoticeWarning("get failed: %s: %s",
  129. string(keyWithPrefix), errors.Trace(err))
  130. return nil
  131. }
  132. return value
  133. }
  134. func (b *datastoreBucket) put(key, value []byte) error {
  135. keyWithPrefix := append(b.name, key...)
  136. err := b.tx.badgerTx.Set(keyWithPrefix, value)
  137. if err != nil {
  138. return errors.Trace(err)
  139. }
  140. return nil
  141. }
  142. func (b *datastoreBucket) delete(key []byte) error {
  143. keyWithPrefix := append(b.name, key...)
  144. err := b.tx.badgerTx.Delete(keyWithPrefix)
  145. if err != nil {
  146. return errors.Trace(err)
  147. }
  148. return nil
  149. }
  150. func (b *datastoreBucket) cursor() *datastoreCursor {
  151. opts := badger.DefaultIteratorOptions
  152. opts.PrefetchValues = false
  153. iterator := b.tx.badgerTx.NewIterator(opts)
  154. return &datastoreCursor{badgerIterator: iterator, prefix: b.name}
  155. }
  156. func (c *datastoreCursor) firstKey() []byte {
  157. c.badgerIterator.Seek(c.prefix)
  158. return c.currentKey()
  159. }
  160. func (c *datastoreCursor) currentKey() []byte {
  161. if !c.badgerIterator.ValidForPrefix(c.prefix) {
  162. return nil
  163. }
  164. item := c.badgerIterator.Item()
  165. return item.Key()[len(c.prefix):]
  166. }
  167. func (c *datastoreCursor) nextKey() []byte {
  168. c.badgerIterator.Next()
  169. return c.currentKey()
  170. }
  171. func (c *datastoreCursor) first() ([]byte, []byte) {
  172. c.badgerIterator.Seek(c.prefix)
  173. return c.current()
  174. }
  175. func (c *datastoreCursor) current() ([]byte, []byte) {
  176. if !c.badgerIterator.ValidForPrefix(c.prefix) {
  177. return nil, nil
  178. }
  179. item := c.badgerIterator.Item()
  180. value, err := item.Value()
  181. if err != nil {
  182. return nil, nil
  183. }
  184. return item.Key()[len(c.prefix):], value
  185. }
  186. func (c *datastoreCursor) next() ([]byte, []byte) {
  187. c.badgerIterator.Next()
  188. return c.current()
  189. }
  190. func (c *datastoreCursor) close() {
  191. c.badgerIterator.Close()
  192. }