[#1004] blobovnicza: Use TTL for blobovnicza tree cache
All checks were successful
DCO action / DCO (pull_request) Successful in 12m46s
Vulncheck / Vulncheck (pull_request) Successful in 14m10s
Build / Build Components (1.22) (pull_request) Successful in 15m23s
Build / Build Components (1.21) (pull_request) Successful in 15m38s
Tests and linters / Staticcheck (pull_request) Successful in 3m36s
Tests and linters / gopls check (pull_request) Successful in 4m0s
Tests and linters / Lint (pull_request) Successful in 5m8s
Tests and linters / Tests (1.21) (pull_request) Successful in 7m41s
Tests and linters / Tests with -race (pull_request) Successful in 7m46s
Tests and linters / Tests (1.22) (pull_request) Successful in 7m58s
All checks were successful
DCO action / DCO (pull_request) Successful in 12m46s
Vulncheck / Vulncheck (pull_request) Successful in 14m10s
Build / Build Components (1.22) (pull_request) Successful in 15m23s
Build / Build Components (1.21) (pull_request) Successful in 15m38s
Tests and linters / Staticcheck (pull_request) Successful in 3m36s
Tests and linters / gopls check (pull_request) Successful in 4m0s
Tests and linters / Lint (pull_request) Successful in 5m8s
Tests and linters / Tests (1.21) (pull_request) Successful in 7m41s
Tests and linters / Tests with -race (pull_request) Successful in 7m46s
Tests and linters / Tests (1.22) (pull_request) Successful in 7m58s
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
parent
112a7c690f
commit
411a8d0245
26 changed files with 203 additions and 65 deletions
|
@ -1,11 +1,12 @@
|
|||
package blobovniczatree
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
utilSync "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/sync"
|
||||
"github.com/hashicorp/golang-lru/v2/simplelru"
|
||||
cache "github.com/go-pkgz/expirable-cache/v3"
|
||||
)
|
||||
|
||||
// dbCache caches sharedDB instances that are NOT open for Put.
|
||||
|
@ -13,30 +14,55 @@ import (
|
|||
// Uses dbManager for opening/closing sharedDB instances.
|
||||
// Stores a reference to an cached sharedDB, so dbManager does not close it.
|
||||
type dbCache struct {
|
||||
cacheGuard *sync.RWMutex
|
||||
cache simplelru.LRUCache[string, *sharedDB]
|
||||
cacheGuard *sync.Mutex
|
||||
cache cache.Cache[string, *sharedDB]
|
||||
pathLock *utilSync.KeyLocker[string] // the order of locks is important: pathLock first, cacheGuard second
|
||||
closed bool
|
||||
nonCached map[string]struct{}
|
||||
wg sync.WaitGroup
|
||||
cancel context.CancelFunc
|
||||
|
||||
dbManager *dbManager
|
||||
}
|
||||
|
||||
func newDBCache(size int, dbManager *dbManager) *dbCache {
|
||||
cache, err := simplelru.NewLRU(size, func(_ string, evictedDB *sharedDB) {
|
||||
evictedDB.Close()
|
||||
})
|
||||
if err != nil {
|
||||
// occurs only if the size is not positive
|
||||
panic(fmt.Errorf("could not create LRU cache of size %d: %w", size, err))
|
||||
}
|
||||
return &dbCache{
|
||||
cacheGuard: &sync.RWMutex{},
|
||||
cache: cache,
|
||||
func newDBCache(parentCtx context.Context, size int,
|
||||
ttl time.Duration, expInterval time.Duration,
|
||||
dbManager *dbManager,
|
||||
) *dbCache {
|
||||
ch := cache.NewCache[string, *sharedDB]().
|
||||
WithTTL(ttl).WithLRU().WithMaxKeys(size).
|
||||
WithOnEvicted(func(_ string, db *sharedDB) {
|
||||
db.Close()
|
||||
})
|
||||
ctx, cancel := context.WithCancel(parentCtx)
|
||||
res := &dbCache{
|
||||
cacheGuard: &sync.Mutex{},
|
||||
wg: sync.WaitGroup{},
|
||||
cancel: cancel,
|
||||
cache: ch,
|
||||
dbManager: dbManager,
|
||||
pathLock: utilSync.NewKeyLocker[string](),
|
||||
nonCached: make(map[string]struct{}),
|
||||
}
|
||||
if ttl > 0 {
|
||||
res.wg.Add(1)
|
||||
go func() {
|
||||
ticker := time.NewTicker(expInterval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
res.wg.Done()
|
||||
return
|
||||
case <-ticker.C:
|
||||
res.cacheGuard.Lock()
|
||||
res.cache.DeleteExpired()
|
||||
res.cacheGuard.Unlock()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *dbCache) Open() {
|
||||
|
@ -49,6 +75,8 @@ func (c *dbCache) Open() {
|
|||
func (c *dbCache) Close() {
|
||||
c.cacheGuard.Lock()
|
||||
defer c.cacheGuard.Unlock()
|
||||
c.cancel()
|
||||
c.wg.Wait()
|
||||
c.cache.Purge()
|
||||
c.closed = true
|
||||
}
|
||||
|
@ -88,6 +116,8 @@ func (c *dbCache) getExisted(path string) *sharedDB {
|
|||
|
||||
if value, ok := c.cache.Get(path); ok {
|
||||
return value
|
||||
} else if value != nil {
|
||||
c.cache.Invalidate(path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -119,10 +149,9 @@ func (c *dbCache) put(path string, db *sharedDB) bool {
|
|||
|
||||
_, isNonCached := c.nonCached[path]
|
||||
|
||||
if !isNonCached && !c.closed {
|
||||
c.cache.Add(path, db)
|
||||
return true
|
||||
if isNonCached || c.closed {
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
c.cache.Add(path, db)
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue