Example #1
0
func asAFile(t Fataler, rws []Object, nops, maxoff, maxsz int) {
	rw := rws[0]
	fd, err := ioutil.TempFile("", "rwtest")
	if err != nil {
		t.Fatalf("temp file: %s", err)
	}
	defer fd.Close()
	opc := make(chan int)
	rrw, ok := rw.(Resizeable)
	nrsz := 0
	if ok {
		nrsz = nops / 10
		nops -= nrsz
	}
	nrd := nops/2
	nwr := nops - nrd
	defer t.Logf("%d reads, %d writes, %d resizes\n", nrd, nwr, nrsz)
	go func() {
		for i := 0; i < nrd; i++ {
			if ok := opc <- 0; !ok {
				break
			}
		}
	}()
	go func() {
		for i := 0; i < nwr; i++ {
			if ok := opc <- 1; !ok {
				break
			}
		}
	}()
	go func() {
		for i := 0; i < nrsz; i++ {
			if ok := opc <- 2; !ok {
				break
			}
		}
	}()
	defer func() {
		close(opc, "done")
	}()
	wdata := make([]byte, maxsz)
	for i := 0; i < maxsz; i++ {
		wdata[i] = byte(i)
	}
	xrw, ok := rw.(FullyReadable)
	for i := 0; i < nops; i++ {
		off := rand.Intn(maxoff)
		sz := rand.Intn(maxsz)
		rw = pick(rws)
		switch <-opc {
		case 0:
			dataf:= make([]byte, sz)
			datarw:= make([]byte, sz)
			nf, errf := fd.ReadAt(dataf, int64(off))
			nrw, errrw := rw.ReadAt(datarw, int64(off))
			if nf != nrw {
				t.Fatalf("didn't read the same")
			}
			if errf == io.EOF {
				errf = nil
			}
			if errrw == io.EOF {
				errrw = nil
			}
			if errf != nil && errrw == nil || errf == nil && errrw != nil {
				t.Logf("file sts %v", errf)
				t.Logf("rw sts %v", errrw)
				t.Fatalf("didn't fail the same in read")
			}
			if bytes.Compare(dataf[:nf], datarw[:nrw]) != 0 {
				s1 := dbg.HexStr(dataf[:nf], 32)
				s2 := dbg.HexStr(datarw[:nrw], 32)
				t.Logf("os %d bytes: %s", nf, s1)
				t.Logf("rw %d bytes: %s", nrw, s2)
				t.Fatalf("didn't read the same content")
			}
		case 1:
			if sz == 0 { sz++ }
			nf, errf := fd.WriteAt(wdata[:sz], int64(off))
			nrw, errrw := rw.WriteAt(wdata[:sz], int64(off))
			if nf != nrw {
				t.Fatalf("didn't write the same")
			}
			if errf != nil && errrw == nil || errf == nil && errrw != nil {
				t.Fatalf("didn't fail the same in write")
			}
			if ok {
				compare(t, xrw, fd)
			}
		case 2:
			if err := fd.Truncate(int64(off)); err != nil {
				t.Fatalf("file resize: %s", err)
			}
			if err := rrw.Truncate(int64(off)); err != nil {
				t.Fatalf("user resize: %s", err)
			}
			if ok {
				compare(t, xrw, fd)
			}
		}
	}

	if !ok {
		return
	}
	// Now compare everything.
	compare(t, xrw, fd)
}

func compare(t Fataler, rw, fd FullyReadable) {
	fdata, err := readall(fd)
	if err != nil {
		t.Fatalf("read all fd: %s", err)
	}
	rwdata, err := readall(rw)
	if err != nil {
		t.Fatalf("read all rw: %s", err)
	}
	if bytes.Compare(fdata, rwdata) != 0 {
		t.Logf("file %d bytes: %s\n", len(fdata), dbg.HexStr(fdata, 32))
		t.Logf("rw %d bytes: %s\n", len(rwdata), dbg.HexStr(rwdata, 32))
		for i := 0; i < len(fdata) && i < len(rwdata); i++ {
			if fdata[i] != rwdata[i] {
				t.Logf("[%d] file %x rw %x\n", i,
					fdata[i], rwdata[i])
				break
			}
		}
		t.Fatalf("files do not match")
	}
}

func readall(rw FullyReadable) ([]byte, error) {
	old, err := rw.Seek(0, 1)
	if err != nil {
		return nil, err
	}
	n, err := rw.Seek(0, 0)
	if n != 0 || err != nil {
		return nil, err
	}
	data, err := ioutil.ReadAll(rw)
	if err != nil {
		return nil, err
	}
	_, err = rw.Seek(old, 0)
	if err != nil {
		return nil, err
	}
	return data, nil
}
Example #2
0
func (t *Fs) Get(rid string, off, count int64, pred string) <-chan []byte {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->get[%d] %s %d %d '%s'", n, rid, off, count, pred)
	dc := make(chan []byte)
	go func(){
		xc := t.fs.Get(rid, off, count, pred)
		nb, nm := 0, 0
		for d := range xc {
			s := dbg.HexStr(d, 16)
			t.vprintf("<-get[%d] %d bytes %s", n, len(d), s)
			if ok := dc <- d; !ok {
				close(xc, "client gone")
			}
			nb += len(d)
			nm++
		}
		err := cerror(xc)
		t.printf("<-get[%d] %d bytes %d msgs sts %v", n, nb, nm, err)
		close(dc, err)
	}()
	return dc
}

func (t *Fs) Put(rid string, d zx.Dir, off int64, dc <-chan []byte, pred string) chan zx.Dir {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->put[%d] %s %s %d '%s'", n, rid, d, off, pred)
	rc := make(chan zx.Dir, 1)
	datc := make(chan []byte)
	if dc == nil {
		datc = nil
	} else {
		go func() {
			for d := range dc {
				s := dbg.HexStr(d, 16)
				t.vprintf("->put[%d] %d bytes %s", n, len(d), s)
				if ok := datc <- d; !ok {
					close(dc, cerror(datc))
					break
				}
			}
			err := cerror(dc)
			t.vprintf("->put[%d] sts %v", n, err)
			close(datc, err)
		}()
	}
	go func() {
		xc := t.fs.Put(rid, d, off, datc, pred)
		d := <-xc
		err := cerror(xc)
		if err != nil {
			close(datc, err)
		}
		t.printf("<-put[%d] %s sts %v", n, d, err)
		rc <-d
		close(rc, err)
	}()
	return rc
}

func (t *Fs) Mkdir(rid string, d zx.Dir) chan error {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->mkdir[%d] %s %s", n, rid, d)
	dc := make(chan error, 1)
	go func() {
		xc := t.fs.Mkdir(rid, d)
		err := <- xc
		t.printf("<-mkdir[%d] sts %v", n, err)
		dc <- err
		close(dc, cerror(xc))
	}()
	return dc
}

func (t *Fs) Wstat(rid string, d zx.Dir) chan error {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->wstat[%d] %s %s", n, rid, d)
	dc := make(chan error, 1)
	go func() {
		xc := t.fs.Wstat(rid, d)
		err := <- xc
		t.printf("<-wstat[%d] sts %v", n, err)
		dc <- err
		close(dc, cerror(xc))
	}()
	return dc
}

func (t *Fs) Move(from, to string) chan error {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->move[%d] %s %s", n, from, to)
	dc := make(chan error, 1)
	go func() {
		xc := t.fs.Move(from, to)
		err := <- xc
		t.printf("<-move[%d] sts %v", n, err)
		dc <- err
		close(dc, cerror(xc))
	}()
	return dc
}

func (t *Fs) Remove(rid string) chan error {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->remove[%d] %s", n, rid)
	dc := make(chan error, 1)
	go func() {
		xc := t.fs.Remove(rid)
		err := <- xc
		t.printf("<-remove[%d] sts %v", n, err)
		dc <- err
		close(dc, cerror(xc))
	}()
	return dc
}

func (t *Fs) RemoveAll(rid string) chan error {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->removeall[%d] %s", n, rid)
	dc := make(chan error, 1)
	go func() {
		xc := t.fs.RemoveAll(rid)
		err := <- xc
		t.printf("<-removeall[%d] sts %v", n, err)
		dc <- err
		close(dc, cerror(xc))
	}()
	return dc
}

func (t *Fs) Fsys(name string) <-chan error {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->fsys[%d] %s", n, name)
	dc := make(chan error, 1)
	go func() {
		var xc <-chan error
		if fnd, ok := t.fs.(zx.Finder); ok {
			xc = fnd.Fsys(name)
		} else {
			xx := make(chan error, 1)
			xx <- dbg.ErrBug
			close(xx, dbg.ErrBug)
			xc = xx
		}
		err := <- xc
		t.printf("<-fsys[%d] sts %v", n, err)
		dc <- err
		close(dc, cerror(xc))
	}()
	return dc
}

func (t *Fs) Find(rid, fpred, spref, dpref string, depth int) <-chan zx.Dir {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->find[%d] %s '%s' '%s' '%s' %d", n, rid, fpred, spref, dpref, depth)
	dc := make(chan zx.Dir, 1)
	go func() {
		xc := t.fs.Find(rid, fpred, spref, dpref, depth)
		nm := 0
		for d := range xc {
			nm++
			t.vprintf("<-find[%d] %s", n, d)
			dc <- d
		}
		err := cerror(xc)
		t.printf("<-find[%d] %d msgs sts %v", n, nm, err)
		close(dc, err)
	}()
	return dc
}

func (t *Fs) FindGet(rid, fpred, spref, dpref string, depth int) <-chan zx.DirData {
	n := atomic.AddInt32(&t.nb, 1)
	t.printf("->findget[%d] %s '%s' '%s' '%s' %d", n, rid, fpred, spref, dpref, depth)
	dc := make(chan zx.DirData)
	go func() {
		xc := t.fs.FindGet(rid, fpred, spref, dpref, depth)
		nm := 0
		for d := range xc {
			nm++
			t.vprintf("<-findget[%d] %s", n, d)
			if ok := dc <- d; !ok {
				close(xc, "client gone")
			}
		}
		err := cerror(xc)
		t.printf("<-findget[%d] %d msgs sts %v", n, nm, err)
		close(dc, err)
	}()
	return dc
}

// Ask the tree to perform auth checks on behalf of ai.
func (t *Fs) AuthFor(ai *auth.Info) (zx.Tree, error) {
	nfs := &Fs{}
	*nfs = *t
	if afs, ok := t.ufs.(zx.AuthTree); ok {
		x, err := afs.AuthFor(ai)
		if err == nil {
			nfs.ufs = x
			nfs.fs = zx.RWTreeFor(nfs.ufs)
			return nfs, nil
		}
		return nil, err
	}
	return nil, errors.New("no auth")
}

func (t *Fs) Dump(w io.Writer) {
	if dfs, ok := t.fs.(zx.Dumper); ok {
		dfs.Dump(w)
	} else {
		fmt.Fprintf(w, "no dumps for %s\n", t)
	}
}

func (t *Fs) Stats() *zx.IOstats {
	if dfs, ok := t.fs.(zx.StatTree); ok {
		return dfs.Stats()
	}
	return nil
}