CompileAndRun compiles a program read from the input, starting execution if it succeeds. If an existing virtual machine of the same name already exists, the previous virtual machine is terminated and the new loaded over it. If the new program fails to compile, any existing virtual machine with the
(name string, input io.Reader)
| 139 | // it. If the new program fails to compile, any existing virtual machine with |
| 140 | // the same name remains running. |
| 141 | func (r *Runtime) CompileAndRun(name string, input io.Reader) error { |
| 142 | glog.V(2).Infof("CompileAndRun %s", name) |
| 143 | var buf bytes.Buffer |
| 144 | tee := io.TeeReader(input, &buf) |
| 145 | hasher := sha256.New() |
| 146 | if _, err := io.Copy(hasher, tee); err != nil { |
| 147 | ProgLoadErrors.Add(name, 1) |
| 148 | return errors.Wrapf(err, "hashing failed for %q", name) |
| 149 | } |
| 150 | contentHash := hasher.Sum(nil) |
| 151 | r.handleMu.RLock() |
| 152 | vh, ok := r.handles[name] |
| 153 | r.handleMu.RUnlock() |
| 154 | if ok && bytes.Equal(vh.contentHash, contentHash) { |
| 155 | glog.V(1).Infof("contents match, not recompiling %q", name) |
| 156 | return nil |
| 157 | } |
| 158 | obj, errs := r.c.Compile(name, &buf) |
| 159 | if errs != nil { |
| 160 | ProgLoadErrors.Add(name, 1) |
| 161 | return errors.Errorf("compile failed for %s:\n%s", name, errs) |
| 162 | } |
| 163 | if obj == nil { |
| 164 | ProgLoadErrors.Add(name, 1) |
| 165 | return errors.Errorf("internal error: compilation failed for %s: no program returned, but no errors", name) |
| 166 | } |
| 167 | v := vm.New(name, obj, r.syslogUseCurrentYear, r.overrideLocation, r.logRuntimeErrors, r.trace) |
| 168 | |
| 169 | if r.dumpBytecode { |
| 170 | glog.Info("Dumping program objects and bytecode\n", v.DumpByteCode()) |
| 171 | } |
| 172 | |
| 173 | // Load the metrics from the compilation into the global metric storage for export. |
| 174 | for _, m := range v.Metrics { |
| 175 | if !m.Hidden { |
| 176 | if r.omitMetricSource { |
| 177 | m.Source = "" |
| 178 | } |
| 179 | err := r.ms.Add(m) |
| 180 | if err != nil { |
| 181 | return err |
| 182 | } |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | ProgLoads.Add(name, 1) |
| 187 | glog.Infof("Loaded program %s", name) |
| 188 | |
| 189 | if r.compileOnly { |
| 190 | return nil |
| 191 | } |
| 192 | |
| 193 | r.handleMu.Lock() |
| 194 | defer r.handleMu.Unlock() |
| 195 | // Terminates the existing vm. |
| 196 | if handle, ok := r.handles[name]; ok { |
| 197 | close(handle.lines) |
| 198 | } |