transactions.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  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/db/backend"
  11. "github.com/syncthing/syncthing/lib/protocol"
  12. )
  13. var errEntryFromGlobalMissing = errors.New("device present in global list but missing as device/fileinfo entry")
  14. // A readOnlyTransaction represents a database snapshot.
  15. type readOnlyTransaction struct {
  16. backend.ReadTransaction
  17. keyer keyer
  18. }
  19. func (db *Lowlevel) newReadOnlyTransaction() (readOnlyTransaction, error) {
  20. tran, err := db.NewReadTransaction()
  21. if err != nil {
  22. return readOnlyTransaction{}, err
  23. }
  24. return readOnlyTransaction{
  25. ReadTransaction: tran,
  26. keyer: db.keyer,
  27. }, nil
  28. }
  29. func (t readOnlyTransaction) close() {
  30. t.Release()
  31. }
  32. func (t readOnlyTransaction) getFile(folder, device, file []byte) (protocol.FileInfo, bool, error) {
  33. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, device, file)
  34. if err != nil {
  35. return protocol.FileInfo{}, false, err
  36. }
  37. return t.getFileByKey(key)
  38. }
  39. func (t readOnlyTransaction) getFileByKey(key []byte) (protocol.FileInfo, bool, error) {
  40. f, ok, err := t.getFileTrunc(key, false)
  41. if err != nil || !ok {
  42. return protocol.FileInfo{}, false, err
  43. }
  44. return f.(protocol.FileInfo), true, nil
  45. }
  46. func (t readOnlyTransaction) getFileTrunc(key []byte, trunc bool) (FileIntf, bool, error) {
  47. bs, err := t.Get(key)
  48. if backend.IsNotFound(err) {
  49. return nil, false, nil
  50. }
  51. if err != nil {
  52. return nil, false, err
  53. }
  54. f, err := t.unmarshalTrunc(bs, trunc)
  55. if backend.IsNotFound(err) {
  56. return nil, false, nil
  57. }
  58. if err != nil {
  59. return nil, false, err
  60. }
  61. return f, true, nil
  62. }
  63. func (t readOnlyTransaction) unmarshalTrunc(bs []byte, trunc bool) (FileIntf, error) {
  64. if trunc {
  65. var tf FileInfoTruncated
  66. err := tf.Unmarshal(bs)
  67. if err != nil {
  68. return nil, err
  69. }
  70. return tf, nil
  71. }
  72. var fi protocol.FileInfo
  73. if err := fi.Unmarshal(bs); err != nil {
  74. return nil, err
  75. }
  76. if err := t.fillFileInfo(&fi); err != nil {
  77. return nil, err
  78. }
  79. return fi, nil
  80. }
  81. // fillFileInfo follows the (possible) indirection of blocks and fills it out.
  82. func (t readOnlyTransaction) fillFileInfo(fi *protocol.FileInfo) error {
  83. var key []byte
  84. if len(fi.Blocks) == 0 && len(fi.BlocksHash) != 0 {
  85. // The blocks list is indirected and we need to load it.
  86. key = t.keyer.GenerateBlockListKey(key, fi.BlocksHash)
  87. bs, err := t.Get(key)
  88. if err != nil {
  89. return err
  90. }
  91. var bl BlockList
  92. if err := bl.Unmarshal(bs); err != nil {
  93. return err
  94. }
  95. fi.Blocks = bl.Blocks
  96. }
  97. return nil
  98. }
  99. func (t readOnlyTransaction) getGlobalVersions(keyBuf, folder, file []byte) (VersionList, error) {
  100. var err error
  101. keyBuf, err = t.keyer.GenerateGlobalVersionKey(keyBuf, folder, file)
  102. if err != nil {
  103. return VersionList{}, err
  104. }
  105. return t.getGlobalVersionsByKey(keyBuf)
  106. }
  107. func (t readOnlyTransaction) getGlobalVersionsByKey(key []byte) (VersionList, error) {
  108. bs, err := t.Get(key)
  109. if err != nil {
  110. return VersionList{}, err
  111. }
  112. var vl VersionList
  113. if err := vl.Unmarshal(bs); err != nil {
  114. return VersionList{}, err
  115. }
  116. return vl, nil
  117. }
  118. func (t readOnlyTransaction) getGlobal(keyBuf, folder, file []byte, truncate bool) ([]byte, FileIntf, bool, error) {
  119. vl, err := t.getGlobalVersions(keyBuf, folder, file)
  120. if backend.IsNotFound(err) {
  121. return keyBuf, nil, false, nil
  122. } else if err != nil {
  123. return nil, nil, false, err
  124. }
  125. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, vl.Versions[0].Device, file)
  126. if err != nil {
  127. return nil, nil, false, err
  128. }
  129. fi, ok, err := t.getFileTrunc(keyBuf, truncate)
  130. if err != nil || !ok {
  131. return keyBuf, nil, false, err
  132. }
  133. return keyBuf, fi, true, nil
  134. }
  135. func (t *readOnlyTransaction) withHave(folder, device, prefix []byte, truncate bool, fn Iterator) error {
  136. if len(prefix) > 0 {
  137. unslashedPrefix := prefix
  138. if bytes.HasSuffix(prefix, []byte{'/'}) {
  139. unslashedPrefix = unslashedPrefix[:len(unslashedPrefix)-1]
  140. } else {
  141. prefix = append(prefix, '/')
  142. }
  143. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, device, unslashedPrefix)
  144. if err != nil {
  145. return err
  146. }
  147. if f, ok, err := t.getFileTrunc(key, true); err != nil {
  148. return err
  149. } else if ok && !fn(f) {
  150. return nil
  151. }
  152. }
  153. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, device, prefix)
  154. if err != nil {
  155. return err
  156. }
  157. dbi, err := t.NewPrefixIterator(key)
  158. if err != nil {
  159. return err
  160. }
  161. defer dbi.Release()
  162. for dbi.Next() {
  163. name := t.keyer.NameFromDeviceFileKey(dbi.Key())
  164. if len(prefix) > 0 && !bytes.HasPrefix(name, prefix) {
  165. return nil
  166. }
  167. f, err := t.unmarshalTrunc(dbi.Value(), truncate)
  168. if err != nil {
  169. l.Debugln("unmarshal error:", err)
  170. continue
  171. }
  172. if !fn(f) {
  173. return nil
  174. }
  175. }
  176. return dbi.Error()
  177. }
  178. func (t *readOnlyTransaction) withHaveSequence(folder []byte, startSeq int64, fn Iterator) error {
  179. first, err := t.keyer.GenerateSequenceKey(nil, folder, startSeq)
  180. if err != nil {
  181. return err
  182. }
  183. last, err := t.keyer.GenerateSequenceKey(nil, folder, maxInt64)
  184. if err != nil {
  185. return err
  186. }
  187. dbi, err := t.NewRangeIterator(first, last)
  188. if err != nil {
  189. return err
  190. }
  191. defer dbi.Release()
  192. for dbi.Next() {
  193. f, ok, err := t.getFileByKey(dbi.Value())
  194. if err != nil {
  195. return err
  196. }
  197. if !ok {
  198. l.Debugln("missing file for sequence number", t.keyer.SequenceFromSequenceKey(dbi.Key()))
  199. continue
  200. }
  201. if shouldDebug() {
  202. if seq := t.keyer.SequenceFromSequenceKey(dbi.Key()); f.Sequence != seq {
  203. l.Warnf("Sequence index corruption (folder %v, file %v): sequence %d != expected %d", string(folder), f.Name, f.Sequence, seq)
  204. panic("sequence index corruption")
  205. }
  206. }
  207. if !fn(f) {
  208. return nil
  209. }
  210. }
  211. return dbi.Error()
  212. }
  213. func (t *readOnlyTransaction) withGlobal(folder, prefix []byte, truncate bool, fn Iterator) error {
  214. if len(prefix) > 0 {
  215. unslashedPrefix := prefix
  216. if bytes.HasSuffix(prefix, []byte{'/'}) {
  217. unslashedPrefix = unslashedPrefix[:len(unslashedPrefix)-1]
  218. } else {
  219. prefix = append(prefix, '/')
  220. }
  221. if _, f, ok, err := t.getGlobal(nil, folder, unslashedPrefix, truncate); err != nil {
  222. return err
  223. } else if ok && !fn(f) {
  224. return nil
  225. }
  226. }
  227. key, err := t.keyer.GenerateGlobalVersionKey(nil, folder, prefix)
  228. if err != nil {
  229. return err
  230. }
  231. dbi, err := t.NewPrefixIterator(key)
  232. if err != nil {
  233. return err
  234. }
  235. defer dbi.Release()
  236. var dk []byte
  237. for dbi.Next() {
  238. name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
  239. if len(prefix) > 0 && !bytes.HasPrefix(name, prefix) {
  240. return nil
  241. }
  242. var vl VersionList
  243. if err := vl.Unmarshal(dbi.Value()); err != nil {
  244. return err
  245. }
  246. dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[0].Device, name)
  247. if err != nil {
  248. return err
  249. }
  250. f, ok, err := t.getFileTrunc(dk, truncate)
  251. if err != nil {
  252. return err
  253. }
  254. if !ok {
  255. continue
  256. }
  257. if !fn(f) {
  258. return nil
  259. }
  260. }
  261. if err != nil {
  262. return err
  263. }
  264. return dbi.Error()
  265. }
  266. func (t *readOnlyTransaction) availability(folder, file []byte) ([]protocol.DeviceID, error) {
  267. vl, err := t.getGlobalVersions(nil, folder, file)
  268. if backend.IsNotFound(err) {
  269. return nil, nil
  270. }
  271. if err != nil {
  272. return nil, err
  273. }
  274. var devices []protocol.DeviceID
  275. for _, v := range vl.Versions {
  276. if !v.Version.Equal(vl.Versions[0].Version) {
  277. break
  278. }
  279. if v.Invalid {
  280. continue
  281. }
  282. n := protocol.DeviceIDFromBytes(v.Device)
  283. devices = append(devices, n)
  284. }
  285. return devices, nil
  286. }
  287. func (t *readOnlyTransaction) withNeed(folder, device []byte, truncate bool, fn Iterator) error {
  288. if bytes.Equal(device, protocol.LocalDeviceID[:]) {
  289. return t.withNeedLocal(folder, truncate, fn)
  290. }
  291. key, err := t.keyer.GenerateGlobalVersionKey(nil, folder, nil)
  292. if err != nil {
  293. return err
  294. }
  295. dbi, err := t.NewPrefixIterator(key.WithoutName())
  296. if err != nil {
  297. return err
  298. }
  299. defer dbi.Release()
  300. var dk []byte
  301. devID := protocol.DeviceIDFromBytes(device)
  302. for dbi.Next() {
  303. var vl VersionList
  304. if err := vl.Unmarshal(dbi.Value()); err != nil {
  305. return err
  306. }
  307. haveFV, have := vl.Get(device)
  308. name := t.keyer.NameFromGlobalVersionKey(dbi.Key())
  309. dk, err = t.keyer.GenerateDeviceFileKey(dk, folder, vl.Versions[0].Device, name)
  310. if err != nil {
  311. return err
  312. }
  313. gf, ok, err := t.getFileTrunc(dk, truncate)
  314. if err != nil {
  315. return err
  316. }
  317. if !ok {
  318. return errEntryFromGlobalMissing
  319. }
  320. if !need(gf, have, haveFV.Version) {
  321. continue
  322. }
  323. 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, vl.Versions[0].Version, vl.Versions[0].Device)
  324. if !fn(gf) {
  325. return dbi.Error()
  326. }
  327. }
  328. return dbi.Error()
  329. }
  330. func (t *readOnlyTransaction) withNeedLocal(folder []byte, truncate bool, fn Iterator) error {
  331. key, err := t.keyer.GenerateNeedFileKey(nil, folder, nil)
  332. if err != nil {
  333. return err
  334. }
  335. dbi, err := t.NewPrefixIterator(key.WithoutName())
  336. if err != nil {
  337. return err
  338. }
  339. defer dbi.Release()
  340. var keyBuf []byte
  341. var f FileIntf
  342. var ok bool
  343. for dbi.Next() {
  344. keyBuf, f, ok, err = t.getGlobal(keyBuf, folder, t.keyer.NameFromGlobalVersionKey(dbi.Key()), truncate)
  345. if err != nil {
  346. return err
  347. }
  348. if !ok {
  349. continue
  350. }
  351. if !fn(f) {
  352. return nil
  353. }
  354. }
  355. return dbi.Error()
  356. }
  357. // A readWriteTransaction is a readOnlyTransaction plus a batch for writes.
  358. // The batch will be committed on close() or by checkFlush() if it exceeds the
  359. // batch size.
  360. type readWriteTransaction struct {
  361. backend.WriteTransaction
  362. readOnlyTransaction
  363. }
  364. func (db *Lowlevel) newReadWriteTransaction() (readWriteTransaction, error) {
  365. tran, err := db.NewWriteTransaction()
  366. if err != nil {
  367. return readWriteTransaction{}, err
  368. }
  369. return readWriteTransaction{
  370. WriteTransaction: tran,
  371. readOnlyTransaction: readOnlyTransaction{
  372. ReadTransaction: tran,
  373. keyer: db.keyer,
  374. },
  375. }, nil
  376. }
  377. func (t readWriteTransaction) Commit() error {
  378. t.readOnlyTransaction.close()
  379. return t.WriteTransaction.Commit()
  380. }
  381. func (t readWriteTransaction) close() {
  382. t.readOnlyTransaction.close()
  383. t.WriteTransaction.Release()
  384. }
  385. // putFile stores a file in the database, taking care of indirected fields.
  386. // Set the truncated flag when putting a file that deliberatly can have an
  387. // empty block list but a non-empty block list hash. This should normally be
  388. // false.
  389. func (t readWriteTransaction) putFile(fkey []byte, fi protocol.FileInfo, truncated bool) error {
  390. var bkey []byte
  391. // Always set the blocks hash when there are blocks. Leave the blocks
  392. // hash alone when there are no blocks and we might be putting a
  393. // "truncated" FileInfo (no blocks, but the hash reference is live).
  394. if len(fi.Blocks) > 0 {
  395. fi.BlocksHash = protocol.BlocksHash(fi.Blocks)
  396. } else if !truncated {
  397. fi.BlocksHash = nil
  398. }
  399. // Indirect the blocks if the block list is large enough.
  400. if len(fi.Blocks) > blocksIndirectionCutoff {
  401. bkey = t.keyer.GenerateBlockListKey(bkey, fi.BlocksHash)
  402. if _, err := t.Get(bkey); backend.IsNotFound(err) {
  403. // Marshal the block list and save it
  404. blocksBs := mustMarshal(&BlockList{Blocks: fi.Blocks})
  405. if err := t.Put(bkey, blocksBs); err != nil {
  406. return err
  407. }
  408. } else if err != nil {
  409. return err
  410. }
  411. fi.Blocks = nil
  412. }
  413. fiBs := mustMarshal(&fi)
  414. return t.Put(fkey, fiBs)
  415. }
  416. // updateGlobal adds this device+version to the version list for the given
  417. // file. If the device is already present in the list, the version is updated.
  418. // If the file does not have an entry in the global list, it is created.
  419. func (t readWriteTransaction) updateGlobal(gk, keyBuf, folder, device []byte, file protocol.FileInfo, meta *metadataTracker) ([]byte, bool, error) {
  420. l.Debugf("update global; folder=%q device=%v file=%q version=%v invalid=%v", folder, protocol.DeviceIDFromBytes(device), file.Name, file.Version, file.IsInvalid())
  421. fl, err := t.getGlobalVersionsByKey(gk)
  422. if err != nil && !backend.IsNotFound(err) {
  423. return nil, false, err
  424. }
  425. fl, removedFV, removedAt, insertedAt, err := fl.update(folder, device, file, t.readOnlyTransaction)
  426. if err != nil {
  427. return nil, false, err
  428. }
  429. name := []byte(file.Name)
  430. var global FileIntf
  431. if insertedAt == 0 {
  432. // Inserted a new newest version
  433. global = file
  434. } else {
  435. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, fl.Versions[0].Device, name)
  436. if err != nil {
  437. return nil, false, err
  438. }
  439. new, ok, err := t.getFileTrunc(keyBuf, true)
  440. if err != nil || !ok {
  441. return keyBuf, false, err
  442. }
  443. global = new
  444. }
  445. // Fixup the list of files we need.
  446. keyBuf, err = t.updateLocalNeed(keyBuf, folder, name, fl, global)
  447. if err != nil {
  448. return nil, false, err
  449. }
  450. if removedAt != 0 && insertedAt != 0 {
  451. l.Debugf(`new global for "%v" after update: %v`, file.Name, fl)
  452. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  453. return nil, false, err
  454. }
  455. return keyBuf, true, nil
  456. }
  457. // Remove the old global from the global size counter
  458. var oldGlobalFV FileVersion
  459. if removedAt == 0 {
  460. oldGlobalFV = removedFV
  461. } else if len(fl.Versions) > 1 {
  462. // The previous newest version is now at index 1
  463. oldGlobalFV = fl.Versions[1]
  464. }
  465. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, oldGlobalFV.Device, name)
  466. if err != nil {
  467. return nil, false, err
  468. }
  469. oldFile, ok, err := t.getFileTrunc(keyBuf, true)
  470. if err != nil {
  471. return nil, false, err
  472. }
  473. if ok {
  474. // A failure to get the file here is surprising and our
  475. // global size data will be incorrect until a restart...
  476. meta.removeFile(protocol.GlobalDeviceID, oldFile)
  477. }
  478. // Add the new global to the global size counter
  479. meta.addFile(protocol.GlobalDeviceID, global)
  480. l.Debugf(`new global for "%v" after update: %v`, file.Name, fl)
  481. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  482. return nil, false, err
  483. }
  484. return keyBuf, true, nil
  485. }
  486. // updateLocalNeed checks whether the given file is still needed on the local
  487. // device according to the version list and global FileInfo given and updates
  488. // the db accordingly.
  489. func (t readWriteTransaction) updateLocalNeed(keyBuf, folder, name []byte, fl VersionList, global FileIntf) ([]byte, error) {
  490. var err error
  491. keyBuf, err = t.keyer.GenerateNeedFileKey(keyBuf, folder, name)
  492. if err != nil {
  493. return nil, err
  494. }
  495. _, err = t.Get(keyBuf)
  496. if err != nil && !backend.IsNotFound(err) {
  497. return nil, err
  498. }
  499. hasNeeded := err == nil
  500. if localFV, haveLocalFV := fl.Get(protocol.LocalDeviceID[:]); need(global, haveLocalFV, localFV.Version) {
  501. if !hasNeeded {
  502. l.Debugf("local need insert; folder=%q, name=%q", folder, name)
  503. if err := t.Put(keyBuf, nil); err != nil {
  504. return nil, err
  505. }
  506. }
  507. } else if hasNeeded {
  508. l.Debugf("local need delete; folder=%q, name=%q", folder, name)
  509. if err := t.Delete(keyBuf); err != nil {
  510. return nil, err
  511. }
  512. }
  513. return keyBuf, nil
  514. }
  515. func need(global FileIntf, haveLocal bool, localVersion protocol.Vector) bool {
  516. // We never need an invalid file.
  517. if global.IsInvalid() {
  518. return false
  519. }
  520. // We don't need a deleted file if we don't have it.
  521. if global.IsDeleted() && !haveLocal {
  522. return false
  523. }
  524. // We don't need the global file if we already have the same version.
  525. if haveLocal && localVersion.GreaterEqual(global.FileVersion()) {
  526. return false
  527. }
  528. return true
  529. }
  530. // removeFromGlobal removes the device from the global version list for the
  531. // given file. If the version list is empty after this, the file entry is
  532. // removed entirely.
  533. func (t readWriteTransaction) removeFromGlobal(gk, keyBuf, folder, device []byte, file []byte, meta *metadataTracker) ([]byte, error) {
  534. l.Debugf("remove from global; folder=%q device=%v file=%q", folder, protocol.DeviceIDFromBytes(device), file)
  535. fl, err := t.getGlobalVersionsByKey(gk)
  536. if backend.IsNotFound(err) {
  537. // We might be called to "remove" a global version that doesn't exist
  538. // if the first update for the file is already marked invalid.
  539. return keyBuf, nil
  540. } else if err != nil {
  541. return nil, err
  542. }
  543. fl, _, removedAt := fl.pop(device)
  544. if removedAt == -1 {
  545. // There is no version for the given device
  546. return keyBuf, nil
  547. }
  548. if removedAt == 0 {
  549. // A failure to get the file here is surprising and our
  550. // global size data will be incorrect until a restart...
  551. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, device, file)
  552. if err != nil {
  553. return nil, err
  554. }
  555. if f, ok, err := t.getFileTrunc(keyBuf, true); err != nil {
  556. return nil, err
  557. } else if ok {
  558. meta.removeFile(protocol.GlobalDeviceID, f)
  559. }
  560. }
  561. if len(fl.Versions) == 0 {
  562. keyBuf, err = t.keyer.GenerateNeedFileKey(keyBuf, folder, file)
  563. if err != nil {
  564. return nil, err
  565. }
  566. if err := t.Delete(keyBuf); err != nil {
  567. return nil, err
  568. }
  569. if err := t.Delete(gk); err != nil {
  570. return nil, err
  571. }
  572. return keyBuf, nil
  573. }
  574. if removedAt == 0 {
  575. keyBuf, err = t.keyer.GenerateDeviceFileKey(keyBuf, folder, fl.Versions[0].Device, file)
  576. if err != nil {
  577. return nil, err
  578. }
  579. global, ok, err := t.getFileTrunc(keyBuf, true)
  580. if err != nil {
  581. return nil, err
  582. }
  583. if !ok {
  584. return nil, errEntryFromGlobalMissing
  585. }
  586. keyBuf, err = t.updateLocalNeed(keyBuf, folder, file, fl, global)
  587. if err != nil {
  588. return nil, err
  589. }
  590. meta.addFile(protocol.GlobalDeviceID, global)
  591. }
  592. l.Debugf("new global after remove: %v", fl)
  593. if err := t.Put(gk, mustMarshal(&fl)); err != nil {
  594. return nil, err
  595. }
  596. return keyBuf, nil
  597. }
  598. func (t readWriteTransaction) deleteKeyPrefix(prefix []byte) error {
  599. dbi, err := t.NewPrefixIterator(prefix)
  600. if err != nil {
  601. return err
  602. }
  603. defer dbi.Release()
  604. for dbi.Next() {
  605. if err := t.Delete(dbi.Key()); err != nil {
  606. return err
  607. }
  608. }
  609. return dbi.Error()
  610. }
  611. func (t *readWriteTransaction) withAllFolderTruncated(folder []byte, fn func(device []byte, f FileInfoTruncated) bool) error {
  612. key, err := t.keyer.GenerateDeviceFileKey(nil, folder, nil, nil)
  613. if err != nil {
  614. return err
  615. }
  616. dbi, err := t.NewPrefixIterator(key.WithoutNameAndDevice())
  617. if err != nil {
  618. return err
  619. }
  620. defer dbi.Release()
  621. var gk, keyBuf []byte
  622. for dbi.Next() {
  623. device, ok := t.keyer.DeviceFromDeviceFileKey(dbi.Key())
  624. if !ok {
  625. // Not having the device in the index is bad. Clear it.
  626. if err := t.Delete(dbi.Key()); err != nil {
  627. return err
  628. }
  629. continue
  630. }
  631. intf, err := t.unmarshalTrunc(dbi.Value(), true)
  632. if err != nil {
  633. return err
  634. }
  635. f := intf.(FileInfoTruncated)
  636. switch f.Name {
  637. case "", ".", "..", "/": // A few obviously invalid filenames
  638. l.Infof("Dropping invalid filename %q from database", f.Name)
  639. name := []byte(f.Name)
  640. gk, err = t.keyer.GenerateGlobalVersionKey(gk, folder, name)
  641. if err != nil {
  642. return err
  643. }
  644. keyBuf, err = t.removeFromGlobal(gk, keyBuf, folder, device, name, nil)
  645. if err != nil {
  646. return err
  647. }
  648. if err := t.Delete(dbi.Key()); err != nil {
  649. return err
  650. }
  651. continue
  652. }
  653. if !fn(device, f) {
  654. return nil
  655. }
  656. }
  657. return dbi.Error()
  658. }
  659. type marshaller interface {
  660. Marshal() ([]byte, error)
  661. }
  662. func mustMarshal(f marshaller) []byte {
  663. bs, err := f.Marshal()
  664. if err != nil {
  665. panic(err)
  666. }
  667. return bs
  668. }