folderdb_open.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (C) 2025 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 sqlite
  7. import (
  8. "time"
  9. "github.com/syncthing/syncthing/lib/protocol"
  10. )
  11. type folderDB struct {
  12. folderID string
  13. *baseDB
  14. localDeviceIdx int64
  15. deleteRetention time.Duration
  16. }
  17. func openFolderDB(folder, path string, deleteRetention time.Duration) (*folderDB, error) {
  18. pragmas := []string{
  19. "journal_mode = WAL",
  20. "optimize = 0x10002",
  21. "auto_vacuum = INCREMENTAL",
  22. "default_temp_store = MEMORY",
  23. "temp_store = MEMORY",
  24. }
  25. schemas := []string{
  26. "sql/schema/common/*",
  27. "sql/schema/folder/*",
  28. }
  29. base, err := openBase(path, maxDBConns, pragmas, schemas, nil)
  30. if err != nil {
  31. return nil, err
  32. }
  33. fdb := &folderDB{
  34. folderID: folder,
  35. baseDB: base,
  36. deleteRetention: deleteRetention,
  37. }
  38. _ = fdb.PutKV("folderID", []byte(folder))
  39. // Touch device IDs that should always exist and have a low index
  40. // numbers, and will never change
  41. fdb.localDeviceIdx, _ = fdb.deviceIdxLocked(protocol.LocalDeviceID)
  42. fdb.tplInput["LocalDeviceIdx"] = fdb.localDeviceIdx
  43. return fdb, nil
  44. }
  45. // Open the database with options suitable for the migration inserts. This
  46. // is not a safe mode of operation for normal processing, use only for bulk
  47. // inserts with a close afterwards.
  48. func openFolderDBForMigration(folder, path string, deleteRetention time.Duration) (*folderDB, error) {
  49. pragmas := []string{
  50. "journal_mode = OFF",
  51. "default_temp_store = MEMORY",
  52. "temp_store = MEMORY",
  53. "foreign_keys = 0",
  54. "synchronous = 0",
  55. "locking_mode = EXCLUSIVE",
  56. }
  57. schemas := []string{
  58. "sql/schema/common/*",
  59. "sql/schema/folder/*",
  60. }
  61. base, err := openBase(path, 1, pragmas, schemas, nil)
  62. if err != nil {
  63. return nil, err
  64. }
  65. fdb := &folderDB{
  66. folderID: folder,
  67. baseDB: base,
  68. deleteRetention: deleteRetention,
  69. }
  70. // Touch device IDs that should always exist and have a low index
  71. // numbers, and will never change
  72. fdb.localDeviceIdx, _ = fdb.deviceIdxLocked(protocol.LocalDeviceID)
  73. fdb.tplInput["LocalDeviceIdx"] = fdb.localDeviceIdx
  74. return fdb, nil
  75. }
  76. func (s *folderDB) deviceIdxLocked(deviceID protocol.DeviceID) (int64, error) {
  77. devStr := deviceID.String()
  78. if _, err := s.stmt(`
  79. INSERT OR IGNORE INTO devices(device_id)
  80. VALUES (?)
  81. `).Exec(devStr); err != nil {
  82. return 0, wrap(err)
  83. }
  84. var idx int64
  85. if err := s.stmt(`
  86. SELECT idx FROM devices
  87. WHERE device_id = ?
  88. `).Get(&idx, devStr); err != nil {
  89. return 0, wrap(err)
  90. }
  91. return idx, nil
  92. }