1
0

transactions.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. // Copyright (C) 2014 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. "errors"
  10. "github.com/syncthing/syncthing/lib/osutil"
  11. "github.com/syncthing/syncthing/lib/db/backend"
  12. "github.com/syncthing/syncthing/lib/protocol"
  13. )
  14. var errEntryFromGlobalMissing = errors.New("device present in global list but missing as device/fileinfo entry")
  15. // A readOnlyTransaction represents a database snapshot.
  16. type readOnlyTransaction struct {
  17. backend.ReadTransaction
  18. keyer keyer
  19. }
  20. func (db *Lowlevel) newReadOnlyTransaction() (readOnlyTransaction, error) {
  21. tran, err := db.NewReadTransaction()
  22. if err != nil {
  23. return readOnlyTransaction{}, err
  24. }
  25. return readOnlyTransaction{
  26. ReadTransaction: tran,
  27. keyer: db.keyer,
  28. }, nil
  29. }
  30. func (t readOnlyTransaction) close() {
  31. t.Release()
  32. }
  33. func (t readOnlyTransaction) getFile(folder, device, file []byte) (protocol.FileInfo, bool, error) {
  34. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, device, file)
  35. if err != nil {
  36. return protocol.FileInfo{}, false, err
  37. }
  38. return t.getFileByKey(key)
  39. }
  40. func (t readOnlyTransaction) getFileByKey(key []byte) (protocol.FileInfo, bool, error) {
  41. f, ok, err := t.getFileTrunc(key, false)
  42. if err != nil || !ok {
  43. return protocol.FileInfo{}, false, err
  44. }
  45. return f.(protocol.FileInfo), true, nil
  46. }
  47. func (t readOnlyTransaction) getFileTrunc(key []byte, trunc bool) (FileIntf, bool, error) {
  48. bs, err := t.Get(key)
  49. if backend.IsNotFound(err) {
  50. return nil, false, nil
  51. }
  52. if err != nil {
  53. return nil, false, err
  54. }
  55. f, err := t.unmarshalTrunc(bs, trunc)
  56. if backend.IsNotFound(err) {
  57. return nil, false, nil
  58. }
  59. if err != nil {
  60. return nil, false, err
  61. }
  62. return f, true, nil
  63. }
  64. func (t readOnlyTransaction) unmarshalTrunc(bs []byte, trunc bool) (FileIntf, error) {
  65. if trunc {
  66. var tf FileInfoTruncated
  67. err := tf.Unmarshal(bs)
  68. if err != nil {
  69. return nil, err
  70. }
  71. return tf, nil
  72. }
  73. var fi protocol.FileInfo
  74. if err := fi.Unmarshal(bs); err != nil {
  75. return nil, err
  76. }
  77. if err := t.fillFileInfo(&fi); err != nil {
  78. return nil, err
  79. }
  80. return fi, nil
  81. }
  82. // fillFileInfo follows the (possible) indirection of blocks and fills it out.
  83. func (t readOnlyTransaction) fillFileInfo(fi *protocol.FileInfo) error {
  84. var key []byte
  85. if len(fi.Blocks) == 0 && len(fi.BlocksHash) != 0 {
  86. // The blocks list is indirected and we need to load it.
  87. key = t.keyer.GenerateBlockListKey(key, fi.BlocksHash)
  88. bs, err := t.Get(key)
  89. if err != nil {
  90. return err
  91. }
  92. var bl BlockList
  93. if err := bl.Unmarshal(bs); err != nil {
  94. return err
  95. }
  96. fi.Blocks = bl.Blocks
  97. }
  98. return nil
  99. }
  100. func (t readOnlyTransaction) getGlobalVersions(keyBuf, folder, file []byte) (VersionList, error) {
  101. var err error
  102. keyBuf, err = t.keyer.GenerateGlobalVersionKey(keyBuf, folder, file)
  103. if err != nil {
  104. return VersionList{}, err
  105. }
  106. return t.getGlobalVersionsByKey(keyBuf)
  107. }
  108. func (t readOnlyTransaction) getGlobalVersionsByKey(key []byte) (VersionList, error) {
  109. bs, err := t.Get(key)
  110. if err != nil {
  111. return VersionList{}, err
  112. }
  113. var vl VersionList
  114. if err := vl.Unmarshal(bs); err != nil {
  115. return VersionList{}, err
  116. }
  117. return vl, nil
  118. }
  119. func (t readOnlyTransaction) getGlobal(keyBuf, folder, file []byte, truncate bool) ([]byte, FileIntf, bool, error) {
  120. vl, err := t.getGlobalVersions(keyBuf, folder, file)
  121. if backend.IsNotFound(err) {
  122. return keyBuf, nil, false, nil
  123. } else if err != nil {
  124. return nil, nil, false, err
  125. }
  126. if len(vl.Versions) == 0 {
  127. return nil, nil, false, nil
  128. }
  129. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, vl.Versions[0].Device, file)
  130. if err != nil {
  131. return nil, nil, false, err
  132. }
  133. fi, ok, err := t.getFileTrunc(keyBuf, truncate)
  134. if err != nil || !ok {
  135. return keyBuf, nil, false, err
  136. }
  137. return keyBuf, fi, true, nil
  138. }
  139. func (t *readOnlyTransaction) withHave(folder, device, prefix []byte, truncate bool, fn Iterator) error {
  140. if len(prefix) > 0 {
  141. unslashedPrefix := prefix
  142. if bytes.HasSuffix(prefix, []byte{'/'}) {
  143. unslashedPrefix = unslashedPrefix[:len(unslashedPrefix)-1]
  144. } else {
  145. prefix = append(prefix, '/')
  146. }
  147. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, device, unslashedPrefix)
  148. if err != nil {
  149. return err
  150. }
  151. if f, ok, err := t.getFileTrunc(key, truncate); err != nil {
  152. return err
  153. } else if ok && !fn(f) {
  154. return nil
  155. }
  156. }
  157. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, device, prefix)
  158. if err != nil {
  159. return err
  160. }
  161. dbi, err := t.NewPrefixIterator(key)
  162. if err != nil {
  163. return err
  164. }
  165. defer dbi.Release()
  166. for dbi.Next() {
  167. name := t.keyer.NameFromDeviceFileKey(dbi.Key())
  168. if len(prefix) > 0 && !bytes.HasPrefix(name, prefix) {
  169. return nil
  170. }
  171. f, err := t.unmarshalTrunc(dbi.Value(), truncate)
  172. if err != nil {
  173. l.Debugln("unmarshal error:", err)
  174. continue
  175. }
  176. if !fn(f) {
  177. return nil
  178. }
  179. }
  180. return dbi.Error()
  181. }
  182. func (t *readOnlyTransaction) withHaveSequence(folder []byte, startSeq int64, fn Iterator) error {
  183. first, err := t.keyer.GenerateSequenceKey(nil, folder, startSeq)
  184. if err != nil {
  185. return err
  186. }
  187. last, err := t.keyer.GenerateSequenceKey(nil, folder, maxInt64)
  188. if err != nil {
  189. return err
  190. }
  191. dbi, err := t.NewRangeIterator(first, last)
  192. if err != nil {
  193. return err
  194. }
  195. defer dbi.Release()
  196. for dbi.Next() {
  197. f, ok, err := t.getFileByKey(dbi.Value())
  198. if err != nil {
  199. return err
  200. }
  201. if !ok {
  202. l.Debugln("missing file for sequence number", t.keyer.SequenceFromSequenceKey(dbi.Key()))
  203. continue
  204. }
  205. if shouldDebug() {
  206. if seq := t.keyer.SequenceFromSequenceKey(dbi.Key()); f.Sequence != seq {
  207. l.Warnf("Sequence index corruption (folder %v, file %v): sequence %d != expected %d", string(folder), f.Name, f.Sequence, seq)
  208. panic("sequence index corruption")
  209. }
  210. }
  211. if !fn(f) {
  212. return nil
  213. }
  214. }
  215. return dbi.Error()
  216. }
  217. func (t *readOnlyTransaction) withGlobal(folder, prefix []byte, truncate bool, fn Iterator) error {
  218. if len(prefix) > 0 {
  219. unslashedPrefix := prefix
  220. if bytes.HasSuffix(prefix, []byte{'/'}) {
  221. unslashedPrefix = unslashedPrefix[:len(unslashedPrefix)-1]
  222. } else {
  223. prefix = append(prefix, '/')
  224. }
  225. if _, f, ok, err := t.getGlobal(nil, folder, unslashedPrefix, truncate); err != nil {
  226. return err
  227. } else if ok && !fn(f) {
  228. return nil
  229. }
  230. }
  231. key, err := t.keyer.GenerateGlobalVersionKey(nil, folder, prefix)
  232. if err != nil {
  233. return err
  234. }
  235. dbi, err := t.NewPrefixIterator(key)
  236. if err != nil {
  237. return err
  238. }
  239. defer dbi.Release()
  240. var dk []byte
  241. for dbi.Next() {
  242. name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
  243. if len(prefix) > 0 && !bytes.HasPrefix(name, prefix) {
  244. return nil
  245. }
  246. var vl VersionList
  247. if err := vl.Unmarshal(dbi.Value()); err != nil {
  248. return err
  249. }
  250. dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[0].Device, name)
  251. if err != nil {
  252. return err
  253. }
  254. f, ok, err := t.getFileTrunc(dk, truncate)
  255. if err != nil {
  256. return err
  257. }
  258. if !ok {
  259. continue
  260. }
  261. if !fn(f) {
  262. return nil
  263. }
  264. }
  265. if err != nil {
  266. return err
  267. }
  268. return dbi.Error()
  269. }
  270. func (t *readOnlyTransaction) withBlocksHash(folder, hash []byte, iterator Iterator) error {
  271. key, err := t.keyer.GenerateBlockListMapKey(nil, folder, hash, nil)
  272. if err != nil {
  273. return err
  274. }
  275. iter, err := t.NewPrefixIterator(key)
  276. if err != nil {
  277. return err
  278. }
  279. defer iter.Release()
  280. for iter.Next() {
  281. file := string(t.keyer.NameFromBlockListMapKey(iter.Key()))
  282. f, ok, err := t.getFile(folder, protocol.LocalDeviceID[:], []byte(osutil.NormalizedFilename(file)))
  283. if err != nil {
  284. return err
  285. }
  286. if !ok {
  287. continue
  288. }
  289. f.Name = osutil.NativeFilename(f.Name)
  290. if !bytes.Equal(f.BlocksHash, hash) {
  291. l.Warnf("Mismatching block map list hashes: got %x expected %x", f.BlocksHash, hash)
  292. continue
  293. }
  294. if f.IsDeleted() || f.IsInvalid() || f.IsDirectory() || f.IsSymlink() {
  295. l.Warnf("Found something of unexpected type in block list map: %s", f)
  296. continue
  297. }
  298. if !iterator(f) {
  299. break
  300. }
  301. }
  302. return iter.Error()
  303. }
  304. func (t *readOnlyTransaction) availability(folder, file []byte) ([]protocol.DeviceID, error) {
  305. vl, err := t.getGlobalVersions(nil, folder, file)
  306. if backend.IsNotFound(err) {
  307. return nil, nil
  308. }
  309. if err != nil {
  310. return nil, err
  311. }
  312. var devices []protocol.DeviceID
  313. for _, v := range vl.Versions {
  314. if !v.Version.Equal(vl.Versions[0].Version) {
  315. break
  316. }
  317. if v.Invalid {
  318. continue
  319. }
  320. n := protocol.DeviceIDFromBytes(v.Device)
  321. devices = append(devices, n)
  322. }
  323. return devices, nil
  324. }
  325. func (t *readOnlyTransaction) withNeed(folder, device []byte, truncate bool, fn Iterator) error {
  326. if bytes.Equal(device, protocol.LocalDeviceID[:]) {
  327. return t.withNeedLocal(folder, truncate, fn)
  328. }
  329. key, err := t.keyer.GenerateGlobalVersionKey(nil, folder, nil)
  330. if err != nil {
  331. return err
  332. }
  333. dbi, err := t.NewPrefixIterator(key.WithoutName())
  334. if err != nil {
  335. return err
  336. }
  337. defer dbi.Release()
  338. var dk []byte
  339. devID := protocol.DeviceIDFromBytes(device)
  340. for dbi.Next() {
  341. var vl VersionList
  342. if err := vl.Unmarshal(dbi.Value()); err != nil {
  343. return err
  344. }
  345. globalFV := vl.Versions[0]
  346. haveFV, have := vl.Get(device)
  347. if !need(globalFV, have, haveFV.Version) {
  348. continue
  349. }
  350. name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
  351. dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, globalFV.Device, name)
  352. if err != nil {
  353. return err
  354. }
  355. gf, ok, err := t.getFileTrunc(dk, truncate)
  356. if err != nil {
  357. return err
  358. }
  359. if !ok {
  360. return errEntryFromGlobalMissing
  361. }
  362. l.Debugf("need folder=%q device=%v name=%q have=%v invalid=%v haveV=%v globalV=%v globalDev=%v", folder, devID, name, have, haveFV.Invalid, haveFV.Version, globalFV.Version, globalFV.Device)
  363. if !fn(gf) {
  364. return dbi.Error()
  365. }
  366. }
  367. return dbi.Error()
  368. }
  369. func (t *readOnlyTransaction) withNeedLocal(folder []byte, truncate bool, fn Iterator) error {
  370. key, err := t.keyer.GenerateNeedFileKey(nil, folder, nil)
  371. if err != nil {
  372. return err
  373. }
  374. dbi, err := t.NewPrefixIterator(key.WithoutName())
  375. if err != nil {
  376. return err
  377. }
  378. defer dbi.Release()
  379. var keyBuf []byte
  380. var f FileIntf
  381. var ok bool
  382. for dbi.Next() {
  383. keyBuf, f, ok, err = t.getGlobal(keyBuf, folder, t.keyer.NameFromGlobalVersionKey(dbi.Key()), truncate)
  384. if err != nil {
  385. return err
  386. }
  387. if !ok {
  388. continue
  389. }
  390. if !fn(f) {
  391. return nil
  392. }
  393. }
  394. return dbi.Error()
  395. }
  396. // A readWriteTransaction is a readOnlyTransaction plus a batch for writes.
  397. // The batch will be committed on close() or by checkFlush() if it exceeds the
  398. // batch size.
  399. type readWriteTransaction struct {
  400. backend.WriteTransaction
  401. readOnlyTransaction
  402. }
  403. func (db *Lowlevel) newReadWriteTransaction() (readWriteTransaction, error) {
  404. tran, err := db.NewWriteTransaction()
  405. if err != nil {
  406. return readWriteTransaction{}, err
  407. }
  408. return readWriteTransaction{
  409. WriteTransaction: tran,
  410. readOnlyTransaction: readOnlyTransaction{
  411. ReadTransaction: tran,
  412. keyer: db.keyer,
  413. },
  414. }, nil
  415. }
  416. func (t readWriteTransaction) Commit() error {
  417. t.readOnlyTransaction.close()
  418. return t.WriteTransaction.Commit()
  419. }
  420. func (t readWriteTransaction) close() {
  421. t.readOnlyTransaction.close()
  422. t.WriteTransaction.Release()
  423. }
  424. // putFile stores a file in the database, taking care of indirected fields.
  425. // Set the truncated flag when putting a file that deliberatly can have an
  426. // empty block list but a non-empty block list hash. This should normally be
  427. // false.
  428. func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo, truncated bool) error {
  429. var bkey []byte
  430. // Always set the blocks hash when there are blocks. Leave the blocks
  431. // hash alone when there are no blocks and we might be putting a
  432. // "truncated" FileInfo (no blocks, but the hash reference is live).
  433. if len(fi.Blocks) > 0 {
  434. fi.BlocksHash = protocol.BlocksHash(fi.Blocks)
  435. } else if !truncated {
  436. fi.BlocksHash = nil
  437. }
  438. // Indirect the blocks if the block list is large enough.
  439. if len(fi.Blocks) > blocksIndirectionCutoff {
  440. bkey = t.keyer.GenerateBlockListKey(bkey, fi.BlocksHash)
  441. if _, err := t.Get(bkey); backend.IsNotFound(err) {
  442. // Marshal the block list and save it
  443. blocksBs := mustMarshal(&BlockList{Blocks: fi.Blocks})
  444. if err := t.Put(bkey, blocksBs); err != nil {
  445. return err
  446. }
  447. } else if err != nil {
  448. return err
  449. }
  450. fi.Blocks = nil
  451. }
  452. fiBs := mustMarshal(&fi)
  453. return t.Put(fkey, fiBs)
  454. }
  455. // updateGlobal adds this device+version to the version list for the given
  456. // file. If the device is already present in the list, the version is updated.
  457. // If the file does not have an entry in the global list, it is created.
  458. func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, file protocol.FileInfo, meta *metadataTracker) ([]byte, bool, error) {
  459. deviceID := protocol.DeviceIDFromBytes(device)
  460. l.Debugf("update global; folder=%q device=%v file=%q version=%v invalid=%v", folder, deviceID, file.Name, file.Version, file.IsInvalid())
  461. fl, err := t.getGlobalVersionsByKey(gk)
  462. if err != nil && !backend.IsNotFound(err) {
  463. return nil, false, err
  464. }
  465. fl, removedFV, removedAt, insertedAt, err := fl.update(folder, device, file, t.readOnlyTransaction)
  466. if err != nil {
  467. return nil, false, err
  468. }
  469. name := []byte(file.Name)
  470. l.Debugf(`new global for "%v" after update: %v`, file.Name, fl)
  471. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  472. return nil, false, err
  473. }
  474. // Only load those from db if actually needed
  475. var gotGlobal, gotOldGlobal bool
  476. var global, oldGlobal FileIntf
  477. globalFV := fl.Versions[0]
  478. var oldGlobalFV FileVersion
  479. haveOldGlobal := false
  480. globalUnaffected := removedAt != 0 && insertedAt != 0
  481. if globalUnaffected {
  482. oldGlobalFV = globalFV
  483. haveOldGlobal = true
  484. } else {
  485. if removedAt == 0 {
  486. oldGlobalFV = removedFV
  487. haveOldGlobal = true
  488. } else if len(fl.Versions) > 1 {
  489. // The previous newest version is now at index 1
  490. oldGlobalFV = fl.Versions[1]
  491. haveOldGlobal = true
  492. }
  493. }
  494. // Check the need of the device that was updated
  495. // Must happen before updating global meta: If this is the first
  496. // item from this device, it will be initialized with the global state.
  497. needBefore := false
  498. if haveOldGlobal {
  499. needBefore = need(oldGlobalFV, removedAt >= 0, removedFV.Version)
  500. }
  501. needNow := need(globalFV, true, fl.Versions[insertedAt].Version)
  502. if needBefore {
  503. if !gotOldGlobal {
  504. if oldGlobal, err = t.updateGlobalGetOldGlobal(keyBuf, folder, name, oldGlobalFV); err != nil {
  505. return nil, false, err
  506. }
  507. gotOldGlobal = true
  508. }
  509. meta.removeNeeded(deviceID, oldGlobal)
  510. if !needNow && bytes.Equal(device, protocol.LocalDeviceID[:]) {
  511. if keyBuf, err = t.updateLocalNeed(keyBuf, folder, name, false); err != nil {
  512. return nil, false, err
  513. }
  514. }
  515. }
  516. if needNow {
  517. if !gotGlobal {
  518. if global, err = t.updateGlobalGetGlobal(keyBuf, folder, name, file, insertedAt, fl); err != nil {
  519. return nil, false, err
  520. }
  521. gotGlobal = true
  522. }
  523. meta.addNeeded(deviceID, global)
  524. if !needBefore && bytes.Equal(device, protocol.LocalDeviceID[:]) {
  525. if keyBuf, err = t.updateLocalNeed(keyBuf, folder, name, true); err != nil {
  526. return nil, false, err
  527. }
  528. }
  529. }
  530. // Update global size counter if necessary
  531. // Necessary here means the first item in the global list was changed,
  532. // even if both new and old are invalid, due to potential change in
  533. // LocalFlags.
  534. if !globalUnaffected {
  535. if global, err = t.updateGlobalGetGlobal(keyBuf, folder, name, file, insertedAt, fl); err != nil {
  536. return nil, false, err
  537. }
  538. gotGlobal = true
  539. if haveOldGlobal {
  540. if oldGlobal, err = t.updateGlobalGetOldGlobal(keyBuf, folder, name, oldGlobalFV); err != nil {
  541. return nil, false, err
  542. }
  543. gotOldGlobal = true
  544. // Remove the old global from the global size counter
  545. meta.removeFile(protocol.GlobalDeviceID, oldGlobal)
  546. }
  547. // Add the new global to the global size counter
  548. meta.addFile(protocol.GlobalDeviceID, global)
  549. }
  550. if globalUnaffected {
  551. // Neither the global state nor the needs of any devices, except
  552. // the one updated, changed.
  553. return keyBuf, true, nil
  554. }
  555. // If global changed, but both the new and old are invalid, noone needed
  556. // the file before and now -> nothing to do.
  557. if global.IsInvalid() && (!haveOldGlobal || oldGlobal.IsInvalid()) {
  558. return keyBuf, true, nil
  559. }
  560. // check for local (if not already done before)
  561. if !bytes.Equal(device, protocol.LocalDeviceID[:]) {
  562. localFV, haveLocal := fl.Get(protocol.LocalDeviceID[:])
  563. needBefore := false
  564. if haveOldGlobal {
  565. needBefore = need(oldGlobalFV, haveLocal, localFV.Version)
  566. }
  567. needNow := need(globalFV, haveLocal, localFV.Version)
  568. if needBefore {
  569. meta.removeNeeded(protocol.LocalDeviceID, oldGlobal)
  570. if !needNow {
  571. if keyBuf, err = t.updateLocalNeed(keyBuf, folder, name, false); err != nil {
  572. return nil, false, err
  573. }
  574. }
  575. }
  576. if need(globalFV, haveLocal, localFV.Version) {
  577. meta.addNeeded(protocol.LocalDeviceID, global)
  578. if !needBefore {
  579. if keyBuf, err = t.updateLocalNeed(keyBuf, folder, name, true); err != nil {
  580. return nil, false, err
  581. }
  582. }
  583. }
  584. }
  585. for _, dev := range meta.devices() {
  586. if bytes.Equal(dev[:], device) {
  587. // Already handled above
  588. continue
  589. }
  590. fv, have := fl.Get(dev[:])
  591. if haveOldGlobal && need(oldGlobalFV, have, fv.Version) {
  592. meta.removeNeeded(dev, oldGlobal)
  593. }
  594. if need(globalFV, have, fv.Version) {
  595. meta.addNeeded(dev, global)
  596. }
  597. }
  598. return keyBuf, true, nil
  599. }
  600. func (t readWriteTransaction) updateGlobalGetGlobal(keyBuf, folder, name []byte, file protocol.FileInfo, insertedAt int, fl VersionList) (FileIntf, error) {
  601. if insertedAt == 0 {
  602. // Inserted a new newest version
  603. return file, nil
  604. }
  605. var err error
  606. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, fl.Versions[0].Device, name)
  607. if err != nil {
  608. return nil, err
  609. }
  610. global, ok, err := t.getFileTrunc(keyBuf, true)
  611. if err != nil {
  612. return nil, err
  613. }
  614. if !ok {
  615. return nil, errEntryFromGlobalMissing
  616. }
  617. return global, nil
  618. }
  619. func (t readWriteTransaction) updateGlobalGetOldGlobal(keyBuf, folder, name []byte, oldGlobalFV FileVersion) (FileIntf, error) {
  620. var err error
  621. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, oldGlobalFV.Device, name)
  622. if err != nil {
  623. return nil, err
  624. }
  625. oldGlobal, ok, err := t.getFileTrunc(keyBuf, true)
  626. if err != nil {
  627. return nil, err
  628. }
  629. if !ok {
  630. return nil, errEntryFromGlobalMissing
  631. }
  632. return oldGlobal, nil
  633. }
  634. func (t readWriteTransaction) updateLocalNeed(keyBuf, folder, name []byte, add bool) ([]byte, error) {
  635. var err error
  636. keyBuf, err = t.keyer.GenerateNeedFileKey(keyBuf, folder, name)
  637. if err != nil {
  638. return nil, err
  639. }
  640. if add {
  641. l.Debugf("local need insert; folder=%q, name=%q", folder, name)
  642. err = t.Put(keyBuf, nil)
  643. } else {
  644. l.Debugf("local need delete; folder=%q, name=%q", folder, name)
  645. err = t.Delete(keyBuf)
  646. }
  647. return keyBuf, err
  648. }
  649. func need(global FileVersion, haveLocal bool, localVersion protocol.Vector) bool {
  650. // We never need an invalid file.
  651. if global.Invalid {
  652. return false
  653. }
  654. // We don't need a deleted file if we don't have it.
  655. if global.Deleted && !haveLocal {
  656. return false
  657. }
  658. // We don't need the global file if we already have the same version.
  659. if haveLocal && localVersion.GreaterEqual(global.Version) {
  660. return false
  661. }
  662. return true
  663. }
  664. // removeFromGlobal removes the device from the global version list for the
  665. // given file. If the version list is empty after this, the file entry is
  666. // removed entirely.
  667. func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device []byte, file []byte, meta *metadataTracker) ([]byte, error) {
  668. deviceID := protocol.DeviceIDFromBytes(device)
  669. l.Debugf("remove from global; folder=%q device=%v file=%q", folder, deviceID, file)
  670. fl, err := t.getGlobalVersionsByKey(gk)
  671. if backend.IsNotFound(err) {
  672. // We might be called to "remove" a global version that doesn't exist
  673. // if the first update for the file is already marked invalid.
  674. return keyBuf, nil
  675. } else if err != nil {
  676. return nil, err
  677. }
  678. fl, removedFV, removedAt := fl.pop(device)
  679. if removedAt == -1 {
  680. // There is no version for the given device
  681. return keyBuf, nil
  682. }
  683. if removedAt != 0 {
  684. l.Debugf("new global after remove: %v", fl)
  685. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  686. return nil, err
  687. }
  688. }
  689. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, device, file)
  690. if err != nil {
  691. return nil, err
  692. }
  693. f, ok, err := t.getFileTrunc(keyBuf, true)
  694. if err != nil {
  695. return nil, err
  696. } else if !ok {
  697. return nil, errEntryFromGlobalMissing
  698. }
  699. meta.removeFile(protocol.GlobalDeviceID, f)
  700. if fv, have := fl.Get(protocol.LocalDeviceID[:]); need(removedFV, have, fv.Version) {
  701. meta.removeNeeded(protocol.LocalDeviceID, f)
  702. if keyBuf, err = t.updateLocalNeed(keyBuf, folder, file, false); err != nil {
  703. return nil, err
  704. }
  705. }
  706. for _, dev := range meta.devices() {
  707. if bytes.Equal(dev[:], device) {
  708. continue
  709. }
  710. if fv, have := fl.Get(dev[:]); need(removedFV, have, fv.Version) {
  711. meta.removeNeeded(deviceID, f)
  712. }
  713. }
  714. if len(fl.Versions) == 0 {
  715. if err := t.Delete(gk); err != nil {
  716. return nil, err
  717. }
  718. return keyBuf, nil
  719. }
  720. globalFV := fl.Versions[0]
  721. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, globalFV.Device, file)
  722. if err != nil {
  723. return nil, err
  724. }
  725. global, ok, err := t.getFileTrunc(keyBuf, true)
  726. if err != nil {
  727. return nil, err
  728. }
  729. if !ok {
  730. return nil, errEntryFromGlobalMissing
  731. }
  732. meta.addFile(protocol.GlobalDeviceID, global)
  733. if !globalFV.Invalid {
  734. if fv, have := fl.Get(protocol.LocalDeviceID[:]); need(globalFV, have, fv.Version) {
  735. meta.addNeeded(deviceID, global)
  736. if keyBuf, err = t.updateLocalNeed(keyBuf, folder, file, true); err != nil {
  737. return nil, err
  738. }
  739. }
  740. for _, dev := range meta.devices() {
  741. if fv, have := fl.Get(dev[:]); need(globalFV, have, fv.Version) {
  742. meta.addNeeded(deviceID, global)
  743. }
  744. }
  745. }
  746. l.Debugf("new global after remove: %v", fl)
  747. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  748. return nil, err
  749. }
  750. return keyBuf, nil
  751. }
  752. func (t readWriteTransaction) deleteKeyPrefix(prefix []byte) error {
  753. dbi, err := t.NewPrefixIterator(prefix)
  754. if err != nil {
  755. return err
  756. }
  757. defer dbi.Release()
  758. for dbi.Next() {
  759. if err := t.Delete(dbi.Key()); err != nil {
  760. return err
  761. }
  762. }
  763. return dbi.Error()
  764. }
  765. func (t *readWriteTransaction) withAllFolderTruncated(folder []byte, fn func(device []byte, f FileInfoTruncated) bool) error {
  766. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, nil, nil)
  767. if err != nil {
  768. return err
  769. }
  770. dbi, err := t.NewPrefixIterator(key.WithoutNameAndDevice())
  771. if err != nil {
  772. return err
  773. }
  774. defer dbi.Release()
  775. var gk, keyBuf []byte
  776. for dbi.Next() {
  777. device, ok := t.keyer.DeviceFromDeviceFileKey(dbi.Key())
  778. if !ok {
  779. // Not having the device in the index is bad. Clear it.
  780. if err := t.Delete(dbi.Key()); err != nil {
  781. return err
  782. }
  783. continue
  784. }
  785. intf, err := t.unmarshalTrunc(dbi.Value(), true)
  786. if err != nil {
  787. return err
  788. }
  789. f := intf.(FileInfoTruncated)
  790. switch f.Name {
  791. case "", ".", "..", "/": // A few obviously invalid filenames
  792. l.Infof("Dropping invalid filename %q from database", f.Name)
  793. name := []byte(f.Name)
  794. gk, err = t.keyer.GenerateGlobalVersionKey(gk, folder, name)
  795. if err != nil {
  796. return err
  797. }
  798. keyBuf, err = t.removeFromGlobal(gk, keyBuf, folder, device, name, nil)
  799. if err != nil {
  800. return err
  801. }
  802. if err := t.Delete(dbi.Key()); err != nil {
  803. return err
  804. }
  805. continue
  806. }
  807. if !fn(device, f) {
  808. return nil
  809. }
  810. }
  811. return dbi.Error()
  812. }
  813. type marshaller interface {
  814. Marshal() ([]byte, error)
  815. }
  816. func mustMarshal(f marshaller) []byte {
  817. bs, err := f.Marshal()
  818. if err != nil {
  819. panic(err)
  820. }
  821. return bs
  822. }