From: Matt Joiner Date: Fri, 27 Mar 2015 15:50:55 +0000 (+1100) Subject: AddTorrentSpec now merges in new information an existing torrent didn't have X-Git-Tag: v1.0.0~1230 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=6582cffe068fb9d2fadb051e1f3414b6ab21cd9c;p=btrtrc.git AddTorrentSpec now merges in new information an existing torrent didn't have --- diff --git a/client.go b/client.go index 30e6aa30..8b21c44c 100644 --- a/client.go +++ b/client.go @@ -2258,59 +2258,69 @@ func TorrentSpecFromMetaInfo(mi *metainfo.MetaInfo) (spec *TorrentSpec) { return } +// Add or merge a torrent spec. If the torrent is already present, the +// trackers will be merged with the existing ones. If the Info isn't yet +// known, it will be set. The display name is replaced if the new spec +// provides one. Returns new if the torrent wasn't already in the client. func (cl *Client) AddTorrentSpec(spec *TorrentSpec) (T Torrent, new bool, err error) { T.cl = cl cl.mu.Lock() defer cl.mu.Unlock() t, ok := cl.torrents[spec.InfoHash] - if ok { - T.torrent = t - return - } - - new = true + if !ok { + new = true - if _, ok := cl.bannedTorrents[spec.InfoHash]; ok { - err = errors.New("banned torrent") - return - } + if _, ok := cl.bannedTorrents[spec.InfoHash]; ok { + err = errors.New("banned torrent") + return + } - t, err = newTorrent(spec.InfoHash) - if err != nil { - return + t, err = newTorrent(spec.InfoHash) + if err != nil { + return + } } if spec.DisplayName != "" { t.DisplayName = spec.DisplayName } - if spec.Info != nil { - err = cl.setMetaData(t, &spec.Info.Info, spec.Info.Bytes) - } else { - var mi *metainfo.MetaInfo - mi, err = cl.torrentCacheMetaInfo(spec.InfoHash) - if err != nil { - log.Printf("error getting cached metainfo: %s", err) - } else if mi != nil { - t.addTrackers(mi.AnnounceList) - err = cl.setMetaData(t, &mi.Info.Info, mi.Info.Bytes) + // Try to merge in info we have on the torrent. Any err left will + // terminate the function. + if t.Info == nil { + if spec.Info != nil { + err = cl.setMetaData(t, &spec.Info.Info, spec.Info.Bytes) + } else { + var mi *metainfo.MetaInfo + mi, err = cl.torrentCacheMetaInfo(spec.InfoHash) + if err != nil { + log.Printf("error getting cached metainfo: %s", err) + err = nil + } else if mi != nil { + t.addTrackers(mi.AnnounceList) + err = cl.setMetaData(t, &mi.Info.Info, mi.Info.Bytes) + } } } if err != nil { return } + t.addTrackers(spec.Trackers) cl.torrents[spec.InfoHash] = t T.torrent = t - T.torrent.pruneTimer = time.AfterFunc(0, func() { - cl.pruneConnectionsUnlocked(T.torrent) - }) - t.addTrackers(spec.Trackers) - if !cl.disableTrackers { - go cl.announceTorrentTrackers(T.torrent) - } - if cl.dHT != nil { - go cl.announceTorrentDHT(T.torrent, true) + // From this point onwards, we can consider the torrent a part of the + // client. + if new { + t.pruneTimer = time.AfterFunc(0, func() { + cl.pruneConnectionsUnlocked(T.torrent) + }) + if !cl.disableTrackers { + go cl.announceTorrentTrackers(T.torrent) + } + if cl.dHT != nil { + go cl.announceTorrentDHT(T.torrent, true) + } } return } diff --git a/client_test.go b/client_test.go index 447d9414..08dbc80c 100644 --- a/client_test.go +++ b/client_test.go @@ -14,6 +14,7 @@ import ( "github.com/anacrolix/libtorgo/bencode" "github.com/anacrolix/utp" "github.com/bradfitz/iter" + "gopkg.in/check.v1" "github.com/anacrolix/torrent/data/blob" "github.com/anacrolix/torrent/internal/testutil" @@ -299,3 +300,20 @@ func TestReadaheadPieces(t *testing.T) { } } } + +func (suite) TestMergingTrackersByAddingSpecs(c *check.C) { + cl, _ := NewClient(&TestingConfig) + defer cl.Close() + spec := TorrentSpec{} + T, new, _ := cl.AddTorrentSpec(&spec) + if !new { + c.FailNow() + } + spec.Trackers = [][]string{{"http://a"}, {"udp://b"}} + _, new, _ = cl.AddTorrentSpec(&spec) + if new { + c.FailNow() + } + c.Assert(T.Trackers[0][0].URL(), check.Equals, "http://a") + c.Assert(T.Trackers[1][0].URL(), check.Equals, "udp://b") +}