// RegisterTmp create a ephemeral node, and watch it, if node droped then send a SIGQUIT to self. func RegisterTemp(conn *zk.Conn, fpath, data string) error { tpath, err := conn.Create(path.Join(fpath)+"/", []byte(data), zk.FlagEphemeral|zk.FlagSequence, zk.WorldACL(zk.PermAll)) if err != nil { glog.Errorf("conn.Create(\"%s\", \"%s\", zk.FlagEphemeral|zk.FlagSequence) error(%v)", fpath, data, err) return err } glog.V(1).Infof("create a zookeeper node:%s", tpath) // watch self go func() { for { glog.Infof("zk path: \"%s\" set a watch", tpath) exist, _, watch, err := conn.ExistsW(tpath) if err != nil { glog.Errorf("zk.ExistsW(\"%s\") error(%v)", tpath, err) glog.Warningf("zk path: \"%s\" set watch failed, kill itself", tpath) killSelf() return } if !exist { glog.Warningf("zk path: \"%s\" not exist, kill itself", tpath) killSelf() return } event := <-watch glog.Infof("zk path: \"%s\" receive a event %v", tpath, event) } }() return nil }
// 创建一个临时节点,并监听自己 func CreateTempW(conn *zk.Conn, fpath, data string, watchFunc func(bool, zk.Event)) error { tpath, err := conn.Create(path.Join(fpath)+"/", []byte(data), zk.FlagEphemeral|zk.FlagSequence, zk.WorldACL(zk.PermAll)) if err != nil { glog.Errorf("conn.Create(\"%s\", \"%s\", zk.FlagEphemeral|zk.FlagSequence) error(%v)", fpath, data, err) return err } glog.V(1).Infof("create a zookeeper node:%s", tpath) // watch self if watchFunc != nil { go func() { for { glog.Infof("zk path: \"%s\" set a watch", tpath) exist, _, watch, err := conn.ExistsW(tpath) if err != nil { glog.Errorf("zk.ExistsW(%s) error(%v)", tpath, err) return } event := <-watch watchFunc(exist, event) glog.Infof("zk path: \"%s\" receive a event %v", tpath, event) } }() } return nil }
// The lexically lowest node is the lock holder - verify that this // path holds the lock. Call this queue-lock because the semantics are // a hybrid. Normal zookeeper locks make assumptions about sequential // numbering that don't hold when the data in a lock is modified. // if the provided 'interrupted' chan is closed, we'll just stop waiting // and return an interruption error func ObtainQueueLock(zconn zookeeper.Conn, zkPath string, wait time.Duration, interrupted chan struct{}) error { queueNode := path.Dir(zkPath) lockNode := path.Base(zkPath) timer := time.NewTimer(wait) trylock: children, _, err := zconn.Children(queueNode) if err != nil { return fmt.Errorf("zkutil: trylock failed %v", err) } sort.Strings(children) if len(children) > 0 { if children[0] == lockNode { return nil } if wait > 0 { prevLock := "" for i := 1; i < len(children); i++ { if children[i] == lockNode { prevLock = children[i-1] break } } if prevLock == "" { return fmt.Errorf("zkutil: no previous queue node found: %v", zkPath) } zkPrevLock := path.Join(queueNode, prevLock) _, stat, watch, err := zconn.ExistsW(zkPrevLock) if err != nil { return fmt.Errorf("zkutil: unable to watch queued node %v %v", zkPrevLock, err) } if stat == nil { goto trylock } select { case <-timer.C: break case <-interrupted: return ErrInterrupted case <-watch: // The precise event doesn't matter - try to read again regardless. goto trylock } } return ErrTimeout } return fmt.Errorf("zkutil: empty queue node: %v", queueNode) }
func ZkCreateRoot(zkConn *zk.Conn, root string) { flags := int32(0) acl := zk.WorldACL(zk.PermAll) found, _, _, err := zkConn.ExistsW(root) if err != nil { panic(err.Error()) } if !found { fmt.Printf("create %s\n", root) path, err := zkConn.Create(root, []byte(""), flags, acl) if err != nil { panic(err.Error()) } fmt.Printf("created %s\n", path) } }