| index 285d74f17..30e0cb631 100644 |
| --- a/internal/host/movespaging.go |
| +++ b/internal/host/movespaging.go |
| @@ -261,8 +261,9 @@ func firePage(ctx context.Context, page pageFunc, warned *sync.Map, dataDir, hos |
| } |
| } |
| if item := pageIndex[key]; item != nil { |
| + delivered := item.delivered |
| pageOutboxMu.Unlock() |
| - if item.delivered { |
| + if delivered { |
| return pagePagedBefore |
| } |
| return pagePending |
| @@ -348,7 +349,8 @@ func markPageDelivered(dataDir string, e pageEntry, now time.Time) error { |
| // backoff (the later of the disk's and the index's) is over, its attempt |
| // counted and the next put off before the send, so two senders in one |
| // window send it once. A deadline the disk cannot record is kept in the |
| -// index (fix round 3, ruling 2). Unwired, the disk's pages wait. |
| +// index (fix round 3, ruling 2), with its attempt count, until a write of |
| +// the entry lands (re-review 3). Unwired, the disk's pages wait. |
| func (w *movesWorker) flushPageOutbox(ctx context.Context) { |
| page, dd := w.cfg.Page, w.cfg.DataDir |
| now := w.now() |
| @@ -394,24 +396,35 @@ func (w *movesWorker) flushPageEntry(ctx context.Context, page pageFunc, dd, p s |
| pagingLogf("moves: the page outbox: %s is not an entry, and is left for an operator: %v", p, err) |
| return |
| } |
| + key := pageKeyOf(dd, e) |
| + item := pageIndex[key] |
| if e.Delivered != nil { |
| + if item != nil && !item.memory { |
| + delete(pageIndex, key) // the disk says it all now |
| + } |
| pageOutboxMu.Unlock() |
| return |
| } |
| - key := pageKeyOf(dd, e) |
| - if item := pageIndex[key]; item != nil && (item.delivered || now.Before(item.next)) { |
| + if item != nil && (item.delivered || now.Before(item.next)) { |
| pageOutboxMu.Unlock() |
| return // delivered (its mark is the index's to write) or backing off |
| } |
| - if now.Before(e.Next) { |
| + if item == nil && now.Before(e.Next) { |
| pageOutboxMu.Unlock() |
| return |
| } |
| + // The index's attempts and deadline, when the disk could not record |
| + // them, stand over the disk's until a write lands (re-review 3). |
| + if item != nil && item.e.Tries > e.Tries { |
| + e.Tries = item.e.Tries |
| + } |
| e.Tries++ |
| e.Next = now.UTC().Add(pageBackoff(e.Tries)) |
| if err := writePageEntry(dd, e); err != nil { |
| pageIndex[key] = &pageIndexItem{e: e, next: e.Next} |
| pagingLogf("moves: %s: the %s page of move %s is sent with its backoff kept in memory: the outbox cannot record it: %v", e.Host, e.Rule, e.Op, err) |
| + } else if item != nil { |
| + delete(pageIndex, key) |
| } |
| pageOutboxMu.Unlock() |
| deliverPageEntry(ctx, page, dd, e, now) |
| @@ -434,8 +447,6 @@ func flushPageIndex(ctx context.Context, now time.Time) { |
| item.e.Tries++ |
| item.next = now.UTC().Add(pageBackoff(item.e.Tries)) |
| due = append(due, item) |
| - case !item.memory && !now.Before(item.next): |
| - delete(pageIndex, key) // the disk's own deadline governs again |
| } |
| } |
| pageOutboxMu.Unlock() |