file_store.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package stores
  2. import (
  3. "encoding/json"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. log "github.com/alecthomas/log4go"
  9. "github.com/torkelo/grafana-pro/pkg/models"
  10. )
  11. type fileStore struct {
  12. dataDir string
  13. dashDir string
  14. cache map[string]*models.Dashboard
  15. }
  16. func NewFileStore(dataDir string) *fileStore {
  17. if dirDoesNotExist(dataDir) {
  18. log.Crashf("FileStore failed to initialize, dataDir does not exist %v", dataDir)
  19. }
  20. dashDir := filepath.Join(dataDir, "dashboards")
  21. if dirDoesNotExist(dashDir) {
  22. log.Debug("Did not find dashboard dir, creating...")
  23. err := os.Mkdir(dashDir, 0777)
  24. if err != nil {
  25. log.Crashf("FileStore failed to initialize, could not create directory %v, error: %v", dashDir, err)
  26. }
  27. }
  28. store := &fileStore{}
  29. store.dataDir = dataDir
  30. store.dashDir = dashDir
  31. store.cache = make(map[string]*models.Dashboard)
  32. go store.scanFiles()
  33. return store
  34. }
  35. func (store *fileStore) scanFiles() {
  36. visitor := func(path string, f os.FileInfo, err error) error {
  37. if err != nil {
  38. return err
  39. }
  40. if f.IsDir() {
  41. return nil
  42. }
  43. if strings.HasSuffix(f.Name(), ".json") {
  44. err = store.loadDashboardIntoCache(path)
  45. if err != nil {
  46. return err
  47. }
  48. }
  49. return nil
  50. }
  51. err := filepath.Walk(store.dashDir, visitor)
  52. if err != nil {
  53. log.Error("FileStore::updateCache failed %v", err)
  54. }
  55. }
  56. func (store fileStore) loadDashboardIntoCache(filename string) error {
  57. log.Info("Loading dashboard file %v into cache", filename)
  58. dash, err := loadDashboardFromFile(filename)
  59. if err != nil {
  60. return err
  61. }
  62. store.cache[dash.Title()] = dash
  63. return nil
  64. }
  65. func (store *fileStore) Close() {
  66. }
  67. func (store *fileStore) GetById(id string) (*models.Dashboard, error) {
  68. log.Debug("FileStore::GetById id = %v", id)
  69. filename := store.getFilePathForDashboard(id)
  70. return loadDashboardFromFile(filename)
  71. }
  72. func (store *fileStore) Save(dash *models.Dashboard) error {
  73. filename := store.getFilePathForDashboard(dash.Title())
  74. log.Debug("Saving dashboard %v to %v", dash.Title(), filename)
  75. var err error
  76. var data []byte
  77. if data, err = json.Marshal(dash.Data); err != nil {
  78. return err
  79. }
  80. return writeFile(filename, data)
  81. }
  82. func (store *fileStore) Query(query string) ([]*models.SearchResult, error) {
  83. results := make([]*models.SearchResult, 0, 50)
  84. for _, dash := range store.cache {
  85. item := &models.SearchResult{
  86. Id: dash.Title(),
  87. Type: "dashboard",
  88. }
  89. results = append(results, item)
  90. }
  91. return results, nil
  92. }
  93. func loadDashboardFromFile(filename string) (*models.Dashboard, error) {
  94. log.Debug("FileStore::loading dashboard from file %v", filename)
  95. configFile, err := os.Open(filename)
  96. if err != nil {
  97. return nil, err
  98. }
  99. return models.NewFromJson(configFile)
  100. }
  101. func (store *fileStore) getFilePathForDashboard(id string) string {
  102. id = strings.ToLower(id)
  103. id = strings.Replace(id, " ", "-", -1)
  104. return filepath.Join(store.dashDir, id) + ".json"
  105. }
  106. func dirDoesNotExist(dir string) bool {
  107. _, err := os.Stat(dir)
  108. return os.IsNotExist(err)
  109. }
  110. func writeFile(filename string, data []byte) error {
  111. f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
  112. if err != nil {
  113. return err
  114. }
  115. n, err := f.Write(data)
  116. if err == nil && n < len(data) {
  117. err = io.ErrShortWrite
  118. }
  119. if err1 := f.Close(); err == nil {
  120. err = err1
  121. }
  122. return err
  123. }