Shinichiro Hamaji | b69bf8a | 2015-06-10 14:52:06 +0900 | [diff] [blame] | 1 | // Copyright 2015 Google Inc. All rights reserved |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
Fumitoshi Ukai | 744bb2b | 2015-06-25 00:10:52 +0900 | [diff] [blame] | 15 | package kati |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 16 | |
| 17 | import ( |
| 18 | "bufio" |
| 19 | "encoding/binary" |
| 20 | "fmt" |
| 21 | "io" |
| 22 | "os/exec" |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 23 | ) |
| 24 | |
| 25 | func btoi(b bool) int { |
| 26 | if b { |
| 27 | return 1 |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 28 | } |
Fumitoshi Ukai | 936de10 | 2015-06-08 11:21:16 +0900 | [diff] [blame] | 29 | return 0 |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 30 | } |
| 31 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 32 | type paraConn struct { |
| 33 | w io.WriteCloser |
| 34 | r *bufio.Reader |
| 35 | err error |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 36 | } |
| 37 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 38 | func (c *paraConn) sendMsg(data []byte) error { |
| 39 | if c.err != nil { |
| 40 | return c.err |
| 41 | } |
| 42 | _, err := c.w.Write(data) |
| 43 | c.err = err |
| 44 | return err |
| 45 | } |
| 46 | |
| 47 | func (c *paraConn) sendInt(i int) error { |
| 48 | if c.err != nil { |
| 49 | return c.err |
| 50 | } |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 51 | v := int32(i) |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 52 | c.err = binary.Write(c.w, binary.LittleEndian, &v) |
| 53 | return c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 54 | } |
| 55 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 56 | func (c *paraConn) sendString(s string) error { |
| 57 | c.sendInt(len(s)) |
| 58 | c.sendMsg([]byte(s)) |
| 59 | return c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 60 | } |
| 61 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 62 | func (c *paraConn) sendRunners(runners []runner) error { |
| 63 | c.sendInt(len(runners)) |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 64 | for _, r := range runners { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 65 | c.sendString(r.output) |
| 66 | c.sendString(r.cmd) |
| 67 | c.sendString(r.shell) |
| 68 | c.sendInt(btoi(r.echo)) |
| 69 | c.sendInt(btoi(r.ignoreError)) |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 70 | } |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 71 | return c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 72 | } |
| 73 | |
Fumitoshi Ukai | ff4e580 | 2015-06-25 13:12:26 +0900 | [diff] [blame] | 74 | type paraResult struct { |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 75 | output string |
| 76 | stdout string |
| 77 | stderr string |
| 78 | status int |
Shinichiro Hamaji | a680842 | 2015-05-13 18:00:50 +0900 | [diff] [blame] | 79 | signal int |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 80 | } |
| 81 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 82 | func (c *paraConn) recvInt() (int, error) { |
| 83 | if c.err != nil { |
| 84 | return 0, c.err |
| 85 | } |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 86 | var v int32 |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 87 | c.err = binary.Read(c.r, binary.LittleEndian, &v) |
| 88 | return int(v), c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 89 | } |
| 90 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 91 | func (c *paraConn) recvString() (string, error) { |
| 92 | l, err := c.recvInt() |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 93 | if err != nil { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 94 | c.err = err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 95 | return "", err |
| 96 | } |
| 97 | buf := make([]byte, l) |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 98 | _, c.err = io.ReadFull(c.r, buf) |
| 99 | if c.err != nil { |
| 100 | return "", c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 101 | } |
| 102 | return string(buf), nil |
| 103 | } |
| 104 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 105 | func (c *paraConn) recvResult() (*paraResult, error) { |
| 106 | output, _ := c.recvString() |
| 107 | stdout, _ := c.recvString() |
| 108 | stderr, _ := c.recvString() |
| 109 | status, _ := c.recvInt() |
| 110 | signal, _ := c.recvInt() |
| 111 | if c.err != nil { |
| 112 | return nil, c.err |
Shinichiro Hamaji | a680842 | 2015-05-13 18:00:50 +0900 | [diff] [blame] | 113 | } |
Fumitoshi Ukai | ff4e580 | 2015-06-25 13:12:26 +0900 | [diff] [blame] | 114 | return ¶Result{ |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 115 | output: output, |
| 116 | stdout: stdout, |
| 117 | stderr: stderr, |
| 118 | status: status, |
Shinichiro Hamaji | a680842 | 2015-05-13 18:00:50 +0900 | [diff] [blame] | 119 | signal: signal, |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 120 | }, nil |
| 121 | } |
| 122 | |
Fumitoshi Ukai | ff4e580 | 2015-06-25 13:12:26 +0900 | [diff] [blame] | 123 | type paraWorker struct { |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 124 | para *exec.Cmd |
Fumitoshi Ukai | ff4e580 | 2015-06-25 13:12:26 +0900 | [diff] [blame] | 125 | paraChan chan *paraResult |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 126 | c *paraConn |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 127 | doneChan chan bool |
| 128 | } |
| 129 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 130 | func newParaWorker(paraChan chan *paraResult, numJobs int, paraPath string) (*paraWorker, error) { |
Fumitoshi Ukai | 744bb2b | 2015-06-25 00:10:52 +0900 | [diff] [blame] | 131 | para := exec.Command(paraPath, fmt.Sprintf("-j%d", numJobs), "--kati") |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 132 | stdin, err := para.StdinPipe() |
| 133 | if err != nil { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 134 | return nil, err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 135 | } |
| 136 | stdout, err := para.StdoutPipe() |
| 137 | if err != nil { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 138 | return nil, err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 139 | } |
| 140 | err = para.Start() |
| 141 | if err != nil { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 142 | return nil, err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 143 | } |
Fumitoshi Ukai | ff4e580 | 2015-06-25 13:12:26 +0900 | [diff] [blame] | 144 | return ¶Worker{ |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 145 | para: para, |
| 146 | paraChan: paraChan, |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 147 | c: ¶Conn{ |
| 148 | w: stdin, |
| 149 | r: bufio.NewReader(stdout), |
| 150 | }, |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 151 | doneChan: make(chan bool), |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 152 | }, nil |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 153 | } |
| 154 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 155 | func (para *paraWorker) Run() error { |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 156 | for { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 157 | r, err := para.c.recvResult() |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 158 | if err != nil { |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 159 | break |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 160 | } |
| 161 | para.paraChan <- r |
| 162 | } |
| 163 | para.para.Process.Kill() |
| 164 | para.para.Process.Wait() |
| 165 | para.doneChan <- true |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 166 | return para.c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 167 | } |
| 168 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 169 | func (para *paraWorker) Wait() error { |
| 170 | para.c.w.Close() |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 171 | <-para.doneChan |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 172 | if para.c.err == io.EOF { |
| 173 | return nil |
| 174 | } |
| 175 | return para.c.err |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 176 | } |
| 177 | |
Fumitoshi Ukai | 65c7233 | 2015-06-26 21:32:50 +0900 | [diff] [blame] | 178 | func (para *paraWorker) RunCommand(runners []runner) error { |
| 179 | return para.c.sendRunners(runners) |
Shinichiro Hamaji | cedc5c8 | 2015-05-13 17:03:20 +0900 | [diff] [blame] | 180 | } |