From 81b1e4aa4db0186498543e01413cf986e6f86210 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Wed, 27 Nov 2013 03:51:19 -0500 Subject: [PATCH 1/2] initial mock tracker storage --- storage/tracker/mock/conn.go | 109 +++++++++++++++++++++++++++++++++ storage/tracker/mock/driver.go | 24 ++++++++ storage/tracker/mock/pool.go | 32 ++++++++++ 3 files changed, 165 insertions(+) create mode 100644 storage/tracker/mock/conn.go create mode 100644 storage/tracker/mock/driver.go create mode 100644 storage/tracker/mock/pool.go diff --git a/storage/tracker/mock/conn.go b/storage/tracker/mock/conn.go new file mode 100644 index 0000000..e1136d3 --- /dev/null +++ b/storage/tracker/mock/conn.go @@ -0,0 +1,109 @@ +// Copyright 2013 The Chihaya Authors. All rights reserved. +// Use of this source code is governed by the BSD 2-Clause license, +// which can be found in the LICENSE file. + +package mock + +import ( + "github.com/pushrax/chihaya/storage" +) + +type Conn struct { + *Pool +} + +func (c *Conn) FindUser(passkey string) (*storage.User, bool, error) { + c.usersM.RLock() + defer c.usersM.RUnlock() + user, ok := c.users[passkey] + if !ok { + return nil, false, nil + } + return user, true, nil +} + +func (c *Conn) FindTorrent(infohash string) (*storage.Torrent, bool, error) { + c.torrentsM.RLock() + defer c.torrentsM.RUnlock() + torrent, ok := c.torrents[infohash] + if !ok { + return nil, false, nil + } + return torrent, true, nil +} + +func (c *Conn) ClientWhitelisted(peerID string) (bool, error) { + _, ok := c.whitelist[peerID] + if !ok { + return false, nil + } + return true, nil +} + +func (c *Conn) RecordSnatch(u *storage.User, t *storage.Torrent) error { + return nil +} + +func (c *Conn) MarkActive(t *storage.Torrent) error { + return nil +} + +func (c *Conn) AddLeecher(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) AddSeeder(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) RemoveLeecher(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) RemoveSeeder(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) SetLeecher(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) SetSeeder(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) IncrementSlots(u *storage.User) error { + return nil +} + +func (c *Conn) DecrementSlots(u *storage.User) error { + return nil +} + +func (c *Conn) LeecherFinished(t *storage.Torrent, p *storage.Peer) error { + return nil +} + +func (c *Conn) AddTorrent(t *storage.Torrent) error { + return nil +} + +func (c *Conn) RemoveTorrent(t *storage.Torrent) error { + return nil +} + +func (c *Conn) AddUser(u *storage.User) error { + return nil +} + +func (c *Conn) RemoveUser(u *storage.User) error { + return nil +} + +func (c *Conn) WhitelistClient(peerID string) error { + return nil +} + +func (c *Conn) UnWhitelistClient(peerID string) error { + return nil +} diff --git a/storage/tracker/mock/driver.go b/storage/tracker/mock/driver.go new file mode 100644 index 0000000..7e16c65 --- /dev/null +++ b/storage/tracker/mock/driver.go @@ -0,0 +1,24 @@ +// Copyright 2013 The Chihaya Authors. All rights reserved. +// Use of this source code is governed by the BSD 2-Clause license, +// which can be found in the LICENSE file. + +// Package mock implements the storage interface for a BitTorrent tracker +// within memory. It can be used in production, but isn't recommended. +// Stored values will not persist if the tracker is restarted. +package mock + +import ( + "github.com/pushrax/chihaya/config" + "github.com/pushrax/chihaya/storage" + "github.com/pushrax/chihaya/storage/tracker" +) + +type driver struct{} + +func (d *driver) New(conf *config.DataStore) tracker.Pool { + return &Pool{ + users: make(map[string]*storage.User), + torrents: make(map[string]*storage.Torrent), + whitelist: make(map[string]string), + } +} diff --git a/storage/tracker/mock/pool.go b/storage/tracker/mock/pool.go new file mode 100644 index 0000000..28194b2 --- /dev/null +++ b/storage/tracker/mock/pool.go @@ -0,0 +1,32 @@ +// Copyright 2013 The Chihaya Authors. All rights reserved. +// Use of this source code is governed by the BSD 2-Clause license, +// which can be found in the LICENSE file. + +package mock + +import ( + "sync" + + "github.com/pushrax/chihaya/storage" + "github.com/pushrax/chihaya/storage/tracker" +) + +type Pool struct { + users map[string]*storage.User + usersM sync.RWMutex + + torrents map[string]*storage.Torrent + torrentsM sync.RWMutex + + whitelist map[string]string +} + +func (p *Pool) Get() (tracker.Conn, error) { + return &Conn{ + Pool: p, + }, nil +} + +func (p *Pool) Close() error { + return nil +} From 1eac36771160b44c71fb871915ff314fceff87f4 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Sat, 30 Nov 2013 00:54:08 -0500 Subject: [PATCH 2/2] mock interface complete --- storage/tracker/mock/conn.go | 133 ++++++++++++++++++++++++++++++++- storage/tracker/mock/driver.go | 2 +- storage/tracker/mock/pool.go | 3 +- storage/tracker/tracker.go | 5 +- 4 files changed, 138 insertions(+), 5 deletions(-) diff --git a/storage/tracker/mock/conn.go b/storage/tracker/mock/conn.go index e1136d3..9b68bf4 100644 --- a/storage/tracker/mock/conn.go +++ b/storage/tracker/mock/conn.go @@ -6,6 +6,7 @@ package mock import ( "github.com/pushrax/chihaya/storage" + "github.com/pushrax/chihaya/storage/tracker" ) type Conn struct { @@ -19,7 +20,8 @@ func (c *Conn) FindUser(passkey string) (*storage.User, bool, error) { if !ok { return nil, false, nil } - return user, true, nil + u := *user + return &u, true, nil } func (c *Conn) FindTorrent(infohash string) (*storage.Torrent, bool, error) { @@ -29,10 +31,13 @@ func (c *Conn) FindTorrent(infohash string) (*storage.Torrent, bool, error) { if !ok { return nil, false, nil } - return torrent, true, nil + t := *torrent + return &t, true, nil } func (c *Conn) ClientWhitelisted(peerID string) (bool, error) { + c.whitelistM.RLock() + defer c.whitelistM.RUnlock() _, ok := c.whitelist[peerID] if !ok { return false, nil @@ -41,69 +46,193 @@ func (c *Conn) ClientWhitelisted(peerID string) (bool, error) { } func (c *Conn) RecordSnatch(u *storage.User, t *storage.Torrent) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Snatches++ + t.Snatches++ return nil } func (c *Conn) MarkActive(t *storage.Torrent) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Active = true + t.Active = true + return nil +} + +func (c *Conn) MarkInactive(t *storage.Torrent) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Active = false + t.Active = false return nil } func (c *Conn) AddLeecher(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Leechers[storage.PeerMapKey(p)] = *p + t.Leechers[storage.PeerMapKey(p)] = *p return nil } func (c *Conn) AddSeeder(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Leechers[storage.PeerMapKey(p)] = *p + t.Leechers[storage.PeerMapKey(p)] = *p return nil } func (c *Conn) RemoveLeecher(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + delete(torrent.Leechers, storage.PeerMapKey(p)) + delete(t.Leechers, storage.PeerMapKey(p)) return nil } func (c *Conn) RemoveSeeder(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + delete(torrent.Seeders, storage.PeerMapKey(p)) + delete(t.Seeders, storage.PeerMapKey(p)) return nil } func (c *Conn) SetLeecher(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Leechers[storage.PeerMapKey(p)] = *p + t.Leechers[storage.PeerMapKey(p)] = *p return nil } func (c *Conn) SetSeeder(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + torrent.Seeders[storage.PeerMapKey(p)] = *p + t.Seeders[storage.PeerMapKey(p)] = *p return nil } func (c *Conn) IncrementSlots(u *storage.User) error { + c.usersM.Lock() + defer c.usersM.Unlock() + user, ok := c.users[u.Passkey] + if !ok { + return tracker.ErrMissingResource + } + user.Slots++ + u.Slots++ return nil } func (c *Conn) DecrementSlots(u *storage.User) error { + c.usersM.Lock() + defer c.usersM.Unlock() + user, ok := c.users[u.Passkey] + if !ok { + return tracker.ErrMissingResource + } + user.Slots-- + u.Slots-- return nil } func (c *Conn) LeecherFinished(t *storage.Torrent, p *storage.Peer) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + + torrent, ok := c.torrents[t.Infohash] + if !ok { + return tracker.ErrMissingResource + } + + torrent.Seeders[storage.PeerMapKey(p)] = *p + delete(torrent.Leechers, storage.PeerMapKey(p)) + t.Seeders[storage.PeerMapKey(p)] = *p + delete(t.Leechers, storage.PeerMapKey(p)) return nil } func (c *Conn) AddTorrent(t *storage.Torrent) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + torrent := *t + c.torrents[t.Infohash] = &torrent return nil } func (c *Conn) RemoveTorrent(t *storage.Torrent) error { + c.torrentsM.Lock() + defer c.torrentsM.Unlock() + delete(c.torrents, t.Infohash) return nil } func (c *Conn) AddUser(u *storage.User) error { + c.usersM.Lock() + defer c.usersM.Unlock() + user := *u + c.users[u.Passkey] = &user return nil } func (c *Conn) RemoveUser(u *storage.User) error { + c.usersM.Lock() + defer c.usersM.Unlock() + delete(c.users, u.Passkey) return nil } func (c *Conn) WhitelistClient(peerID string) error { + c.whitelistM.Lock() + defer c.whitelistM.Unlock() + c.whitelist[peerID] = true return nil } func (c *Conn) UnWhitelistClient(peerID string) error { + c.whitelistM.Lock() + defer c.whitelistM.Unlock() + delete(c.whitelist, peerID) return nil } diff --git a/storage/tracker/mock/driver.go b/storage/tracker/mock/driver.go index 7e16c65..2ccfbf7 100644 --- a/storage/tracker/mock/driver.go +++ b/storage/tracker/mock/driver.go @@ -19,6 +19,6 @@ func (d *driver) New(conf *config.DataStore) tracker.Pool { return &Pool{ users: make(map[string]*storage.User), torrents: make(map[string]*storage.Torrent), - whitelist: make(map[string]string), + whitelist: make(map[string]bool), } } diff --git a/storage/tracker/mock/pool.go b/storage/tracker/mock/pool.go index 28194b2..3f31aec 100644 --- a/storage/tracker/mock/pool.go +++ b/storage/tracker/mock/pool.go @@ -18,7 +18,8 @@ type Pool struct { torrents map[string]*storage.Torrent torrentsM sync.RWMutex - whitelist map[string]string + whitelist map[string]bool + whitelistM sync.RWMutex } func (p *Pool) Get() (tracker.Conn, error) { diff --git a/storage/tracker/tracker.go b/storage/tracker/tracker.go index d0a2cf7..e775a50 100644 --- a/storage/tracker/tracker.go +++ b/storage/tracker/tracker.go @@ -7,6 +7,7 @@ package tracker import ( + "errors" "fmt" "github.com/pushrax/chihaya/config" @@ -14,7 +15,8 @@ import ( ) var ( - drivers = make(map[string]Driver) + ErrMissingResource = errors.New("tracker: resource missing") + drivers = make(map[string]Driver) ) type Driver interface { @@ -65,6 +67,7 @@ type Conn interface { // Writes RecordSnatch(u *storage.User, t *storage.Torrent) error MarkActive(t *storage.Torrent) error + MarkInactive(t *storage.Torrent) error AddLeecher(t *storage.Torrent, p *storage.Peer) error AddSeeder(t *storage.Torrent, p *storage.Peer) error RemoveLeecher(t *storage.Torrent, p *storage.Peer) error