diff --git a/storage/storage.go b/storage/storage.go index 352c684..5326919 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -14,13 +14,14 @@ var ( drivers = make(map[string]Driver) ) -// Driver is the interface used to initalize a new type of PeerStore. +// Driver is the interface used to initialize a new type of PeerStore. type Driver interface { NewPeerStore(cfg interface{}) (PeerStore, error) } -// ErrResourceDoesNotExist is the error returned by all delete methods in the -// store if the requested resource does not exist. +// ErrResourceDoesNotExist is the error returned by all delete methods and the +// AnnouncePeers method of the PeerStore interface if the requested resource +// does not exist. var ErrResourceDoesNotExist = bittorrent.ClientError("resource does not exist") // ErrDriverDoesNotExist is the error returned by NewPeerStore when a peer @@ -29,39 +30,59 @@ var ErrDriverDoesNotExist = errors.New("peer store driver with that name does no // PeerStore is an interface that abstracts the interactions of storing and // manipulating Peers such that it can be implemented for various data stores. +// +// Implementations of the PeerStore interface must do the following in addition +// to implementing the methods of the interface in the way documented: +// +// - Implement a garbage-collection strategy that ensures stale data is removed. +// For example, a timestamp on each InfoHash/Peer combination can be used +// to track the last activity for that Peer. The entire database can then +// be scanned periodically and too old Peers removed. The intervals and +// durations involved should be configurable. +// - IPv4 and IPv6 swarms must be isolated from each other. +// A PeerStore must be able to transparently handle IPv4 and IPv6 Peers, but +// must separate them. AnnouncePeers and ScrapeSwarm must return information +// about the Swarm matching the given AddressFamily only. +// +// Implementations can be tested against this interface using the tests in +// storage_tests.go and the benchmarks in storage_bench.go. type PeerStore interface { // PutSeeder adds a Seeder to the Swarm identified by the provided - // infoHash. + // InfoHash. PutSeeder(infoHash bittorrent.InfoHash, p bittorrent.Peer) error // DeleteSeeder removes a Seeder from the Swarm identified by the - // provided infoHash. + // provided InfoHash. // - // If the Swarm or Peer does not exist, this function should return + // If the Swarm or Peer does not exist, this function returns // ErrResourceDoesNotExist. DeleteSeeder(infoHash bittorrent.InfoHash, p bittorrent.Peer) error // PutLeecher adds a Leecher to the Swarm identified by the provided - // infoHash. + // InfoHash. + // If the Swarm does not exist already, it is created. PutLeecher(infoHash bittorrent.InfoHash, p bittorrent.Peer) error // DeleteLeecher removes a Leecher from the Swarm identified by the - // provided infoHash. + // provided InfoHash. // - // If the Swarm or Peer does not exist, this function should return + // If the Swarm or Peer does not exist, this function returns // ErrResourceDoesNotExist. DeleteLeecher(infoHash bittorrent.InfoHash, p bittorrent.Peer) error // GraduateLeecher promotes a Leecher to a Seeder in the Swarm - // identified by the provided infoHash. + // identified by the provided InfoHash. // - // If the given Peer is not present as a Leecher, add the Peer as a - // Seeder and return no error. + // If the given Peer is not present as a Leecher or the swarm does not exist + // already, the Peer is added as a Seeder and no error is returned. GraduateLeecher(infoHash bittorrent.InfoHash, p bittorrent.Peer) error // AnnouncePeers is a best effort attempt to return Peers from the Swarm - // identified by the provided infoHash. The returned Peers are required - // to be either all IPv4 or all IPv6. + // identified by the provided InfoHash. + // The numWant parameter indicates the number of peers requested by the + // announcing Peer p. The seeder flag determines whether the Peer announced + // as a Seeder. + // The returned Peers are required to be either all IPv4 or all IPv6. // // The returned Peers should strive be: // - as close to length equal to numWant as possible without going over @@ -70,17 +91,17 @@ type PeerStore interface { // - if seeder is false, should ideally return more seeders than // leechers // - // Returns ErrResourceDoesNotExist if the provided infoHash is not tracked. + // Returns ErrResourceDoesNotExist if the provided InfoHash is not tracked. AnnouncePeers(infoHash bittorrent.InfoHash, seeder bool, numWant int, p bittorrent.Peer) (peers []bittorrent.Peer, err error) - // ScrapeSwarm returns information required to answer a scrape request - // about a swarm identified by the given infohash. + // ScrapeSwarm returns information required to answer a Scrape request + // about a Swarm identified by the given InfoHash. // The AddressFamily indicates whether or not the IPv6 swarm should be // scraped. // The Complete and Incomplete fields of the Scrape must be filled, // filling the Snatches field is optional. - // If the infohash is unknown to the PeerStore, an empty Scrape is - // returned. + // + // If the Swarm does not exist, an empty Scrape and no error is returned. ScrapeSwarm(infoHash bittorrent.InfoHash, addressFamily bittorrent.AddressFamily) bittorrent.Scrape // stop.Stopper is an interface that expects a Stop method to stop the @@ -89,7 +110,7 @@ type PeerStore interface { stop.Stopper // log.Fielder returns a loggable version of the data used to configure and - // operate a particular peer store. + // operate a particular PeerStore. log.Fielder } diff --git a/storage/storage_tests.go b/storage/storage_tests.go index 03936b8..4cf0f41 100644 --- a/storage/storage_tests.go +++ b/storage/storage_tests.go @@ -9,7 +9,10 @@ import ( "github.com/chihaya/chihaya/bittorrent" ) -// PeerEqualityFunc is the boolean function to use to check two Peers for equality. +// PeerEqualityFunc is the boolean function to use to check two Peers for +// equality. +// Depending on the implementation of the PeerStore, this can be changed to +// use (Peer).EqualEndpoint instead. var PeerEqualityFunc = func(p1, p2 bittorrent.Peer) bool { return p1.Equal(p2) } // TestPeerStore tests a PeerStore implementation against the interface.