// Create a node if it doesn't exist, otherwise do nothing func (zk *ZkConn) Touch(nodePath string) (string, error) { if stat, err := zk.Exists(nodePath); err == nil && stat != nil { return nodePath, nil } // touch all directores above nodePath because zookeeper sucks dir := path.Dir(nodePath) if dir != "/" && dir != "." { zk.Touch(dir) } return zk.Create(nodePath, "", 0, gozk.WorldACL(gozk.PERM_ALL)) }
func rlock(conn *gozk.Conn, basePath, prefix string, checkPrefix []string) (lock string, err error) { // step 1 lock, err = conn.Create(path.Join(basePath, prefix), "", gozk.EPHEMERAL|gozk.SEQUENCE, gozk.WorldACL(gozk.PERM_ALL)) if err != nil { return lock, err } for { // step 2 children, _, err := conn.Children(basePath) if err != nil { return lock, err } // step 3 if children == nil || len(children) == 0 { return lock, errors.New("get children didn't return my lock") } // filter out non-lock children and extract sequence numbers filteredChildren := map[string]string{} filteredChildrenKeys := []string{} for _, v := range children { for _, pfx := range checkPrefix { if strings.HasPrefix(v, pfx) { seqNum := strings.Replace(v, pfx, "", 1) filteredChildren[seqNum] = v filteredChildrenKeys = append(filteredChildrenKeys, seqNum) break } } } sort.Strings(filteredChildrenKeys) prevLock := "" for _, seqNum := range filteredChildrenKeys { if path.Base(lock) == filteredChildren[seqNum] { break } prevLock = path.Join(basePath, filteredChildren[seqNum]) } if prevLock == "" { return lock, nil } // step 4 stat, watchCh, err := conn.ExistsW(prevLock) if err != nil { return lock, err } // step 5 if stat == nil { continue } <-watchCh } return lock, nil }