Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX: panic: unaligned 64-bit atomic operation [32 bit machines] #1487 #1502

Merged
merged 9 commits into from
Aug 22, 2021
19 changes: 10 additions & 9 deletions internal/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ import (
type Storage struct {
sync.RWMutex
data map[string]item // data
ts uint64 // timestamp
ts uint32 // timestamp
}

type item struct {
// max value is 4294967295 -> Sun Feb 07 2106 06:28:15 GMT+0000
e uint32 // exp
v interface{} // val
e uint64 // exp
}

func New() *Storage {
store := &Storage{
data: make(map[string]item),
ts: uint64(time.Now().Unix()),
ts: uint32(time.Now().Unix()),
}
go store.gc(10 * time.Millisecond)
go store.updater(1 * time.Second)
Expand All @@ -32,20 +33,20 @@ func (s *Storage) Get(key string) interface{} {
s.RLock()
v, ok := s.data[key]
s.RUnlock()
if !ok || v.e != 0 && v.e <= atomic.LoadUint64(&s.ts) {
if !ok || v.e != 0 && v.e <= atomic.LoadUint32(&s.ts) {
return nil
}
return v.v
}

// Set key with value
func (s *Storage) Set(key string, val interface{}, ttl time.Duration) {
var exp uint64
var exp uint32
if ttl > 0 {
exp = uint64(ttl.Seconds()) + atomic.LoadUint64(&s.ts)
exp = uint32(ttl.Seconds()) + atomic.LoadUint32(&s.ts)
}
s.Lock()
s.data[key] = item{val, exp}
s.data[key] = item{exp, val}
s.Unlock()
}

Expand All @@ -66,7 +67,7 @@ func (s *Storage) Reset() {
func (s *Storage) updater(sleep time.Duration) {
for {
time.Sleep(sleep)
atomic.StoreUint64(&s.ts, uint64(time.Now().Unix()))
atomic.StoreUint32(&s.ts, uint32(time.Now().Unix()))
}
}
func (s *Storage) gc(sleep time.Duration) {
Expand All @@ -76,7 +77,7 @@ func (s *Storage) gc(sleep time.Duration) {
expired = expired[:0]
s.RLock()
for key, v := range s.data {
if v.e != 0 && v.e <= atomic.LoadUint64(&s.ts) {
if v.e != 0 && v.e <= atomic.LoadUint32(&s.ts) {
expired = append(expired, key)
}
}
Expand Down
13 changes: 7 additions & 6 deletions internal/storage/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ type Storage struct {
}

type entry struct {
// max value is 4294967295 -> Sun Feb 07 2106 06:28:15 GMT+0000
expiry uint32
data []byte
expiry int64
}

// New creates a new memory storage
Expand All @@ -41,7 +42,7 @@ func (s *Storage) Get(key string) ([]byte, error) {
s.mux.RLock()
v, ok := s.db[key]
s.mux.RUnlock()
if !ok || v.expiry != 0 && v.expiry <= time.Now().Unix() {
if !ok || v.expiry != 0 && v.expiry <= uint32(time.Now().Unix()) {
return nil, nil
}

Expand All @@ -55,13 +56,13 @@ func (s *Storage) Set(key string, val []byte, exp time.Duration) error {
return nil
}

var expire int64
var expire uint32
if exp != 0 {
expire = time.Now().Add(exp).Unix()
expire = uint32(time.Now().Add(exp).Unix())
}

s.mux.Lock()
s.db[key] = entry{val, expire}
s.db[key] = entry{expire, val}
s.mux.Unlock()
return nil
}
Expand Down Expand Up @@ -101,7 +102,7 @@ func (s *Storage) gc() {
case <-s.done:
return
case t := <-ticker.C:
now := t.Unix()
now := uint32(t.Unix())
s.mux.Lock()
for id, v := range s.db {
if v.expiry != 0 && v.expiry < now {
Expand Down