Example #1
0
// ChildrenChange blocks until the children of the watched Zookeeper node change
// relative to the returned values of the last invokation of Children or ChildrenChange.
// It returns the new children and stat values.
func (w *Watch) ChildrenChange(sinceStat *zookeeper.Stat, expire time.Duration) (children []string, stat *zookeeper.Stat, err error) {
	// Still alive?
	w.lk.Lock()
	z, cwatch := w.zookeeper, w.cwatch
	w.lk.Unlock()
	if z == nil {
		return nil, nil, ErrClosed
	}

	// Wait if watch present, otherwise read from Zookeeper
	if cwatch != nil {
		// If we already have a newer revision, return it
		w.lk.Lock()
		if sinceStat == nil || w.cstat.CVersion() > sinceStat.CVersion() {
			defer w.lk.Unlock()
			return w.children, w.cstat, nil
		}
		w.lk.Unlock()

		if expire == 0 {
			<-cwatch
		} else {
			select {
			case <-cwatch:
			case <-time.After(expire):
				return nil, nil, ErrExpire
			}
		}
	}
	return w.fetchChildren()
}
Example #2
0
func (dir *Dir) update(children []string, stat *zookeeper.Stat) {
	// If no change since last time, just return
	dir.Lock()
	defer dir.Unlock()

	if dir.stat != nil && dir.stat.CVersion() >= stat.CVersion() {
		return
	}
	dir.stat = stat
	dir.children = make(map[string]durablefs.Info)
	for _, c := range children {
		nodepath := path.Join(dir.zroot, dir.dpath, c)
		// Get node data
		data, dstat, err := dir.conn.Get(nodepath)
		if zutil.IsNoNode(err) {
			continue
		} else if err != nil {
			println("problem fetching durable node data", nodepath, err.Error())
			continue
		}
		// Get node children
		chld, cstat, err := dir.conn.Children(nodepath)
		if zutil.IsNoNode(err) {
			continue
		} else if err != nil {
			println("problem fetching durable node children", nodepath, err.Error())
			continue
		}
		// TODO: To implement efficient recursive garbage collection, we'd need to keep a global in-memory
		// directories structure, as in for the anchor file system
		info := durablefs.Info{
			Name:        c,
			HasBody:     len(data) > 0,
			HasChildren: len(chld) > 0,
		}
		if cstat.Version() != dstat.Version() {
			println("durable file", nodepath, "changed during pruning; leaving alone")
		} else if !info.HasBody && !info.HasChildren {
			if err = dir.conn.Delete(nodepath, dstat.Version()); err != nil && !zutil.IsNoNode(err) {
				// panic(err)
			}
			continue
		}
		dir.children[c] = info
	}
}