From f7583d6acbd91b2cdb2b22152f026f65af937def Mon Sep 17 00:00:00 2001 From: Jeremy Stribling Date: Thu, 20 Dec 2018 12:34:08 -0800 Subject: [PATCH] block_types: add a `NewEmptier` func for block-making function So the prefetcher can get a new block function without holding a reference to the block that supplied it. Issue: #1958 --- libkbfs/block_types.go | 15 +++++++++++++++ libkbfs/crypto_common_test.go | 8 ++++++++ libkbfs/interfaces.go | 3 +++ libkbfs/mocks_test.go | 28 ++++++++++++++++++++++++++++ libkbfs/prefetcher.go | 6 +++--- 5 files changed, 57 insertions(+), 3 deletions(-) diff --git a/libkbfs/block_types.go b/libkbfs/block_types.go index 6347be5359..06e36d43cf 100644 --- a/libkbfs/block_types.go +++ b/libkbfs/block_types.go @@ -148,6 +148,11 @@ func (cb *CommonBlock) NewEmpty() Block { return NewCommonBlock() } +// NewEmptier implements the Block interface for CommonBlock. +func (cb *CommonBlock) NewEmptier() func() Block { + return NewCommonBlock +} + // ToCommonBlock implements the Block interface for CommonBlock. func (cb *CommonBlock) ToCommonBlock() *CommonBlock { return cb @@ -226,6 +231,11 @@ func (db *DirBlock) NewEmpty() Block { return NewDirBlock() } +// NewEmptier implements the Block interface for DirBlock. +func (db *DirBlock) NewEmptier() func() Block { + return NewDirBlock +} + // IsTail implements the Block interface for DirBlock. func (db *DirBlock) IsTail() bool { if db.IsInd { @@ -449,6 +459,11 @@ func (fb *FileBlock) NewEmpty() Block { return &FileBlock{} } +// NewEmptier implements the Block interface for FileBlock. +func (fb *FileBlock) NewEmptier() func() Block { + return NewFileBlock +} + // IsTail implements the Block interface for FileBlock. func (fb *FileBlock) IsTail() bool { if fb.IsInd { diff --git a/libkbfs/crypto_common_test.go b/libkbfs/crypto_common_test.go index 1f39170be4..6e6725ba12 100644 --- a/libkbfs/crypto_common_test.go +++ b/libkbfs/crypto_common_test.go @@ -94,6 +94,10 @@ func (tb TestBlock) NewEmpty() Block { return &TestBlock{} } +func (tb TestBlock) NewEmptier() func() Block { + return tb.NewEmpty +} + func (tb *TestBlock) Set(other Block) { otherTb := other.(*TestBlock) tb.A = otherTb.A @@ -396,6 +400,10 @@ func (tba testBlockArray) NewEmpty() Block { return &testBlockArray{} } +func (tba testBlockArray) NewEmptier() func() Block { + return tba.NewEmpty +} + func (tba testBlockArray) ToCommonBlock() *CommonBlock { return nil } diff --git a/libkbfs/interfaces.go b/libkbfs/interfaces.go index b817cfdc9f..32f1d5106a 100644 --- a/libkbfs/interfaces.go +++ b/libkbfs/interfaces.go @@ -142,6 +142,9 @@ type Block interface { SetEncodedSize(size uint32) // NewEmpty returns a new block of the same type as this block NewEmpty() Block + // NewEmptier returns a function that creates a new block of the + // same type as this block. + NewEmptier() func() Block // Set sets this block to the same value as the passed-in block Set(other Block) // ToCommonBlock retrieves this block as a *CommonBlock. diff --git a/libkbfs/mocks_test.go b/libkbfs/mocks_test.go index d9b5afbfc0..707c08bfea 100644 --- a/libkbfs/mocks_test.go +++ b/libkbfs/mocks_test.go @@ -1092,6 +1092,20 @@ func (mr *MockBlockMockRecorder) NewEmpty() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewEmpty", reflect.TypeOf((*MockBlock)(nil).NewEmpty)) } +// NewEmptier mocks base method +func (m *MockBlock) NewEmptier() func() Block { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewEmptier") + ret0, _ := ret[0].(func() Block) + return ret0 +} + +// NewEmptier indicates an expected call of NewEmptier +func (mr *MockBlockMockRecorder) NewEmptier() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewEmptier", reflect.TypeOf((*MockBlock)(nil).NewEmptier)) +} + // Set mocks base method func (m *MockBlock) Set(other Block) { m.ctrl.T.Helper() @@ -1251,6 +1265,20 @@ func (mr *MockBlockWithPtrsMockRecorder) NewEmpty() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewEmpty", reflect.TypeOf((*MockBlockWithPtrs)(nil).NewEmpty)) } +// NewEmptier mocks base method +func (m *MockBlockWithPtrs) NewEmptier() func() Block { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewEmptier") + ret0, _ := ret[0].(func() Block) + return ret0 +} + +// NewEmptier indicates an expected call of NewEmptier +func (mr *MockBlockWithPtrsMockRecorder) NewEmptier() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewEmptier", reflect.TypeOf((*MockBlockWithPtrs)(nil).NewEmptier)) +} + // Set mocks base method func (m *MockBlockWithPtrs) Set(other Block) { m.ctrl.T.Helper() diff --git a/libkbfs/prefetcher.go b/libkbfs/prefetcher.go index 19c9ba4b69..75a6e34937 100644 --- a/libkbfs/prefetcher.go +++ b/libkbfs/prefetcher.go @@ -360,8 +360,8 @@ func (p *blockPrefetcher) request(ctx context.Context, priority int, if !isPrefetchWaiting { // If the block isn't in the tree, we add it with a block count of 1 (a // later TriggerPrefetch will come in and decrement it). - req := &prefetchRequest{ptr, block.NewEmpty, kmd, priority, lifetime, - NoPrefetch, action, nil} + req := &prefetchRequest{ptr, block.NewEmptier(), kmd, priority, + lifetime, NoPrefetch, action, nil} pre = p.newPrefetch(1, false, req) p.prefetches[ptr.ID] = pre } @@ -971,7 +971,7 @@ func (p *blockPrefetcher) ProcessBlockForPrefetch(ctx context.Context, ptr BlockPointer, block Block, kmd KeyMetadata, priority int, lifetime BlockCacheLifetime, prefetchStatus PrefetchStatus, action BlockRequestAction) { - req := &prefetchRequest{ptr, block.NewEmpty, kmd, priority, lifetime, + req := &prefetchRequest{ptr, block.NewEmptier(), kmd, priority, lifetime, prefetchStatus, action, nil} if prefetchStatus == FinishedPrefetch { // Finished prefetches can always be short circuited.