Add intial memcache support.

FIXME: serialization needs work.
This commit is contained in:
Dhananjay Balan 2016-02-12 21:38:48 +05:30
parent b541f6e371
commit 8c4b338257
3 changed files with 88 additions and 10 deletions

View File

@ -7,6 +7,7 @@ import (
"sync"
"time"
"github.com/bradfitz/gomemcache/memcache"
"github.com/hoisie/redis"
"github.com/miekg/dns"
)
@ -50,8 +51,13 @@ type Cache interface {
Get(key string) (Msg *dns.Msg, err error)
Set(key string, Msg *dns.Msg) error
Exists(key string) bool
Remove(key string)
Length() int
Remove(key string) error
Full() bool
}
type Serializer interface {
Loads([]byte) (*dns.Msg, error)
Dumps(*dns.Msg) ([]byte, error)
}
type MemoryCache struct {
@ -91,10 +97,11 @@ func (c *MemoryCache) Set(key string, msg *dns.Msg) error {
return nil
}
func (c *MemoryCache) Remove(key string) {
func (c *MemoryCache) Remove(key string) error {
c.mu.Lock()
delete(c.Backend, key)
c.mu.Unlock()
return nil
}
func (c *MemoryCache) Exists(key string) bool {
@ -118,6 +125,68 @@ func (c *MemoryCache) Full() bool {
return c.Length() >= c.Maxcount
}
/*
Memcached backend
*/
func NewMemcachedCache(servers []string, expire int32) *MemcachedCache {
c := memcache.New(servers...)
return &MemcachedCache{
backend: c,
serializer: &JsonSerializer{},
expire: expire,
}
}
type MemcachedCache struct {
backend *memcache.Client
serializer Serializer
expire int32
}
func (m *MemcachedCache) Set(key string, msg *dns.Msg) error {
var val []byte
var err error
// handle cases for negacache where it sets nil values
if msg == nil {
val = []byte("nil")
} else {
val, err = m.serializer.Dumps(msg)
}
if err != nil {
return err
}
return m.backend.Set(&memcache.Item{Key: key, Value: val, Expiration: m.expire})
}
func (m *MemcachedCache) Get(key string) (msg *dns.Msg, err error) {
item, err := m.backend.Get(key)
if err != nil {
err = KeyNotFound{key}
return
}
msg, err = m.serializer.Loads(item.Value)
return
}
func (m *MemcachedCache) Exists(key string) bool {
_, err := m.backend.Get(key)
if err != nil {
return true
}
return false
}
func (m *MemcachedCache) Remove(key string) error {
return m.backend.Delete(key)
}
func (m *MemcachedCache) Full() bool {
// memcache is never full (LRU)
return false
}
/*
TODO: Redis cache Backend
*/
@ -149,16 +218,18 @@ func KeyGen(q Question) string {
return key
}
/* we need to define marsheling to encode and decode
*/
type JsonSerializer struct {
}
func (*JsonSerializer) Dumps(mesg *dns.Msg) (encoded []byte, err error) {
encoded, err = json.Marshal(mesg)
encoded, err = json.Marshal(*mesg)
return
}
func (*JsonSerializer) Loads(data []byte, mesg **dns.Msg) error {
err := json.Unmarshal(data, mesg)
return err
func (*JsonSerializer) Loads(data []byte) (*dns.Msg, error) {
var mesg dns.Msg
err := json.Unmarshal(data, &mesg)
return &mesg, err
}

View File

@ -30,7 +30,7 @@ servers = ["127.0.0.1:11211"]
[log]
stdout = true
file = "./godns.log"
level = "INFO" #DEBUG | INFO |NOTICE | WARN | ERROR
level = "DEBUG" #DEBUG | INFO |NOTICE | WARN | ERROR
@ -38,7 +38,7 @@ level = "INFO" #DEBUG | INFO |NOTICE | WARN | ERROR
# backend option [memory|memcache|redis]
# redis backend not implemented yet
backend = "memory"
expire = 600 # 10 minutes
expire = 6000 # 10 minutes
maxcount = 0 #If set zero. The Sum of cache itmes will be unlimit.
[hosts]

View File

@ -61,6 +61,13 @@ func NewHandler() *GODNSHandler {
Expire: time.Duration(cacheConfig.Expire) * time.Second / 2,
Maxcount: cacheConfig.Maxcount,
}
case "memcache":
cache = NewMemcachedCache(
settings.Memcache.Servers,
int32(cacheConfig.Expire))
negCache = NewMemcachedCache(
settings.Memcache.Servers,
int32(cacheConfig.Expire/2))
case "redis":
// cache = &MemoryCache{
// Backend: make(map[string]*dns.Msg),