/server/kvstore/sqlite.go

https://github.com/smancke/guble · Go · 109 lines · 89 code · 16 blank · 4 comment · 21 complexity · 9e3581b066e6c33d2c6230da49ffba18 MD5 · raw file

  1. package kvstore
  2. import (
  3. // use this as gorm's sqlite dialect / implementation
  4. _ "github.com/mattn/go-sqlite3"
  5. "github.com/jinzhu/gorm"
  6. log "github.com/Sirupsen/logrus"
  7. "fmt"
  8. "io/ioutil"
  9. "os"
  10. "path"
  11. "path/filepath"
  12. )
  13. const (
  14. sqliteMaxIdleConns = 2
  15. sqliteMaxOpenConns = 5
  16. sqliteGormLogMode = false
  17. )
  18. var writeTestFilename = "db_testfile"
  19. // SqliteKVStore is a struct representing a sqlite database which embeds a kvStore.
  20. type SqliteKVStore struct {
  21. *kvStore
  22. filename string
  23. syncOnWrite bool
  24. }
  25. // NewSqliteKVStore returns a new configured SqliteKVStore (not opened yet).
  26. func NewSqliteKVStore(filename string, syncOnWrite bool) *SqliteKVStore {
  27. return &SqliteKVStore{
  28. kvStore: &kvStore{logger: log.WithFields(log.Fields{
  29. "module": "kv-sqlite",
  30. "filename": filename,
  31. "syncOnWrite": syncOnWrite,
  32. })},
  33. filename: filename,
  34. syncOnWrite: syncOnWrite,
  35. }
  36. }
  37. // Open opens the database file. If the directory does not exist, it will be created.
  38. func (kvStore *SqliteKVStore) Open() error {
  39. directoryPath := filepath.Dir(kvStore.filename)
  40. if err := ensureWriteableDirectory(directoryPath); err != nil {
  41. kvStore.logger.WithError(err).Error("DB Directory is not writeable")
  42. return err
  43. }
  44. kvStore.logger.Info("Opening database")
  45. gormdb, err := gorm.Open("sqlite3", kvStore.filename)
  46. if err != nil {
  47. kvStore.logger.WithError(err).Error("Error opening database")
  48. return err
  49. }
  50. if err := gormdb.DB().Ping(); err != nil {
  51. kvStore.logger.WithError(err).Error("Error pinging database")
  52. return err
  53. }
  54. kvStore.logger.Info("Ping reply from database")
  55. gormdb.LogMode(sqliteGormLogMode)
  56. gormdb.SingularTable(true)
  57. gormdb.DB().SetMaxIdleConns(sqliteMaxIdleConns)
  58. gormdb.DB().SetMaxOpenConns(sqliteMaxOpenConns)
  59. if err := gormdb.AutoMigrate(&kvEntry{}).Error; err != nil {
  60. kvStore.logger.WithError(err).Error("Error in schema migration")
  61. return err
  62. }
  63. kvStore.logger.Info("Ensured database schema")
  64. if !kvStore.syncOnWrite {
  65. kvStore.logger.Info("Setting db: PRAGMA synchronous = OFF")
  66. if err := gormdb.Exec("PRAGMA synchronous = OFF").Error; err != nil {
  67. kvStore.logger.WithError(err).Error("Error setting PRAGMA synchronous = OFF")
  68. return err
  69. }
  70. }
  71. kvStore.db = gormdb
  72. return nil
  73. }
  74. func ensureWriteableDirectory(dir string) error {
  75. dirInfo, errStat := os.Stat(dir)
  76. if os.IsNotExist(errStat) {
  77. if errMkdir := os.MkdirAll(dir, 0755); errMkdir != nil {
  78. return errMkdir
  79. }
  80. dirInfo, errStat = os.Stat(dir)
  81. }
  82. if errStat != nil || !dirInfo.IsDir() {
  83. return fmt.Errorf("kv-sqlite: not a directory %v", dir)
  84. }
  85. writeTest := path.Join(dir, writeTestFilename)
  86. if err := ioutil.WriteFile(writeTest, []byte("writeTest"), 0644); err != nil {
  87. return err
  88. }
  89. if err := os.Remove(writeTest); err != nil {
  90. return err
  91. }
  92. return nil
  93. }