// open writer and write header func (t *DataTable) init() { if t.inited() { return } f, err := httpfs.Create(OD() + t.name + ".txt") util.FatalErr(err) t.output = f // write header fprint(t, "# t (s)") for _, o := range t.outputs { if o.NComp() == 1 { fprint(t, "\t", o.Name(), " (", o.Unit(), ")") } else { for c := 0; c < o.NComp(); c++ { fprint(t, "\t", o.Name()+string('x'+c), " (", o.Unit(), ")") } } } fprintln(t) t.Flush() // periodically flush so GUI shows graph, // but don't flush after every output for performance // (httpfs flush is expensive) go func() { for { time.Sleep(TableAutoflushRate * time.Second) Table.flush() } }() }
func initLog() { if logfile != nil { panic("log already inited") } // open log file and flush what was logged before the file existed var err error logfile, err = httpfs.Create(OD() + "log.txt") if err != nil { panic(err) } util.FatalErr(err) logfile.Write(([]byte)(hist)) logfile.Write([]byte{'\n'}) }
// synchronous save func saveAs_sync(fname string, s *data.Slice, info data.Meta, format OutputFormat) { f, err := httpfs.Create(fname) util.FatalErr(err) defer f.Close() switch format { case OVF1_TEXT: oommf.WriteOVF1(f, s, info, "text") case OVF1_BINARY: oommf.WriteOVF1(f, s, info, "binary 4") case OVF2_TEXT: oommf.WriteOVF2(f, s, info, "text") case OVF2_BINARY: oommf.WriteOVF2(f, s, info, "binary 4") case DUMP: dump.Write(f, s, info) default: panic("invalid output format") } }
// prepare exec.Cmd to run mumax3 compute process func NewProcess(ID string, gpu int, webAddr string) *Process { // prepare command inputURL := "http://" + ID command := *flag_mumax gpuFlag := fmt.Sprint(`-gpu=`, gpu) httpFlag := fmt.Sprint(`-http=`, webAddr) cacheFlag := fmt.Sprint(`-cache=`, *flag_cachedir) forceFlag := `-f=0` cmd := exec.Command(command, gpuFlag, httpFlag, cacheFlag, forceFlag, inputURL) // Pipe stdout, stderr to log file over httpfs outDir := util.NoExt(inputURL) + ".out" errMkdir := httpfs.Mkdir(outDir) if errMkdir != nil { SetJobError(ID, errMkdir) log.Println("makeProcess", errMkdir) j := JobByName(ID) if j != nil { j.Reque() } return nil } out, errD := httpfs.Create(outDir + "/stdout.txt") if errD != nil { SetJobError(ID, errD) log.Println("makeProcess", errD) j := JobByName(ID) if j != nil { j.Reque() } return nil } cmd.Stderr = out cmd.Stdout = out return &Process{ID: ID, Cmd: cmd, Start: time.Now(), Out: out, OutputURL: OutputDir(inputURL), GUI: webAddr} }
func doFile(infname string, outp output) { // determine output file outfname := util.NoExt(infname) + outp.Ext if *flag_dir != "" { outfname = *flag_dir + "/" + path.Base(outfname) } msg := infname + "\t-> " + outfname defer func() { log.Println(msg) }() if infname == outfname { msg = fail(msg, "input and output file are the same") return } defer func() { if err := recover(); err != nil { msg = fail(msg, err) os.Remove(outfname) } }() if !(strings.HasPrefix(infname, "http://") || strings.HasPrefix(outfname, "http://")) { inStat, errS := os.Stat(infname) if errS != nil { panic(errS) } outStat, errO := os.Stat(outfname) if errO == nil && outStat.ModTime().Sub(inStat.ModTime()) > 0 { msg = "[skip] " + msg + ": skipped based on time stamps" skipped.Add(1) return } } var slice *data.Slice var info data.Meta var err error in, errI := httpfs.Open(infname) if errI != nil { msg = fail(msg, errI) return } defer in.Close() switch path.Ext(infname) { default: msg = fail(msg, ": skipping unsupported type: "+path.Ext(infname)) return case ".ovf", ".omf", ".ovf2": slice, info, err = oommf.Read(in) case ".dump": slice, info, err = dump.Read(in) } if err != nil { msg = fail(msg, err) return } out, err := httpfs.Create(outfname) if err != nil { msg = fail(msg, err) return } defer out.Close() preprocess(slice) outp.Convert(slice, info, panicWriter{out}) succeeded.Add(1) msg = "[ ok ] " + msg }
// synchronous snapshot func snapshot_sync(fname string, output *data.Slice) { f, err := httpfs.Create(fname) util.FatalErr(err) defer f.Close() draw.RenderFormat(f, output, "auto", "auto", arrowSize, path.Ext(fname)) }