-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4bb31c3
commit ca20be8
Showing
7 changed files
with
76 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,6 +62,5 @@ func (a *Aof) Read(fn func(args []resp.RESP)) error { | |
} | ||
fn(args) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,100 +1,104 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/cockroachdb/swiss" | ||
"github.com/xgzlucario/rotom/internal/timer" | ||
"time" | ||
) | ||
|
||
// Dict is the hashmap for rotom. | ||
type Dict struct { | ||
data map[string]any | ||
expire map[string]int64 | ||
data *swiss.Map[string, any] | ||
expire *swiss.Map[string, int64] | ||
} | ||
|
||
func init() { | ||
timer.Init() | ||
} | ||
|
||
func New() *Dict { | ||
return &Dict{ | ||
data: make(map[string]any, 64), | ||
expire: make(map[string]int64, 64), | ||
data: swiss.New[string, any](64), | ||
expire: swiss.New[string, int64](64), | ||
} | ||
} | ||
|
||
func (dict *Dict) Get(key string) (any, int) { | ||
data, ok := dict.data[key] | ||
data, ok := dict.data.Get(key) | ||
if !ok { | ||
// key not exist | ||
return nil, KEY_NOT_EXIST | ||
} | ||
|
||
ts, ok := dict.expire[key] | ||
ts, ok := dict.expire.Get(key) | ||
if !ok { | ||
return data, TTL_FOREVER | ||
} | ||
|
||
// key expired | ||
now := time.Now().UnixNano() | ||
now := timer.GetNanoTime() | ||
if ts < now { | ||
delete(dict.data, key) | ||
delete(dict.expire, key) | ||
dict.delete(key) | ||
return nil, KEY_NOT_EXIST | ||
} | ||
|
||
return data, int(ts-now) / int(time.Second) | ||
} | ||
|
||
func (dict *Dict) Set(key string, data any) { | ||
dict.data[key] = data | ||
dict.data.Put(key, data) | ||
} | ||
|
||
func (dict *Dict) SetWithTTL(key string, data any, ttl int64) { | ||
if ttl > 0 { | ||
dict.expire[key] = ttl | ||
dict.expire.Put(key, ttl) | ||
} | ||
dict.data[key] = data | ||
dict.data.Put(key, data) | ||
} | ||
|
||
func (dict *Dict) delete(key string) { | ||
dict.data.Delete(key) | ||
dict.expire.Delete(key) | ||
} | ||
|
||
func (dict *Dict) Delete(key string) bool { | ||
_, ok := dict.data[key] | ||
_, ok := dict.data.Get(key) | ||
if !ok { | ||
return false | ||
} | ||
delete(dict.data, key) | ||
delete(dict.expire, key) | ||
dict.delete(key) | ||
return true | ||
} | ||
|
||
// SetTTL set expire time for key. | ||
// return `0` if key not exist or expired. | ||
// return `1` if set success. | ||
func (dict *Dict) SetTTL(key string, ttl int64) int { | ||
_, ok := dict.data[key] | ||
_, ok := dict.data.Get(key) | ||
if !ok { | ||
// key not exist | ||
return 0 | ||
} | ||
|
||
// check key if already expired | ||
ts, ok := dict.expire[key] | ||
if ok && ts < time.Now().UnixNano() { | ||
delete(dict.data, key) | ||
delete(dict.expire, key) | ||
ts, ok := dict.expire.Get(key) | ||
if ok && ts < timer.GetNanoTime() { | ||
dict.delete(key) | ||
return 0 | ||
} | ||
|
||
// set ttl | ||
dict.expire[key] = ttl | ||
dict.expire.Put(key, ttl) | ||
return 1 | ||
} | ||
|
||
func (dict *Dict) EvictExpired() { | ||
var count int | ||
now := time.Now().UnixNano() | ||
for key, ts := range dict.expire { | ||
if now > ts { | ||
delete(dict.expire, key) | ||
delete(dict.data, key) | ||
dict.expire.All(func(key string, ts int64) bool { | ||
if timer.GetNanoTime() > ts { | ||
dict.Delete(key) | ||
} | ||
count++ | ||
if count > 20 { | ||
return | ||
} | ||
} | ||
return count <= 20 | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package timer | ||
|
||
import ( | ||
"sync/atomic" | ||
"time" | ||
) | ||
|
||
var ( | ||
nanotime atomic.Int64 | ||
) | ||
|
||
func Init() { | ||
go func() { | ||
tk := time.NewTicker(time.Millisecond / 10) | ||
for t := range tk.C { | ||
nanotime.Store(t.UnixNano()) | ||
} | ||
}() | ||
} | ||
|
||
func GetNanoTime() int64 { | ||
return nanotime.Load() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters