diff --git a/cache_test.go b/cache_test.go index 43b5ae4..6659ee1 100644 --- a/cache_test.go +++ b/cache_test.go @@ -248,7 +248,7 @@ func TestCache_Advanced(t *testing.T) { e1.Cost() == 1 && e1 == e2 && e1.TTL() < defaultTTL && - !e1.IsExpired() + !e1.HasExpired() if !isValidEntries { t.Fatalf("found not valid entries. e1: %+v, e2: %+v, v1:%d", e1, e2, v1) diff --git a/cmd/generator/main.go b/cmd/generator/main.go index dd7bb2a..757e18f 100644 --- a/cmd/generator/main.go +++ b/cmd/generator/main.go @@ -336,10 +336,10 @@ func (g *generator) printFunctions() { g.p("}") g.p("") - g.p("func (n *%s[K, V]) IsExpired() bool {", g.structName) + g.p("func (n *%s[K, V]) HasExpired() bool {", g.structName) g.in() if g.features[expiration] { - g.p("return n.expiration > 0 && n.expiration < unixtime.Now()") + g.p("return n.expiration <= unixtime.Now()") } else { g.p("return false") } @@ -501,8 +501,8 @@ type Node[K comparable, V any] interface { NextExp() Node[K, V] // SetNextExp sets the next node in the expiration policy. SetNextExp(v Node[K, V]) - // IsExpired returns true if node is expired. - IsExpired() bool + // HasExpired returns true if node has expired. + HasExpired() bool // Expiration returns the expiration time. Expiration() uint32 // Cost returns the cost of the node. diff --git a/entry.go b/entry.go index 842e9ae..5dcfaf0 100644 --- a/entry.go +++ b/entry.go @@ -64,8 +64,8 @@ func (e Entry[K, V]) TTL() time.Duration { return time.Duration(expiration-now) * time.Second } -// IsExpired returns true if the entry is expired. -func (e Entry[K, V]) IsExpired() bool { +// HasExpired returns true if the entry has expired. +func (e Entry[K, V]) HasExpired() bool { expiration := e.Expiration() if expiration == 0 { return false diff --git a/entry_test.go b/entry_test.go index 6ab47d4..e2a8f11 100644 --- a/entry_test.go +++ b/entry_test.go @@ -46,7 +46,7 @@ func TestEntry(t *testing.T) { if ttl := e.TTL(); ttl != -1 { t.Fatalf("not valid ttl. want -1, got %d", ttl) } - if e.IsExpired() { + if e.HasExpired() { t.Fatal("entry should not be expire") } @@ -55,7 +55,7 @@ func TestEntry(t *testing.T) { if ttl := e.TTL(); ttl <= 0 || ttl > time.Duration(newTTL)*time.Second { t.Fatalf("ttl should be in the range (0, %d] seconds, but got %d seconds", newTTL, ttl/time.Second) } - if e.IsExpired() { + if e.HasExpired() { t.Fatal("entry should not be expire") } @@ -63,7 +63,7 @@ func TestEntry(t *testing.T) { if ttl := e.TTL(); ttl != 0 { t.Fatalf("ttl should be 0 seconds, but got %d seconds", ttl/time.Second) } - if !e.IsExpired() { + if !e.HasExpired() { t.Fatalf("entry should have expired") } } diff --git a/internal/core/cache.go b/internal/core/cache.go index 597e637..f8db448 100644 --- a/internal/core/cache.go +++ b/internal/core/cache.go @@ -18,7 +18,7 @@ import ( "sync" "time" - "github.com/maypok86/otter/internal/expire" + "github.com/maypok86/otter/internal/expiry" "github.com/maypok86/otter/internal/generated/node" "github.com/maypok86/otter/internal/hashtable" "github.com/maypok86/otter/internal/lossy" @@ -35,9 +35,12 @@ func zeroValue[V any]() V { return zero } +func getTTL(ttl time.Duration) uint32 { + return uint32((ttl + time.Second - 1) / time.Second) +} + func getExpiration(ttl time.Duration) uint32 { - ttlSecond := (ttl + time.Second - 1) / time.Second - return unixtime.Now() + uint32(ttlSecond) + return unixtime.Now() + getTTL(ttl) } // Config is a set of cache settings. @@ -51,7 +54,7 @@ type Config[K comparable, V any] struct { WithCost bool } -type expirePolicy[K comparable, V any] interface { +type expiryPolicy[K comparable, V any] interface { Add(n node.Node[K, V]) Delete(n node.Node[K, V]) RemoveExpired(expired []node.Node[K, V]) []node.Node[K, V] @@ -64,7 +67,7 @@ type Cache[K comparable, V any] struct { nodeManager *node.Manager[K, V] hashmap *hashtable.Map[K, V] policy *s3fifo.Policy[K, V] - expirePolicy expirePolicy[K, V] + expirePolicy expiryPolicy[K, V] stats *stats.Stats readBuffers []*lossy.Buffer[K, V] writeBuffer *queue.MPSC[task[K, V]] @@ -103,14 +106,14 @@ func NewCache[K comparable, V any](c Config[K, V]) *Cache[K, V] { hashmap = hashtable.NewWithSize[K, V](nodeManager, *c.InitialCapacity) } - var expPolicy expirePolicy[K, V] + var expPolicy expiryPolicy[K, V] switch { case c.TTL != nil: - expPolicy = expire.NewFixed[K, V]() + expPolicy = expiry.NewFixed[K, V]() case c.WithVariableTTL: - expPolicy = expire.NewVariable[K, V](nodeManager) + expPolicy = expiry.NewVariable[K, V](nodeManager) default: - expPolicy = expire.NewDisabled[K, V]() + expPolicy = expiry.NewDisabled[K, V]() } cache := &Cache[K, V]{ @@ -130,7 +133,7 @@ func NewCache[K comparable, V any](c Config[K, V]) *Cache[K, V] { cache.stats = stats.New() } if c.TTL != nil { - cache.ttl = uint32((*c.TTL + time.Second - 1) / time.Second) + cache.ttl = getTTL(*c.TTL) } cache.withExpiration = c.TTL != nil || c.WithVariableTTL @@ -173,7 +176,7 @@ func (c *Cache[K, V]) GetNode(key K) (node.Node[K, V], bool) { return nil, false } - if n.IsExpired() { + if n.HasExpired() { c.writeBuffer.Insert(newDeleteTask(n)) c.stats.IncMisses() return nil, false @@ -191,7 +194,7 @@ func (c *Cache[K, V]) GetNode(key K) (node.Node[K, V], bool) { // such as updating statistics or the eviction policy. func (c *Cache[K, V]) GetNodeQuietly(key K) (node.Node[K, V], bool) { n, ok := c.hashmap.Get(key) - if !ok || !n.IsAlive() || n.IsExpired() { + if !ok || !n.IsAlive() || n.HasExpired() { return nil, false } @@ -302,7 +305,7 @@ func (c *Cache[K, V]) afterDelete(deleted node.Node[K, V]) { // DeleteByFunc removes the association for this key from the cache when the given function returns true. func (c *Cache[K, V]) DeleteByFunc(f func(key K, value V) bool) { c.hashmap.Range(func(n node.Node[K, V]) bool { - if !n.IsAlive() || n.IsExpired() { + if !n.IsAlive() || n.HasExpired() { return true } @@ -427,7 +430,7 @@ func (c *Cache[K, V]) process() { // Iteration stops early when the given function returns false. func (c *Cache[K, V]) Range(f func(key K, value V) bool) { c.hashmap.Range(func(n node.Node[K, V]) bool { - if !n.IsAlive() || n.IsExpired() { + if !n.IsAlive() || n.HasExpired() { return true } diff --git a/internal/expire/disabled.go b/internal/expiry/disabled.go similarity index 98% rename from internal/expire/disabled.go rename to internal/expiry/disabled.go index fb46cd5..61271f8 100644 --- a/internal/expire/disabled.go +++ b/internal/expiry/disabled.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expire +package expiry import "github.com/maypok86/otter/internal/generated/node" diff --git a/internal/expire/fixed.go b/internal/expiry/fixed.go similarity index 94% rename from internal/expire/fixed.go rename to internal/expiry/fixed.go index ceb0cfa..6ca7f9b 100644 --- a/internal/expire/fixed.go +++ b/internal/expiry/fixed.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expire +package expiry import "github.com/maypok86/otter/internal/generated/node" @@ -35,7 +35,7 @@ func (f *Fixed[K, V]) Delete(n node.Node[K, V]) { } func (f *Fixed[K, V]) RemoveExpired(expired []node.Node[K, V]) []node.Node[K, V] { - for !f.q.isEmpty() && f.q.head.IsExpired() { + for !f.q.isEmpty() && f.q.head.HasExpired() { expired = append(expired, f.q.pop()) } return expired diff --git a/internal/expire/queue.go b/internal/expiry/queue.go similarity index 99% rename from internal/expire/queue.go rename to internal/expiry/queue.go index dc906b9..18c5a85 100644 --- a/internal/expire/queue.go +++ b/internal/expiry/queue.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expire +package expiry import "github.com/maypok86/otter/internal/generated/node" diff --git a/internal/expire/queue_test.go b/internal/expiry/queue_test.go similarity index 99% rename from internal/expire/queue_test.go rename to internal/expiry/queue_test.go index 2b6034f..9a31856 100644 --- a/internal/expire/queue_test.go +++ b/internal/expiry/queue_test.go @@ -9,7 +9,7 @@ // license that can be found in the LICENSE file. // That can be found at https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:LICENSE -package expire +package expiry import ( "strconv" diff --git a/internal/expire/variable.go b/internal/expiry/variable.go similarity index 99% rename from internal/expire/variable.go rename to internal/expiry/variable.go index 522a318..b5791a1 100644 --- a/internal/expire/variable.go +++ b/internal/expiry/variable.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expire +package expiry import ( "math" diff --git a/internal/expire/variable_test.go b/internal/expiry/variable_test.go similarity index 99% rename from internal/expire/variable_test.go rename to internal/expiry/variable_test.go index ef10431..f041e7e 100644 --- a/internal/expire/variable_test.go +++ b/internal/expiry/variable_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package expire +package expiry import ( "testing" diff --git a/internal/generated/node/b.go b/internal/generated/node/b.go index 28190aa..a10e484 100644 --- a/internal/generated/node/b.go +++ b/internal/generated/node/b.go @@ -87,7 +87,7 @@ func (n *B[K, V]) SetNextExp(v Node[K, V]) { panic("not implemented") } -func (n *B[K, V]) IsExpired() bool { +func (n *B[K, V]) HasExpired() bool { return false } diff --git a/internal/generated/node/bc.go b/internal/generated/node/bc.go index 7342597..962ecde 100644 --- a/internal/generated/node/bc.go +++ b/internal/generated/node/bc.go @@ -91,7 +91,7 @@ func (n *BC[K, V]) SetNextExp(v Node[K, V]) { panic("not implemented") } -func (n *BC[K, V]) IsExpired() bool { +func (n *BC[K, V]) HasExpired() bool { return false } diff --git a/internal/generated/node/be.go b/internal/generated/node/be.go index 15377d9..ef66eef 100644 --- a/internal/generated/node/be.go +++ b/internal/generated/node/be.go @@ -103,8 +103,8 @@ func (n *BE[K, V]) SetNextExp(v Node[K, V]) { n.nextExp = (*BE[K, V])(v.AsPointer()) } -func (n *BE[K, V]) IsExpired() bool { - return n.expiration > 0 && n.expiration < unixtime.Now() +func (n *BE[K, V]) HasExpired() bool { + return n.expiration <= unixtime.Now() } func (n *BE[K, V]) Expiration() uint32 { diff --git a/internal/generated/node/bec.go b/internal/generated/node/bec.go index e438d13..f4813ca 100644 --- a/internal/generated/node/bec.go +++ b/internal/generated/node/bec.go @@ -107,8 +107,8 @@ func (n *BEC[K, V]) SetNextExp(v Node[K, V]) { n.nextExp = (*BEC[K, V])(v.AsPointer()) } -func (n *BEC[K, V]) IsExpired() bool { - return n.expiration > 0 && n.expiration < unixtime.Now() +func (n *BEC[K, V]) HasExpired() bool { + return n.expiration <= unixtime.Now() } func (n *BEC[K, V]) Expiration() uint32 { diff --git a/internal/generated/node/manager.go b/internal/generated/node/manager.go index 8ea396e..e48b900 100644 --- a/internal/generated/node/manager.go +++ b/internal/generated/node/manager.go @@ -45,8 +45,8 @@ type Node[K comparable, V any] interface { NextExp() Node[K, V] // SetNextExp sets the next node in the expiration policy. SetNextExp(v Node[K, V]) - // IsExpired returns true if node is expired. - IsExpired() bool + // HasExpired returns true if node has expired. + HasExpired() bool // Expiration returns the expiration time. Expiration() uint32 // Cost returns the cost of the node. diff --git a/internal/s3fifo/main.go b/internal/s3fifo/main.go index d03bf80..684e262 100644 --- a/internal/s3fifo/main.go +++ b/internal/s3fifo/main.go @@ -44,7 +44,7 @@ func (m *main[K, V]) evict(deleted []node.Node[K, V]) []node.Node[K, V] { for m.cost > 0 { n := m.q.pop() - if !n.IsAlive() || n.IsExpired() || n.Frequency() == 0 { + if !n.IsAlive() || n.HasExpired() || n.Frequency() == 0 { n.Unmark() m.cost -= n.Cost() return append(deleted, n) diff --git a/internal/s3fifo/small.go b/internal/s3fifo/small.go index cb84528..acab906 100644 --- a/internal/s3fifo/small.go +++ b/internal/s3fifo/small.go @@ -53,7 +53,7 @@ func (s *small[K, V]) evict(deleted []node.Node[K, V]) []node.Node[K, V] { n := s.q.pop() s.cost -= n.Cost() n.Unmark() - if !n.IsAlive() || n.IsExpired() { + if !n.IsAlive() || n.HasExpired() { return append(deleted, n) }