blockqueue.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
  2. //
  3. // This program is free software: you can redistribute it and/or modify it
  4. // under the terms of the GNU General Public License as published by the Free
  5. // Software Foundation, either version 3 of the License, or (at your option)
  6. // any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful, but WITHOUT
  9. // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  11. // more details.
  12. //
  13. // You should have received a copy of the GNU General Public License along
  14. // with this program. If not, see <http://www.gnu.org/licenses/>.
  15. package model
  16. import "github.com/syncthing/syncthing/internal/protocol"
  17. type bqAdd struct {
  18. file protocol.FileInfo
  19. have []protocol.BlockInfo
  20. need []protocol.BlockInfo
  21. }
  22. type bqBlock struct {
  23. file protocol.FileInfo
  24. block protocol.BlockInfo // get this block from the network
  25. copy []protocol.BlockInfo // copy these blocks from the old version of the file
  26. first bool
  27. last bool
  28. }
  29. type blockQueue struct {
  30. queued []bqBlock
  31. }
  32. func (q *blockQueue) put(a bqAdd) {
  33. // If we already have it queued, return
  34. for _, b := range q.queued {
  35. if b.file.Name == a.file.Name {
  36. return
  37. }
  38. }
  39. l := len(a.need)
  40. if len(a.have) > 0 {
  41. // First queue a copy operation
  42. q.queued = append(q.queued, bqBlock{
  43. file: a.file,
  44. copy: a.have,
  45. first: true,
  46. last: l == 0,
  47. })
  48. }
  49. // Queue the needed blocks individually
  50. for i, b := range a.need {
  51. q.queued = append(q.queued, bqBlock{
  52. file: a.file,
  53. block: b,
  54. first: len(a.have) == 0 && i == 0,
  55. last: i == l-1,
  56. })
  57. }
  58. if len(a.need)+len(a.have) == 0 {
  59. // If we didn't have anything to fetch, queue an empty block with the "last" flag set to close the file.
  60. q.queued = append(q.queued, bqBlock{
  61. file: a.file,
  62. last: true,
  63. })
  64. }
  65. }
  66. func (q *blockQueue) get() (bqBlock, bool) {
  67. if len(q.queued) == 0 {
  68. return bqBlock{}, false
  69. }
  70. b := q.queued[0]
  71. q.queued = q.queued[1:]
  72. return b, true
  73. }