init
commit
cf28620949
@ -0,0 +1,37 @@
|
||||
package starmap
|
||||
|
||||
import "errors"
|
||||
|
||||
func Get(key string) (interface{}, error) {
|
||||
var err error
|
||||
kvmu.RLock()
|
||||
defer kvmu.RUnlock()
|
||||
data, ok := kvMap[key]
|
||||
if !ok {
|
||||
err = errors.New("key not exists")
|
||||
}
|
||||
return data, err
|
||||
}
|
||||
|
||||
func Store(key string, value interface{}) error {
|
||||
kvmu.Lock()
|
||||
defer kvmu.Unlock()
|
||||
kvMap[key] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func Delete(key string) error {
|
||||
kvmu.Lock()
|
||||
defer kvmu.Unlock()
|
||||
delete(kvMap, key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Range(run func(k string, v interface{}) bool) error {
|
||||
for k, v := range kvMap {
|
||||
if !run(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (kv *RemoteKv) clientOnline() error {
|
||||
if kv.client == nil || (kv.setKeepAlive && !kv.client.Online) {
|
||||
return errors.New("Client Not Online,Please Contact A Server First")
|
||||
}
|
||||
if (!kv.setKeepAlive) && (!kv.client.Online) {
|
||||
err := kv.reconnect()
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (kv *RemoteKv) Get(key string) (interface{}, error) {
|
||||
kv.kvmu.Lock()
|
||||
defer kv.kvmu.Unlock()
|
||||
defer kv.keepalive()
|
||||
if err := kv.clientOnline(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := kv.client.SendValueWait("Get", key, kv.TimeOut)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inf, err := decode([]byte(data.Value))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var repInf *basicReply
|
||||
repInf = inf.(*basicReply)
|
||||
if repInf.Key == "ok" {
|
||||
inf2, err := decode(repInf.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return inf2, nil
|
||||
}
|
||||
return nil, errors.New(string(repInf.Value))
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) Store(key string, value interface{}) error {
|
||||
kv.kvmu.Lock()
|
||||
defer kv.kvmu.Unlock()
|
||||
defer kv.keepalive()
|
||||
if err := kv.clientOnline(); err != nil {
|
||||
return err
|
||||
}
|
||||
encodeData, err := encode(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sendData, _ := encode(basicReply{key, encodeData})
|
||||
data, err := kv.client.SendValueWait("Store", string(sendData), kv.TimeOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data.Value == "ok" {
|
||||
return nil
|
||||
}
|
||||
return errors.New(data.Value)
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) Delete(key string) error {
|
||||
kv.kvmu.Lock()
|
||||
defer kv.kvmu.Unlock()
|
||||
defer kv.keepalive()
|
||||
if err := kv.clientOnline(); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := kv.client.SendValueWait("Delete", key, kv.TimeOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if data.Value == "ok" {
|
||||
return nil
|
||||
}
|
||||
return errors.New(data.Value)
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) keepalive() {
|
||||
if !kv.setKeepAlive && kv.client.Online {
|
||||
kv.client.ClientStop()
|
||||
for kv.client.Online {
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
func (kv *RemoteKv) GetMap(key string) (StarMap, error) {
|
||||
kv.kvmu.Lock()
|
||||
defer kv.kvmu.Unlock()
|
||||
defer kv.keepalive()
|
||||
recv, err := kv.client.SendValueWait("GetMap", key, kv.TimeOut)
|
||||
if err != nil {
|
||||
return StarMapSample{}, err
|
||||
}
|
||||
if recv.Key == "error" {
|
||||
return StarMapSample{}, errors.New(recv.Value)
|
||||
}
|
||||
value, err := decodeMap([]byte(recv.Value))
|
||||
if err != nil {
|
||||
return StarMapSample{}, err
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) StoreMap(value StarMap) error {
|
||||
kv.kvmu.Lock()
|
||||
defer kv.kvmu.Unlock()
|
||||
defer kv.keepalive()
|
||||
encodeData, err := encodeMap(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recv, err := kv.client.SendValueWait("StoreMap", string(encodeData), kv.TimeOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if recv.Key == "error" {
|
||||
return errors.New(recv.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) DeleteMap(value StarMap) error {
|
||||
kv.kvmu.Lock()
|
||||
defer kv.kvmu.Unlock()
|
||||
defer kv.keepalive()
|
||||
recv, err := kv.client.SendValueWait("DeleteMap", value.GetName(), kv.TimeOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if recv.Key == "error" {
|
||||
return errors.New(recv.Value)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type StarMap interface {
|
||||
GetName() string
|
||||
}
|
||||
|
||||
type StarMapSample struct{}
|
||||
|
||||
func (sample StarMapSample) GetName() string {
|
||||
return "starsample"
|
||||
}
|
||||
|
||||
func GetMap(value StarMap) error {
|
||||
kvmuPro.RLock()
|
||||
defer kvmuPro.RUnlock()
|
||||
value, ok := kvMapPro[value.GetName()]
|
||||
if !ok {
|
||||
return errors.New("key not exists")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func StoreMap(value StarMap) error {
|
||||
kvmuPro.Lock()
|
||||
defer kvmuPro.Unlock()
|
||||
kvMapPro[value.GetName()] = value
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteMap(value StarMap) error {
|
||||
delete(kvMapPro, value.GetName())
|
||||
return nil
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"b612.me/notify"
|
||||
)
|
||||
|
||||
type RemoteKv struct {
|
||||
kvmu sync.RWMutex
|
||||
server *notify.StarNotifyS
|
||||
client *notify.StarNotifyC
|
||||
addr string
|
||||
setKeepAlive bool
|
||||
TimeOut time.Duration
|
||||
ErrMsg string
|
||||
}
|
||||
|
||||
func NewServer(addr string) (*RemoteKv, error) {
|
||||
var kv RemoteKv
|
||||
var err error
|
||||
kv.addr = addr
|
||||
kv.TimeOut = time.Second * 10
|
||||
kv.server, err = notify.NewNotifyS("tcp", addr)
|
||||
if err == nil {
|
||||
kv.bind()
|
||||
}
|
||||
return &kv, err
|
||||
}
|
||||
|
||||
func NewClient(addr string) (*RemoteKv, error) {
|
||||
var err error
|
||||
var kv RemoteKv
|
||||
kv.addr = addr
|
||||
kv.TimeOut = time.Second * 10
|
||||
kv.client, err = notify.NewNotifyC("tcp", addr)
|
||||
if err == nil {
|
||||
kv.setKeepAlive = true
|
||||
kv.client.UseChannel = false
|
||||
}
|
||||
return &kv, err
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) Register(data interface{}) {
|
||||
gob.Register(data)
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) RegisterAll(data []interface{}) {
|
||||
for _, v := range data {
|
||||
gob.Register(v)
|
||||
}
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) SetKeepAlive(alive bool) {
|
||||
kv.setKeepAlive = alive
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) GetKeepAlive() bool {
|
||||
return kv.setKeepAlive
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) reconnect() error {
|
||||
var err error
|
||||
if kv.addr != "" {
|
||||
kv.client, err = notify.NewNotifyC("tcp", kv.addr)
|
||||
if err == nil {
|
||||
kv.client.UseChannel = false
|
||||
}
|
||||
return err
|
||||
}
|
||||
return errors.New("Client Not Online!")
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) bind() {
|
||||
kv.server.SetNotify("Get", kv.get)
|
||||
kv.server.SetNotify("Store", kv.store)
|
||||
kv.server.SetNotify("Delete", kv.store)
|
||||
kv.server.SetNotify("GetMap", kv.getMap)
|
||||
kv.server.SetNotify("StoreMap", kv.storeMap)
|
||||
kv.server.SetNotify("DeleteMap", kv.deleteMap)
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) ErrTimeOut(err error) bool {
|
||||
if err.Error() == "Time Exceed" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package starmap
|
||||
|
||||
import "b612.me/notify"
|
||||
|
||||
type basicReply struct {
|
||||
Key string
|
||||
Value []byte
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) get(data notify.SMsg) string {
|
||||
key := data.Value
|
||||
value, err := Get(key)
|
||||
if err != nil {
|
||||
sendData, err := encode(basicReply{"error", []byte("key not exists")})
|
||||
if err != nil {
|
||||
kv.ErrMsg += err.Error()
|
||||
return ""
|
||||
}
|
||||
data.Reply(string(sendData))
|
||||
} else {
|
||||
prepareData, err := encode(value)
|
||||
if err != nil {
|
||||
kv.ErrMsg += err.Error()
|
||||
sendData, _ := encode(basicReply{"error", []byte(err.Error())})
|
||||
data.Reply(string(sendData))
|
||||
return ""
|
||||
}
|
||||
sendData, err := encode(basicReply{"ok", prepareData})
|
||||
if err != nil {
|
||||
kv.ErrMsg += err.Error()
|
||||
sendData, _ := encode(basicReply{"error", []byte(err.Error())})
|
||||
data.Reply(string(sendData))
|
||||
return ""
|
||||
}
|
||||
data.Reply(string(sendData))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) store(data notify.SMsg) string {
|
||||
decodeData, err := decode([]byte(data.Value))
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
inf := decodeData.(*basicReply)
|
||||
customStruct, err := decode(inf.Value)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
err = Store(inf.Key, customStruct)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return "ok"
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) delete(data notify.SMsg) string {
|
||||
err := Delete(data.Value)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return "ok"
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"b612.me/notify"
|
||||
)
|
||||
|
||||
func (kv *RemoteKv) getMap(data notify.SMsg) string {
|
||||
val, ok := kvMapPro[data.Value]
|
||||
if !ok {
|
||||
data.Key = "error"
|
||||
data.Reply("key not exists")
|
||||
return ""
|
||||
}
|
||||
encodeData, err := encodeMap(val)
|
||||
if err != nil {
|
||||
data.Key = "error"
|
||||
data.Reply(err.Error())
|
||||
return ""
|
||||
}
|
||||
return string(encodeData)
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) storeMap(data notify.SMsg) string {
|
||||
recvData, err := decodeMap([]byte(data.Value))
|
||||
if err != nil {
|
||||
data.Key = "error"
|
||||
data.Reply(err.Error())
|
||||
return ""
|
||||
}
|
||||
err = StoreMap(recvData)
|
||||
if err != nil {
|
||||
data.Key = "error"
|
||||
data.Reply(err.Error())
|
||||
return ""
|
||||
}
|
||||
return "ok"
|
||||
}
|
||||
|
||||
func (kv *RemoteKv) deleteMap(data notify.SMsg) string {
|
||||
delete(kvMapPro, data.Value)
|
||||
return "ok"
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package starmap
|
||||
|
||||
import "sync"
|
||||
|
||||
var kvMap map[string]interface{}
|
||||
var kvmu sync.RWMutex
|
||||
var kvMapPro map[string]StarMap
|
||||
var kvmuPro sync.RWMutex
|
||||
|
||||
func init() {
|
||||
kvMap = make(map[string]interface{})
|
||||
kvMapPro = make(map[string]StarMap)
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Miaomiao struct {
|
||||
Sakura string
|
||||
Fuck int
|
||||
Mimi bool
|
||||
}
|
||||
|
||||
func Test_Remote(t *testing.T) {
|
||||
Store("nmb", 22222)
|
||||
server, err := NewServer("127.0.0.1:45678")
|
||||
server.Register(&Miaomiao{})
|
||||
fmt.Println(err)
|
||||
client, err := NewClient("127.0.0.1:45678")
|
||||
client.SetKeepAlive(false)
|
||||
fmt.Println(err)
|
||||
_ = server
|
||||
fmt.Println(client.Get("nmb"))
|
||||
fmt.Println(client.Store("maio", Miaomiao{"sss", 222, true}))
|
||||
fmt.Println(client.Get("maio"))
|
||||
}
|
||||
|
||||
func (cat *Miaomiao) GetName() string {
|
||||
return "miaomiao"
|
||||
}
|
||||
func Test_Remote2(t *testing.T) {
|
||||
server, err := NewServer("127.0.0.1:45678")
|
||||
server.Register(&Miaomiao{})
|
||||
fmt.Println(err)
|
||||
client, err := NewClient("127.0.0.1:45678")
|
||||
//client.SetKeepAlive(false)
|
||||
fmt.Println(err)
|
||||
_ = server
|
||||
fmt.Println(client.StoreMap(&Miaomiao{"suki", 1127, false}))
|
||||
fmt.Println(client.GetMap("miaomiao"))
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package starmap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(&basicReply{})
|
||||
}
|
||||
|
||||
func encode(src interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
err := enc.Encode(&src)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func decode(src []byte) (interface{}, error) {
|
||||
dec := gob.NewDecoder(bytes.NewReader(src))
|
||||
var dst interface{}
|
||||
err := dec.Decode(&dst)
|
||||
return dst, err
|
||||
}
|
||||
|
||||
func encodeMap(src StarMap) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
enc := gob.NewEncoder(&buf)
|
||||
err := enc.Encode(&src)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func decodeMap(src []byte) (StarMap, error) {
|
||||
dec := gob.NewDecoder(bytes.NewReader(src))
|
||||
var dst StarMap
|
||||
err := dec.Decode(&dst)
|
||||
return dst, err
|
||||
}
|
Loading…
Reference in New Issue