set.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. // All rights reserved. Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. // Package files provides a set type to track local/remote files with newness checks.
  5. package files
  6. import (
  7. "sync"
  8. "github.com/calmh/syncthing/lamport"
  9. "github.com/calmh/syncthing/protocol"
  10. "github.com/syndtr/goleveldb/leveldb"
  11. )
  12. type fileRecord struct {
  13. File protocol.FileInfo
  14. Usage int
  15. Global bool
  16. }
  17. type bitset uint64
  18. type Set struct {
  19. localVersion map[protocol.NodeID]uint64
  20. mutex sync.Mutex
  21. repo string
  22. db *leveldb.DB
  23. }
  24. func NewSet(repo string, db *leveldb.DB) *Set {
  25. var s = Set{
  26. localVersion: make(map[protocol.NodeID]uint64),
  27. repo: repo,
  28. db: db,
  29. }
  30. var nodeID protocol.NodeID
  31. ldbWithAllRepo(db, []byte(repo), func(node []byte, f protocol.FileInfo) bool {
  32. copy(nodeID[:], node)
  33. if f.LocalVersion > s.localVersion[nodeID] {
  34. s.localVersion[nodeID] = f.LocalVersion
  35. }
  36. lamport.Default.Tick(f.Version)
  37. return true
  38. })
  39. if debug {
  40. l.Debugf("loaded localVersion for %q: %#v", repo, s.localVersion)
  41. }
  42. clock(s.localVersion[protocol.LocalNodeID])
  43. return &s
  44. }
  45. func (s *Set) Replace(node protocol.NodeID, fs []protocol.FileInfo) {
  46. if debug {
  47. l.Debugf("%s Replace(%v, [%d])", s.repo, node, len(fs))
  48. }
  49. s.mutex.Lock()
  50. defer s.mutex.Unlock()
  51. s.localVersion[node] = ldbReplace(s.db, []byte(s.repo), node[:], fs)
  52. }
  53. func (s *Set) ReplaceWithDelete(node protocol.NodeID, fs []protocol.FileInfo) {
  54. if debug {
  55. l.Debugf("%s ReplaceWithDelete(%v, [%d])", s.repo, node, len(fs))
  56. }
  57. s.mutex.Lock()
  58. defer s.mutex.Unlock()
  59. if lv := ldbReplaceWithDelete(s.db, []byte(s.repo), node[:], fs); lv > s.localVersion[node] {
  60. s.localVersion[node] = lv
  61. }
  62. }
  63. func (s *Set) Update(node protocol.NodeID, fs []protocol.FileInfo) {
  64. if debug {
  65. l.Debugf("%s Update(%v, [%d])", s.repo, node, len(fs))
  66. }
  67. s.mutex.Lock()
  68. defer s.mutex.Unlock()
  69. if lv := ldbUpdate(s.db, []byte(s.repo), node[:], fs); lv > s.localVersion[node] {
  70. s.localVersion[node] = lv
  71. }
  72. }
  73. func (s *Set) WithNeed(node protocol.NodeID, fn fileIterator) {
  74. if debug {
  75. l.Debugf("%s WithNeed(%v)", s.repo, node)
  76. }
  77. ldbWithNeed(s.db, []byte(s.repo), node[:], fn)
  78. }
  79. func (s *Set) WithHave(node protocol.NodeID, fn fileIterator) {
  80. if debug {
  81. l.Debugf("%s WithHave(%v)", s.repo, node)
  82. }
  83. ldbWithHave(s.db, []byte(s.repo), node[:], fn)
  84. }
  85. func (s *Set) WithGlobal(fn fileIterator) {
  86. if debug {
  87. l.Debugf("%s WithGlobal()", s.repo)
  88. }
  89. ldbWithGlobal(s.db, []byte(s.repo), fn)
  90. }
  91. func (s *Set) Get(node protocol.NodeID, file string) protocol.FileInfo {
  92. return ldbGet(s.db, []byte(s.repo), node[:], []byte(file))
  93. }
  94. func (s *Set) GetGlobal(file string) protocol.FileInfo {
  95. return ldbGetGlobal(s.db, []byte(s.repo), []byte(file))
  96. }
  97. func (s *Set) Availability(file string) []protocol.NodeID {
  98. return ldbAvailability(s.db, []byte(s.repo), []byte(file))
  99. }
  100. func (s *Set) LocalVersion(node protocol.NodeID) uint64 {
  101. s.mutex.Lock()
  102. defer s.mutex.Unlock()
  103. return s.localVersion[node]
  104. }