schemaupdater.go 26 KB

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