folder.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This program is free software: you can redistribute it and/or modify it
  4. // under the terms of the GNU General Public License as published by the Free
  5. // Software Foundation, either version 3 of the License, or (at your option)
  6. // any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful, but WITHOUT
  9. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. // more details.
  12. //
  13. // You should have received a copy of the GNU General Public License along
  14. // with this program. If not, see <http://www.gnu.org/licenses/>.
  15. package stats
  16. import (
  17. "encoding/binary"
  18. "time"
  19. "github.com/syndtr/goleveldb/leveldb"
  20. )
  21. const (
  22. folderStatisticTypeLastFile = iota
  23. )
  24. var folderStatisticsTypes = []byte{
  25. folderStatisticTypeLastFile,
  26. }
  27. type FolderStatistics struct {
  28. LastFile *LastFile
  29. }
  30. type FolderStatisticsReference struct {
  31. db *leveldb.DB
  32. folder string
  33. }
  34. func NewFolderStatisticsReference(db *leveldb.DB, folder string) *FolderStatisticsReference {
  35. return &FolderStatisticsReference{
  36. db: db,
  37. folder: folder,
  38. }
  39. }
  40. func (s *FolderStatisticsReference) key(stat byte) []byte {
  41. k := make([]byte, 1+1+64)
  42. k[0] = keyTypeFolderStatistic
  43. k[1] = stat
  44. copy(k[1+1:], s.folder[:])
  45. return k
  46. }
  47. func (s *FolderStatisticsReference) GetLastFile() *LastFile {
  48. value, err := s.db.Get(s.key(folderStatisticTypeLastFile), nil)
  49. if err != nil {
  50. if err != leveldb.ErrNotFound {
  51. l.Warnln("FolderStatisticsReference: Failed loading last file filename value for", s.folder, ":", err)
  52. }
  53. return nil
  54. }
  55. file := LastFile{}
  56. err = file.UnmarshalBinary(value)
  57. if err != nil {
  58. l.Warnln("FolderStatisticsReference: Failed loading last file value for", s.folder, ":", err)
  59. return nil
  60. }
  61. return &file
  62. }
  63. func (s *FolderStatisticsReference) ReceivedFile(filename string) {
  64. f := LastFile{
  65. Filename: filename,
  66. At: time.Now(),
  67. }
  68. if debug {
  69. l.Debugln("stats.FolderStatisticsReference.ReceivedFile:", s.folder)
  70. }
  71. value, err := f.MarshalBinary()
  72. if err != nil {
  73. l.Warnln("FolderStatisticsReference: Failed serializing last file value for", s.folder, ":", err)
  74. return
  75. }
  76. err = s.db.Put(s.key(folderStatisticTypeLastFile), value, nil)
  77. if err != nil {
  78. l.Warnln("Failed update last file value for", s.folder, ":", err)
  79. }
  80. }
  81. // Never called, maybe because it's worth while to keep the data
  82. // or maybe because we have no easy way of knowing that a folder has been removed.
  83. func (s *FolderStatisticsReference) Delete() error {
  84. for _, stype := range folderStatisticsTypes {
  85. err := s.db.Delete(s.key(stype), nil)
  86. if debug && err == nil {
  87. l.Debugln("stats.FolderStatisticsReference.Delete:", s.folder, stype)
  88. }
  89. if err != nil && err != leveldb.ErrNotFound {
  90. return err
  91. }
  92. }
  93. return nil
  94. }
  95. func (s *FolderStatisticsReference) GetStatistics() FolderStatistics {
  96. return FolderStatistics{
  97. LastFile: s.GetLastFile(),
  98. }
  99. }
  100. type LastFile struct {
  101. At time.Time
  102. Filename string
  103. }
  104. func (f *LastFile) MarshalBinary() ([]byte, error) {
  105. buf := make([]byte, 8+len(f.Filename))
  106. binary.BigEndian.PutUint64(buf[:8], uint64(f.At.Unix()))
  107. copy(buf[8:], []byte(f.Filename))
  108. return buf, nil
  109. }
  110. func (f *LastFile) UnmarshalBinary(buf []byte) error {
  111. f.At = time.Unix(int64(binary.BigEndian.Uint64(buf[:8])), 0)
  112. f.Filename = string(buf[8:])
  113. return nil
  114. }