Beispiel #1
0
// prune garbage-collects zookeeper anchor directories that have no descendant files in them
func (dir *Dir) prune(dirs map[string]struct{}) error {
	for cname, _ := range dirs {
		cdir_, err := dir.OpenDir(cname)
		if zutil.IsNoNode(err) {
			delete(dirs, cname)
			continue
		} else if err != nil {
			return err
		}
		cdir := cdir_.(*Dir)
		_, dfiles, err := cdir.Files()
		if err != nil {
			return err
		}
		if len(dfiles) > 0 {
			continue
		}
		ddirs, dstat, err := cdir.syncDirs()
		if err != nil {
			return err
		}
		if len(ddirs) > 0 {
			continue
		}
		delete(dirs, cname)
		if err = dir.fs.zookeeper.Delete(cdir.zdir(), dstat.Version()); err != nil {
			return err
		}
	}
	return nil
}
Beispiel #2
0
func (fs *FS) Resolve(id int64) error {
	fs.Lock()
	defer fs.Unlock()

	// Read issue file
	unresolved := path.Join(fs.root, "unresolved", issuefs.IDString(id))
	data, _, err := fs.z.Get(unresolved)
	if err != nil && zutil.IsNoNode(err) {
		return err
	}
	if err != nil {
		panic(err)
	}

	// Write issue file in resolved
	if _, err = fs.z.Create(path.Join(fs.root, "resolved", issuefs.IDString(id)), data, 0, zutil.PermitAll); err != nil {
		panic(err)
	}

	// Remove issue file
	if err = fs.z.Delete(unresolved, -1); err != nil {
		panic(err)
	}
	return nil
}
Beispiel #3
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
	}
}
Beispiel #4
0
func (fs *FS) Unsubscribe(email string) error {
	fs.Lock()
	defer fs.Unlock()
	err := fs.z.Delete(path.Join(fs.root, "listener", email), -1)
	if err != nil && zutil.IsNoNode(err) {
		return err
	}
	if err != nil {
		panic(err)
	}
	return nil
}
Beispiel #5
0
// sync updates the files view from Zookeeper, if necessary
func (dir *Dir) sync() error {
	dir.Lock()
	watch := dir.watch
	dir.Unlock()
	if watch == nil {
		return ErrClosed
	}
	children, stat, err := dir.watch.Children()
	if zutil.IsNoNode(err) {
		// No represents a present and empty directory.
	} else if err != nil {
		return err
	}
	dir.update(children, stat)
	return nil
}
Beispiel #6
0
// sync updates the files view from Zookeeper, if necessary
func (dir *Dir) sync() error {

	children, stat, err := dir.watch.Children()
	if zutil.IsNoNode(err) {
		return dir.clear()
	} else if err != nil {
		return err
	}

	// If no change since last time, just return
	dir.Lock()
	if dir.stat != nil && dir.stat.CVersion() >= stat.CVersion() {
		dir.Unlock()
		return nil
	}
	dir.Unlock()

	return dir.fetch(children, stat)
}
Beispiel #7
0
func (dir *Dir) change(sinceRev int64, expire time.Duration) error {
	// Check whether the present data is newer than sinceRev
	dir.Lock()
	if dir.rev() > sinceRev {
		dir.Unlock()
		return nil
	}
	stat := dir.stat
	dir.Unlock()

	children, stat, err := dir.watch.ChildrenChange(stat, expire)
	if zutil.IsNoNode(err) {
		return dir.clear()
	} else if err != nil {
		return err
	}

	return dir.fetch(children, stat)
}
Beispiel #8
0
func (dir *Dir) change(expire time.Duration) error {
	dir.Lock()
	watch := dir.watch
	dir.Unlock()
	if watch == nil {
		return ErrClosed
	}

	dir.Lock()
	stat := dir.stat
	dir.Unlock()

	children, stat, err := dir.watch.ChildrenChange(stat, expire)
	if zutil.IsNoNode(err) {
		// No represents a present and empty directory.
	} else if err != nil {
		return err
	}
	dir.update(children, stat)
	return nil
}