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() }() }
func (t *traverser) readFile(sq *seq.Sequencer, fid *g9pc.NsFile, path string) { t.printf("readFile %s", path) sq, results := sq.Subsequencer("readFile") go func() { _, ok := <-results // open if !ok { t.printf("cannot open %s: %v", path, sq.Error()) return } <-results // stream _, ok = <-results if ok { panic("expected closed") } sq.Result(seq.StringResult("readFile"), sq.Error()) }() sq.Do(fid.File(), seq.OpenReq{g9p.OREAD}) rd := fid.SeqReadStream(sq, 20, 8192) tot, _ := io.Copy(nullWriter{}, rd) t.printf("%10d %s", tot, path) sq.Do(nil, nil) }
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) }