示例#1
0
func (ch Chg) applyData(lfs zx.RWTree, rfs zx.Tree) error {
	nd := ch.D.UsrAttrs()
	for _, k := range ignoredPutAttrs {
		delete(nd, k)
	}
	datc := rfs.Get(ch.D["path"], 0, zx.All, "")
	dc := lfs.Put(ch.D["path"], nd, 0, datc, "")
	<-dc
	return cerror(dc)
}
示例#2
0
func (ch Chg) applyAdd(lfs zx.RWTree, rfs zx.Tree, pred string, ec chan<- error) error {
	var err error
	gc := rfs.FindGet(ch.D["path"], pred, "", "", 0)
	for g := range gc {
		dprintf("get %s\n", g)
		d := g.Dir
		if d == nil {
			break
		}
		for _, k := range ignoredPutAttrs {
			delete(d, k)
		}
		if d["err"] != "" {
			e := errors.New(d["err"])
			perr(ec, e)
			dprintf("%s: %s\n", d["path"], d["err"])
			if err == nil {
				err = e
			}
			continue
		}
		if g.Datac == nil && d["type"] != "d" {
			g.Datac = nchan.Null
		}
		if d["type"] == "d" {
			e := <-lfs.Mkdir(d["path"], d)
			if e != nil {
				perr(ec, e)
				if err == nil {
					err = e
				}
			}
			continue
		}
		dc := lfs.Put(d["path"], d, 0, g.Datac, "")
		<-dc
		if e := cerror(dc); e != nil {
			dprintf("%s: put: %s\n", d["path"], e)
			perr(ec, e)
			if err == nil {
				err = e
			}
		}
	}
	close(gc)
	if e := cerror(gc); e != nil {
		dprintf("get: %s\n", e)
		perr(ec, e)
		if err == nil {
			err = e
		}
	}
	return err
}
示例#3
0
func StatsBench(b *testing.B, fs zx.Tree) {
	for bi := 0; bi < b.N; bi++ {
		i := bi%len(StatTests)
		st := StatTests[i]
		if st.Fails {
			continue
		}
		dc := fs.Stat(st.Path)
		d := <-dc
		if d == nil {
			b.Fatalf("stat %s: %s", st.Path, cerror(dc))
		}
	}
}
示例#4
0
// Facade that serves t at the given address by using the ds
// to serve and calling Serve for each client.
func Server(t zx.Tree, addr string) {
	dbg.Warn("serve %s at %s...", t.Name(), addr)
	cc, ec, err := ds.Serve(os.Args[0], addr)
	if err != nil {
		dbg.Warn("serve: %s", err)
		return
	}
	go func() {
		for c := range cc {
			if c != nil {
				go serveFor(t, *c)
			}
		}
		if err := cerror(cc); err != nil {
			dbg.Warn("serve: %s", err)
		}
		close(ec, "done")
	}()
}
示例#5
0
// returns true if the caller must poll itself rfs for changes
func newInvalQ(tag string, dbgf *bool, rfs zx.Tree) (*invalQ, bool) {
	iq := &invalQ{
		Tag: tag,
		Dbg: dbgf,
		cchgc: make(chan bool, 1),
		rfs: rfs,
		invalsc: make(chan bool, 1),
	}
	go iq.postinvalproc()
	if rfs == nil {
		return iq, false
	}
	// Use /Chg from rfs or poll rfs it if there's no other way.
	dc := rfs.Get("/Chg", 0, zx.All, "")
	msg := <-dc
	if len(msg) == 0 {
		dbg.Warn("no invalidations: %s", cerror(dc))
		return iq, true
	}
	go iq.getinvalproc(dc)
	return iq, false
}
示例#6
0
func mkfs(addr string) (zx.Tree, func(), error) {
	if len(addr) == 0 {
		opts.Usage(os.Stderr)
		dbg.Fatal("usage")
	}
	var fs zx.Tree
	var st *zx.IOstats
	var err error
	if _, err := os.Stat(addr); err == nil {
		fs, st, err = mklfs(addr)
	} else {
		fs, st, err = mkrfs(addr)
	}
	if err != nil {
		return nil, nil, err
	}
	fn := func() {}
	if sflag {
		fn = func() {
			st.Averages()
			dbg.Warn("%s iostats:\n%s\n", fs.Name(), st)
		}
	}
	if mfscfs {
		dbg.Warn("%s: mfs cache", addr)
		return mfscache(fs, fn)
	}
	if lfsdir != "" {
		dbg.Warn("%s: lfs cache", addr)
		return lfscache(fs, fn)
	}
	if !nocaching && !delayed {
		dbg.Warn("%s: old cache", addr)
		return cache(fs, fn)
	}
	dbg.Warn("%s: uncached", addr)
	return fs, fn, nil
}
示例#7
0
func chkok(fs zx.Tree, attr string) error {
	d, err := zx.Stat(fs, "/")
	if err != nil  {
		return fmt.Errorf("%s: %s", fs.Name(), err)
	}
	rwfs, ok := fs.(zx.RWTree)
	if !ok {
		return nil
	}
	if err := <-rwfs.Wstat("/", zx.Dir{attr: "666"}); err != nil {
		return err
	}
	d, err = zx.Stat(fs, "/")
	if err != nil  {
		return fmt.Errorf("%s: %s", fs.Name(), err)
	}
	if d[attr] != "666" {
		return fmt.Errorf("%s: does not preserve %s", fs.Name(), attr)
	}
	if err := <-rwfs.Wstat("/", zx.Dir{attr: ""}); err != nil {
		return err
	}
	return nil
}
示例#8
0
// Create a new cfs given a local tree used as a cache of a remote one.
// Operations are performed on behalf of each file owner.
// The lfs tree must have permission checking disabled
// (cfs will want to update everything in it no matter the user who makes the requests)
func New(tag string, lfs zx.RWTree, rfs zx.Tree, rdonly bool) (*Cfs, error) {
	if lfs == nil || rfs == nil {
		return nil, errors.New("no lfs or rfs")
	}
	rwrfs, ok := rfs.(zx.RWTree)
	if !ok && !rdonly {
		rdonly = true
		rwrfs = zx.ROTreeFor(rfs)
		dbg.Warn("remote %T not rw: rdonly set", rfs)
	}
	if !rdonly {
		if err := chkok(lfs, "Rtime"); err != nil {
			return nil, err
		}
	}
	if tag == "" {
		tag = "cfs!" + rfs.Name()
	}
	fs := &Cfs {
		Tag: tag,
		lfs: lfs,
		cfs: lfs,		// but will keep its ai as nil to wstat uids
		rfs: rwrfs,
		rdonly: rdonly,
		noinvalproto: NoInvalProto,
		Flags: &zx.Flags{Dbg: Debug},
		cUsers: &cUsers {
			who: make(map[string]time.Time),
		},
		cache: cache.New(),
		closedc: make(chan bool),
		polldonec: make(chan bool),
	}
	if DebugLocks {
		fs.lktrz = &lockTrzs{}
	}
	fs.cache.Tag = tag
	fs.cache.Dbg = &fs.Flags.Dbg
	fs.tpath = fmt.Sprintf("cfs%p", fs)
	if fs.noinvalproto {
		fs.invalQ, _ = newInvalQ(tag, &fs.Flags.Dbg, nil)
		close(fs.polldonec)
	} else {
		var mustpoll bool
		fs.invalQ, mustpoll = newInvalQ(tag, &fs.Flags.Dbg, fs.rfs)
		if mustpoll {
			dbg.Warn("%s: polling %s for external changes", tag, fs.rfs)
			// runs with no ai
			go fs.pollproc()
		} else {
			close(fs.polldonec)
		}
	}
	go fs.invalproc()
	fs.Flags.Add("verbsync", &fs.cache.Verb)
	fs.Flags.Add("debug", &fs.Flags.Dbg)
	if d, ok := lfs.(zx.Debugger); ok {
		fs.Flags.Add("ldebug", d.Debug())
	}
	if d, ok := rfs.(zx.Debugger); ok {
		fs.Flags.Add("rdebug", d.Debug())
	}
	fs.Flags.AddRO("rdonly", &fs.rdonly)
	fs.Flags.AddRO("noperm", &fs.NoPermCheck)
	fs.Flags.Add("clear", func(...string)error{
		fs.IOstats.Clear()
		return nil
	})
	return fs, nil
}
示例#9
0
func dump(dir string, t zx.Tree, ec chan bool) {
	defer func() {
		ec <- true
	}()
	name := t.Name()
	data := zx.Path(dir, "data")
	doskip := Skip
	for {
		if doskip {
			waitDumpTime(name)
			doskip = false
			continue
		}
		dbg.Warn("snap %s...", name)
		if err := os.MkdirAll(data, 0750); err != nil {
			dbg.Warn("%s: %s", data, err)
			return
		}
		rd, err := zx.Stat(t, "/")
		if err != nil {
			dbg.Warn("%s: %s", name, err)
			continue
		}
		// make sure it's not empty
		ds, err := zx.GetDir(t, "/")
		if err != nil {
			dbg.Warn("%s: %s", name, err)
			continue
		}
		if len(ds) == 0 {
			dbg.Warn("%s: file system is empty. ignored.", name)
			continue
		}
		s, err := dumpDir(data, name, zx.File{t, rd})
		if err != nil {
			dbg.Warn("%s: %s", name, err)
		}
		ts := time.Now().Format("2006/0102")
		tree := strings.Replace(name, "/", ".", -1)
		tspath0 := zx.Path(dir, tree, ts)
		os.MkdirAll(path.Dir(tspath0), 0755)
		spath := zx.Path(data, s)
		tspath := tspath0
		for i := 1; ; i++ {
			fi, _ := os.Stat(tspath)
			if fi == nil {
				break
			}
			tspath = fmt.Sprintf("%s.%d", tspath0, i)
		}
		os.MkdirAll(path.Dir(tspath), 0755)
		if err := os.Symlink(spath, tspath); err != nil {
			dbg.Warn("%s: %s", name, err)
		}
		dbg.Warn("snap %s %s", tspath, s)
		if Once {
			break
		}
		waitDumpTime(name)
	}
}