database_core.go 4.2 KB

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