]> Sergey Matveev's repositories - btrtrc.git/commitdiff
Cache sqlite storage capacity for a short while
authorMatt Joiner <anacrolix@gmail.com>
Tue, 27 Feb 2024 06:28:13 +0000 (17:28 +1100)
committerMatt Joiner <anacrolix@gmail.com>
Wed, 28 Feb 2024 04:41:19 +0000 (15:41 +1100)
request-strategy-impls.go
storage/possum/possum-provider.go
storage/sqlite/direct.go

index 9d779ded01c06c3937f1a76d98f9e2b166ba622a..661769f3c1a94d5767397444d455d273785e8726 100644 (file)
@@ -51,7 +51,7 @@ func (cl *Client) getRequestStrategyInputCommon() requestStrategyInputCommon {
 
 // Returns what is necessary to run request_strategy.GetRequestablePieces for primaryTorrent.
 func (cl *Client) getRequestStrategyInput(primaryTorrent *Torrent) (input request_strategy.Input) {
-       if primaryTorrent.storage.Capacity == nil {
+       if !primaryTorrent.hasStorageCap() {
                return requestStrategyInputSingleTorrent{
                        requestStrategyInputCommon: cl.getRequestStrategyInputCommon(),
                        t:                          primaryTorrent,
index fd7810d317e35f054414a4762ef7725255a622a8..ebd659e668919dad016d7b5113e16c7c97481ad4 100644 (file)
@@ -17,7 +17,7 @@ import (
 )
 
 // Extends possum resource.Provider with an efficient implementation of torrent
-// storage.ConsecutiveChunkReader.
+// storage.ConsecutiveChunkReader. TODO: This doesn't expose Capacity
 type Provider struct {
        possumResource.Provider
        Logger log.Logger
index 8e0a4a8d4e435be70cf4d381b3b0b1966b27fef5..9758ddb8d4cf3228aeba184285fafe3200e52fc5 100644 (file)
@@ -5,6 +5,8 @@ package sqliteStorage
 
 import (
        "io"
+       "sync"
+       "time"
 
        "github.com/anacrolix/squirrel"
 
@@ -20,26 +22,48 @@ func NewDirectStorage(opts NewDirectStorageOpts) (_ storage.ClientImplCloser, er
                return
        }
        return &client{
-               cache,
-               cache.GetCapacity,
+               cache: cache,
        }, nil
 }
 
+// Creates a storage.ClientImpl from a provided squirrel.Cache. The caller is responsible for
+// closing the squirrel.Cache.
 func NewWrappingClient(cache *squirrel.Cache) storage.ClientImpl {
        return &client{
-               cache,
-               cache.GetCapacity,
+               cache: cache,
        }
 }
 
 type client struct {
-       *squirrel.Cache
-       capacity func() (int64, bool)
+       cache           *squirrel.Cache
+       capacityMu      sync.Mutex
+       capacityFetched time.Time
+       capacityCap     int64
+       capacityCapped  bool
+}
+
+func (c *client) Close() error {
+       return c.cache.Close()
+}
+
+func (c *client) capacity() (cap int64, capped bool) {
+       c.capacityMu.Lock()
+       defer c.capacityMu.Unlock()
+       if !c.capacityFetched.IsZero() && time.Since(c.capacityFetched) < time.Second {
+               cap, capped = c.capacityCap, c.capacityCapped
+               return
+       }
+       c.capacityCap, c.capacityCapped = c.cache.GetCapacity()
+       // Should this go before or after the capacityCap and capacityCapped assignments?
+       c.capacityFetched = time.Now()
+       cap, capped = c.capacityCap, c.capacityCapped
+       return
 }
 
 func (c *client) OpenTorrent(*metainfo.Info, metainfo.Hash) (storage.TorrentImpl, error) {
-       t := torrent{c.Cache}
-       return storage.TorrentImpl{Piece: t.Piece, Close: t.Close, Capacity: &c.capacity}, nil
+       t := torrent{c.cache}
+       capFunc := c.capacity
+       return storage.TorrentImpl{Piece: t.Piece, Close: t.Close, Capacity: &capFunc}, nil
 }
 
 type torrent struct {