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.

326 lines
6.1 KiB

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