]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Make opening a torrent in storage an explicit method
authorMatt Joiner <anacrolix@gmail.com>
Mon, 28 Mar 2016 11:40:29 +0000 (22:40 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Mon, 28 Mar 2016 11:40:29 +0000 (22:40 +1100)
This is storage types where opening can fail, like mmap

client.go
client_test.go
mmap_span/mmap_span.go
storage/file.go
storage/file_test.go
storage/interface.go
storage/mmap.go
torrent.go

index 7f0d54845a38e671d135f092d789bcb714a01c5d..d470ceac6acd3e08c5d909e0a6918c5c8c804107 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1949,9 +1949,9 @@ func (cl *Client) AddTorrentSpec(spec *TorrentSpec) (T Torrent, new bool, err er
                if spec.ChunkSize != 0 {
                        t.chunkSize = pp.Integer(spec.ChunkSize)
                }
-               t.storage = spec.Storage
-               if t.storage == nil {
-                       t.storage = cl.defaultStorage
+               t.storageOpener = spec.Storage
+               if t.storageOpener == nil {
+                       t.storageOpener = cl.defaultStorage
                }
        }
        if spec.DisplayName != "" {
index 6a33f3b8c4be6af125b5b333b3521d63a69c75f7..faded767ef37fddce923be879c8a7e16db9c2fb5 100644 (file)
@@ -92,7 +92,7 @@ func TestTorrentInitialState(t *testing.T) {
                return
        }())
        tor.chunkSize = 2
-       tor.storage = storage.NewFile(dir)
+       tor.storageOpener = storage.NewFile(dir)
        // Needed to lock for asynchronous piece verification.
        tor.cl = new(Client)
        err := tor.setMetadata(&mi.Info.Info, mi.Info.Bytes)
@@ -464,6 +464,14 @@ func TestMergingTrackersByAddingSpecs(t *testing.T) {
 
 type badStorage struct{}
 
+func (me badStorage) OpenTorrent(*metainfo.InfoEx) (storage.Torrent, error) {
+       return me, nil
+}
+
+func (me badStorage) Close() error {
+       return nil
+}
+
 func (me badStorage) Piece(p metainfo.Piece) storage.Piece {
        return badStoragePiece{p}
 }
index 43e5458f0db07b7c762a592f8786a9044d78e8ab..58d86732f432d8a5324a4f08e37c26162f8ea836 100644 (file)
@@ -2,6 +2,7 @@ package mmap_span
 
 import (
        "io"
+       "log"
 
        "github.com/edsrzf/mmap-go"
 )
@@ -22,10 +23,14 @@ func (me *MMapSpan) Append(mmap mmap.MMap) {
        me.span = append(me.span, segment{&mmap})
 }
 
-func (me MMapSpan) Close() {
+func (me MMapSpan) Close() error {
        for _, mMap := range me.span {
-               mMap.(segment).Unmap()
+               err := mMap.(segment).Unmap()
+               if err != nil {
+                       log.Print(err)
+               }
        }
+       return nil
 }
 
 func (me MMapSpan) Size() (ret int64) {
index 7f9d61b363ad0184dcb253319f7da66dc75357e2..10df26376a8820e119655048823d0fc9e95006ea 100644 (file)
@@ -21,6 +21,14 @@ func NewFile(baseDir string) I {
        }
 }
 
+func (me *fileStorage) OpenTorrent(info *metainfo.InfoEx) (Torrent, error) {
+       return fileTorrentStorage{me}, nil
+}
+
+type fileTorrentStorage struct {
+       *fileStorage
+}
+
 func (me *fileStorage) Piece(p metainfo.Piece) Piece {
        _io := &fileStorageTorrent{
                p.Info,
@@ -34,6 +42,10 @@ func (me *fileStorage) Piece(p metainfo.Piece) Piece {
        }
 }
 
+func (me *fileStorage) Close() error {
+       return nil
+}
+
 type fileStoragePiece struct {
        *fileStorage
        p metainfo.Piece
index 0297c389eaae839a328749332f5e4e9edbc1425f..6e1d055e7d65c13a6e9fa32078b8a2f1c6d839b4 100644 (file)
@@ -19,7 +19,7 @@ func TestShortFile(t *testing.T) {
        td, err := ioutil.TempDir("", "")
        require.NoError(t, err)
        defer os.RemoveAll(td)
-       data := NewFile(td)
+       s := NewFile(td)
        info := &metainfo.InfoEx{
                Info: metainfo.Info{
                        Name:        "a",
@@ -27,12 +27,14 @@ func TestShortFile(t *testing.T) {
                        PieceLength: missinggo.MiB,
                },
        }
+       ts, err := s.OpenTorrent(info)
+       assert.NoError(t, err)
        f, err := os.Create(filepath.Join(td, "a"))
        err = f.Truncate(1)
        f.Close()
        var buf bytes.Buffer
        p := info.Piece(0)
-       n, err := io.Copy(&buf, io.NewSectionReader(data.Piece(p), 0, p.Length()))
+       n, err := io.Copy(&buf, io.NewSectionReader(ts.Piece(p), 0, p.Length()))
        assert.EqualValues(t, 1, n)
        assert.Equal(t, io.ErrUnexpectedEOF, err)
 }
index 0662ebd261fea64e1eb02d9068cd9d076c195708..71b34abd0f076ed5da6237baa0b6ddc95da57d13 100644 (file)
@@ -6,11 +6,18 @@ import (
        "github.com/anacrolix/torrent/metainfo"
 )
 
-// Represents data storage for a Torrent.
+// Represents data storage for an unspecified torrent.
 type I interface {
+       OpenTorrent(info *metainfo.InfoEx) (Torrent, error)
+}
+
+// Data storage bound to a torrent.
+type Torrent interface {
        Piece(metainfo.Piece) Piece
+       Close() error
 }
 
+// Interacts with torrent piece data.
 type Piece interface {
        // Should return io.EOF only at end of torrent. Short reads due to missing
        // data should return io.ErrUnexpectedEOF.
@@ -23,20 +30,3 @@ type Piece interface {
        // Returns true if the piece is complete.
        GetIsComplete() bool
 }
-
-// type PieceStorage interface {
-//     ReadAt(metainfo.Piece, []byte, int64) (int, error)
-//     WriteAt(metainfo.Piece, []byte, int64) (int, error)
-//     MarkComplete(metainfo.Piece) error
-//     GetIsComplete(metainfo.Piece) bool
-// }
-
-// type wrappedPieceStorage struct {
-//     ps PieceStorage
-// }
-
-// func WrapPieceStorage(ps PieceStorage) I {
-//     return wrappedPieceStorage{ps}
-// }
-
-// func (me wrappedPieceStorage) Piece(metainfo.Piece)
index e24c9c69ea1a063e3999259c105c06b2fbf329fd..07faa191239c1155d658eb6c60a1bddc109890a7 100644 (file)
@@ -14,9 +14,7 @@ import (
 )
 
 type mmapStorage struct {
-       baseDir   string
-       spans     map[metainfo.InfoHash]mmap_span.MMapSpan
-       completed map[metainfo.InfoHash]bool
+       baseDir string
 }
 
 func NewMMap(baseDir string) I {
@@ -25,36 +23,35 @@ func NewMMap(baseDir string) I {
        }
 }
 
-func (me *mmapStorage) lazySpan(info *metainfo.InfoEx) error {
-       if me.spans == nil {
-               me.spans = make(map[metainfo.InfoHash]mmap_span.MMapSpan)
-       }
-       if _, ok := me.spans[*info.Hash]; ok {
-               return nil
-       }
+func (me *mmapStorage) OpenTorrent(info *metainfo.InfoEx) (t Torrent, err error) {
        span, err := MMapTorrent(&info.Info, me.baseDir)
-       if err != nil {
-               return err
+       t = &mmapTorrentStorage{
+               span: span,
        }
-       me.spans[*info.Hash] = span
-       return nil
+       return
 }
 
-func (me *mmapStorage) Piece(p metainfo.Piece) Piece {
-       err := me.lazySpan(p.Info)
-       if err != nil {
-               panic(err)
-       }
+type mmapTorrentStorage struct {
+       span      mmap_span.MMapSpan
+       completed map[metainfo.InfoHash]bool
+}
+
+func (me *mmapTorrentStorage) Piece(p metainfo.Piece) Piece {
        return mmapStoragePiece{
                storage:  me,
                p:        p,
-               ReaderAt: io.NewSectionReader(me.spans[*p.Info.Hash], p.Offset(), p.Length()),
-               WriterAt: missinggo.NewSectionWriter(me.spans[*p.Info.Hash], p.Offset(), p.Length()),
+               ReaderAt: io.NewSectionReader(me.span, p.Offset(), p.Length()),
+               WriterAt: missinggo.NewSectionWriter(me.span, p.Offset(), p.Length()),
        }
 }
 
+func (me *mmapTorrentStorage) Close() error {
+       me.span.Close()
+       return nil
+}
+
 type mmapStoragePiece struct {
-       storage *mmapStorage
+       storage *mmapTorrentStorage
        p       metainfo.Piece
        io.ReaderAt
        io.WriterAt
index 228135c3a03b2ae577a0c31feb70e882e3305a46..a7aa57e0d65cc88e22244cd4e0da5448b4be29d0 100644 (file)
@@ -54,7 +54,8 @@ type torrent struct {
        // get this from the info dict.
        length int64
 
-       storage storage.I
+       storageOpener storage.I
+       storage       storage.Torrent
 
        // The info dict. Nil if we don't have it (yet).
        Info *metainfo.InfoEx
@@ -230,6 +231,10 @@ func (t *torrent) setMetadata(md *metainfo.Info, infoBytes []byte) (err error) {
                Bytes: infoBytes,
                Hash:  &t.InfoHash,
        }
+       t.storage, err = t.storageOpener.OpenTorrent(t.Info)
+       if err != nil {
+               return
+       }
        t.length = 0
        for _, f := range t.Info.UpvertedFiles() {
                t.length += f.Length