cl := &Client{}
ts := &torrentStorage{}
t := &Torrent{
- cl: cl,
- info: &metainfo.Info{
- Pieces: make([]byte, 20),
- Length: 1 << 20,
- PieceLength: 1 << 20,
- },
+ cl: cl,
storage: &storage.Torrent{ts},
pieceStateChanges: pubsub.NewPubSub(),
}
+ require.NoError(b, t.setInfo(&metainfo.Info{
+ Pieces: make([]byte, 20),
+ Length: 1 << 20,
+ PieceLength: 1 << 20,
+ }))
t.setChunkSize(defaultChunkSize)
- t.makePieces()
t.pendingPieces.Set(0, PiecePriorityNormal.BitmapPriority())
r, w := io.Pipe()
cn := &connection{
td, err := ioutil.TempDir("", "")
require.NoError(t, err)
defer os.RemoveAll(td)
- cs := storage.NewClient(storage.NewFile(td))
- tt := &Torrent{}
+ tt := &Torrent{
+ storageOpener: storage.NewClient(storage.NewFile(td)),
+ }
mi := testutil.GreetingMetaInfo()
info, err := mi.UnmarshalInfo()
require.NoError(t, err)
- tt.info = &info
- tt.cacheLength(&info)
- tt.initFiles()
- tt.makePieces()
- tt.storage, err = cs.OpenTorrent(tt.info, mi.HashInfoBytes())
- require.NoError(t, err)
+ require.NoError(t, tt.setInfo(&info))
require.NoError(t, tt.storage.Close())
tt.hashPiece(0)
}
return 0
}
-func (t *Torrent) cacheLength(info *metainfo.Info) {
+func (t *Torrent) cacheLength() {
var l int64
for _, f := range t.info.UpvertedFiles() {
l += f.Length
t.length = &l
}
-// Called when metadata for a torrent becomes available.
-func (t *Torrent) setInfoBytes(b []byte) error {
- if t.haveInfo() {
- return nil
- }
- if metainfo.HashBytes(b) != t.infoHash {
- return errors.New("info bytes have wrong hash")
- }
- var info metainfo.Info
- err := bencode.Unmarshal(b, &info)
- if err != nil {
- return fmt.Errorf("error unmarshalling info bytes: %s", err)
- }
- err = validateInfo(&info)
- if err != nil {
+func (t *Torrent) setInfo(info *metainfo.Info) error {
+ if err := validateInfo(info); err != nil {
return fmt.Errorf("bad info: %s", err)
}
- defer t.updateWantPeersEvent()
- t.info = &info
- t.initFiles()
- t.displayName = "" // Save a few bytes lol.
- t.cl.event.Broadcast()
- t.gotMetainfo.Set()
- t.storage, err = t.storageOpener.OpenTorrent(t.info, t.infoHash)
- if err != nil {
- return fmt.Errorf("error opening torrent storage: %s", err)
+ if t.storageOpener != nil {
+ var err error
+ t.storage, err = t.storageOpener.OpenTorrent(info, t.infoHash)
+ if err != nil {
+ return fmt.Errorf("error opening torrent storage: %s", err)
+ }
}
- t.cacheLength(&info)
- t.metadataBytes = b
- t.metadataCompletedChunks = nil
+ t.info = info
+ t.displayName = "" // Save a few bytes lol.
+ t.initFiles()
+ t.cacheLength()
t.makePieces()
+ return nil
+}
+
+func (t *Torrent) onSetInfo() {
for conn := range t.conns {
if err := conn.setNumPieces(t.numPieces()); err != nil {
log.Printf("closing connection: %s", err)
t.queuePieceCheck(i)
}
}
+ t.cl.event.Broadcast()
+ t.gotMetainfo.Set()
+ t.updateWantPeersEvent()
+}
+
+// Called when metadata for a torrent becomes available.
+func (t *Torrent) setInfoBytes(b []byte) error {
+ if metainfo.HashBytes(b) != t.infoHash {
+ return errors.New("info bytes have wrong hash")
+ }
+ var info metainfo.Info
+ if err := bencode.Unmarshal(b, &info); err != nil {
+ return fmt.Errorf("error unmarshalling info bytes: %s", err)
+ }
+ if err := t.setInfo(&info); err != nil {
+ return err
+ }
+ t.metadataBytes = b
+ t.metadataCompletedChunks = nil
+ t.onSetInfo()
return nil
}
// a large torrent with small pieces had a lot of overhead in recalculating
// piece priorities everytime a reader (possibly in another Torrent) changed.
func BenchmarkUpdatePiecePriorities(b *testing.B) {
+ const (
+ numPieces = 13410
+ pieceLength = 256 << 10
+ )
cl := &Client{}
t := cl.newTorrent(metainfo.Hash{}, nil)
- t.info = &metainfo.Info{
- Pieces: make([]byte, 20*13410),
- PieceLength: 256 << 10,
- }
- t.makePieces()
+ require.NoError(b, t.setInfo(&metainfo.Info{
+ Pieces: make([]byte, metainfo.HashSize*numPieces),
+ PieceLength: pieceLength,
+ Length: pieceLength * numPieces,
+ }))
assert.EqualValues(b, 13410, t.numPieces())
for range iter.N(7) {
r := t.NewReader()