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 != "" {
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)
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}
}
import (
"io"
+ "log"
"github.com/edsrzf/mmap-go"
)
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) {
}
}
+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,
}
}
+func (me *fileStorage) Close() error {
+ return nil
+}
+
type fileStoragePiece struct {
*fileStorage
p metainfo.Piece
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",
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)
}
"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.
// 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)
)
type mmapStorage struct {
- baseDir string
- spans map[metainfo.InfoHash]mmap_span.MMapSpan
- completed map[metainfo.InfoHash]bool
+ baseDir string
}
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
// 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
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