Skip to content

Commit

Permalink
Cache sqlite storage capacity for a short while
Browse files Browse the repository at this point in the history
  • Loading branch information
anacrolix committed Feb 27, 2024
1 parent 50a0e1a commit 638a955
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 10 deletions.
2 changes: 1 addition & 1 deletion request-strategy-impls.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion storage/possum/possum-provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 32 additions & 8 deletions storage/sqlite/direct.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package sqliteStorage

import (
"io"
"sync"
"time"

"github.com/anacrolix/squirrel"

Expand All @@ -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 {
Expand Down

0 comments on commit 638a955

Please sign in to comment.