From: Matt Joiner Date: Fri, 21 Feb 2020 03:12:44 +0000 (+1100) Subject: Differentiate between storage.ClientImpl{,Closer} X-Git-Tag: v1.15.0~18 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=c855c7a3665fcd1c5b73cfc22778796e9cf8267e;p=btrtrc.git Differentiate between storage.ClientImpl{,Closer} --- diff --git a/client.go b/client.go index 3a3084a4..2ce57d0f 100644 --- a/client.go +++ b/client.go @@ -190,13 +190,14 @@ func NewClient(cfg *ClientConfig) (cl *Client, err error) { cl.event.L = cl.locker() storageImpl := cfg.DefaultStorage if storageImpl == nil { - // We'd use mmap but HFS+ doesn't support sparse files. - storageImpl = storage.NewFile(cfg.DataDir) + // We'd use mmap by default but HFS+ doesn't support sparse files. + storageImplCloser := storage.NewFile(cfg.DataDir) cl.onClose = append(cl.onClose, func() { - if err := storageImpl.Close(); err != nil { + if err := storageImplCloser.Close(); err != nil { cl.logger.Printf("error closing default storage: %s", err) } }) + storageImpl = storageImplCloser } cl.defaultStorage = storage.NewClient(storageImpl) if cfg.IPBlocklist != nil { diff --git a/client_test.go b/client_test.go index 0f65da6c..0ca330a9 100644 --- a/client_test.go +++ b/client_test.go @@ -151,7 +151,7 @@ func TestAddDropManyTorrents(t *testing.T) { } } -func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl { +func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImplCloser { return storage.NewResourcePieces(fc.AsResourceProvider()) } @@ -366,7 +366,7 @@ func writeTorrentData(ts *storage.Torrent, info metainfo.Info, b []byte) { } } -func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImpl) { +func testAddTorrentPriorPieceCompletion(t *testing.T, alreadyCompleted bool, csf func(*filecache.Cache) storage.ClientImplCloser) { fileCacheDir, err := ioutil.TempDir("", "") require.NoError(t, err) defer os.RemoveAll(fileCacheDir) diff --git a/config.go b/config.go index ee41ba02..c0ea9ed3 100644 --- a/config.go +++ b/config.go @@ -65,7 +65,7 @@ type ClientConfig struct { DisableTCP bool `long:"disable-tcp"` // Called to instantiate storage for each added torrent. Builtin backends // are in the storage package. If not set, the "file" implementation is - // used. + // used (and Closed when the Client is Closed). DefaultStorage storage.ClientImpl HeaderObfuscationPolicy HeaderObfuscationPolicy diff --git a/storage/boltdb.go b/storage/boltdb.go index 045bb600..6e4faddc 100644 --- a/storage/boltdb.go +++ b/storage/boltdb.go @@ -26,7 +26,7 @@ type boltDBTorrent struct { ih metainfo.Hash } -func NewBoltDB(filePath string) ClientImpl { +func NewBoltDB(filePath string) ClientImplCloser { db, err := bolt.Open(filepath.Join(filePath, "bolt.db"), 0600, &bolt.Options{ Timeout: time.Second, }) diff --git a/storage/file.go b/storage/file.go index fd4d5601..415ac5df 100644 --- a/storage/file.go +++ b/storage/file.go @@ -28,11 +28,11 @@ func infoHashPathMaker(baseDir string, info *metainfo.Info, infoHash metainfo.Ha } // All Torrent data stored in this baseDir -func NewFile(baseDir string) ClientImpl { +func NewFile(baseDir string) ClientImplCloser { return NewFileWithCompletion(baseDir, pieceCompletionForDir(baseDir)) } -func NewFileWithCompletion(baseDir string, completion PieceCompletion) ClientImpl { +func NewFileWithCompletion(baseDir string, completion PieceCompletion) *fileClientImpl { return newFileWithCustomPathMakerAndCompletion(baseDir, nil, completion) } @@ -46,7 +46,7 @@ func NewFileWithCustomPathMaker(baseDir string, pathMaker func(baseDir string, i return newFileWithCustomPathMakerAndCompletion(baseDir, pathMaker, pieceCompletionForDir(baseDir)) } -func newFileWithCustomPathMakerAndCompletion(baseDir string, pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string, completion PieceCompletion) ClientImpl { +func newFileWithCustomPathMakerAndCompletion(baseDir string, pathMaker func(baseDir string, info *metainfo.Info, infoHash metainfo.Hash) string, completion PieceCompletion) *fileClientImpl { if pathMaker == nil { pathMaker = defaultPathMaker } diff --git a/storage/interface.go b/storage/interface.go index 307ba893..49314677 100644 --- a/storage/interface.go +++ b/storage/interface.go @@ -6,10 +6,14 @@ import ( "github.com/anacrolix/torrent/metainfo" ) +type ClientImplCloser interface { + ClientImpl + Close() error +} + // Represents data storage for an unspecified torrent. type ClientImpl interface { OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (TorrentImpl, error) - Close() error } // Data storage bound to a torrent. diff --git a/storage/issue96_test.go b/storage/issue96_test.go index 1bdbbf15..50356c7a 100644 --- a/storage/issue96_test.go +++ b/storage/issue96_test.go @@ -10,7 +10,7 @@ import ( "github.com/anacrolix/torrent/metainfo" ) -func testMarkedCompleteMissingOnRead(t *testing.T, csf func(string) ClientImpl) { +func testMarkedCompleteMissingOnRead(t *testing.T, csf func(string) ClientImplCloser) { td, err := ioutil.TempDir("", "") require.NoError(t, err) defer os.RemoveAll(td) diff --git a/storage/mmap.go b/storage/mmap.go index f5437eed..aebf1094 100644 --- a/storage/mmap.go +++ b/storage/mmap.go @@ -19,11 +19,11 @@ type mmapClientImpl struct { pc PieceCompletion } -func NewMMap(baseDir string) ClientImpl { +func NewMMap(baseDir string) ClientImplCloser { return NewMMapWithCompletion(baseDir, pieceCompletionForDir(baseDir)) } -func NewMMapWithCompletion(baseDir string, completion PieceCompletion) ClientImpl { +func NewMMapWithCompletion(baseDir string, completion PieceCompletion) *mmapClientImpl { return &mmapClientImpl{ baseDir: baseDir, pc: completion, diff --git a/storage/piece_resource.go b/storage/piece_resource.go index e57e8a89..1ef0e602 100644 --- a/storage/piece_resource.go +++ b/storage/piece_resource.go @@ -16,7 +16,7 @@ type piecePerResource struct { p resource.Provider } -func NewResourcePieces(p resource.Provider) ClientImpl { +func NewResourcePieces(p resource.Provider) ClientImplCloser { return &piecePerResource{ p: p, } diff --git a/t.go b/t.go index 82c18bfc..fcaec919 100644 --- a/t.go +++ b/t.go @@ -28,8 +28,8 @@ func (t *Torrent) Info() *metainfo.Info { return t.info } -// Returns a Reader bound to the torrent's data. All read calls block until -// the data requested is actually available. +// Returns a Reader bound to the torrent's data. All read calls block until the data requested is +// actually available. Note that you probably want to ensure the Torrent Info is available first. func (t *Torrent) NewReader() Reader { r := reader{ mu: t.cl.locker(), diff --git a/test/transfer_test.go b/test/transfer_test.go index dd04dc62..7d7e51bb 100644 --- a/test/transfer_test.go +++ b/test/transfer_test.go @@ -24,8 +24,8 @@ type testClientTransferParams struct { Readahead int64 SetReadahead bool ExportClientStatus bool - LeecherStorage func(string) storage.ClientImpl - SeederStorage func(string) storage.ClientImpl + LeecherStorage func(string) storage.ClientImplCloser + SeederStorage func(string) storage.ClientImplCloser SeederUploadRateLimiter *rate.Limiter LeecherDownloadRateLimiter *rate.Limiter ConfigureSeeder ConfigureClient @@ -54,8 +54,9 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) { } // cfg.ListenAddr = "localhost:4000" if ps.SeederStorage != nil { - cfg.DefaultStorage = ps.SeederStorage(greetingTempDir) - defer cfg.DefaultStorage.Close() + storage := ps.SeederStorage(greetingTempDir) + defer storage.Close() + cfg.DefaultStorage = storage } else { cfg.DataDir = greetingTempDir } @@ -84,7 +85,9 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) { if ps.LeecherStorage == nil { cfg.DataDir = leecherDataDir } else { - cfg.DefaultStorage = ps.LeecherStorage(leecherDataDir) + storage := ps.LeecherStorage(leecherDataDir) + defer storage.Close() + cfg.DefaultStorage = storage } if ps.LeecherDownloadRateLimiter != nil { cfg.DownloadRateLimiter = ps.LeecherDownloadRateLimiter @@ -152,11 +155,11 @@ func testClientTransfer(t *testing.T, ps testClientTransferParams) { type fileCacheClientStorageFactoryParams struct { Capacity int64 SetCapacity bool - Wrapper func(*filecache.Cache) storage.ClientImpl + Wrapper func(*filecache.Cache) storage.ClientImplCloser } func newFileCacheClientStorageFactory(ps fileCacheClientStorageFactoryParams) storageFactory { - return func(dataDir string) storage.ClientImpl { + return func(dataDir string) storage.ClientImplCloser { fc, err := filecache.NewCache(dataDir) if err != nil { panic(err) @@ -168,7 +171,7 @@ func newFileCacheClientStorageFactory(ps fileCacheClientStorageFactoryParams) st } } -type storageFactory func(string) storage.ClientImpl +type storageFactory func(string) storage.ClientImplCloser func TestClientTransferDefault(t *testing.T) { testClientTransfer(t, testClientTransferParams{ @@ -197,7 +200,7 @@ func TestClientTransferRateLimitedDownload(t *testing.T) { }) } -func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImpl { +func fileCachePieceResourceStorage(fc *filecache.Cache) storage.ClientImplCloser { return storage.NewResourcePieces(fc.AsResourceProvider()) } @@ -245,7 +248,7 @@ func TestClientTransferVarious(t *testing.T) { // Seeder storage for _, ss := range []struct { name string - f func(string) storage.ClientImpl + f func(string) storage.ClientImplCloser }{ {"File", storage.NewFile}, {"Mmap", storage.NewMMap},