close evicted era files

This commit is contained in:
Sina Mahmoodi 2025-04-15 17:24:56 +02:00 committed by lightclient
parent 930d969611
commit 01e48f3e19
No known key found for this signature in database
GPG key ID: 657913021EF45A6A
4 changed files with 39 additions and 6 deletions

View file

@ -25,6 +25,7 @@ type BasicLRU[K comparable, V any] struct {
list *list[K] list *list[K]
items map[K]cacheItem[K, V] items map[K]cacheItem[K, V]
cap int cap int
onEvicted func(key K, value V)
} }
type cacheItem[K any, V any] struct { type cacheItem[K any, V any] struct {
@ -61,6 +62,10 @@ func (c *BasicLRU[K, V]) Add(key K, value V) (evicted bool) {
elem = c.list.removeLast() elem = c.list.removeLast()
delete(c.items, elem.v) delete(c.items, elem.v)
evicted = true evicted = true
if c.onEvicted != nil {
v := c.items[elem.v]
c.onEvicted(elem.v, v.value)
}
} else { } else {
elem = new(listElem[K]) elem = new(listElem[K])
} }
@ -142,6 +147,11 @@ func (c *BasicLRU[K, V]) RemoveOldest() (key K, value V, ok bool) {
return key, item.value, true return key, item.value, true
} }
// OnEvicted sets a callback function to be called when an item is evicted from the cache.
func (c *BasicLRU[K, V]) OnEvicted(fn func(k K, v V)) {
c.onEvicted = fn
}
// Keys returns all keys in the cache. // Keys returns all keys in the cache.
func (c *BasicLRU[K, V]) Keys() []K { func (c *BasicLRU[K, V]) Keys() []K {
keys := make([]K, 0, len(c.items)) keys := make([]K, 0, len(c.items))

View file

@ -93,3 +93,11 @@ func (c *Cache[K, V]) Keys() []K {
return c.cache.Keys() return c.cache.Keys()
} }
// OnEvicted sets a callback function to be called when an item is evicted from the cache.
func (c *Cache[K, V]) OnEvicted(fn func(key K, value V)) {
c.mu.Lock()
defer c.mu.Unlock()
c.cache.OnEvicted(fn)
}

View file

@ -61,20 +61,33 @@ func New(datadir string) (*EraDatabase, error) {
return nil, err return nil, err
} }
db := &EraDatabase{datadir: datadir, cache: lru.NewCache[uint64, *era.Era](openFileLimit)} db := &EraDatabase{datadir: datadir, cache: lru.NewCache[uint64, *era.Era](openFileLimit)}
db.cache.OnEvicted(func(key uint64, value *era.Era) {
// Close the era1 file when it is evicted from the cache
// to avoid leaks.
if value != nil {
if err := value.Close(); err != nil {
log.Warn("Error closing era1 file", "epoch", key, "err", err)
}
}
})
log.Info("Opened erastore", "datadir", datadir) log.Info("Opened erastore", "datadir", datadir)
return db, nil return db, nil
} }
// Close closes all open era1 files in the cache. // Close closes all open era1 files in the cache.
func (db *EraDatabase) Close() { func (db *EraDatabase) Close() error {
// Close all open era1 files in the cache. // Close all open era1 files in the cache.
keys := db.cache.Keys() keys := db.cache.Keys()
errs := make([]error, len(keys))
for _, key := range keys { for _, key := range keys {
if e, ok := db.cache.Get(key); ok { if e, ok := db.cache.Get(key); ok {
e.Close() if err := e.Close(); err != nil {
errs = append(errs, err)
} }
} }
} }
return errors.Join(errs...)
}
// GetRawBody returns the raw body for a given block number. // GetRawBody returns the raw body for a given block number.
func (db *EraDatabase) GetRawBody(number uint64) ([]byte, error) { func (db *EraDatabase) GetRawBody(number uint64) ([]byte, error) {

View file

@ -176,7 +176,9 @@ func (f *Freezer) Close() error {
errs = append(errs, err) errs = append(errs, err)
} }
if f.eradb != nil { if f.eradb != nil {
f.eradb.Close() if err := f.eradb.Close(); err != nil {
errs = append(errs, err)
}
} }
}) })
if errs != nil { if errs != nil {