Commit e6e5b9ec authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent d344db94
...@@ -47,64 +47,89 @@ import ( ...@@ -47,64 +47,89 @@ import (
) )
// TreeGenSrv represents connection to running `treegen ...` server.
type TreeGenSrv struct {
argv []string
pysrv *exec.Cmd // spawned `treegen ...`
pyin io.WriteCloser // input to pysrv
pyoutRaw io.ReadCloser // output from pysrv
pyout *bufio.Reader // buffered ^^^
}
// TreeSrv represents connection to running `treegen trees` server. // TreeSrv represents connection to running `treegen trees` server.
// //
// Create it with StartTreeSrv(zurl). // Create it with StartTreeSrv(zurl).
// - Commit(treeTopology) -> tid // - Commit(treeTopology) -> tid
type TreeSrv struct { type TreeSrv struct {
*TreeGenSrv
zurl string zurl string
pysrv *exec.Cmd // spawned `treegen trees`
pyin io.WriteCloser // input to pysrv
pyoutRaw io.ReadCloser // output from pysrv
pyout *bufio.Reader // buffered ^^^
treeRoot zodb.Oid // oid of the tree treegen works on treeRoot zodb.Oid // oid of the tree treegen works on
head zodb.Tid // last made commit head zodb.Tid // last made commit
} }
// StartTreeGen spawns `treegen trees` server. // StartTreeGenSrv spawns `treegen ...` server.
func StartTreeGen(zurl string) (_ *TreeSrv, err error) { func StartTreeGenSrv(argv ...string) (_ *TreeGenSrv, hello string, err error) {
defer xerr.Contextf(&err, "treegen %s: start", zurl) defer xerr.Contextf(&err, "treesrv %v: start", argv)
// spawn `treegen trees` // spawn `treegen ...`
tg := &TreeSrv{zurl: zurl} tg := &TreeGenSrv{argv: argv}
tg.pysrv = exec.Command("./testprog/treegen.py", "trees", zurl) tg.pysrv = exec.Command("./testprog/treegen.py", argv...)
tg.pyin, err = tg.pysrv.StdinPipe() tg.pyin, err = tg.pysrv.StdinPipe()
if err != nil { if err != nil {
return nil, err return nil, "", err
} }
tg.pyoutRaw, err = tg.pysrv.StdoutPipe() tg.pyoutRaw, err = tg.pysrv.StdoutPipe()
if err != nil { if err != nil {
return nil, err return nil, "", err
} }
tg.pyout = bufio.NewReader(tg.pyoutRaw) tg.pyout = bufio.NewReader(tg.pyoutRaw)
tg.pysrv.Stderr = os.Stderr // no redirection tg.pysrv.Stderr = os.Stderr // no redirection
err = tg.pysrv.Start() err = tg.pysrv.Start()
if err != nil { if err != nil {
return nil, err return nil, "", err
} }
// wait for start message; initialize .head and .treeRoot from it // wait for hello message and return it
defer func() { defer func() {
if err != nil { if err != nil {
tg.Close() // ignore error tg.Close() // ignore error
} }
}() }()
defer xerr.Context(&err, "handshake") defer xerr.Context(&err, "handshake")
start, err := tg.pyout.ReadString('\n') hello, err = tg.pyout.ReadString('\n')
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
err = io.ErrUnexpectedEOF err = io.ErrUnexpectedEOF
} }
return nil, "", err
}
hello = strings.TrimSuffix(hello, "\n")
defer xerr.Contextf(&err, "invalid hello %q", hello)
return tg, hello, nil
}
// StartTreeSrv spawns `treegen trees` server.
func StartTreeSrv(zurl string) (_ *TreeSrv, err error) {
defer xerr.Contextf(&err, "treesrv %s: start", zurl)
tgSrv, hello, err := StartTreeGenSrv("trees", zurl)
if err != nil {
return nil, err return nil, err
} }
start = strings.TrimSuffix(start, "\n")
defer xerr.Contextf(&err, "invalid start %q", start) tg := &TreeSrv{TreeGenSrv: tgSrv, zurl: zurl}
defer func() {
if err != nil {
tgSrv.Close() // ignore error
}
}()
defer xerr.Context(&err, "handshake")
// tree.srv start @<at> tree=<root> // tree.srv start @<at> tree=<root>
startRe := regexp.MustCompile(`^tree.srv start @([^ ]+) root=([^ ]+)$`) startRe := regexp.MustCompile(`^tree.srv start @([^ ]+) root=([^ ]+)$`)
m := startRe.FindStringSubmatch(start) m := startRe.FindStringSubmatch(hello)
if m == nil { if m == nil {
return nil, fmt.Errorf("unexpected format") return nil, fmt.Errorf("unexpected format")
} }
...@@ -121,8 +146,8 @@ func StartTreeGen(zurl string) (_ *TreeSrv, err error) { ...@@ -121,8 +146,8 @@ func StartTreeGen(zurl string) (_ *TreeSrv, err error) {
} }
// Close shutdowns treegen server. // Close shutdowns treegen server.
func (tg *TreeSrv) Close() (err error) { func (tg *TreeGenSrv) Close() (err error) {
defer xerr.Contextf(&err, "treegen %s: close", tg.zurl) defer xerr.Contextf(&err, "treegen %v: close", tg.argv)
err1 := tg.pyin.Close() err1 := tg.pyin.Close()
err2 := tg.pyoutRaw.Close() err2 := tg.pyoutRaw.Close()
...@@ -356,7 +381,7 @@ func testΔBTail(t *testing.T, testq chan string) { ...@@ -356,7 +381,7 @@ func testΔBTail(t *testing.T, testq chan string) {
defer func() { defer func() {
err := os.RemoveAll(work); X(err) err := os.RemoveAll(work); X(err)
}() }()
tg, err := StartTreeGen(work + "/1.fs"); X(err) tg, err := StartTreeSrv(work + "/1.fs"); X(err)
defer func() { defer func() {
err := tg.Close(); X(err) err := tg.Close(); X(err)
}() }()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment