Skip to content

Commit

Permalink
[Chore] Refactor expiry policy
Browse files Browse the repository at this point in the history
  • Loading branch information
maypok86 committed Mar 7, 2024
1 parent 48ce93b commit ff1d8b9
Show file tree
Hide file tree
Showing 18 changed files with 44 additions and 41 deletions.
2 changes: 1 addition & 1 deletion cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions cmd/generator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions entry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}

Expand All @@ -55,15 +55,15 @@ 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")
}

e.expiration -= 2 * newTTL
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")
}
}
31 changes: 17 additions & 14 deletions internal/core/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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.
Expand All @@ -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]
Expand All @@ -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]]
Expand Down Expand Up @@ -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]{
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
}

Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
4 changes: 2 additions & 2 deletions internal/expire/fixed.go → internal/expiry/fixed.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion internal/expire/queue.go → internal/expiry/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package expire
package expiry

import (
"math"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package expire
package expiry

import (
"testing"
Expand Down
2 changes: 1 addition & 1 deletion internal/generated/node/b.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/generated/node/bc.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/generated/node/be.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/generated/node/bec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/generated/node/manager.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/s3fifo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion internal/s3fifo/small.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down

0 comments on commit ff1d8b9

Please sign in to comment.