Example #1
0
// 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))
}
Example #2
0
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
}