dbleveldb.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package dbleveldb
  2. import (
  3. "encoding/json"
  4. "path/filepath"
  5. "strings"
  6. "sync"
  7. "github.com/syndtr/goleveldb/leveldb"
  8. "github.com/syndtr/goleveldb/leveldb/util"
  9. "imuslab.com/zoraxy/mod/database/dbinc"
  10. )
  11. // Ensure the DB struct implements the Backend interface
  12. var _ dbinc.Backend = (*DB)(nil)
  13. type DB struct {
  14. db *leveldb.DB
  15. Table sync.Map //For emulating table creation
  16. }
  17. func NewDB(path string) (*DB, error) {
  18. //If the path is not a directory (e.g. /tmp/dbfile.db), convert the filename to directory
  19. if filepath.Ext(path) != "" {
  20. path = strings.ReplaceAll(path, ".", "_")
  21. }
  22. db, err := leveldb.OpenFile(path, nil)
  23. if err != nil {
  24. return nil, err
  25. }
  26. return &DB{db: db, Table: sync.Map{}}, nil
  27. }
  28. func (d *DB) NewTable(tableName string) error {
  29. //Create a table entry in the sync.Map
  30. d.Table.Store(tableName, true)
  31. return nil
  32. }
  33. func (d *DB) TableExists(tableName string) bool {
  34. _, ok := d.Table.Load(tableName)
  35. return ok
  36. }
  37. func (d *DB) DropTable(tableName string) error {
  38. d.Table.Delete(tableName)
  39. iter := d.db.NewIterator(nil, nil)
  40. defer iter.Release()
  41. for iter.Next() {
  42. key := iter.Key()
  43. if filepath.Dir(string(key)) == tableName {
  44. err := d.db.Delete(key, nil)
  45. if err != nil {
  46. return err
  47. }
  48. }
  49. }
  50. return nil
  51. }
  52. func (d *DB) Write(tableName string, key string, value interface{}) error {
  53. data, err := json.Marshal(value)
  54. if err != nil {
  55. return err
  56. }
  57. return d.db.Put([]byte(filepath.ToSlash(filepath.Join(tableName, key))), data, nil)
  58. }
  59. func (d *DB) Read(tableName string, key string, assignee interface{}) error {
  60. data, err := d.db.Get([]byte(filepath.ToSlash(filepath.Join(tableName, key))), nil)
  61. if err != nil {
  62. return err
  63. }
  64. return json.Unmarshal(data, assignee)
  65. }
  66. func (d *DB) KeyExists(tableName string, key string) bool {
  67. _, err := d.db.Get([]byte(filepath.ToSlash(filepath.Join(tableName, key))), nil)
  68. return err == nil
  69. }
  70. func (d *DB) Delete(tableName string, key string) error {
  71. return d.db.Delete([]byte(filepath.ToSlash(filepath.Join(tableName, key))), nil)
  72. }
  73. func (d *DB) ListTable(tableName string) ([][][]byte, error) {
  74. iter := d.db.NewIterator(util.BytesPrefix([]byte(tableName+"/")), nil)
  75. defer iter.Release()
  76. var result [][][]byte
  77. for iter.Next() {
  78. key := iter.Key()
  79. //The key contains the table name as prefix. Trim it before returning
  80. value := iter.Value()
  81. result = append(result, [][]byte{[]byte(strings.TrimPrefix(string(key), tableName+"/")), value})
  82. }
  83. err := iter.Error()
  84. if err != nil {
  85. return nil, err
  86. }
  87. return result, nil
  88. }
  89. func (d *DB) Close() {
  90. d.db.Close()
  91. }