database_core.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. //go:build !mipsle && !riscv64
  2. // +build !mipsle,!riscv64
  3. package database
  4. import (
  5. "encoding/json"
  6. "errors"
  7. "log"
  8. "sync"
  9. "github.com/boltdb/bolt"
  10. )
  11. func newDatabase(dbfile string, readOnlyMode bool) (*Database, error) {
  12. db, err := bolt.Open(dbfile, 0600, nil)
  13. if err != nil {
  14. return nil, err
  15. }
  16. log.Println("Key-value Database Service Started: " + dbfile)
  17. tableMap := sync.Map{}
  18. //Build the table list from database
  19. err = db.View(func(tx *bolt.Tx) error {
  20. return tx.ForEach(func(name []byte, _ *bolt.Bucket) error {
  21. tableMap.Store(string(name), "")
  22. return nil
  23. })
  24. })
  25. return &Database{
  26. Db: db,
  27. Tables: tableMap,
  28. ReadOnly: readOnlyMode,
  29. }, err
  30. }
  31. //Dump the whole db into a log file
  32. func (d *Database) dump(filename string) ([]string, error) {
  33. results := []string{}
  34. d.Tables.Range(func(tableName, v interface{}) bool {
  35. entries, err := d.ListTable(tableName.(string))
  36. if err != nil {
  37. log.Println("Reading table " + tableName.(string) + " failed: " + err.Error())
  38. return false
  39. }
  40. for _, keypairs := range entries {
  41. results = append(results, string(keypairs[0])+":"+string(keypairs[1])+"\n")
  42. }
  43. return true
  44. })
  45. return results, nil
  46. }
  47. //Create a new table
  48. func (d *Database) newTable(tableName string) error {
  49. if d.ReadOnly == true {
  50. return errors.New("Operation rejected in ReadOnly mode")
  51. }
  52. err := d.Db.(*bolt.DB).Update(func(tx *bolt.Tx) error {
  53. _, err := tx.CreateBucketIfNotExists([]byte(tableName))
  54. if err != nil {
  55. return err
  56. }
  57. return nil
  58. })
  59. d.Tables.Store(tableName, "")
  60. return err
  61. }
  62. //Check is table exists
  63. func (d *Database) tableExists(tableName string) bool {
  64. if _, ok := d.Tables.Load(tableName); ok {
  65. return true
  66. }
  67. return false
  68. }
  69. //Drop the given table
  70. func (d *Database) dropTable(tableName string) error {
  71. if d.ReadOnly == true {
  72. return errors.New("Operation rejected in ReadOnly mode")
  73. }
  74. err := d.Db.(*bolt.DB).Update(func(tx *bolt.Tx) error {
  75. err := tx.DeleteBucket([]byte(tableName))
  76. if err != nil {
  77. return err
  78. }
  79. return nil
  80. })
  81. return err
  82. }
  83. //Write to table
  84. func (d *Database) write(tableName string, key string, value interface{}) error {
  85. if d.ReadOnly {
  86. return errors.New("Operation rejected in ReadOnly mode")
  87. }
  88. jsonString, err := json.Marshal(value)
  89. if err != nil {
  90. return err
  91. }
  92. err = d.Db.(*bolt.DB).Update(func(tx *bolt.Tx) error {
  93. _, err := tx.CreateBucketIfNotExists([]byte(tableName))
  94. if err != nil {
  95. return err
  96. }
  97. b := tx.Bucket([]byte(tableName))
  98. err = b.Put([]byte(key), jsonString)
  99. return err
  100. })
  101. return err
  102. }
  103. func (d *Database) read(tableName string, key string, assignee interface{}) error {
  104. err := d.Db.(*bolt.DB).View(func(tx *bolt.Tx) error {
  105. b := tx.Bucket([]byte(tableName))
  106. v := b.Get([]byte(key))
  107. json.Unmarshal(v, &assignee)
  108. return nil
  109. })
  110. return err
  111. }
  112. func (d *Database) keyExists(tableName string, key string) bool {
  113. resultIsNil := false
  114. if !d.TableExists(tableName) {
  115. //Table not exists. Do not proceed accessing key
  116. log.Println("[DB] ERROR: Requesting key from table that didn't exist!!!")
  117. return false
  118. }
  119. err := d.Db.(*bolt.DB).View(func(tx *bolt.Tx) error {
  120. b := tx.Bucket([]byte(tableName))
  121. v := b.Get([]byte(key))
  122. if v == nil {
  123. resultIsNil = true
  124. }
  125. return nil
  126. })
  127. if err != nil {
  128. return false
  129. } else {
  130. if resultIsNil {
  131. return false
  132. } else {
  133. return true
  134. }
  135. }
  136. }
  137. func (d *Database) delete(tableName string, key string) error {
  138. if d.ReadOnly {
  139. return errors.New("Operation rejected in ReadOnly mode")
  140. }
  141. err := d.Db.(*bolt.DB).Update(func(tx *bolt.Tx) error {
  142. tx.Bucket([]byte(tableName)).Delete([]byte(key))
  143. return nil
  144. })
  145. return err
  146. }
  147. func (d *Database) listTable(tableName string) ([][][]byte, error) {
  148. var results [][][]byte
  149. err := d.Db.(*bolt.DB).View(func(tx *bolt.Tx) error {
  150. b := tx.Bucket([]byte(tableName))
  151. c := b.Cursor()
  152. for k, v := c.First(); k != nil; k, v = c.Next() {
  153. results = append(results, [][]byte{k, v})
  154. }
  155. return nil
  156. })
  157. return results, err
  158. }
  159. func (d *Database) close() {
  160. d.Db.(*bolt.DB).Close()
  161. }