Add sync => go-sync
This commit is contained in:
178
sync/data/memcached/memcached.go
Normal file
178
sync/data/memcached/memcached.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package memcached
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mc "github.com/bradfitz/gomemcache/memcache"
|
||||
"github.com/micro/go-micro/sync/data"
|
||||
)
|
||||
|
||||
type mkv struct {
|
||||
Server *mc.ServerList
|
||||
Client *mc.Client
|
||||
}
|
||||
|
||||
func (m *mkv) Read(key string) (*data.Record, error) {
|
||||
keyval, err := m.Client.Get(key)
|
||||
if err != nil && err == mc.ErrCacheMiss {
|
||||
return nil, data.ErrNotFound
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if keyval == nil {
|
||||
return nil, data.ErrNotFound
|
||||
}
|
||||
|
||||
return &data.Record{
|
||||
Key: keyval.Key,
|
||||
Value: keyval.Value,
|
||||
Expiration: time.Second * time.Duration(keyval.Expiration),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *mkv) Delete(key string) error {
|
||||
return m.Client.Delete(key)
|
||||
}
|
||||
|
||||
func (m *mkv) Write(record *data.Record) error {
|
||||
return m.Client.Set(&mc.Item{
|
||||
Key: record.Key,
|
||||
Value: record.Value,
|
||||
Expiration: int32(record.Expiration.Seconds()),
|
||||
})
|
||||
}
|
||||
|
||||
func (m *mkv) Dump() ([]*data.Record, error) {
|
||||
// stats
|
||||
// cachedump
|
||||
// get keys
|
||||
|
||||
var keys []string
|
||||
|
||||
//data := make(map[string]string)
|
||||
if err := m.Server.Each(func(c net.Addr) error {
|
||||
cc, err := net.Dial("tcp", c.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cc.Close()
|
||||
|
||||
b := bufio.NewReadWriter(bufio.NewReader(cc), bufio.NewWriter(cc))
|
||||
|
||||
// get records
|
||||
if _, err := fmt.Fprintf(b, "stats records\r\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.Flush()
|
||||
|
||||
v, err := b.ReadSlice('\n')
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
parts := bytes.Split(v, []byte("\n"))
|
||||
if len(parts) < 1 {
|
||||
return nil
|
||||
}
|
||||
vals := strings.Split(string(parts[0]), ":")
|
||||
records := vals[1]
|
||||
|
||||
// drain
|
||||
for {
|
||||
buf, err := b.ReadSlice('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasPrefix(string(buf), "END") {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
b.Writer.Reset(cc)
|
||||
b.Reader.Reset(cc)
|
||||
|
||||
if _, err := fmt.Fprintf(b, "lru_crawler metadump %s\r\n", records); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Flush()
|
||||
|
||||
for {
|
||||
v, err := b.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.HasPrefix(v, "END") {
|
||||
break
|
||||
}
|
||||
key := strings.Split(v, " ")[0]
|
||||
keys = append(keys, strings.TrimPrefix(key, "key="))
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var vals []*data.Record
|
||||
|
||||
// concurrent op
|
||||
ch := make(chan *data.Record, len(keys))
|
||||
|
||||
for _, k := range keys {
|
||||
go func(key string) {
|
||||
i, _ := m.Read(key)
|
||||
ch <- i
|
||||
}(k)
|
||||
}
|
||||
|
||||
for i := 0; i < len(keys); i++ {
|
||||
record := <-ch
|
||||
|
||||
if record == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
vals = append(vals, record)
|
||||
}
|
||||
|
||||
close(ch)
|
||||
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
func (m *mkv) String() string {
|
||||
return "memcached"
|
||||
}
|
||||
|
||||
func NewData(opts ...data.Option) data.Data {
|
||||
var options data.Options
|
||||
for _, o := range opts {
|
||||
o(&options)
|
||||
}
|
||||
|
||||
if len(options.Nodes) == 0 {
|
||||
options.Nodes = []string{"127.0.0.1:11211"}
|
||||
}
|
||||
|
||||
ss := new(mc.ServerList)
|
||||
ss.SetServers(options.Nodes...)
|
||||
|
||||
return &mkv{
|
||||
Server: ss,
|
||||
Client: mc.New(options.Nodes...),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user