예제 #1
0
func (t *Rfs) Stat(rid string) chan zx.Dir {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan zx.Dir, 1)
	msg := &Msg{Op: Tstat, Rid: rid}
	t.dprintf("stat %s\n", rid)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sstat, len(raw))
		reqc <- raw
		close(reqc)
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			c <- d
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("stat %s: %s\n", rid, err)
		} else {
			t.dprintf("stat %s: ok\n", rid)
		}
		close(c, err)
	}()
	return c
}
예제 #2
0
func (t *Lfs) dirAttrs(dpath string) (map[string]zx.Dir, error) {
	attrlk.Lock()
	defer attrlk.Unlock()
	fn := path.Join(dpath, afname)
	dat, err := readAttrFile(fn)
	if err != nil {
		return nil, err
	}
	ds := make(map[string]zx.Dir)
	var d zx.Dir
	n := 0
	for len(dat) > 0 {
		n++
		d, dat, err = zx.UnpackDir(dat)
		if err != nil {
			return ds, err
		}
		nm := d["name"]
		setUids(d)
		if !DoSum {
			delete(d, "Sum")
		}
		ds[nm] = d
	}
	if n > len(ds)*2 && t.saveattrs {
		t.writeDirAttrs(dpath, ds)
	}
	return ds, nil
}
예제 #3
0
func Gets(t Fataler, fss ...zx.Tree) {
	for i := 0; i < Repeats; i++ {
		for _, fs := range fss {
			for _, p := range GetFPaths {
				printf("getall %s\n", p)
				dat, err := zx.GetAll(fs, p)
				if err != nil {
					t.Fatalf("get %s: %s", p, err)
				}
				printf("got %d bytes \n\n", len(dat))
				if string(dat) != string(FileData[p]) {
					printf("got <%s>\nexpected<%s>\n",
						string(dat), string(FileData[p]))
					t.Fatalf("%s: bad data", p)
				}
			}

			for _, p := range GetDPaths {
				printf("getall %s\n", p)
				dat, err := zx.GetAll(fs, p)
				if err != nil {
					t.Fatalf("get %s: %s", p, err)
				}
				var d zx.Dir
				ents := []string{}
				for len(dat) > 0 {
					d, dat, err = zx.UnpackDir(dat)
					if err != nil {
						t.Fatalf("dir: %s", err)
					}
					if d["path"] == "/Ctl" || d["path"] == "/Chg" {
						continue
					}
					ents = append(ents, d.TestFmt())
				}
				if strings.Join(GetDOuts[p], "\n") != strings.Join(ents, "\n") {
					t.Fatalf("bad dir data for %s", p)
				}
				printf("got %d ents (ctl, chg excluded)\n", len(ents))
			}
			for _, p := range BadPaths {
				dat, err := zx.GetAll(fs, p)
				if err==nil || len(dat)>0 {
					t.Fatalf("get %s didn't fail", p)
				}
			}
			printf("\n")
		}
	}
}
예제 #4
0
파일: gets.go 프로젝트: fjballest/clive
func Gets(t Fataler, xfs zx.Fs) {
	fs, ok := xfs.(zx.Getter)
	if !ok {
		t.Fatalf("not a getter")
	}
	for _, p := range Files {
		data, err := zx.GetAll(fs, p)
		Printf("get all %s: %d bytes sts %v\n", p, len(data), err)
		if err != nil {
			t.Fatalf("get %s: %s", p, err)
		}
		if bytes.Compare(FileData[p], data) != 0 {
			t.Logf("%d get %d data", len(data), len(FileData[p]))
			t.Fatalf("get %s: bad data", p)
		}
	}

	for _, p := range Files {
		data, err := get(fs, p, 1024, 10*1024)
		Printf("get %s 1k 2k: %d bytes sts %v\n", p, len(data), err)
		if err != nil {
			t.Fatalf("get %s: %s", p, err)
		}
		if bytes.Compare(slice(FileData[p], 1024, 10*1024), data) != 0 {
			t.Fatalf("get %s: bad data", p)
		}
	}

	for i, p := range Dirs {
		Printf("get %s\n", p)
		out := ""
		gc := fs.Get(p, 0, -1)
		for b := range gc {
			_, dir, err := zx.UnpackDir(b)
			Printf("%s\n", dir.Fmt())
			if err != nil {
				t.Fatalf("get sts %v", err)
			}
			out += dir.Fmt() + "\n"
		}
		Printf("\n")
		if i > len(dirs) || dirs[i] != out {
			t.Logf("dirs: <%s>\n out <%s>\n", dirs, out)
			t.Fatalf("bad output")
		}
	}

	for i, p := range Dirs {
		Printf("get %s 2 3\n", p)
		out := ""
		gc := fs.Get(p, 2, 3)
		for b := range gc {
			_, dir, err := zx.UnpackDir(b)
			Printf("%s\n", dir.Fmt())
			if err != nil {
				t.Fatalf("get sts %v", err)
			}
			out += dir.Fmt() + "\n"
		}
		Printf("\n")
		if i > len(dirs23) || dirs23[i] != out {
			t.Fatalf("bad dir contents")
		}
		if err := cerror(gc); err != nil {
			t.Fatalf("err %v", err)
		}
	}

	for _, p := range BadPaths[1:] {
		data, err := zx.GetAll(fs, p)
		Printf("get %s: %s\n", p, err)
		if err == nil || len(data) > 0 {
			t.Fatalf("could get")
		}
	}
}
예제 #5
0
func (t *Rfs) getrpc(rid string, msg *Msg) <-chan []byte {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan []byte, 10)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sget, len(raw))
		reqc <- raw
		close(reqc)
		some := false
		for rep := range repc {
			cs.Send(int64(len(rep)))
			if ok := c <- rep; !ok {
				close(repc, cerror(c))
				break
			}
			some = true
			t.dprintf("get %s: ok\n", rid)
		}
		if !some {
			c <- nil
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("get %s: %s\n", rid, err)
		} else {
			t.dprintf("get %s: ok\n", rid)
		}
		close(c, err)
	}()
	return c
}

func (t *Rfs) Get(rid string, off, count int64, pred string) <-chan []byte {
	t.dprintf("get %s %d %d %q\n", rid, off, count, pred)
	msg := &Msg{Op: Tget, Rid: rid, Off: off, Count: count, Pred: pred}
	return t.getrpc(rid, msg)
}

func (t *Rfs) putrpc(rid string, msg *Msg, dc <-chan []byte) chan zx.Dir {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan zx.Dir, 1)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sput, len(raw))
		reqc <- raw
		nm := 0
		tot := 0
		for m := range dc {
			nm++
			cs.Recv(int64(len(m)))
			if ok := reqc <- m; !ok {
				err := cerror(reqc)
				close(dc, err)
				close(c, err)
				cs.End(err != nil)
				return
			}
			if len(m) == 0 {
				break
			}
			tot += len(m)
		}
		close(reqc, cerror(dc))
		rep := <-repc
		var err error
		var d zx.Dir
		if len(rep) == 0 {
			err = cerror(repc)
		} else {
			d, _, err = zx.UnpackDir(rep)
			if err==nil && d==nil {
				err = errors.New("null dir in put reply")
			}
		}
		cs.End(err != nil)
		if err == nil {
			t.dprintf("put %s: %s\n", rid, d)
			c <- d
		} else {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("put %s: %s\n", rid, err)
		}
		close(c, err)
	}()
	return c
}

func (t *Rfs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir {
	t.dprintf("put %s %v %d '%s'\n", rid, d, off, pred)
	msg := &Msg{Op: Tput, Rid: rid, D: d, Off: off, Pred: pred}
	return t.putrpc(rid, msg, dc)
}

func (t *Rfs) errrpc(rid, op string, msg *Msg, k int) chan error {
	t.c.Debug = t.Dbg && VerbDebug
	c := make(chan error, 1)
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		var cs *zx.CallStat
		if k >= 0 {
			cs = t.IOstats.NewCallSize(k, len(raw))
		}
		reqc <- raw
		close(reqc)
		<-repc
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("%s %s: %s\n", op, rid, err)
		} else {
			t.dprintf("%s %s: ok\n", op, rid)
		}
		c <- err
		close(c, err)
		cs.End(err != nil)
	}()
	return c
}

func (t *Rfs) Fsys(name string) <-chan error {
	t.dprintf("fsys %s\n", name)
	msg := &Msg{Op: Tfsys, Rid: name}
	return t.errrpc(name, "fsys", msg, -1)
}

func (t *Rfs) Mkdir(rid string, d zx.Dir) chan error {
	msg := &Msg{Op: Tmkdir, Rid: rid, D: d}
	t.dprintf("mkdir %s %v\n", rid, d)
	return t.errrpc(rid, "mkdir", msg, zx.Smkdir)
}

func (t *Rfs) Move(from, to string) chan error {
	t.dprintf("move %s %s \n", from, to)
	msg := &Msg{Op: Tmove, Rid: from, To: to}
	return t.errrpc(from, "move", msg, zx.Smove)
}

func (t *Rfs) Remove(rid string) chan error {
	t.dprintf("remove %s\n", rid)
	msg := &Msg{Op: Tremove, Rid: rid}
	return t.errrpc(rid, "remove", msg, zx.Sremove)
}

func (t *Rfs) RemoveAll(rid string) chan error {
	t.dprintf("removeall %s\n", rid)
	msg := &Msg{Op: Tremoveall, Rid: rid}
	return t.errrpc(rid, "removeall", msg, zx.Sremoveall)
}

func (t *Rfs) Wstat(rid string, d zx.Dir) chan error {
	t.dprintf("wstat %s %v\n", rid, d)
	msg := &Msg{Op: Twstat, Rid: rid, D: d}
	return t.errrpc(rid, "wstat", msg, zx.Swstat)
}

func (t *Rfs) Find(rid, pred, spref, dpref string, depth int) <-chan zx.Dir {
	t.dprintf("find %s '%s' '%s' '%s' %d\n", rid, pred, spref, dpref, depth)
	dc := make(chan zx.Dir)
	msg := &Msg{Op: Tfind, Rid: rid, Pred: pred, Spref: spref, Dpref: dpref, Depth: depth}
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sfind, len(raw))
		reqc <- raw
		close(reqc)
		some := false
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			if ok := dc <- d; !ok {
				close(repc, cerror(dc))
				break
			}
			some = true
			t.dprintf(rid, "find", "<- %v\n", d)
		}
		if !some {
			dc <- nil
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(dc, err)
		cs.End(err != nil)
	}()
	return dc

}

func (t *Rfs) FindGet(rid, pred, spref, dpref string, depth int) <-chan zx.DirData {
	t.dprintf("findget %s '%s' '%s' '%s' %d\n", rid, pred, spref, dpref, depth)
	dc := make(chan zx.DirData)
	msg := &Msg{Op: Tfindget, Rid: rid, Pred: pred, Spref: spref, Dpref: dpref, Depth: depth}
	go func() {
		reqc, repc := t.c.Rpc()
		raw := msg.Pack()
		cs := t.IOstats.NewCallSize(zx.Sfind, len(raw))
		reqc <- raw
		close(reqc)
		for rep := range repc {
			cs.Send(int64(len(rep)))
			d, _, _ := zx.UnpackDir(rep)
			if d != nil {
				d["addr"] = t.addr
				d["proto"] = "zx"
			}
			res := zx.DirData{Dir: d}
			var datc chan []byte
			if d["err"]=="" && d["type"]=="-" {
				datc = make(chan []byte)
				res.Datac = datc
			}
			if ok := dc <- res; !ok {
				close(repc, cerror(dc))
				break
			}
			t.dprintf(rid, "find", "<- %v\n", d)
			if datc != nil {
				for rep := range repc {
					if len(rep) == 0 {
						break
					}
					if ok := datc <- rep; !ok {
						continue
					}
				}
				close(datc, cerror(repc))
			}
		}
		err := cerror(repc)
		cs.End(err != nil)
		if err != nil {
			if isHangup(err) {
				t.Close(ErrHangUp)
			}
			t.dprintf("find %s: %s\n", rid, err)
		} else {
			t.dprintf("find %s: ok\n", rid)
		}
		close(dc, err)
	}()
	return dc

}
예제 #6
0
func UnpackMsg(buf []byte) (*Msg, error) {
	m := &Msg{}

	if len(buf) < 1 {
		return nil, errors.New("short msg")
	}
	m.Op = MsgId(buf[0])
	if m.Op<Tmin || m.Op>=Tend {
		return nil, fmt.Errorf("unknown msg type %d", buf[0])
	}
	buf = buf[1:]
	var err error
	m.Rid, buf, err = nchan.GetString(buf)
	if err != nil {
		return nil, err
	}
	if m.Op==Tget || m.Op==Tput {
		if len(buf) < 8 {
			return nil, errors.New("short msg")
		}
		m.Off = int64(binary.LittleEndian.Uint64(buf[0:]))
		buf = buf[8:]
	}
	if m.Op == Tget {
		if len(buf) < 8 {
			return nil, errors.New("short msg")
		}
		m.Count = int64(binary.LittleEndian.Uint64(buf[0:]))
		buf = buf[8:]
	}
	if m.Op==Tput || m.Op==Tmkdir || m.Op==Twstat {
		m.D, buf, err = zx.UnpackDir(buf)
		if err != nil {
			return nil, err
		}
	}
	if m.Op == Tmove {
		m.To, buf, err = nchan.GetString(buf)
		if err != nil {
			return nil, err
		}
	}
	if m.Op==Tfind || m.Op==Tget || m.Op==Tput || m.Op==Tfindget {
		m.Pred, buf, err = nchan.GetString(buf)
		if err != nil {
			return nil, err
		}
	}
	if m.Op==Tfind || m.Op==Tfindget {
		m.Spref, buf, err = nchan.GetString(buf)
		if err != nil {
			return nil, err
		}
		m.Dpref, buf, err = nchan.GetString(buf)
		if err != nil {
			return nil, err
		}
		if len(buf) < 8 {
			return nil, errors.New("short msg")
		}
		m.Depth = int(binary.LittleEndian.Uint64(buf[0:]))
		buf = buf[8:]
	}
	return m, nil
}