Пример #1
0
func (t *traverser) traverse(parent *g9pc.NsFile, path, name string, sync chan bool) {
	sq, results := seq.NewSequencer()
	doneWalk := make(chan bool)
	go func() {
		defer close(doneWalk)
		if name != "" {
			_, ok := <-results // SeqWalk
			if !ok {
				t.printf("cannot walk to %q: %v", path+"/"+name, sq.Error())
				return
			}
		}
		doneWalk <- true
		<-results          // readDir or readFile.
		_, ok := <-results // eof.
		if ok {
			panic("expected closed")
		}
	}()
	fid := parent
	if name != "" {
		fid = parent.SeqWalk(sq, name)
	}
	_, ok := <-doneWalk
	if !ok {
		return
	}
	sync <- true
	t.printf("read %q, dir %v", path+"/"+name, fid.IsDir())
	t.refc <- 1
	go func() {
		t.grab()
		path += "/" + name
		if fid.IsDir() {
			t.readDir(sq, fid, path)
		} else {
			t.readFile(sq, fid, path)
		}
		sq.Do(nil, nil)
		t.refc <- -1
		t.release()
	}()
}
Пример #2
0
func (t *traverser) readDir(pseq *seq.Sequencer, fid *g9pc.NsFile, path string) {
	t.printf("readDir %s", path)
	sq, results := pseq.Subsequencer("readDir")
	errc := make(chan error, 1)
	go func() {
		<-results          // SeqWalk (clone)
		_, ok := <-results // OpenReq
		if !ok {
			errc <- fmt.Errorf("cannot open %q: %#v", path, sq.Error())
			return
		}
		<-results // NonseqReq
		<-results // ReadStream
		errc <- nil
		_, ok = <-results // eof
		if ok {
			panic("expected closed")
		}
		errc <- nil
	}()

	rfid := fid.SeqWalk(sq)
	//	defer rfid.Close()		TODO something better!

	sq.Do(rfid.File(), seq.OpenReq{g9p.OREAD})
	sq.Do(fid.File(), seq.NonseqReq{})
	rd := rfid.SeqReadStream(sq, 5, 8192)
	defer rd.Close()

	buf, _ := ioutil.ReadAll(rd)
	t.printf("read %d bytes from %q", len(buf), path)
	err := <-errc
	sq.Do(nil, nil)
	<-errc
	//we get here but fid still can be part of the sequence.
	//maybe that means that subsequence has not terminated
	//correctly. no it doesn't. it means that the overall sequence
	//has not terminated correctly.
	//
	//question: should files opened as part of a subsequence be
	//ratified by the subsequence finishing?
	//only

	if err != nil && len(buf) == 0 {
		sq.Result(nil, err)
		t.printf("error on %s: %v\n", path, err)
		return
	}

	d, err := g9p.UnmarshalDirs(buf)
	if err != nil {
		t.printf("cannot unpack directory %s: %v\n", path, err)
		return
	}

	sync := make(chan bool)
	for i, dir := range d {
		t.printf("%q[%d]: %v", path, i, dir)
		go t.traverse(fid, path, dir.Name, sync)
	}
	for i := 0; i < len(d); i++ {
		<-sync
	}
	t.printf("%s: %d entries", path, len(d))
	sq.Result(seq.StringResult("readDir"), nil)
}