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.

334 lines
6.7 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
7 years ago
9 years ago
9 years ago
9 years ago
7 years ago
7 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package db
  2. import (
  3. "bytes"
  4. "fmt"
  5. "path/filepath"
  6. "github.com/syndtr/goleveldb/leveldb"
  7. "github.com/syndtr/goleveldb/leveldb/errors"
  8. "github.com/syndtr/goleveldb/leveldb/iterator"
  9. "github.com/syndtr/goleveldb/leveldb/opt"
  10. )
  11. func init() {
  12. dbCreator := func(name string, dir string) (DB, error) {
  13. return NewGoLevelDB(name, dir)
  14. }
  15. registerDBCreator(LevelDBBackend, dbCreator, false)
  16. registerDBCreator(GoLevelDBBackend, dbCreator, false)
  17. }
  18. var _ DB = (*GoLevelDB)(nil)
  19. type GoLevelDB struct {
  20. db *leveldb.DB
  21. }
  22. func NewGoLevelDB(name string, dir string) (*GoLevelDB, error) {
  23. return NewGoLevelDBWithOpts(name, dir, nil)
  24. }
  25. func NewGoLevelDBWithOpts(name string, dir string, o *opt.Options) (*GoLevelDB, error) {
  26. dbPath := filepath.Join(dir, name+".db")
  27. db, err := leveldb.OpenFile(dbPath, o)
  28. if err != nil {
  29. return nil, err
  30. }
  31. database := &GoLevelDB{
  32. db: db,
  33. }
  34. return database, nil
  35. }
  36. // Implements DB.
  37. func (db *GoLevelDB) Get(key []byte) []byte {
  38. key = nonNilBytes(key)
  39. res, err := db.db.Get(key, nil)
  40. if err != nil {
  41. if err == errors.ErrNotFound {
  42. return nil
  43. }
  44. panic(err)
  45. }
  46. return res
  47. }
  48. // Implements DB.
  49. func (db *GoLevelDB) Has(key []byte) bool {
  50. return db.Get(key) != nil
  51. }
  52. // Implements DB.
  53. func (db *GoLevelDB) Set(key []byte, value []byte) {
  54. key = nonNilBytes(key)
  55. value = nonNilBytes(value)
  56. err := db.db.Put(key, value, nil)
  57. if err != nil {
  58. panic(err)
  59. }
  60. }
  61. // Implements DB.
  62. func (db *GoLevelDB) SetSync(key []byte, value []byte) {
  63. key = nonNilBytes(key)
  64. value = nonNilBytes(value)
  65. err := db.db.Put(key, value, &opt.WriteOptions{Sync: true})
  66. if err != nil {
  67. panic(err)
  68. }
  69. }
  70. // Implements DB.
  71. func (db *GoLevelDB) Delete(key []byte) {
  72. key = nonNilBytes(key)
  73. err := db.db.Delete(key, nil)
  74. if err != nil {
  75. panic(err)
  76. }
  77. }
  78. // Implements DB.
  79. func (db *GoLevelDB) DeleteSync(key []byte) {
  80. key = nonNilBytes(key)
  81. err := db.db.Delete(key, &opt.WriteOptions{Sync: true})
  82. if err != nil {
  83. panic(err)
  84. }
  85. }
  86. func (db *GoLevelDB) DB() *leveldb.DB {
  87. return db.db
  88. }
  89. // Implements DB.
  90. func (db *GoLevelDB) Close() {
  91. db.db.Close()
  92. }
  93. // Implements DB.
  94. func (db *GoLevelDB) Print() {
  95. str, _ := db.db.GetProperty("leveldb.stats")
  96. fmt.Printf("%v\n", str)
  97. itr := db.db.NewIterator(nil, nil)
  98. for itr.Next() {
  99. key := itr.Key()
  100. value := itr.Value()
  101. fmt.Printf("[%X]:\t[%X]\n", key, value)
  102. }
  103. }
  104. // Implements DB.
  105. func (db *GoLevelDB) Stats() map[string]string {
  106. keys := []string{
  107. "leveldb.num-files-at-level{n}",
  108. "leveldb.stats",
  109. "leveldb.sstables",
  110. "leveldb.blockpool",
  111. "leveldb.cachedblock",
  112. "leveldb.openedtables",
  113. "leveldb.alivesnaps",
  114. "leveldb.aliveiters",
  115. }
  116. stats := make(map[string]string)
  117. for _, key := range keys {
  118. str, err := db.db.GetProperty(key)
  119. if err == nil {
  120. stats[key] = str
  121. }
  122. }
  123. return stats
  124. }
  125. //----------------------------------------
  126. // Batch
  127. // Implements DB.
  128. func (db *GoLevelDB) NewBatch() Batch {
  129. batch := new(leveldb.Batch)
  130. return &goLevelDBBatch{db, batch}
  131. }
  132. type goLevelDBBatch struct {
  133. db *GoLevelDB
  134. batch *leveldb.Batch
  135. }
  136. // Implements Batch.
  137. func (mBatch *goLevelDBBatch) Set(key, value []byte) {
  138. mBatch.batch.Put(key, value)
  139. }
  140. // Implements Batch.
  141. func (mBatch *goLevelDBBatch) Delete(key []byte) {
  142. mBatch.batch.Delete(key)
  143. }
  144. // Implements Batch.
  145. func (mBatch *goLevelDBBatch) Write() {
  146. err := mBatch.db.db.Write(mBatch.batch, &opt.WriteOptions{Sync: false})
  147. if err != nil {
  148. panic(err)
  149. }
  150. }
  151. // Implements Batch.
  152. func (mBatch *goLevelDBBatch) WriteSync() {
  153. err := mBatch.db.db.Write(mBatch.batch, &opt.WriteOptions{Sync: true})
  154. if err != nil {
  155. panic(err)
  156. }
  157. }
  158. // Implements Batch.
  159. // Close is no-op for goLevelDBBatch.
  160. func (mBatch *goLevelDBBatch) Close() {}
  161. //----------------------------------------
  162. // Iterator
  163. // NOTE This is almost identical to db/c_level_db.Iterator
  164. // Before creating a third version, refactor.
  165. // Implements DB.
  166. func (db *GoLevelDB) Iterator(start, end []byte) Iterator {
  167. itr := db.db.NewIterator(nil, nil)
  168. return newGoLevelDBIterator(itr, start, end, false)
  169. }
  170. // Implements DB.
  171. func (db *GoLevelDB) ReverseIterator(start, end []byte) Iterator {
  172. itr := db.db.NewIterator(nil, nil)
  173. return newGoLevelDBIterator(itr, start, end, true)
  174. }
  175. type goLevelDBIterator struct {
  176. source iterator.Iterator
  177. start []byte
  178. end []byte
  179. isReverse bool
  180. isInvalid bool
  181. }
  182. var _ Iterator = (*goLevelDBIterator)(nil)
  183. func newGoLevelDBIterator(source iterator.Iterator, start, end []byte, isReverse bool) *goLevelDBIterator {
  184. if isReverse {
  185. if end == nil {
  186. source.Last()
  187. } else {
  188. valid := source.Seek(end)
  189. if valid {
  190. eoakey := source.Key() // end or after key
  191. if bytes.Compare(end, eoakey) <= 0 {
  192. source.Prev()
  193. }
  194. } else {
  195. source.Last()
  196. }
  197. }
  198. } else {
  199. if start == nil {
  200. source.First()
  201. } else {
  202. source.Seek(start)
  203. }
  204. }
  205. return &goLevelDBIterator{
  206. source: source,
  207. start: start,
  208. end: end,
  209. isReverse: isReverse,
  210. isInvalid: false,
  211. }
  212. }
  213. // Implements Iterator.
  214. func (itr *goLevelDBIterator) Domain() ([]byte, []byte) {
  215. return itr.start, itr.end
  216. }
  217. // Implements Iterator.
  218. func (itr *goLevelDBIterator) Valid() bool {
  219. // Once invalid, forever invalid.
  220. if itr.isInvalid {
  221. return false
  222. }
  223. // Panic on DB error. No way to recover.
  224. itr.assertNoError()
  225. // If source is invalid, invalid.
  226. if !itr.source.Valid() {
  227. itr.isInvalid = true
  228. return false
  229. }
  230. // If key is end or past it, invalid.
  231. var start = itr.start
  232. var end = itr.end
  233. var key = itr.source.Key()
  234. if itr.isReverse {
  235. if start != nil && bytes.Compare(key, start) < 0 {
  236. itr.isInvalid = true
  237. return false
  238. }
  239. } else {
  240. if end != nil && bytes.Compare(end, key) <= 0 {
  241. itr.isInvalid = true
  242. return false
  243. }
  244. }
  245. // Valid
  246. return true
  247. }
  248. // Implements Iterator.
  249. func (itr *goLevelDBIterator) Key() []byte {
  250. // Key returns a copy of the current key.
  251. // See https://github.com/syndtr/goleveldb/blob/52c212e6c196a1404ea59592d3f1c227c9f034b2/leveldb/iterator/iter.go#L88
  252. itr.assertNoError()
  253. itr.assertIsValid()
  254. return cp(itr.source.Key())
  255. }
  256. // Implements Iterator.
  257. func (itr *goLevelDBIterator) Value() []byte {
  258. // Value returns a copy of the current value.
  259. // See https://github.com/syndtr/goleveldb/blob/52c212e6c196a1404ea59592d3f1c227c9f034b2/leveldb/iterator/iter.go#L88
  260. itr.assertNoError()
  261. itr.assertIsValid()
  262. return cp(itr.source.Value())
  263. }
  264. // Implements Iterator.
  265. func (itr *goLevelDBIterator) Next() {
  266. itr.assertNoError()
  267. itr.assertIsValid()
  268. if itr.isReverse {
  269. itr.source.Prev()
  270. } else {
  271. itr.source.Next()
  272. }
  273. }
  274. // Implements Iterator.
  275. func (itr *goLevelDBIterator) Close() {
  276. itr.source.Release()
  277. }
  278. func (itr *goLevelDBIterator) assertNoError() {
  279. if err := itr.source.Error(); err != nil {
  280. panic(err)
  281. }
  282. }
  283. func (itr goLevelDBIterator) assertIsValid() {
  284. if !itr.Valid() {
  285. panic("goLevelDBIterator is invalid")
  286. }
  287. }