125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package zk
|
|
|
|
import (
|
|
"errors"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/samuel/go-zookeeper/zk"
|
|
"mongo.games.com/goserver/core/logger"
|
|
"mongo.games.com/goserver/core/module"
|
|
)
|
|
|
|
var (
|
|
// error
|
|
ErrNoChild = errors.New("zk: children is nil")
|
|
ErrNodeNotExist = errors.New("zk: node not exist")
|
|
)
|
|
|
|
// Connect connect to zookeeper, and start a goroutine log the event.
|
|
func Connect(addr []string, timeout time.Duration) (*zk.Conn, error) {
|
|
conn, session, err := zk.Connect(addr, timeout)
|
|
if err != nil {
|
|
logger.Logger.Errorf("zk.Connect(\"%v\", %d) error(%v)", addr, timeout, err)
|
|
return nil, err
|
|
}
|
|
go func() {
|
|
for {
|
|
event := <-session
|
|
logger.Logger.Tracef("zookeeper get a event: %s", event.State.String())
|
|
}
|
|
}()
|
|
return conn, nil
|
|
}
|
|
|
|
// Create create zookeeper path, if path exists ignore error
|
|
func Create(conn *zk.Conn, fpath string) error {
|
|
// create zk root path
|
|
tpath := ""
|
|
for _, str := range strings.Split(fpath, "/")[1:] {
|
|
tpath = path.Join(tpath, "/", str)
|
|
logger.Logger.Tracef("create zookeeper path: \"%s\"", tpath)
|
|
_, err := conn.Create(tpath, []byte(""), 0, zk.WorldACL(zk.PermAll))
|
|
if err != nil {
|
|
if err == zk.ErrNodeExists {
|
|
logger.Logger.Warnf("zk.create(\"%s\") exists", tpath)
|
|
} else {
|
|
logger.Logger.Errorf("zk.create(\"%s\") error(%v)", tpath, err)
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RegisterTmp create a ephemeral node, and watch it, if node droped then shutdown.
|
|
func RegisterTemp(conn *zk.Conn, fpath string, data []byte) error {
|
|
tpath, err := conn.Create(path.Join(fpath)+"/", data, zk.FlagEphemeral|zk.FlagSequence, zk.WorldACL(zk.PermAll))
|
|
if err != nil {
|
|
logger.Logger.Errorf("conn.Create(\"%s\", \"%s\", zk.FlagEphemeral|zk.FlagSequence) error(%v)", fpath, string(data), err)
|
|
return err
|
|
}
|
|
logger.Logger.Tracef("create a zookeeper node:%s", tpath)
|
|
// watch self
|
|
go func() {
|
|
for {
|
|
logger.Logger.Infof("zk path: \"%s\" set a watch", tpath)
|
|
exist, _, watch, err := conn.ExistsW(tpath)
|
|
if err != nil {
|
|
logger.Logger.Errorf("zk.ExistsW(\"%s\") error(%v)", tpath, err)
|
|
logger.Logger.Warnf("zk path: \"%s\" set watch failed, shutdown", tpath)
|
|
module.Stop()
|
|
return
|
|
}
|
|
if !exist {
|
|
logger.Logger.Warnf("zk path: \"%s\" not exist, shutdown", tpath)
|
|
module.Stop()
|
|
return
|
|
}
|
|
event := <-watch
|
|
logger.Logger.Infof("zk path: \"%s\" receive a event %v", tpath, event)
|
|
}
|
|
}()
|
|
return nil
|
|
}
|
|
|
|
// GetNodesW get all child from zk path with a watch.
|
|
func GetNodesW(conn *zk.Conn, path string) ([]string, <-chan zk.Event, error) {
|
|
nodes, stat, watch, err := conn.ChildrenW(path)
|
|
if err != nil {
|
|
if err == zk.ErrNoNode {
|
|
return nil, nil, ErrNodeNotExist
|
|
}
|
|
logger.Logger.Errorf("zk.ChildrenW(\"%s\") error(%v)", path, err)
|
|
return nil, nil, err
|
|
}
|
|
if stat == nil {
|
|
return nil, nil, ErrNodeNotExist
|
|
}
|
|
if len(nodes) == 0 {
|
|
return nil, nil, ErrNoChild
|
|
}
|
|
return nodes, watch, nil
|
|
}
|
|
|
|
// GetNodes get all child from zk path.
|
|
func GetNodes(conn *zk.Conn, path string) ([]string, error) {
|
|
nodes, stat, err := conn.Children(path)
|
|
if err != nil {
|
|
if err == zk.ErrNoNode {
|
|
return nil, ErrNodeNotExist
|
|
}
|
|
logger.Logger.Errorf("zk.Children(\"%s\") error(%v)", path, err)
|
|
return nil, err
|
|
}
|
|
if stat == nil {
|
|
return nil, ErrNodeNotExist
|
|
}
|
|
if len(nodes) == 0 {
|
|
return nil, ErrNoChild
|
|
}
|
|
return nodes, nil
|
|
}
|