Skip to content

Commit

Permalink
Issue #150
Browse files Browse the repository at this point in the history
CHANGE:
  - server/peerStore/peerstore.go Added a new method all peerStores should
    implement.
  - server/peerStore/redisStore.go Added new wrapper methods to implement the
    `PeerStore` interface.
  - server/server.go Still attempting to decouple heavily spaghettied code.
  • Loading branch information
Ianleeclark committed Nov 25, 2016
1 parent a879c23 commit b47e4b5
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 23 deletions.
3 changes: 2 additions & 1 deletion server/peerStore/peerstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ package peerStore

type PeerStore interface {
SetKeyIfNotExists(string, string) bool
SetKV(string, string) bool
SetKV(string, string)
RemoveKV(string, string)
KeyExists(string) bool
GetKeyVal(string) []string
GetAllPeers(string) []string
}
53 changes: 40 additions & 13 deletions server/peerStore/redisStore.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"time"
)

type RedisStore struct {
client *redis.Client
}

// EXPIRETIME signifies how long a peer will live under the specified info_hash
// until the reaper removes it.
var EXPIRETIME int64 = 5 * 60
Expand All @@ -23,8 +27,31 @@ func OpenClient() (client *redis.Client) {
return
}

func (p *RedisStore) SetKeyIfNotExists(key, value string) (retval bool) {
return redisSetKeyIfNotExists(p.client, key, value)
}

func (p *RedisStore) SetKV(key, value string) {
redisSetKeyVal(p.client, key, value)
}

func (p *RedisStore) RemoveKV(key, value string) {
// TODO(ian): Refactor this so we don't have to delete a value from a key
if value != "" || value == "" {
redisRemoveKeysValue(p.client, key, value)
}
}

func (p *RedisStore) KeyExists(key string) (retval bool) {
return redisGetBoolKeyVal(key)
}

func (p *RedisStore) GetKeyVal(key string) []string {
return redisGetKeyVal(key)
}

// RedisSetIPMember sets a key as a member of an infohash and sets a timeout.
func RedisSetIPMember(infoHash, ipPort string) (retval int) {
func redisSetIPMember(infoHash, ipPort string) (retval int) {
c := OpenClient()

keymember := concatenateKeyMember(infoHash, "ip")
Expand All @@ -46,7 +73,7 @@ func RedisSetIPMember(infoHash, ipPort string) (retval int) {

// RedisSetKeyVal Sets a key to the specified value. Used mostly with adding a
// peer into an info_hash
func RedisSetKeyVal(c *redis.Client, keymember string, value string) {
func redisSetKeyVal(c *redis.Client, keymember string, value string) {
// RedisSetKeyVal sets a key:member's value to value. Returns nothing as of
// yet.
currTime := int64(time.Now().UTC().Unix())
Expand All @@ -61,7 +88,7 @@ func RedisSetKeyVal(c *redis.Client, keymember string, value string) {
}

// RedisGetKeyVal Lookup a peer in the specified infohash at `key`
func RedisGetKeyVal(key string) []string {
func redisGetKeyVal(key string) []string {
c := OpenClient()

// RedisGetKeyVal retrieves a value from the Redis store by looking up the
Expand All @@ -73,22 +100,22 @@ func RedisGetKeyVal(key string) []string {
val, err := c.SMembers(keymember).Result()
if err != nil {
// Fail because the key doesn't exist in the KV storage.
CreateNewTorrentKey(keymember)
createNewTorrentKey(keymember)
}

return val
}

// RedisGetAllPeers fetches all peers from the info_hash at `key`
func RedisGetAllPeers(key string) []string {
func redisGetAllPeers(key string) []string {
c := OpenClient()

keymember := concatenateKeyMember(key, "complete")

val, err := c.SRandMemberN(keymember, 30).Result()
if err != nil {
// Fail because the key doesn't exist in the KV storage.
CreateNewTorrentKey(keymember)
createNewTorrentKey(keymember)
}

if len(val) == 30 {
Expand All @@ -108,7 +135,7 @@ func RedisGetAllPeers(key string) []string {
}

// RedisGetCount counts all of the peers at `info_hash`
func RedisGetCount(c *redis.Client, info_hash string, member string) (retval int, err error) {
func redisGetCount(c *redis.Client, info_hash string, member string) (retval int, err error) {
// A generic function which is used to retrieve either the complete count
// or the incomplete count for a specified `info_hash`.
keymember := concatenateKeyMember(info_hash, member)
Expand All @@ -124,33 +151,33 @@ func RedisGetCount(c *redis.Client, info_hash string, member string) (retval int
}

// RedisGetBoolKeyVal Checks if a `key` exists
func RedisGetBoolKeyVal(key string) bool {
func redisGetBoolKeyVal(key string) bool {
c := OpenClient()
ret, _ := c.Exists(key).Result()

return ret
}

// RedisSetKeyIfNotExists Set a key if it doesn't exist.
func RedisSetKeyIfNotExists(c *redis.Client, keymember string, value string) (rv bool) {
rv = RedisGetBoolKeyVal(keymember)
func redisSetKeyIfNotExists(c *redis.Client, keymember string, value string) (rv bool) {
rv = redisGetBoolKeyVal(keymember)
if !rv {
RedisSetKeyVal(c, keymember, value)
redisSetKeyVal(c, keymember, value)
}
return
}

// RedisRemoveKeysValue Remove a `value` from `key` in the redis kv storage. `key` is typically
// a keymember of info_hash:(in)complete and the value is typically the
// ip:port concatenated.
func RedisRemoveKeysValue(c *redis.Client, key string, value string) {
func redisRemoveKeysValue(c *redis.Client, key string, value string) {
c.SRem(key, value)
}

// CreateNewTorrentKey creates a new key. By default, it adds a member
// ":ip". I don't think this ought to ever be generalized, as I just want
// Redis to function in one specific way in notorious.
func CreateNewTorrentKey(key string) {
func createNewTorrentKey(key string) {
c := OpenClient()
c.SAdd(key, "complete", "incomplete")

Expand Down
24 changes: 15 additions & 9 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
type applicationContext struct {
config config.ConfigStruct
trackerLevel int
peerStoreClient *peerStore.PeerStore
}

type scrapeData struct {
Expand Down Expand Up @@ -46,19 +47,21 @@ var ANNOUNCE_URL = "/announce"
// FIELDS The fields that we expect from a peer upon info hash lookup
var FIELDS = []string{"port", "uploaded", "downloaded", "left", "event", "compact"}

func worker(data *AnnounceData) []string {
if peerStore.RedisGetBoolKeyVal(data.InfoHash) {
x := peerStore.RedisGetKeyVal(data.InfoHash)
func (app *applicationContext) worker(data *AnnounceData) []string {
if app.peerStoreClient.KeyExists(data.InfoHash) {
x := peerStore.GetKeyVal(data.InfoHash)

peerStore.RedisSetIPMember(data.InfoHash, fmt.Sprintf("%s:%s", data.IP, data.Port))
app.peerStoreClient.RedisSetIPMember(data.InfoHash, fmt.Sprintf("%s:%s", data.IP, data.Port))

return x

}
} else {
app.peerStoreClient.SetKV(data.InfoHash)
}

peerStore.CreateNewTorrentKey(data.InfoHash)
return worker(data)
return app.worker(data)
}

func (app *applicationContext) handleStatsTracking(data *AnnounceData) {
db.UpdateStats(data.Uploaded, data.Downloaded)

Expand Down Expand Up @@ -108,8 +111,8 @@ func (app *applicationContext) requestHandler(w http.ResponseWriter, req *http.R
}

if data.Event == "started" || data.Event == "completed" {
worker(data)
x := peerStore.RedisGetAllPeers(data.InfoHash)
app.worker(data)
x := app.peerStoreClient.GetAllPeers(data.InfoHash)

if len(x) > 0 {
response := formatResponseData(x, data)
Expand Down Expand Up @@ -155,9 +158,12 @@ func writeResponse(w http.ResponseWriter, values string) {

// RunServer spins up the server and muxes the routes.
func RunServer() {
peerStore := new(peerStore.RedisStore)

app := applicationContext{
config: config.LoadConfig(),
trackerLevel: RATIOLESS,
peerStoreClient: peerStore.redisStore,
}

mux := http.NewServeMux()
Expand Down

0 comments on commit b47e4b5

Please sign in to comment.