observed.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright (C) 2020 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package db
  7. import (
  8. "time"
  9. "github.com/syncthing/syncthing/lib/protocol"
  10. )
  11. func (db *Lowlevel) AddOrUpdatePendingDevice(device protocol.DeviceID, name, address string) error {
  12. key := db.keyer.GeneratePendingDeviceKey(nil, device[:])
  13. od := ObservedDevice{
  14. Time: time.Now().Truncate(time.Second),
  15. Name: name,
  16. Address: address,
  17. }
  18. bs, err := od.Marshal()
  19. if err != nil {
  20. return err
  21. }
  22. return db.Put(key, bs)
  23. }
  24. func (db *Lowlevel) RemovePendingDevice(device protocol.DeviceID) {
  25. key := db.keyer.GeneratePendingDeviceKey(nil, device[:])
  26. if err := db.Delete(key); err != nil {
  27. l.Warnf("Failed to remove pending device entry: %v", err)
  28. }
  29. }
  30. // PendingDevices enumerates all entries. Invalid ones are dropped from the database
  31. // after a warning log message, as a side-effect.
  32. func (db *Lowlevel) PendingDevices() (map[protocol.DeviceID]ObservedDevice, error) {
  33. iter, err := db.NewPrefixIterator([]byte{KeyTypePendingDevice})
  34. if err != nil {
  35. return nil, err
  36. }
  37. defer iter.Release()
  38. res := make(map[protocol.DeviceID]ObservedDevice)
  39. for iter.Next() {
  40. keyDev := db.keyer.DeviceFromPendingDeviceKey(iter.Key())
  41. deviceID, err := protocol.DeviceIDFromBytes(keyDev)
  42. var od ObservedDevice
  43. if err != nil {
  44. goto deleteKey
  45. }
  46. if err = od.Unmarshal(iter.Value()); err != nil {
  47. goto deleteKey
  48. }
  49. res[deviceID] = od
  50. continue
  51. deleteKey:
  52. // Deleting invalid entries is the only possible "repair" measure and
  53. // appropriate for the importance of pending entries. They will come back
  54. // soon if still relevant.
  55. l.Infof("Invalid pending device entry, deleting from database: %x", iter.Key())
  56. if err := db.Delete(iter.Key()); err != nil {
  57. return nil, err
  58. }
  59. }
  60. return res, nil
  61. }
  62. func (db *Lowlevel) AddOrUpdatePendingFolder(id string, of ObservedFolder, device protocol.DeviceID) error {
  63. key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
  64. if err != nil {
  65. return err
  66. }
  67. bs, err := of.Marshal()
  68. if err != nil {
  69. return err
  70. }
  71. return db.Put(key, bs)
  72. }
  73. // RemovePendingFolderForDevice removes entries for specific folder / device combinations.
  74. func (db *Lowlevel) RemovePendingFolderForDevice(id string, device protocol.DeviceID) {
  75. key, err := db.keyer.GeneratePendingFolderKey(nil, device[:], []byte(id))
  76. if err != nil {
  77. return
  78. }
  79. if err := db.Delete(key); err != nil {
  80. l.Warnf("Failed to remove pending folder entry: %v", err)
  81. }
  82. }
  83. // RemovePendingFolder removes all entries matching a specific folder ID.
  84. func (db *Lowlevel) RemovePendingFolder(id string) {
  85. iter, err := db.NewPrefixIterator([]byte{KeyTypePendingFolder})
  86. if err != nil {
  87. l.Infof("Could not iterate through pending folder entries: %v", err)
  88. return
  89. }
  90. defer iter.Release()
  91. for iter.Next() {
  92. if id != string(db.keyer.FolderFromPendingFolderKey(iter.Key())) {
  93. continue
  94. }
  95. if err := db.Delete(iter.Key()); err != nil {
  96. l.Warnf("Failed to remove pending folder entry: %v", err)
  97. }
  98. }
  99. }
  100. // Consolidated information about a pending folder
  101. type PendingFolder struct {
  102. OfferedBy map[protocol.DeviceID]ObservedFolder `json:"offeredBy"`
  103. }
  104. func (db *Lowlevel) PendingFolders() (map[string]PendingFolder, error) {
  105. return db.PendingFoldersForDevice(protocol.EmptyDeviceID)
  106. }
  107. // PendingFoldersForDevice enumerates only entries matching the given device ID, unless it
  108. // is EmptyDeviceID. Invalid ones are dropped from the database after a warning log
  109. // message, as a side-effect.
  110. func (db *Lowlevel) PendingFoldersForDevice(device protocol.DeviceID) (map[string]PendingFolder, error) {
  111. var err error
  112. prefixKey := []byte{KeyTypePendingFolder}
  113. if device != protocol.EmptyDeviceID {
  114. prefixKey, err = db.keyer.GeneratePendingFolderKey(nil, device[:], nil)
  115. if err != nil {
  116. return nil, err
  117. }
  118. }
  119. iter, err := db.NewPrefixIterator(prefixKey)
  120. if err != nil {
  121. return nil, err
  122. }
  123. defer iter.Release()
  124. res := make(map[string]PendingFolder)
  125. for iter.Next() {
  126. keyDev, ok := db.keyer.DeviceFromPendingFolderKey(iter.Key())
  127. deviceID, err := protocol.DeviceIDFromBytes(keyDev)
  128. var of ObservedFolder
  129. var folderID string
  130. if !ok || err != nil {
  131. goto deleteKey
  132. }
  133. if folderID = string(db.keyer.FolderFromPendingFolderKey(iter.Key())); len(folderID) < 1 {
  134. goto deleteKey
  135. }
  136. if err = of.Unmarshal(iter.Value()); err != nil {
  137. goto deleteKey
  138. }
  139. if _, ok := res[folderID]; !ok {
  140. res[folderID] = PendingFolder{
  141. OfferedBy: map[protocol.DeviceID]ObservedFolder{},
  142. }
  143. }
  144. res[folderID].OfferedBy[deviceID] = of
  145. continue
  146. deleteKey:
  147. // Deleting invalid entries is the only possible "repair" measure and
  148. // appropriate for the importance of pending entries. They will come back
  149. // soon if still relevant.
  150. l.Infof("Invalid pending folder entry, deleting from database: %x", iter.Key())
  151. if err := db.Delete(iter.Key()); err != nil {
  152. return nil, err
  153. }
  154. }
  155. return res, nil
  156. }