From 7fe6dc3b4ee2675e67fb3da13b45b2729f9b13f4 Mon Sep 17 00:00:00 2001
From: Justin Li <jli.justinli@gmail.com>
Date: Wed, 16 Jul 2014 15:03:33 -0400
Subject: [PATCH] Simpler, more efficient way of deleting inactive torrents

---
 drivers/tracker/memory/conn.go | 36 ++++++++++-------------
 drivers/tracker/routines.go    | 53 ----------------------------------
 drivers/tracker/tracker.go     |  3 +-
 http/announce.go               |  4 +++
 http/http.go                   |  5 ----
 5 files changed, 21 insertions(+), 80 deletions(-)
 delete mode 100644 drivers/tracker/routines.go

diff --git a/drivers/tracker/memory/conn.go b/drivers/tracker/memory/conn.go
index 90eba49..d9a9ce4 100644
--- a/drivers/tracker/memory/conn.go
+++ b/drivers/tracker/memory/conn.go
@@ -171,6 +171,22 @@ func (c *Conn) DeleteTorrent(infohash string) error {
 	return nil
 }
 
+func (c *Conn) PurgeInactiveTorrent(infohash string) error {
+	c.torrentsM.Lock()
+	defer c.torrentsM.Unlock()
+
+	torrent, exists := c.torrents[infohash]
+	if !exists {
+		return tracker.ErrTorrentDNE
+	}
+
+	if torrent.PeerCount() == 0 {
+		delete(c.torrents, infohash)
+	}
+
+	return nil
+}
+
 func (c *Conn) PutUser(u *models.User) error {
 	c.usersM.Lock()
 	defer c.usersM.Unlock()
@@ -207,23 +223,3 @@ func (c *Conn) DeleteClient(peerID string) error {
 	return nil
 }
 
-func (c *Conn) PurgeInactiveTorrents(before time.Time) error {
-	unixtime := before.Unix()
-	var queue []string
-
-	c.torrentsM.RLock()
-	for key, torrent := range c.torrents {
-		if torrent.LastAction < unixtime && torrent.PeerCount() == 0 {
-			queue = append(queue, key)
-		}
-	}
-	c.torrentsM.RUnlock()
-
-	c.torrentsM.Lock()
-	for _, key := range queue {
-		delete(c.torrents, key)
-	}
-	c.torrentsM.Unlock()
-
-	return nil
-}
diff --git a/drivers/tracker/routines.go b/drivers/tracker/routines.go
deleted file mode 100644
index ec50692..0000000
--- a/drivers/tracker/routines.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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 tracker
-
-import (
-	"time"
-
-	"github.com/golang/glog"
-
-	"github.com/chihaya/chihaya/config"
-)
-
-func purgeTorrents(p Pool, threshold time.Duration, interval time.Duration) {
-	for _ = range time.NewTicker(interval).C {
-		before := time.Now().Add(-threshold)
-		glog.V(0).Infof("Purging torrents before %s", before)
-
-		conn, err := p.Get()
-
-		if err != nil {
-			glog.Error("Unable to get connection for a routine")
-			continue
-		}
-
-		err = conn.PurgeInactiveTorrents(before)
-		if err != nil {
-			glog.Errorf("Error purging torrents: %s", err)
-		}
-	}
-}
-
-func StartPurgingRoutines(p Pool, cfg *config.DriverConfig) error {
-	if purgeThreshold := cfg.Params["purge_inactive"]; purgeThreshold != "" {
-		threshold, err := time.ParseDuration(purgeThreshold)
-		if err != nil {
-			return err
-		}
-
-		interval := time.Minute
-
-		if purgeInterval := cfg.Params["purge_interval"]; purgeInterval != "" {
-			interval, err = time.ParseDuration(purgeInterval)
-			if err != nil {
-				return err
-			}
-		}
-
-		go purgeTorrents(p, threshold, interval)
-	}
-	return nil
-}
diff --git a/drivers/tracker/tracker.go b/drivers/tracker/tracker.go
index d1937d1..6e2dff5 100644
--- a/drivers/tracker/tracker.go
+++ b/drivers/tracker/tracker.go
@@ -9,7 +9,6 @@ package tracker
 import (
 	"errors"
 	"fmt"
-	"time"
 
 	"github.com/chihaya/chihaya/config"
 	"github.com/chihaya/chihaya/models"
@@ -80,7 +79,7 @@ type Conn interface {
 	DeleteLeecher(infohash, peerkey string) error
 	PutSeeder(infohash string, p *models.Peer) error
 	DeleteSeeder(infohash, peerkey string) error
-	PurgeInactiveTorrents(before time.Time) error
+	PurgeInactiveTorrent(infohash string) error
 
 	// User interactions
 	FindUser(passkey string) (*models.User, error)
diff --git a/http/announce.go b/http/announce.go
index 0e67f31..a298ed4 100644
--- a/http/announce.go
+++ b/http/announce.go
@@ -91,6 +91,10 @@ func (t *Tracker) ServeAnnounce(w http.ResponseWriter, r *http.Request, p httpro
 		if err != nil {
 			return http.StatusInternalServerError, err
 		}
+	} else if torrent.PeerCount() == 0 {
+		// Rather than deleting the torrent explicitly, let the tracker driver
+		// ensure there are no race conditions.
+		conn.PurgeInactiveTorrent(torrent.Infohash)
 	}
 
 	resp := newAnnounceResponse(ann, user, torrent)
diff --git a/http/http.go b/http/http.go
index ee9a48d..8dd3f98 100644
--- a/http/http.go
+++ b/http/http.go
@@ -31,11 +31,6 @@ func NewTracker(cfg *config.Config) (*Tracker, error) {
 		return nil, err
 	}
 
-	err = tracker.StartPurgingRoutines(tp, &cfg.Tracker)
-	if err != nil {
-		return nil, err
-	}
-
 	bc, err := backend.Open(&cfg.Backend)
 	if err != nil {
 		return nil, err