redis restructured to use strings of JSON

This commit is contained in:
Jimmy Zelinskie 2013-07-24 00:18:43 -04:00
parent f7906b9089
commit 2cd3473d18
3 changed files with 49 additions and 54 deletions

View file

@ -15,7 +15,7 @@ import (
"github.com/pushrax/chihaya/storage" "github.com/pushrax/chihaya/storage"
) )
func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request) { func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
// Parse the required parameters off of a query // Parse the required parameters off of a query
compact, numWant, infohash, peerID, event, ip, port, uploaded, downloaded, left, err := s.validateAnnounceQuery(r) compact, numWant, infohash, peerID, event, ip, port, uploaded, downloaded, left, err := s.validateAnnounceQuery(r)
if err != nil { if err != nil {
@ -116,7 +116,7 @@ func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
default: default:
// Check the user's slots to see if they're allowed to leech // Check the user's slots to see if they're allowed to leech
if s.conf.Slots && user.Slots != -1 && left != 0 { if s.conf.Slots && user.Slots != -1 && left != 0 {
if user.UsedSlots >= user.Slots { if user.SlotsUsed >= user.Slots {
fail(errors.New("You've run out of download slots."), w, r) fail(errors.New("You've run out of download slots."), w, r)
return return
} }
@ -192,7 +192,7 @@ func (s *Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
// TODO compact, response, etc... // TODO compact, response, etc...
} }
func (s *Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant int, infohash, peerID, event, ip string, port, uploaded, downloaded, left uint64, err error) { func (s Server) validateAnnounceQuery(r *http.Request) (compact bool, numWant int, infohash, peerID, event, ip string, port, uploaded, downloaded, left uint64, err error) {
pq, err := parseQuery(r.URL.RawQuery) pq, err := parseQuery(r.URL.RawQuery)
if err != nil { if err != nil {
return false, 0, "", "", "", "", 0, 0, 0, 0, err return false, 0, "", "", "", "", 0, 0, 0, 0, err

View file

@ -5,42 +5,34 @@
package storage package storage
type Peer struct { type Peer struct {
ID string ID string `json:"id"`
UserID uint64 UserID uint64 `json:"user_id"`
TorrentID uint64 TorrentID uint64 `json:"torrent_id"`
IP string `json:"ip"`
IP string Port uint64 `json:"port"`
Port uint64 Uploaded uint64 `json:"uploaded"`
Downloaded uint64 `json:"downloaded`
Uploaded uint64 Left uint64 `json:"left"`
Downloaded uint64 LastAnnounce int64 `json:"last_announce"`
Left uint64
LastAnnounce int64
} }
type Torrent struct { type Torrent struct {
ID uint64 ID uint64 `json:"id"`
Infohash string Infohash string `json:"infohash"`
UpMultiplier float64 Pruned bool `json:"pruned"`
DownMultiplier float64 Seeders map[string]Peer `json:"seeders"`
Leechers map[string]Peer `json:"leechers"`
Seeders map[string]Peer Snatches uint `json:"snatches"`
Leechers map[string]Peer UpMultiplier float64 `json:"up_multiplier"`
DownMultiplier float64 `json:"down_multipler"`
Snatches uint LastAction int64 `json:"last_action"`
Pruned bool
LastAction int64
} }
type User struct { type User struct {
ID uint64 ID uint64 `json:"id"`
Passkey string Passkey string `json:"passkey"`
UpMultiplier float64 `json:"up_multiplier"`
UpMultiplier float64 DownMultiplier float64 `json:"down_multiplier"`
DownMultiplier float64 Slots int64 `json:"slots"`
SlotsUsed int64 `json:"slots_used"`
Slots int64
UsedSlots int64
SlotsLastChecked int64
} }

View file

@ -3,9 +3,16 @@
// which can be found in the LICENSE file. // which can be found in the LICENSE file.
// Package redis implements the storage interface for a BitTorrent tracker. // Package redis implements the storage interface for a BitTorrent tracker.
// The client whitelist is represented as a set with the key name "whitelist"
// with an optional prefix. Torrents and users are JSON-formatted strings.
// Torrents' keys are named "torrent_<infohash>" with an optional prefix.
// Users' keys are named "user_<passkey>" with an optional prefix.
package redis package redis
import ( import (
"encoding/json"
"strings"
"time" "time"
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
@ -67,19 +74,17 @@ func (ds *DS) FindUser(passkey string) (*storage.User, bool, error) {
conn := ds.Get() conn := ds.Get()
defer conn.Close() defer conn.Close()
key := ds.conf.Prefix + "User:" + passkey key := ds.conf.Prefix + "user_" + passkey
reply, err := redis.Values(conn.Do("HGETALL", key)) reply, err := redis.String(conn.Do("GET", key))
if err != nil { if err != nil {
return nil, true, err if err == redis.ErrNil {
} return nil, false, nil
}
// If we get nothing back, the user isn't found. return nil, false, err
if len(reply) == 0 {
return nil, false, nil
} }
user := &storage.User{} user := &storage.User{}
err = redis.ScanStruct(reply, user) err = json.NewDecoder(strings.NewReader(reply)).Decode(user)
if err != nil { if err != nil {
return nil, true, err return nil, true, err
} }
@ -90,19 +95,17 @@ func (ds *DS) FindTorrent(infohash string) (*storage.Torrent, bool, error) {
conn := ds.Get() conn := ds.Get()
defer conn.Close() defer conn.Close()
key := ds.conf.Prefix + "Torrent:" + infohash key := ds.conf.Prefix + "torrent_" + infohash
reply, err := redis.Values(conn.Do("HGETALL", key)) reply, err := redis.String(conn.Do("GET", key))
if err != nil { if err != nil {
if err == redis.ErrNil {
return nil, false, nil
}
return nil, false, err return nil, false, err
} }
// If we get nothing back, the torrent isn't found.
if len(reply) == 0 {
return nil, false, nil
}
torrent := &storage.Torrent{} torrent := &storage.Torrent{}
err = redis.ScanStruct(reply, torrent) err = json.NewDecoder(strings.NewReader(reply)).Decode(torrent)
if err != nil { if err != nil {
return nil, true, err return nil, true, err
} }
@ -113,8 +116,8 @@ func (ds *DS) ClientWhitelisted(peerID string) (bool, error) {
conn := ds.Get() conn := ds.Get()
defer conn.Close() defer conn.Close()
key := ds.conf.Prefix + "Whitelist:" + peerID key := ds.conf.Prefix + "whitelist"
exists, err := redis.Bool(conn.Do("EXISTS", key)) exists, err := redis.Bool(conn.Do("SISMEMBER", key, peerID))
if err != nil { if err != nil {
return false, err return false, err
} }