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.

135 lines
3.7 KiB

  1. package storage
  2. import "os"
  3. import "fmt"
  4. import "path/filepath"
  5. import "encoding/binary"
  6. import "github.com/romana/rlog"
  7. import bolt "github.com/coreos/bbolt"
  8. import log "github.com/sirupsen/logrus"
  9. import "github.com/deroproject/derosuite/globals"
  10. type BoltStore struct {
  11. DB *bolt.DB
  12. }
  13. var Bolt_backend *BoltStore = &BoltStore{} // global variable
  14. var logger *log.Entry
  15. func (b *BoltStore) Init(params map[string]interface{}) (err error) {
  16. logger = globals.Logger.WithFields(log.Fields{"com": "STORE"})
  17. current_path := filepath.Join(os.TempDir(), "derod_database.db")
  18. logger.Infof("Initializing boltdb store at path %s", current_path)
  19. // Open the my.db data file in your current directory.
  20. // It will be created if it doesn't exist.
  21. b.DB, err = bolt.Open(current_path, 0600, nil)
  22. if err != nil {
  23. logger.Fatalf("Cannot open boltdb store err %s\n", err)
  24. }
  25. return nil
  26. }
  27. func (b *BoltStore) Shutdown() (err error) {
  28. logger.Infof("Shutting boltdb store")
  29. if b.DB != nil {
  30. b.DB.Close()
  31. }
  32. return nil
  33. }
  34. func (b *BoltStore) StoreObject(universe_name []byte, galaxy_name []byte, solar_name []byte, key []byte, data []byte) (err error) {
  35. rlog.Tracef(10, "Storing object %s %s %x data len %d\n", string(universe_name), string(galaxy_name), key, len(data))
  36. // open universe bucket
  37. err = b.DB.Update(func(tx *bolt.Tx) error {
  38. universe, err := tx.CreateBucketIfNotExists(universe_name)
  39. if err != nil {
  40. logger.Errorf("Error while creating universe bucket %s\n", err)
  41. return err
  42. }
  43. galaxy, err := universe.CreateBucketIfNotExists(galaxy_name)
  44. if err != nil {
  45. logger.Errorf("Error while creating galaxy bucket %s err\n", string(galaxy_name), err)
  46. return err
  47. }
  48. solar, err := galaxy.CreateBucketIfNotExists(solar_name)
  49. if err != nil {
  50. logger.Errorf("Error while creating solar bucket %s err\n", string(solar_name), err)
  51. return err
  52. }
  53. // now lets update the object attribute
  54. err = solar.Put(key, data)
  55. return err
  56. })
  57. return
  58. }
  59. func (b *BoltStore) LoadObject(universe []byte, bucket_name []byte, solar_bucket []byte, key []byte) (data []byte, err error) {
  60. rlog.Tracef(10, "Loading object %s %s %x\n", string(universe), string(bucket_name), key)
  61. // open universe bucket
  62. err = b.DB.View(func(tx *bolt.Tx) error {
  63. universe := tx.Bucket(universe)
  64. if universe == nil {
  65. return fmt.Errorf("No Such Universe %x\n", universe)
  66. }
  67. bucket := universe.Bucket(bucket_name)
  68. if bucket == nil {
  69. return fmt.Errorf("No Such Bucket %x\n", bucket_name)
  70. }
  71. solar := bucket.Bucket(solar_bucket)
  72. if solar == nil {
  73. return fmt.Errorf("No Such Bucket %x\n", solar)
  74. }
  75. // now lets find the object
  76. value := solar.Get(key)
  77. data = make([]byte, len(value), len(value))
  78. copy(data, value) // job done
  79. return nil
  80. })
  81. return
  82. }
  83. // this function stores a uint64
  84. func (b *BoltStore) StoreUint64(universe_bucket []byte, galaxy_bucket []byte, solar_bucket []byte, key []byte, data uint64) error {
  85. return b.StoreObject(universe_bucket, galaxy_bucket, solar_bucket, key, itob(data))
  86. }
  87. // this function loads the data as 64 byte integer
  88. func (b *BoltStore) LoadUint64(universe_bucket []byte, galaxy_bucket []byte, solar_bucket []byte, key []byte) (uint64, error) {
  89. object_data, err := b.LoadObject(universe_bucket, galaxy_bucket, solar_bucket, key)
  90. if err != nil {
  91. return 0, err
  92. }
  93. if len(object_data) == 0 {
  94. return 0, fmt.Errorf("No value stored here, we should look more")
  95. }
  96. if len(object_data) != 8 {
  97. panic("Database corruption, invalid data ")
  98. }
  99. value := binary.BigEndian.Uint64(object_data)
  100. return value, nil
  101. }
  102. // itob returns an 8-byte big endian representation of v.
  103. func itob(v uint64) []byte {
  104. b := make([]byte, 8)
  105. binary.BigEndian.PutUint64(b, uint64(v))
  106. return b
  107. }