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 }
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 }
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") } } }
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") } } }
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 }
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 }