schemaupdater.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
  1. // Copyright (C) 2018 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. "bytes"
  9. "fmt"
  10. "sort"
  11. "strings"
  12. "github.com/syncthing/syncthing/lib/db/backend"
  13. "github.com/syncthing/syncthing/lib/protocol"
  14. )
  15. // dbMigrationVersion is for migrations that do not change the schema and thus
  16. // do not put restrictions on downgrades (e.g. for repairs after a bugfix).
  17. const (
  18. dbVersion = 14
  19. dbMigrationVersion = 16
  20. dbMinSyncthingVersion = "v1.9.0"
  21. )
  22. type migration struct {
  23. schemaVersion int64
  24. migrationVersion int64
  25. minSyncthingVersion string
  26. migration func(prevSchema int) error
  27. }
  28. type databaseDowngradeError struct {
  29. minSyncthingVersion string
  30. }
  31. func (e *databaseDowngradeError) Error() string {
  32. if e.minSyncthingVersion == "" {
  33. return "newer Syncthing required"
  34. }
  35. return fmt.Sprintf("Syncthing %s required", e.minSyncthingVersion)
  36. }
  37. // UpdateSchema updates a possibly outdated database to the current schema and
  38. // also does repairs where necessary.
  39. func UpdateSchema(db *Lowlevel) error {
  40. updater := &schemaUpdater{db}
  41. return updater.updateSchema()
  42. }
  43. type schemaUpdater struct {
  44. *Lowlevel
  45. }
  46. func (db *schemaUpdater) updateSchema() error {
  47. // Updating the schema can touch any and all parts of the database. Make
  48. // sure we do not run GC concurrently with schema migrations.
  49. db.gcMut.Lock()
  50. defer db.gcMut.Unlock()
  51. miscDB := NewMiscDataNamespace(db.Lowlevel)
  52. prevVersion, _, err := miscDB.Int64("dbVersion")
  53. if err != nil {
  54. return err
  55. }
  56. if prevVersion > dbVersion {
  57. err := &databaseDowngradeError{}
  58. if minSyncthingVersion, ok, dbErr := miscDB.String("dbMinSyncthingVersion"); dbErr != nil {
  59. return dbErr
  60. } else if ok {
  61. err.minSyncthingVersion = minSyncthingVersion
  62. }
  63. return err
  64. }
  65. prevMigration, _, err := miscDB.Int64("dbMigrationVersion")
  66. if err != nil {
  67. return err
  68. }
  69. // Cover versions before adding `dbMigrationVersion` (== 0) and possible future weirdness.
  70. if prevMigration < prevVersion {
  71. prevMigration = prevVersion
  72. }
  73. if prevVersion == dbVersion && prevMigration >= dbMigrationVersion {
  74. return nil
  75. }
  76. migrations := []migration{
  77. {1, 1, "v0.14.0", db.updateSchema0to1},
  78. {2, 2, "v0.14.46", db.updateSchema1to2},
  79. {3, 3, "v0.14.48", db.updateSchema2to3},
  80. {5, 5, "v0.14.49", db.updateSchemaTo5},
  81. {6, 6, "v0.14.50", db.updateSchema5to6},
  82. {7, 7, "v0.14.53", db.updateSchema6to7},
  83. {9, 9, "v1.4.0", db.updateSchemaTo9},
  84. {10, 10, "v1.6.0", db.updateSchemaTo10},
  85. {11, 11, "v1.6.0", db.updateSchemaTo11},
  86. {13, 13, "v1.7.0", db.updateSchemaTo13},
  87. {14, 14, "v1.9.0", db.updateSchemaTo14},
  88. {14, 16, "v1.9.0", db.checkRepairMigration},
  89. }
  90. for _, m := range migrations {
  91. if prevMigration < m.migrationVersion {
  92. l.Infof("Running database migration %d...", m.migrationVersion)
  93. if err := m.migration(int(prevVersion)); err != nil {
  94. return fmt.Errorf("failed to do migration %v: %w", m.migrationVersion, err)
  95. }
  96. if err := db.writeVersions(m, miscDB); err != nil {
  97. return fmt.Errorf("failed to write versions after migration %v: %w", m.migrationVersion, err)
  98. }
  99. }
  100. }
  101. if err := db.writeVersions(migration{
  102. schemaVersion: dbVersion,
  103. migrationVersion: dbMigrationVersion,
  104. minSyncthingVersion: dbMinSyncthingVersion,
  105. }, miscDB); err != nil {
  106. return fmt.Errorf("failed to write versions after migrations: %w", err)
  107. }
  108. l.Infoln("Compacting database after migration...")
  109. return db.Compact()
  110. }
  111. func (*schemaUpdater) writeVersions(m migration, miscDB *NamespacedKV) error {
  112. if err := miscDB.PutInt64("dbVersion", m.schemaVersion); err != nil && err == nil {
  113. return err
  114. }
  115. if err := miscDB.PutString("dbMinSyncthingVersion", m.minSyncthingVersion); err != nil && err == nil {
  116. return err
  117. }
  118. if err := miscDB.PutInt64("dbMigrationVersion", m.migrationVersion); err != nil && err == nil {
  119. return err
  120. }
  121. return nil
  122. }
  123. func (db *schemaUpdater) updateSchema0to1(_ int) error {
  124. t, err := db.newReadWriteTransaction()
  125. if err != nil {
  126. return err
  127. }
  128. defer t.close()
  129. dbi, err := t.NewPrefixIterator([]byte{KeyTypeDevice})
  130. if err != nil {
  131. return err
  132. }
  133. defer dbi.Release()
  134. symlinkConv := 0
  135. changedFolders := make(map[string]struct{})
  136. ignAdded := 0
  137. var gk []byte
  138. ro := t.readOnlyTransaction
  139. for dbi.Next() {
  140. folder, ok := db.keyer.FolderFromDeviceFileKey(dbi.Key())
  141. if !ok {
  142. // not having the folder in the index is bad; delete and continue
  143. if err := t.Delete(dbi.Key()); err != nil {
  144. return err
  145. }
  146. continue
  147. }
  148. device, ok := db.keyer.DeviceFromDeviceFileKey(dbi.Key())
  149. if !ok {
  150. // not having the device in the index is bad; delete and continue
  151. if err := t.Delete(dbi.Key()); err != nil {
  152. return err
  153. }
  154. continue
  155. }
  156. name := db.keyer.NameFromDeviceFileKey(dbi.Key())
  157. // Remove files with absolute path (see #4799)
  158. if strings.HasPrefix(string(name), "/") {
  159. if _, ok := changedFolders[string(folder)]; !ok {
  160. changedFolders[string(folder)] = struct{}{}
  161. }
  162. if err := t.Delete(dbi.Key()); err != nil {
  163. return err
  164. }
  165. gk, err = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
  166. if err != nil {
  167. return err
  168. }
  169. fl, err := getGlobalVersionsByKeyBefore11(gk, ro)
  170. if backend.IsNotFound(err) {
  171. // Shouldn't happen, but not critical.
  172. continue
  173. } else if err != nil {
  174. return err
  175. }
  176. _, _ = fl.pop(device)
  177. if len(fl.Versions) == 0 {
  178. err = t.Delete(gk)
  179. } else {
  180. err = t.Put(gk, mustMarshal(&fl))
  181. }
  182. if err != nil {
  183. return err
  184. }
  185. continue
  186. }
  187. // Change SYMLINK_FILE and SYMLINK_DIRECTORY types to the current SYMLINK
  188. // type (previously SYMLINK_UNKNOWN). It does this for all devices, both
  189. // local and remote, and does not reset delta indexes. It shouldn't really
  190. // matter what the symlink type is, but this cleans it up for a possible
  191. // future when SYMLINK_FILE and SYMLINK_DIRECTORY are no longer understood.
  192. var f protocol.FileInfo
  193. if err := f.Unmarshal(dbi.Value()); err != nil {
  194. // probably can't happen
  195. continue
  196. }
  197. if f.Type == protocol.FileInfoTypeSymlinkDirectory || f.Type == protocol.FileInfoTypeSymlinkFile {
  198. f.Type = protocol.FileInfoTypeSymlink
  199. bs, err := f.Marshal()
  200. if err != nil {
  201. panic("can't happen: " + err.Error())
  202. }
  203. if err := t.Put(dbi.Key(), bs); err != nil {
  204. return err
  205. }
  206. symlinkConv++
  207. }
  208. // Add invalid files to global list
  209. if f.IsInvalid() {
  210. gk, err = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
  211. if err != nil {
  212. return err
  213. }
  214. fl, err := getGlobalVersionsByKeyBefore11(gk, ro)
  215. if err != nil && !backend.IsNotFound(err) {
  216. return err
  217. }
  218. i := 0
  219. i = sort.Search(len(fl.Versions), func(j int) bool {
  220. return fl.Versions[j].Invalid
  221. })
  222. for ; i < len(fl.Versions); i++ {
  223. ordering := fl.Versions[i].Version.Compare(f.Version)
  224. shouldInsert := ordering == protocol.Equal
  225. if !shouldInsert {
  226. shouldInsert, err = shouldInsertBefore(ordering, folder, fl.Versions[i].Device, true, f, ro)
  227. if err != nil {
  228. return err
  229. }
  230. }
  231. if shouldInsert {
  232. nv := FileVersionDeprecated{
  233. Device: device,
  234. Version: f.Version,
  235. Invalid: true,
  236. }
  237. fl.insertAt(i, nv)
  238. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  239. return err
  240. }
  241. if _, ok := changedFolders[string(folder)]; !ok {
  242. changedFolders[string(folder)] = struct{}{}
  243. }
  244. ignAdded++
  245. break
  246. }
  247. }
  248. }
  249. if err := t.Checkpoint(); err != nil {
  250. return err
  251. }
  252. }
  253. dbi.Release()
  254. if err != dbi.Error() {
  255. return err
  256. }
  257. return t.Commit()
  258. }
  259. // updateSchema1to2 introduces a sequenceKey->deviceKey bucket for local items
  260. // to allow iteration in sequence order (simplifies sending indexes).
  261. func (db *schemaUpdater) updateSchema1to2(_ int) error {
  262. t, err := db.newReadWriteTransaction()
  263. if err != nil {
  264. return err
  265. }
  266. defer t.close()
  267. var sk []byte
  268. var dk []byte
  269. for _, folderStr := range db.ListFolders() {
  270. folder := []byte(folderStr)
  271. var putErr error
  272. err := t.withHave(folder, protocol.LocalDeviceID[:], nil, true, func(f protocol.FileIntf) bool {
  273. sk, putErr = db.keyer.GenerateSequenceKey(sk, folder, f.SequenceNo())
  274. if putErr != nil {
  275. return false
  276. }
  277. dk, putErr = db.keyer.GenerateDeviceFileKey(dk, folder, protocol.LocalDeviceID[:], []byte(f.FileName()))
  278. if putErr != nil {
  279. return false
  280. }
  281. putErr = t.Put(sk, dk)
  282. return putErr == nil
  283. })
  284. if putErr != nil {
  285. return putErr
  286. }
  287. if err != nil {
  288. return err
  289. }
  290. }
  291. return t.Commit()
  292. }
  293. // updateSchema2to3 introduces a needKey->nil bucket for locally needed files.
  294. func (db *schemaUpdater) updateSchema2to3(_ int) error {
  295. t, err := db.newReadWriteTransaction()
  296. if err != nil {
  297. return err
  298. }
  299. defer t.close()
  300. var nk []byte
  301. var dk []byte
  302. for _, folderStr := range db.ListFolders() {
  303. folder := []byte(folderStr)
  304. var putErr error
  305. err := withGlobalBefore11(folder, true, func(f protocol.FileIntf) bool {
  306. name := []byte(f.FileName())
  307. dk, putErr = db.keyer.GenerateDeviceFileKey(dk, folder, protocol.LocalDeviceID[:], name)
  308. if putErr != nil {
  309. return false
  310. }
  311. var v protocol.Vector
  312. haveFile, ok, err := t.getFileTrunc(dk, true)
  313. if err != nil {
  314. putErr = err
  315. return false
  316. }
  317. if ok {
  318. v = haveFile.FileVersion()
  319. }
  320. fv := FileVersionDeprecated{
  321. Version: f.FileVersion(),
  322. Invalid: f.IsInvalid(),
  323. Deleted: f.IsDeleted(),
  324. }
  325. if !needDeprecated(fv, ok, v) {
  326. return true
  327. }
  328. nk, putErr = t.keyer.GenerateNeedFileKey(nk, folder, []byte(f.FileName()))
  329. if putErr != nil {
  330. return false
  331. }
  332. putErr = t.Put(nk, nil)
  333. return putErr == nil
  334. }, t.readOnlyTransaction)
  335. if putErr != nil {
  336. return putErr
  337. }
  338. if err != nil {
  339. return err
  340. }
  341. }
  342. return t.Commit()
  343. }
  344. // updateSchemaTo5 resets the need bucket due to bugs existing in the v0.14.49
  345. // release candidates (dbVersion 3 and 4)
  346. // https://github.com/syncthing/syncthing/issues/5007
  347. // https://github.com/syncthing/syncthing/issues/5053
  348. func (db *schemaUpdater) updateSchemaTo5(prevVersion int) error {
  349. if prevVersion != 3 && prevVersion != 4 {
  350. return nil
  351. }
  352. t, err := db.newReadWriteTransaction()
  353. if err != nil {
  354. return err
  355. }
  356. var nk []byte
  357. for _, folderStr := range db.ListFolders() {
  358. nk, err = db.keyer.GenerateNeedFileKey(nk, []byte(folderStr), nil)
  359. if err != nil {
  360. return err
  361. }
  362. if err := t.deleteKeyPrefix(nk[:keyPrefixLen+keyFolderLen]); err != nil {
  363. return err
  364. }
  365. }
  366. if err := t.Commit(); err != nil {
  367. return err
  368. }
  369. return db.updateSchema2to3(2)
  370. }
  371. func (db *schemaUpdater) updateSchema5to6(_ int) error {
  372. // For every local file with the Invalid bit set, clear the Invalid bit and
  373. // set LocalFlags = FlagLocalIgnored.
  374. t, err := db.newReadWriteTransaction()
  375. if err != nil {
  376. return err
  377. }
  378. defer t.close()
  379. var dk []byte
  380. for _, folderStr := range db.ListFolders() {
  381. folder := []byte(folderStr)
  382. var iterErr error
  383. err := t.withHave(folder, protocol.LocalDeviceID[:], nil, false, func(f protocol.FileIntf) bool {
  384. if !f.IsInvalid() {
  385. return true
  386. }
  387. fi := f.(protocol.FileInfo)
  388. fi.RawInvalid = false
  389. fi.LocalFlags = protocol.FlagLocalIgnored
  390. bs, _ := fi.Marshal()
  391. dk, iterErr = db.keyer.GenerateDeviceFileKey(dk, folder, protocol.LocalDeviceID[:], []byte(fi.Name))
  392. if iterErr != nil {
  393. return false
  394. }
  395. if iterErr = t.Put(dk, bs); iterErr != nil {
  396. return false
  397. }
  398. iterErr = t.Checkpoint()
  399. return iterErr == nil
  400. })
  401. if iterErr != nil {
  402. return iterErr
  403. }
  404. if err != nil {
  405. return err
  406. }
  407. }
  408. return t.Commit()
  409. }
  410. // updateSchema6to7 checks whether all currently locally needed files are really
  411. // needed and removes them if not.
  412. func (db *schemaUpdater) updateSchema6to7(_ int) error {
  413. t, err := db.newReadWriteTransaction()
  414. if err != nil {
  415. return err
  416. }
  417. defer t.close()
  418. var gk []byte
  419. var nk []byte
  420. for _, folderStr := range db.ListFolders() {
  421. folder := []byte(folderStr)
  422. var delErr error
  423. err := withNeedLocalBefore11(folder, false, func(f protocol.FileIntf) bool {
  424. name := []byte(f.FileName())
  425. gk, delErr = db.keyer.GenerateGlobalVersionKey(gk, folder, name)
  426. if delErr != nil {
  427. return false
  428. }
  429. svl, err := t.Get(gk)
  430. if err != nil {
  431. // If there is no global list, we hardly need it.
  432. key, err := t.keyer.GenerateNeedFileKey(nk, folder, name)
  433. if err != nil {
  434. delErr = err
  435. return false
  436. }
  437. delErr = t.Delete(key)
  438. return delErr == nil
  439. }
  440. var fl VersionListDeprecated
  441. err = fl.Unmarshal(svl)
  442. if err != nil {
  443. // This can't happen, but it's ignored everywhere else too,
  444. // so lets not act on it.
  445. return true
  446. }
  447. globalFV := FileVersionDeprecated{
  448. Version: f.FileVersion(),
  449. Invalid: f.IsInvalid(),
  450. Deleted: f.IsDeleted(),
  451. }
  452. if localFV, haveLocalFV := fl.Get(protocol.LocalDeviceID[:]); !needDeprecated(globalFV, haveLocalFV, localFV.Version) {
  453. key, err := t.keyer.GenerateNeedFileKey(nk, folder, name)
  454. if err != nil {
  455. delErr = err
  456. return false
  457. }
  458. delErr = t.Delete(key)
  459. }
  460. return delErr == nil
  461. }, t.readOnlyTransaction)
  462. if delErr != nil {
  463. return delErr
  464. }
  465. if err != nil {
  466. return err
  467. }
  468. if err := t.Checkpoint(); err != nil {
  469. return err
  470. }
  471. }
  472. return t.Commit()
  473. }
  474. func (db *schemaUpdater) updateSchemaTo9(prev int) error {
  475. // Loads and rewrites all files with blocks, to deduplicate block lists.
  476. t, err := db.newReadWriteTransaction()
  477. if err != nil {
  478. return err
  479. }
  480. defer t.close()
  481. if err := db.rewriteFiles(t); err != nil {
  482. return err
  483. }
  484. db.recordTime(indirectGCTimeKey)
  485. return t.Commit()
  486. }
  487. func (db *schemaUpdater) rewriteFiles(t readWriteTransaction) error {
  488. it, err := t.NewPrefixIterator([]byte{KeyTypeDevice})
  489. if err != nil {
  490. return err
  491. }
  492. defer it.Release()
  493. for it.Next() {
  494. intf, err := t.unmarshalTrunc(it.Value(), false)
  495. if backend.IsNotFound(err) {
  496. // Unmarshal error due to missing parts (block list), probably
  497. // due to a bad migration in a previous RC. Drop this key, as
  498. // getFile would anyway return this as a "not found" in the
  499. // normal flow of things.
  500. if err := t.Delete(it.Key()); err != nil {
  501. return err
  502. }
  503. continue
  504. } else if err != nil {
  505. return err
  506. }
  507. fi := intf.(protocol.FileInfo)
  508. if fi.Blocks == nil {
  509. continue
  510. }
  511. if err := t.putFile(it.Key(), fi); err != nil {
  512. return err
  513. }
  514. if err := t.Checkpoint(); err != nil {
  515. return err
  516. }
  517. }
  518. it.Release()
  519. return it.Error()
  520. }
  521. func (db *schemaUpdater) updateSchemaTo10(_ int) error {
  522. // Rewrites global lists to include a Deleted flag.
  523. t, err := db.newReadWriteTransaction()
  524. if err != nil {
  525. return err
  526. }
  527. defer t.close()
  528. var buf []byte
  529. for _, folderStr := range db.ListFolders() {
  530. folder := []byte(folderStr)
  531. buf, err = t.keyer.GenerateGlobalVersionKey(buf, folder, nil)
  532. if err != nil {
  533. return err
  534. }
  535. buf = globalVersionKey(buf).WithoutName()
  536. dbi, err := t.NewPrefixIterator(buf)
  537. if err != nil {
  538. return err
  539. }
  540. defer dbi.Release()
  541. for dbi.Next() {
  542. var vl VersionListDeprecated
  543. if err := vl.Unmarshal(dbi.Value()); err != nil {
  544. return err
  545. }
  546. changed := false
  547. name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
  548. for i, fv := range vl.Versions {
  549. buf, err = t.keyer.GenerateDeviceFileKey(buf, folder, fv.Device, name)
  550. if err != nil {
  551. return err
  552. }
  553. f, ok, err := t.getFileTrunc(buf, true)
  554. if !ok {
  555. return errEntryFromGlobalMissing
  556. }
  557. if err != nil {
  558. return err
  559. }
  560. if f.IsDeleted() {
  561. vl.Versions[i].Deleted = true
  562. changed = true
  563. }
  564. }
  565. if changed {
  566. if err := t.Put(dbi.Key(), mustMarshal(&vl)); err != nil {
  567. return err
  568. }
  569. if err := t.Checkpoint(); err != nil {
  570. return err
  571. }
  572. }
  573. }
  574. dbi.Release()
  575. }
  576. // Trigger metadata recalc
  577. if err := t.deleteKeyPrefix([]byte{KeyTypeFolderMeta}); err != nil {
  578. return err
  579. }
  580. return t.Commit()
  581. }
  582. func (db *schemaUpdater) updateSchemaTo11(_ int) error {
  583. // Populates block list map for every folder.
  584. t, err := db.newReadWriteTransaction()
  585. if err != nil {
  586. return err
  587. }
  588. defer t.close()
  589. var dk []byte
  590. for _, folderStr := range db.ListFolders() {
  591. folder := []byte(folderStr)
  592. var putErr error
  593. err := t.withHave(folder, protocol.LocalDeviceID[:], nil, true, func(fi protocol.FileIntf) bool {
  594. f := fi.(FileInfoTruncated)
  595. if f.IsDirectory() || f.IsDeleted() || f.IsSymlink() || f.IsInvalid() || f.BlocksHash == nil {
  596. return true
  597. }
  598. name := []byte(f.FileName())
  599. dk, putErr = db.keyer.GenerateBlockListMapKey(dk, folder, f.BlocksHash, name)
  600. if putErr != nil {
  601. return false
  602. }
  603. if putErr = t.Put(dk, nil); putErr != nil {
  604. return false
  605. }
  606. putErr = t.Checkpoint()
  607. return putErr == nil
  608. })
  609. if putErr != nil {
  610. return putErr
  611. }
  612. if err != nil {
  613. return err
  614. }
  615. }
  616. return t.Commit()
  617. }
  618. func (db *schemaUpdater) updateSchemaTo13(prev int) error {
  619. // Loads and rewrites all files, to deduplicate version vectors.
  620. t, err := db.newReadWriteTransaction()
  621. if err != nil {
  622. return err
  623. }
  624. defer t.close()
  625. if prev < 12 {
  626. if err := db.rewriteFiles(t); err != nil {
  627. return err
  628. }
  629. }
  630. if err := db.rewriteGlobals(t); err != nil {
  631. return err
  632. }
  633. return t.Commit()
  634. }
  635. func (db *schemaUpdater) updateSchemaTo14(_ int) error {
  636. // Checks for missing blocks and marks those entries as requiring a
  637. // rehash/being invalid. The db is checked/repaired afterwards, i.e.
  638. // no care is taken to get metadata and sequences right.
  639. // If the corresponding files changed on disk compared to the global
  640. // version, this will cause a conflict.
  641. var key, gk []byte
  642. for _, folderStr := range db.ListFolders() {
  643. folder := []byte(folderStr)
  644. meta := newMetadataTracker(db.keyer, db.evLogger)
  645. meta.counts.Created = 0 // Recalculate metadata afterwards
  646. t, err := db.newReadWriteTransaction(meta.CommitHook(folder))
  647. if err != nil {
  648. return err
  649. }
  650. defer t.close()
  651. key, err = t.keyer.GenerateDeviceFileKey(key, folder, protocol.LocalDeviceID[:], nil)
  652. if err != nil {
  653. return err
  654. }
  655. it, err := t.NewPrefixIterator(key)
  656. if err != nil {
  657. return err
  658. }
  659. defer it.Release()
  660. for it.Next() {
  661. var fi protocol.FileInfo
  662. if err := fi.Unmarshal(it.Value()); err != nil {
  663. return err
  664. }
  665. if len(fi.Blocks) > 0 || len(fi.BlocksHash) == 0 {
  666. continue
  667. }
  668. key = t.keyer.GenerateBlockListKey(key, fi.BlocksHash)
  669. _, err := t.Get(key)
  670. if err == nil {
  671. continue
  672. }
  673. fi.SetMustRescan()
  674. if err = t.putFile(it.Key(), fi); err != nil {
  675. return err
  676. }
  677. gk, err = t.keyer.GenerateGlobalVersionKey(gk, folder, []byte(fi.Name))
  678. if err != nil {
  679. return err
  680. }
  681. key, _, err = t.updateGlobal(gk, key, folder, protocol.LocalDeviceID[:], fi, meta)
  682. if err != nil {
  683. return err
  684. }
  685. }
  686. it.Release()
  687. if err = t.Commit(); err != nil {
  688. return err
  689. }
  690. t.close()
  691. }
  692. return nil
  693. }
  694. func (db *schemaUpdater) checkRepairMigration(_ int) error {
  695. for _, folder := range db.ListFolders() {
  696. _, err := db.getMetaAndCheckGCLocked(folder)
  697. if err != nil {
  698. return err
  699. }
  700. }
  701. return nil
  702. }
  703. func (db *schemaUpdater) rewriteGlobals(t readWriteTransaction) error {
  704. it, err := t.NewPrefixIterator([]byte{KeyTypeGlobal})
  705. if err != nil {
  706. return err
  707. }
  708. defer it.Release()
  709. for it.Next() {
  710. var vl VersionListDeprecated
  711. if err := vl.Unmarshal(it.Value()); err != nil {
  712. // If we crashed during an earlier migration, some version
  713. // lists might already be in the new format: Skip those.
  714. var nvl VersionList
  715. if nerr := nvl.Unmarshal(it.Value()); nerr == nil {
  716. continue
  717. }
  718. return err
  719. }
  720. if len(vl.Versions) == 0 {
  721. if err := t.Delete(it.Key()); err != nil {
  722. return err
  723. }
  724. }
  725. newVl, err := convertVersionList(vl)
  726. if err != nil {
  727. return err
  728. }
  729. if err := t.Put(it.Key(), mustMarshal(&newVl)); err != nil {
  730. return err
  731. }
  732. if err := t.Checkpoint(); err != nil {
  733. return err
  734. }
  735. }
  736. it.Release()
  737. return it.Error()
  738. }
  739. func convertVersionList(vl VersionListDeprecated) (VersionList, error) {
  740. var newVl VersionList
  741. var newPos, oldPos int
  742. var lastVersion protocol.Vector
  743. for _, fv := range vl.Versions {
  744. if fv.Invalid {
  745. break
  746. }
  747. oldPos++
  748. if len(newVl.RawVersions) > 0 && lastVersion.Equal(fv.Version) {
  749. newVl.RawVersions[newPos].Devices = append(newVl.RawVersions[newPos].Devices, fv.Device)
  750. continue
  751. }
  752. newPos = len(newVl.RawVersions)
  753. newVl.RawVersions = append(newVl.RawVersions, newFileVersion(fv.Device, fv.Version, false, fv.Deleted))
  754. lastVersion = fv.Version
  755. }
  756. if oldPos == len(vl.Versions) {
  757. return newVl, nil
  758. }
  759. if len(newVl.RawVersions) == 0 {
  760. fv := vl.Versions[oldPos]
  761. newVl.RawVersions = []FileVersion{newFileVersion(fv.Device, fv.Version, true, fv.Deleted)}
  762. oldPos++
  763. }
  764. newPos = 0
  765. outer:
  766. for _, fv := range vl.Versions[oldPos:] {
  767. for _, nfv := range newVl.RawVersions[newPos:] {
  768. switch nfv.Version.Compare(fv.Version) {
  769. case protocol.Equal:
  770. newVl.RawVersions[newPos].InvalidDevices = append(newVl.RawVersions[newPos].InvalidDevices, fv.Device)
  771. lastVersion = fv.Version
  772. continue outer
  773. case protocol.Lesser:
  774. newVl.insertAt(newPos, newFileVersion(fv.Device, fv.Version, true, fv.Deleted))
  775. lastVersion = fv.Version
  776. continue outer
  777. case protocol.ConcurrentLesser, protocol.ConcurrentGreater:
  778. // The version is invalid, i.e. it looses anyway,
  779. // no need to check/get the conflicting file.
  780. }
  781. newPos++
  782. }
  783. // Couldn't insert into any existing versions
  784. newVl.RawVersions = append(newVl.RawVersions, newFileVersion(fv.Device, fv.Version, true, fv.Deleted))
  785. lastVersion = fv.Version
  786. newPos++
  787. }
  788. return newVl, nil
  789. }
  790. func getGlobalVersionsByKeyBefore11(key []byte, t readOnlyTransaction) (VersionListDeprecated, error) {
  791. bs, err := t.Get(key)
  792. if err != nil {
  793. return VersionListDeprecated{}, err
  794. }
  795. var vl VersionListDeprecated
  796. if err := vl.Unmarshal(bs); err != nil {
  797. return VersionListDeprecated{}, err
  798. }
  799. return vl, nil
  800. }
  801. func withGlobalBefore11(folder []byte, truncate bool, fn Iterator, t readOnlyTransaction) error {
  802. key, err := t.keyer.GenerateGlobalVersionKey(nil, folder, nil)
  803. if err != nil {
  804. return err
  805. }
  806. dbi, err := t.NewPrefixIterator(key)
  807. if err != nil {
  808. return err
  809. }
  810. defer dbi.Release()
  811. var dk []byte
  812. for dbi.Next() {
  813. name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
  814. var vl VersionListDeprecated
  815. if err := vl.Unmarshal(dbi.Value()); err != nil {
  816. return err
  817. }
  818. dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[0].Device, name)
  819. if err != nil {
  820. return err
  821. }
  822. f, ok, err := t.getFileTrunc(dk, truncate)
  823. if err != nil {
  824. return err
  825. }
  826. if !ok {
  827. continue
  828. }
  829. if !fn(f) {
  830. return nil
  831. }
  832. }
  833. if err != nil {
  834. return err
  835. }
  836. return dbi.Error()
  837. }
  838. func withNeedLocalBefore11(folder []byte, truncate bool, fn Iterator, t readOnlyTransaction) error {
  839. key, err := t.keyer.GenerateNeedFileKey(nil, folder, nil)
  840. if err != nil {
  841. return err
  842. }
  843. dbi, err := t.NewPrefixIterator(key.WithoutName())
  844. if err != nil {
  845. return err
  846. }
  847. defer dbi.Release()
  848. var keyBuf []byte
  849. var f protocol.FileIntf
  850. var ok bool
  851. for dbi.Next() {
  852. keyBuf, f, ok, err = getGlobalBefore11(keyBuf, folder, t.keyer.NameFromGlobalVersionKey(dbi.Key()), truncate, t)
  853. if err != nil {
  854. return err
  855. }
  856. if !ok {
  857. continue
  858. }
  859. if !fn(f) {
  860. return nil
  861. }
  862. }
  863. return dbi.Error()
  864. }
  865. func getGlobalBefore11(keyBuf, folder, file []byte, truncate bool, t readOnlyTransaction) ([]byte, protocol.FileIntf, bool, error) {
  866. keyBuf, err := t.keyer.GenerateGlobalVersionKey(keyBuf, folder, file)
  867. if err != nil {
  868. return nil, nil, false, err
  869. }
  870. bs, err := t.Get(keyBuf)
  871. if backend.IsNotFound(err) {
  872. return keyBuf, nil, false, nil
  873. } else if err != nil {
  874. return nil, nil, false, err
  875. }
  876. var vl VersionListDeprecated
  877. if err := vl.Unmarshal(bs); err != nil {
  878. return nil, nil, false, err
  879. }
  880. if len(vl.Versions) == 0 {
  881. return nil, nil, false, nil
  882. }
  883. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, vl.Versions[0].Device, file)
  884. if err != nil {
  885. return nil, nil, false, err
  886. }
  887. fi, ok, err := t.getFileTrunc(keyBuf, truncate)
  888. if err != nil || !ok {
  889. return keyBuf, nil, false, err
  890. }
  891. return keyBuf, fi, true, nil
  892. }
  893. func (vl *VersionListDeprecated) String() string {
  894. var b bytes.Buffer
  895. var id protocol.DeviceID
  896. b.WriteString("{")
  897. for i, v := range vl.Versions {
  898. if i > 0 {
  899. b.WriteString(", ")
  900. }
  901. copy(id[:], v.Device)
  902. fmt.Fprintf(&b, "{%v, %v}", v.Version, id)
  903. }
  904. b.WriteString("}")
  905. return b.String()
  906. }
  907. func (vl *VersionListDeprecated) pop(device []byte) (FileVersionDeprecated, int) {
  908. for i, v := range vl.Versions {
  909. if bytes.Equal(v.Device, device) {
  910. vl.Versions = append(vl.Versions[:i], vl.Versions[i+1:]...)
  911. return v, i
  912. }
  913. }
  914. return FileVersionDeprecated{}, -1
  915. }
  916. func (vl *VersionListDeprecated) Get(device []byte) (FileVersionDeprecated, bool) {
  917. for _, v := range vl.Versions {
  918. if bytes.Equal(v.Device, device) {
  919. return v, true
  920. }
  921. }
  922. return FileVersionDeprecated{}, false
  923. }
  924. func (vl *VersionListDeprecated) insertAt(i int, v FileVersionDeprecated) {
  925. vl.Versions = append(vl.Versions, FileVersionDeprecated{})
  926. copy(vl.Versions[i+1:], vl.Versions[i:])
  927. vl.Versions[i] = v
  928. }
  929. func needDeprecated(global FileVersionDeprecated, haveLocal bool, localVersion protocol.Vector) bool {
  930. // We never need an invalid file.
  931. if global.Invalid {
  932. return false
  933. }
  934. // We don't need a deleted file if we don't have it.
  935. if global.Deleted && !haveLocal {
  936. return false
  937. }
  938. // We don't need the global file if we already have the same version.
  939. if haveLocal && localVersion.GreaterEqual(global.Version) {
  940. return false
  941. }
  942. return true
  943. }