observed.go 4.9 KB

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