initial work on redis scripts
This commit is contained in:
parent
2cd3473d18
commit
94187e4261
5 changed files with 89 additions and 22 deletions
|
@ -58,8 +58,8 @@ func (s Server) serveAnnounce(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
// If the torrent was pruned and the user is seeding, unprune it
|
||||
if torrent.Pruned && left == 0 {
|
||||
err := tx.Unprune(torrent)
|
||||
if !torrent.Active && left == 0 {
|
||||
err := tx.Active(torrent)
|
||||
if err != nil {
|
||||
log.Panicf("server: %s", err)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ type Peer struct {
|
|||
type Torrent struct {
|
||||
ID uint64 `json:"id"`
|
||||
Infohash string `json:"infohash"`
|
||||
Pruned bool `json:"pruned"`
|
||||
Active bool `json:"active"`
|
||||
Seeders map[string]Peer `json:"seeders"`
|
||||
Leechers map[string]Peer `json:"leechers"`
|
||||
Snatches uint `json:"snatches"`
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
// which can be found in the LICENSE file.
|
||||
|
||||
// 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.
|
||||
// Torrents' keys are named "torrent:<infohash>" with an optional prefix.
|
||||
// Users' keys are named "user:<passkey>" with an optional prefix.
|
||||
package redis
|
||||
|
||||
import (
|
||||
|
@ -74,7 +74,7 @@ func (ds *DS) FindUser(passkey string) (*storage.User, bool, error) {
|
|||
conn := ds.Get()
|
||||
defer conn.Close()
|
||||
|
||||
key := ds.conf.Prefix + "user_" + passkey
|
||||
key := ds.conf.Prefix + "user:" + passkey
|
||||
reply, err := redis.String(conn.Do("GET", key))
|
||||
if err != nil {
|
||||
if err == redis.ErrNil {
|
||||
|
@ -95,7 +95,7 @@ func (ds *DS) FindTorrent(infohash string) (*storage.Torrent, bool, error) {
|
|||
conn := ds.Get()
|
||||
defer conn.Close()
|
||||
|
||||
key := ds.conf.Prefix + "torrent_" + infohash
|
||||
key := ds.conf.Prefix + "torrent:" + infohash
|
||||
reply, err := redis.String(conn.Do("GET", key))
|
||||
if err != nil {
|
||||
if err == redis.ErrNil {
|
||||
|
@ -180,17 +180,14 @@ func (tx *Tx) Snatch(user *storage.User, torrent *storage.Torrent) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) Unprune(t *storage.Torrent) error {
|
||||
func (tx *Tx) Active(t *storage.Torrent) error {
|
||||
if tx.done {
|
||||
return storage.ErrTxDone
|
||||
}
|
||||
key := tx.conf.Prefix + "Torrent:" + t.Infohash
|
||||
err := tx.Send("HSET " + key + " Status 0")
|
||||
if err != nil {
|
||||
key := tx.conf.Prefix + "torrent:" + t.Infohash
|
||||
err := activeScript.Send(tx.Conn, key)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Tx) NewLeecher(t *storage.Torrent, p *storage.Peer) error {
|
||||
if tx.done {
|
||||
|
@ -236,24 +233,27 @@ func (tx *Tx) RmSeeder(t *storage.Torrent, p *storage.Peer) error {
|
|||
if tx.done {
|
||||
return storage.ErrTxDone
|
||||
}
|
||||
// TODO
|
||||
return nil
|
||||
key := tx.conf.Prefix + "torrent:" + t.Infohash
|
||||
err := rmSeederScript.Send(tx.Conn, key, p.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (tx *Tx) IncrementSlots(u *storage.User) error {
|
||||
if tx.done {
|
||||
return storage.ErrTxDone
|
||||
}
|
||||
// TODO
|
||||
return nil
|
||||
key := tx.conf.Prefix + "user:" + u.Passkey
|
||||
err := incSlotsScript.Send(tx.Conn, key)
|
||||
return err
|
||||
}
|
||||
|
||||
func (tx *Tx) DecrementSlots(u *storage.User) error {
|
||||
if tx.done {
|
||||
return storage.ErrTxDone
|
||||
}
|
||||
// TODO
|
||||
return nil
|
||||
key := tx.conf.Prefix + "user:" + u.Passkey
|
||||
err := decSlotsScript.Send(tx.Conn, key)
|
||||
return err
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
67
storage/redis/scripts.go
Normal file
67
storage/redis/scripts.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"github.com/garyburd/redigo/redis"
|
||||
)
|
||||
|
||||
var incSlotsScript = redis.NewScript(1, incSlotsScriptSrc)
|
||||
|
||||
const incSlotsScriptSrc = `
|
||||
if redis.call("exists", keys[1]) == 1 then
|
||||
local json = redis.call("get", keys[1])
|
||||
local user = cjson.decode(json)
|
||||
user["slots_used"] = user["slots_used"] + 1
|
||||
json = cjson.encode(user)
|
||||
redis.call("set", key, json)
|
||||
return user["slots_used"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
`
|
||||
|
||||
var decSlotsScript = redis.NewScript(1, incSlotsScriptSrc)
|
||||
|
||||
const decSlotsScriptSrc = `
|
||||
if redis.call("exists", keys[1]) == 1 then
|
||||
local json = redis.call("get", keys[1])
|
||||
local user = cjson.decode(json)
|
||||
if user["slots_used"] > 0
|
||||
user["slots_used"] = user["slots_used"] - 1
|
||||
end
|
||||
json = cjson.encode(user)
|
||||
redis.call("set", key, json)
|
||||
return user["slots_used"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
`
|
||||
|
||||
var activeScript = redis.NewScript(1, decSlotsScriptSrc)
|
||||
|
||||
const activeScriptSrc = `
|
||||
if redis.call("exists", keys[1]) == 1 then
|
||||
local json = redis.call("get", keys[1])
|
||||
local torrent = cjson.decode(json)
|
||||
torrent["active"] = true
|
||||
json = cjson.encode(torrent)
|
||||
redis.call("set", key, json)
|
||||
return user["slots_used"]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
`
|
||||
|
||||
var rmSeederScript = redis.NewScript(2, rmSeederScriptSrc)
|
||||
|
||||
const rmSeederScriptSrc = `
|
||||
if redis.call("EXISTS", keys[1]) == 1 then
|
||||
local json = redis.call("GET", keys[1])
|
||||
local torrent = cjson.decode(json)
|
||||
table.remove(torrent["seeders"], keys[2])
|
||||
json = cjson.encode(torrent)
|
||||
redis.call("SET", key, json)
|
||||
return 0
|
||||
else
|
||||
return nil
|
||||
end
|
||||
`
|
|
@ -74,7 +74,7 @@ type Tx interface {
|
|||
|
||||
// Torrents
|
||||
Snatch(u *User, t *Torrent) error
|
||||
Unprune(t *Torrent) error
|
||||
Active(t *Torrent) error
|
||||
|
||||
// Peers
|
||||
NewLeecher(t *Torrent, p *Peer) error
|
||||
|
|
Loading…
Reference in a new issue