vfs: make writeback heap sort in insertion order if expiry times equal

This makes the tests 100% consistent on platforms which have a lower
resolution timer like Windows.
This commit is contained in:
Nick Craig-Wood 2020-06-21 11:45:15 +01:00
parent 746c41f527
commit ef2d036884
2 changed files with 17 additions and 1 deletions

View File

@ -30,6 +30,7 @@ type writeBack struct {
timer *time.Timer // next scheduled time for the uploader timer *time.Timer // next scheduled time for the uploader
expiry time.Time // time the next item exires or IsZero expiry time.Time // time the next item exires or IsZero
uploads int // number of uploads in progress uploads int // number of uploads in progress
id uint64 // id of the last writeBackItem created
} }
// make a new writeBack // make a new writeBack
@ -55,6 +56,7 @@ func newWriteBack(ctx context.Context, opt *vfscommon.Options) *writeBack {
// writeBack.mu must be held to manipulate this // writeBack.mu must be held to manipulate this
type writeBackItem struct { type writeBackItem struct {
name string // name of the item so we don't have to read it from item name string // name of the item so we don't have to read it from item
id uint64 // id of the item
index int // index into the priority queue for update index int // index into the priority queue for update
item *Item // Item that needs writeback item *Item // Item that needs writeback
expiry time.Time // When this expires we will write it back expiry time.Time // When this expires we will write it back
@ -74,7 +76,12 @@ type writeBackItems []*writeBackItem
func (ws writeBackItems) Len() int { return len(ws) } func (ws writeBackItems) Len() int { return len(ws) }
func (ws writeBackItems) Less(i, j int) bool { func (ws writeBackItems) Less(i, j int) bool {
return ws[i].expiry.Sub(ws[j].expiry) < 0 a, b := ws[i], ws[j]
// If times are equal then use ID to disambiguate
if a.expiry.Equal(b.expiry) {
return a.id < b.id
}
return a.expiry.Before(b.expiry)
} }
func (ws writeBackItems) Swap(i, j int) { func (ws writeBackItems) Swap(i, j int) {
@ -116,6 +123,7 @@ func (wb *writeBack) _newExpiry() time.Time {
if wb.opt.WriteBack > 0 { if wb.opt.WriteBack > 0 {
expiry = expiry.Add(wb.opt.WriteBack) expiry = expiry.Add(wb.opt.WriteBack)
} }
// expiry = expiry.Round(time.Millisecond)
return expiry return expiry
} }
@ -123,11 +131,13 @@ func (wb *writeBack) _newExpiry() time.Time {
// //
// call with the lock held // call with the lock held
func (wb *writeBack) _newItem(item *Item, name string) *writeBackItem { func (wb *writeBack) _newItem(item *Item, name string) *writeBackItem {
wb.id++
wbItem := &writeBackItem{ wbItem := &writeBackItem{
name: name, name: name,
item: item, item: item,
expiry: wb._newExpiry(), expiry: wb._newExpiry(),
delay: wb.opt.WriteBack, delay: wb.opt.WriteBack,
id: wb.id,
} }
wb._addItem(wbItem) wb._addItem(wbItem)
wb._pushItem(wbItem) wb._pushItem(wbItem)

View File

@ -72,6 +72,12 @@ func TestWriteBackItems(t *testing.T) {
wb.items._update(&wbItem1, now.Add(5*time.Second)) wb.items._update(&wbItem1, now.Add(5*time.Second))
assert.Equal(t, "two,three,one", wb.string(t)) assert.Equal(t, "two,three,one", wb.string(t))
// Set all times the same - should sort in insertion order
wb.items._update(&wbItem1, now)
wb.items._update(&wbItem2, now)
wb.items._update(&wbItem3, now)
assert.Equal(t, "one,two,three", wb.string(t))
} }
func checkOnHeap(t *testing.T, wb *writeBack, wbItem *writeBackItem) { func checkOnHeap(t *testing.T, wb *writeBack, wbItem *writeBackItem) {