go-common/app/service/live/broadcast-proxy/server/zk.go
2019-04-22 18:49:16 +08:00

215 lines
5.1 KiB
Go

package server
import (
"github.com/samuel/go-zookeeper/zk"
"go-common/library/log"
"strings"
"time"
)
type ZkClient struct {
conn *zk.Conn
address []string
timeout time.Duration
dialTime time.Time
closed bool
stopper chan struct{}
}
func NewZkClient(addrs []string, timeout time.Duration) (*ZkClient, error) {
if timeout <= 0 {
timeout = time.Second * 5
}
c := &ZkClient{
address: addrs,
timeout: timeout,
stopper: make(chan struct{}),
}
if err := c.Reset(); err != nil {
return nil, err
}
return c, nil
}
func (c *ZkClient) GetTimeout() time.Duration {
return c.timeout
}
func (c *ZkClient) RecursiveCreate(path string) error {
if path == "" || path == "/" {
return nil
}
if exists, _, err := c.conn.Exists(path); err != nil {
return err
} else if exists {
return nil
}
if err := c.RecursiveCreate(path[0:strings.LastIndex(path, "/")]); err != nil {
return err
}
_, err := c.conn.Create(path, []byte{}, 0, zk.WorldACL(zk.PermAll))
if err != nil && err != zk.ErrNodeExists {
return err
}
return nil
}
func (c *ZkClient) Reset() error {
c.dialTime = time.Now()
conn, events, err := zk.Connect(c.address, c.timeout)
if err != nil {
return err
}
if c.conn != nil {
c.conn.Close()
c.conn = nil
}
c.conn = conn
go func() {
for ev := range events {
if ev.Err == nil {
log.V(2).Info("[ZooKeeper]Event Info:%+v", ev)
} else {
log.Error("[ZooKeeper]Event Error:%+v", ev)
}
}
}()
return nil
}
func (c *ZkClient) CreateEphemeralNode(path string, node string, data []byte) (string, error) {
if err := c.RecursiveCreate(path); err != nil {
return "", err
}
nodePath := strings.Join([]string{path, node}, "/")
path, err := c.conn.Create(nodePath, data, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))
return path, err
}
func (c *ZkClient) CreatePersistNode(path string, node string, data []byte) (string, error) {
if err := c.RecursiveCreate(path); err != nil {
return "", err
}
nodePath := strings.Join([]string{path, node}, "/")
path, err := c.conn.Create(nodePath, data, 0, zk.WorldACL(zk.PermAll))
return path, err
}
func (c *ZkClient) Exists(path string, node string) (bool, int32, error) {
fullPath := strings.Join([]string{path, node}, "/")
exists, stat, err := c.conn.Exists(fullPath)
return exists, stat.Version, err
}
func (c *ZkClient) SetNodeData(path string, node string, data []byte, version int32) error {
var err error
fullPath := strings.Join([]string{path, node}, "/")
_, err = c.conn.Set(fullPath, data, version)
return err
}
func (c *ZkClient) GetNodeData(path string, node string) ([]byte, int32, error) {
var err error
fullPath := strings.Join([]string{path, node}, "/")
data, stat, err := c.conn.Get(fullPath)
return data, stat.Version, err
}
func (c *ZkClient) DeleteNode(path string, node string) error {
var err error
fullPath := strings.Join([]string{path, node}, "/")
exists, stat, err := c.conn.Exists(fullPath)
if err != nil {
return err
}
if !exists {
return nil
}
err = c.conn.Delete(fullPath, stat.Version)
return err
}
func (c *ZkClient) Close() {
if c.closed {
return
}
c.closed = true
if c.conn != nil {
c.conn.Close()
}
close(c.stopper)
}
func (c *ZkClient) GetChildren(node string) ([]string, error) {
children, _, err := c.conn.Children(node)
return children, err
}
func (c *ZkClient) GetChildrenWithData(node string) (map[string]string, error) {
children, _, err := c.conn.Children(node)
result := make(map[string]string)
for _, child := range children {
if data, _, e := c.conn.Get(strings.Join([]string{node, child}, "/")); e == nil {
result[child] = string(data)
} else {
log.Error("[ZookeeperClient]GetChildrenWithData:get child:%s failed, err:%s", child, e.Error())
}
}
return result, err
}
func (c *ZkClient) GetData(path string) (string, error) {
data, _, err := c.conn.Get(path)
return string(data), err
}
func (c *ZkClient) WatchChildren(path string) (map[string]struct{}, <-chan zk.Event, error) {
if exists, _, err := c.conn.Exists(path); err != nil {
return nil, nil, err
} else if !exists {
return nil, nil, zk.ErrNoNode
}
children, _, event, err := c.conn.ChildrenW(path)
if err != nil {
return nil, nil, err
}
result := make(map[string]struct{})
for _, child := range children {
result[child] = struct{}{}
}
return result, event, nil
}
func (c *ZkClient) WatchChildrenWithData(node string) (map[string]string, <-chan zk.Event, error) {
if exists, _, err := c.conn.Exists(node); err != nil {
return nil, nil, err
} else if !exists {
return nil, nil, zk.ErrNoNode
}
children, _, event, err := c.conn.ChildrenW(node)
if err != nil {
return nil, nil, err
}
result := make(map[string]string)
for _, child := range children {
if data, _, e := c.conn.Get(strings.Join([]string{node, child}, "/")); e == nil {
result[child] = string(data)
} else {
return nil, nil, e
}
}
return result, event, nil
}
func (c *ZkClient) WatchData(path string) ([]byte, <-chan zk.Event, error) {
data, _, event, err := c.conn.GetW(path)
return data, event, err
}
func (c *ZkClient) ZooKeeperPath(args ...string) string {
return strings.Join(args, "/")
}