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.

279 lines
5.3 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. //----------------------------------------
  149. // Iterator
  150. // NOTE This is almost identical to db/go_level_db.Iterator
  151. // Before creating a third version, refactor.
  152. func (db *CLevelDB) Iterator(start, end []byte) Iterator {
  153. itr := db.db.NewIterator(db.ro)
  154. return newCLevelDBIterator(itr, start, end, false)
  155. }
  156. func (db *CLevelDB) ReverseIterator(start, end []byte) Iterator {
  157. panic("not implemented yet") // XXX
  158. }
  159. var _ Iterator = (*cLevelDBIterator)(nil)
  160. type cLevelDBIterator struct {
  161. source *levigo.Iterator
  162. start, end []byte
  163. isReverse bool
  164. isInvalid bool
  165. }
  166. func newCLevelDBIterator(source *levigo.Iterator, start, end []byte, isReverse bool) *cLevelDBIterator {
  167. if isReverse {
  168. panic("not implemented yet") // XXX
  169. }
  170. if start != nil {
  171. source.Seek(start)
  172. } else {
  173. source.SeekToFirst()
  174. }
  175. return &cLevelDBIterator{
  176. source: source,
  177. start: start,
  178. end: end,
  179. isReverse: isReverse,
  180. isInvalid: false,
  181. }
  182. }
  183. func (itr cLevelDBIterator) Domain() ([]byte, []byte) {
  184. return itr.start, itr.end
  185. }
  186. func (itr cLevelDBIterator) Valid() bool {
  187. // Once invalid, forever invalid.
  188. if itr.isInvalid {
  189. return false
  190. }
  191. // Panic on DB error. No way to recover.
  192. itr.assertNoError()
  193. // If source is invalid, invalid.
  194. if !itr.source.Valid() {
  195. itr.isInvalid = true
  196. return false
  197. }
  198. // If key is end or past it, invalid.
  199. var end = itr.end
  200. var key = itr.source.Key()
  201. if end != nil && bytes.Compare(end, key) <= 0 {
  202. itr.isInvalid = true
  203. return false
  204. }
  205. // It's valid.
  206. return true
  207. }
  208. func (itr cLevelDBIterator) Key() []byte {
  209. itr.assertNoError()
  210. itr.assertIsValid()
  211. return itr.source.Key()
  212. }
  213. func (itr cLevelDBIterator) Value() []byte {
  214. itr.assertNoError()
  215. itr.assertIsValid()
  216. return itr.source.Value()
  217. }
  218. func (itr cLevelDBIterator) Next() {
  219. itr.assertNoError()
  220. itr.assertIsValid()
  221. itr.source.Next()
  222. }
  223. func (itr cLevelDBIterator) Close() {
  224. itr.source.Close()
  225. }
  226. func (itr cLevelDBIterator) assertNoError() {
  227. if err := itr.source.GetError(); err != nil {
  228. panic(err)
  229. }
  230. }
  231. func (itr cLevelDBIterator) assertIsValid() {
  232. if !itr.Valid() {
  233. panic("cLevelDBIterator is invalid")
  234. }
  235. }