From ac1e00b0fe69278ef45955e9817665bf71a87ded Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 16 Oct 2020 15:01:46 +0200 Subject: [PATCH] Fix locking when updating the interface cache in Put methods Also, update the cache when fetching records from the database. --- database/interface.go | 29 ++++++++++++++++++++++++----- database/interface_cache.go | 6 +++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/database/interface.go b/database/interface.go index 9c6b4a9..d0a6552 100644 --- a/database/interface.go +++ b/database/interface.go @@ -188,6 +188,16 @@ func (i *Interface) getRecord(dbName string, dbKey string, mustBeWriteable bool) return nil, db, ErrPermissionDenied } + r.Lock() + ttl := r.Meta().GetRelativeExpiry() + r.Unlock() + i.updateCache( + r, + false, // writing + false, // remove + ttl, // expiry + ) + return r, db, nil } @@ -243,14 +253,19 @@ func (i *Interface) Put(r record.Record) (err error) { } r.Lock() - defer r.Unlock() i.options.Apply(r) + remove := r.Meta().IsDeleted() + ttl := r.Meta().GetRelativeExpiry() + r.Unlock() - written := i.updateCache(r, true) + // The record may not be locked when updating the cache. + written := i.updateCache(r, true, remove, ttl) if written { return nil } + r.Lock() + defer r.Unlock() return db.Put(r) } @@ -271,18 +286,22 @@ func (i *Interface) PutNew(r record.Record) (err error) { } r.Lock() - defer r.Unlock() - if r.Meta() != nil { r.Meta().Reset() } i.options.Apply(r) + remove := r.Meta().IsDeleted() + ttl := r.Meta().GetRelativeExpiry() + r.Unlock() - written := i.updateCache(r, true) + // The record may not be locked when updating the cache. + written := i.updateCache(r, true, remove, ttl) if written { return nil } + r.Lock() + defer r.Unlock() return db.Put(r) } diff --git a/database/interface_cache.go b/database/interface_cache.go index 3e349e5..5858b61 100644 --- a/database/interface_cache.go +++ b/database/interface_cache.go @@ -159,14 +159,15 @@ func (i *Interface) checkCache(key string) record.Record { return nil } -func (i *Interface) updateCache(r record.Record, write bool) (written bool) { +// updateCache updates an entry in the +func (i *Interface) updateCache(r record.Record, write bool, remove bool, ttl int64) (written bool) { // Check if cache is in use. if i.cache == nil { return false } // Check if record should be deleted - if r.Meta().IsDeleted() { + if remove { // Remove entry from cache. i.cache.Remove(r.Key()) // Let write through to database storage. @@ -174,7 +175,6 @@ func (i *Interface) updateCache(r record.Record, write bool) (written bool) { } // Update cache with record. - ttl := r.Meta().GetRelativeExpiry() if ttl >= 0 { _ = i.cache.SetWithExpire( r.Key(),