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.

287 lines
5.4 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. // TODO: Find the available properties for the C LevelDB implementation
  114. keys := []string{}
  115. stats := make(map[string]string)
  116. for _, key := range keys {
  117. str := db.db.PropertyValue(key)
  118. stats[key] = str
  119. }
  120. return stats
  121. }
  122. //----------------------------------------
  123. // Batch
  124. // Implements DB.
  125. func (db *CLevelDB) NewBatch() Batch {
  126. batch := levigo.NewWriteBatch()
  127. return &cLevelDBBatch{db, batch}
  128. }
  129. type cLevelDBBatch struct {
  130. db *CLevelDB
  131. batch *levigo.WriteBatch
  132. }
  133. // Implements Batch.
  134. func (mBatch *cLevelDBBatch) Set(key, value []byte) {
  135. mBatch.batch.Put(key, value)
  136. }
  137. // Implements Batch.
  138. func (mBatch *cLevelDBBatch) Delete(key []byte) {
  139. mBatch.batch.Delete(key)
  140. }
  141. // Implements Batch.
  142. func (mBatch *cLevelDBBatch) Write() {
  143. err := mBatch.db.db.Write(mBatch.db.wo, mBatch.batch)
  144. if err != nil {
  145. panic(err)
  146. }
  147. }
  148. // Implements Batch.
  149. func (mBatch *cLevelDBBatch) WriteSync() {
  150. err := mBatch.db.db.Write(mBatch.db.woSync, mBatch.batch)
  151. if err != nil {
  152. panic(err)
  153. }
  154. }
  155. //----------------------------------------
  156. // Iterator
  157. // NOTE This is almost identical to db/go_level_db.Iterator
  158. // Before creating a third version, refactor.
  159. func (db *CLevelDB) Iterator(start, end []byte) Iterator {
  160. itr := db.db.NewIterator(db.ro)
  161. return newCLevelDBIterator(itr, start, end, false)
  162. }
  163. func (db *CLevelDB) ReverseIterator(start, end []byte) Iterator {
  164. panic("not implemented yet") // XXX
  165. }
  166. var _ Iterator = (*cLevelDBIterator)(nil)
  167. type cLevelDBIterator struct {
  168. source *levigo.Iterator
  169. start, end []byte
  170. isReverse bool
  171. isInvalid bool
  172. }
  173. func newCLevelDBIterator(source *levigo.Iterator, start, end []byte, isReverse bool) *cLevelDBIterator {
  174. if isReverse {
  175. panic("not implemented yet") // XXX
  176. }
  177. if start != nil {
  178. source.Seek(start)
  179. } else {
  180. source.SeekToFirst()
  181. }
  182. return &cLevelDBIterator{
  183. source: source,
  184. start: start,
  185. end: end,
  186. isReverse: isReverse,
  187. isInvalid: false,
  188. }
  189. }
  190. func (itr cLevelDBIterator) Domain() ([]byte, []byte) {
  191. return itr.start, itr.end
  192. }
  193. func (itr cLevelDBIterator) Valid() bool {
  194. // Once invalid, forever invalid.
  195. if itr.isInvalid {
  196. return false
  197. }
  198. // Panic on DB error. No way to recover.
  199. itr.assertNoError()
  200. // If source is invalid, invalid.
  201. if !itr.source.Valid() {
  202. itr.isInvalid = true
  203. return false
  204. }
  205. // If key is end or past it, invalid.
  206. var end = itr.end
  207. var key = itr.source.Key()
  208. if end != nil && bytes.Compare(end, key) <= 0 {
  209. itr.isInvalid = true
  210. return false
  211. }
  212. // It's valid.
  213. return true
  214. }
  215. func (itr cLevelDBIterator) Key() []byte {
  216. itr.assertNoError()
  217. itr.assertIsValid()
  218. return itr.source.Key()
  219. }
  220. func (itr cLevelDBIterator) Value() []byte {
  221. itr.assertNoError()
  222. itr.assertIsValid()
  223. return itr.source.Value()
  224. }
  225. func (itr cLevelDBIterator) Next() {
  226. itr.assertNoError()
  227. itr.assertIsValid()
  228. itr.source.Next()
  229. }
  230. func (itr cLevelDBIterator) Close() {
  231. itr.source.Close()
  232. }
  233. func (itr cLevelDBIterator) assertNoError() {
  234. if err := itr.source.GetError(); err != nil {
  235. panic(err)
  236. }
  237. }
  238. func (itr cLevelDBIterator) assertIsValid() {
  239. if !itr.Valid() {
  240. panic("cLevelDBIterator is invalid")
  241. }
  242. }