Skip to content

Commit

Permalink
add comment, and finx
Browse files Browse the repository at this point in the history
  • Loading branch information
OrlovEvgeny committed Apr 20, 2018
1 parent 9df7266 commit 9a2182c
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 44 deletions.
26 changes: 16 additions & 10 deletions gcmap/gcmap_worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,51 @@ import (
)

var (
KeyChan = make(chan string, 10000)
gcInstance *GC
loadInstance = false
)

//
//keyset - sync slice for expired keys
type keyset struct {
Keys []string
sync.Mutex
}

//
//GC garbage clean struct
type GC struct {
storage safemap.SafeMap
keyChan chan string
}

//
//NewGC - singleton func, returns *GC struct
func NewGC(ctx context.Context, store safemap.SafeMap) *GC {
if loadInstance {
return gcInstance
}

gc := new(GC)
gc.storage = store
gc.keyChan = make(chan string, 10000)
go gc.ExpireKey(ctx)
gcInstance = gc
loadInstance = true

return gc
}

//
//LenBufferKeyChan - returns len usage buffet of keyChan chanel
func (gc GC) LenBufferKeyChan() int {
return len(gc.keyChan)
}

//collects foul keys, what to remove later
func (gc GC) ExpireKey(ctx context.Context) {
kset := &keyset{Keys: make([]string, 0, 100)}
go gc.heartBeatGC(ctx, kset)

for {
select {
case key := <-KeyChan:
case key := <-gc.keyChan:
kset.Keys = append(kset.Keys, key)

case <-ctx.Done():
Expand All @@ -56,8 +62,9 @@ func (gc GC) ExpireKey(ctx context.Context) {
}
}

//
//removes old keys by timer
func (gc GC) heartBeatGC(ctx context.Context, kset *keyset) {
//TODO it may be worthwhile to set a custom interval for deleting old keys
ticker := time.NewTicker(time.Second * 3)
for {
select {
Expand All @@ -78,12 +85,11 @@ func (gc GC) heartBeatGC(ctx context.Context, kset *keyset) {
}
}

//
//fund Expired - gorutine which is launched every time the method is called, and ensures that the key is removed from the repository after the time expires
func (gc GC) Expired(ctx context.Context, key string, duration time.Duration) {

select {
case <-time.After(duration):
KeyChan <- key
gc.keyChan <- key
return
case <-ctx.Done():
return
Expand Down
4 changes: 2 additions & 2 deletions item/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ package item

import "time"

//
//Item - data storage structure
type Item struct {
Key string
Expire time.Time
Data []byte
DataLink interface{}
}

// check expire cache
//IsExpire check expire cache, return true if the time of cache is expired
func (i Item) IsExpire() bool {
return i.Expire.Before(time.Now().Local())
}
30 changes: 15 additions & 15 deletions mcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ var (
loadInstance = false
)

//
//initStore - returns context and context close func. Inited map storage and remove old cache
func initStore() (context.Context, context.CancelFunc) {
ctx, finish := context.WithCancel(context.Background())
storage = safemap.NewStorage()
gc = gcmap.NewGC(ctx, storage)
return ctx, finish
}

//
//CacheDriver context struct
type CacheDriver struct {
ctx context.Context
closeCtx context.CancelFunc
}

//
//StartInstance - singleton func, returns CacheDriver struct
func StartInstance() *CacheDriver {
if loadInstance {
return instance
Expand All @@ -48,7 +48,7 @@ func StartInstance() *CacheDriver {
return instance
}

//
//Get() - returns serialize data
func (mc *CacheDriver) Get(key string, struc interface{}) bool {
data, ok := storage.Find(key)
if !ok {
Expand All @@ -65,7 +65,7 @@ func (mc *CacheDriver) Get(key string, struc interface{}) bool {
return true
}

//
//GetPointer - returns &pointer
func (mc *CacheDriver) GetPointer(key string) (interface{}, bool) {
data, ok := storage.Find(key)
if !ok {
Expand All @@ -78,7 +78,7 @@ func (mc *CacheDriver) GetPointer(key string) (interface{}, bool) {
return item.DataLink, true
}

//
//Set - add cache data and serialize/deserialize value
func (mc *CacheDriver) Set(key string, value interface{}, ttl time.Duration) error {
expire := time.Now().Local().Add(ttl)
go gc.Expired(mc.ctx, key, ttl)
Expand All @@ -91,32 +91,32 @@ func (mc *CacheDriver) Set(key string, value interface{}, ttl time.Duration) err
return nil
}

//
//SetPointer - add cache &pointer data (more and example info README.md)
func (mc *CacheDriver) SetPointer(key string, value interface{}, ttl time.Duration) error {
expire := time.Now().Local().Add(ttl)
go gc.Expired(mc.ctx, key, ttl)
storage.Insert(key, entity.Item{Key: key, Expire: expire, DataLink: value})
return nil
}

//
//Remove - value by key
func (mc *CacheDriver) Remove(key string) {
storage.Delete(key)
}

//
//Truncate - clean cache storage
func (mc *CacheDriver) Truncate() {
storage.Truncate()
}

//
//Len - returns current count storage
func (mc *CacheDriver) Len() int {
return storage.Len()
}

//
//GCBufferQueue - returns the current use len KeyChan chanel buffer
func (mc *CacheDriver) GCBufferQueue() int {
return len(gcmap.KeyChan)
return gc.LenBufferKeyChan()
}

//
Expand All @@ -126,12 +126,12 @@ func (mc *CacheDriver) Close() map[string]interface{} {
return storage.Close()
}

//
//deserialize value
func encodeBytes(value interface{}) ([]byte, error) {
return msgpack.Marshal(value)
}

//
//serialize value
func decodeBytes(buf []byte, value interface{}) error {
return msgpack.Unmarshal(buf, value)
}
}
2 changes: 2 additions & 0 deletions mcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var (
key2 = "keystr2"
)

//TestData
type TestData struct {
ID int
Name string
Expand Down Expand Up @@ -90,6 +91,7 @@ func TestRemove(t *testing.T) {

}

//TestClose
func TestClose(t *testing.T) {
mcache.Close()
log.Printf("%s : OK\n", t.Name())
Expand Down
34 changes: 17 additions & 17 deletions safeMap/safe.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package safeMap

import entity "github.com/OrlovEvgeny/go-mcache/item"

//
//safeMap - data command chanel
type safeMap chan commandData

//
// commandAction - action constant
type commandAction int

//
//commandData - data for safe communication with the storage
type commandData struct {
action commandAction
key string
Expand All @@ -18,7 +18,7 @@ type commandData struct {
data chan<- map[string]interface{}
}

//
//Auto inc command
const (
REMOVE commandAction = iota
FLUSH
Expand All @@ -29,13 +29,13 @@ const (
END
)

//
//findResult - result data, returns to Find() method
type findResult struct {
value interface{}
found bool
}

//
//SafeMap the main interface for communicating with the storage
type SafeMap interface {
Insert(string, interface{})
Delete(string)
Expand All @@ -46,14 +46,14 @@ type SafeMap interface {
Close() map[string]interface{}
}

//
//NewStorage - make new storage, return interface SafeMap
func NewStorage() SafeMap {
sm := make(safeMap)
go sm.run()
return sm
}

//
//run - gorutina with a safe map
func (sm safeMap) run() {
store := make(map[string]interface{})
for command := range sm {
Expand All @@ -78,56 +78,56 @@ func (sm safeMap) run() {
}
}

//
//Insert - add value to storage
func (sm safeMap) Insert(key string, value interface{}) {
sm <- commandData{action: INSERT, key: key, value: value}
}

//
//Delete - delete value from storage
func (sm safeMap) Delete(key string) {
sm <- commandData{action: REMOVE, key: key}
}

//
//Flush - delete many keys from storage
func (sm safeMap) Flush(keys []string) {
sm <- commandData{action: FLUSH, keys: keys}
}

//
//Find - find storage, returns findResult struct
func (sm safeMap) Find(key string) (value interface{}, found bool) {
reply := make(chan interface{})
sm <- commandData{action: FIND, key: key, result: reply}
result := (<-reply).(findResult)
return result.value, result.found
}

//
//Len - returns current count storage value
func (sm safeMap) Len() int {
reply := make(chan interface{})
sm <- commandData{action: COUNT, result: reply}
return (<-reply).(int)
}

//
//Close - close storage and return storage map
func (sm safeMap) Close() map[string]interface{} {
reply := make(chan map[string]interface{})
sm <- commandData{action: END, data: reply}
return <-reply
}

//
//Truncate - clean storage
func (sm safeMap) Truncate() {
sm <- commandData{action: TRUNCATE}
}

//
//clearMap - helper by Truncate func
func clearMap(store map[string]interface{}) {
for k := range store {
delete(store, k)
}
}

//
//flush - helper by Flush func
func flush(s map[string]interface{}, keys []string) {
for _, v := range keys {
value, ok := s[v]
Expand Down

0 comments on commit 9a2182c

Please sign in to comment.