func pipeLogs(r io.Reader, prefix string) { logger := util.GetLogger() scanner := bufio.NewScanner(r) for scanner.Scan() { logger.Info("%s %s", prefix, scanner.Text()) } }
func (pt1 *Pt1Recorder) checkPrograms() { logger := util.GetLogger() for { var channels []*tv.TvChannel var err error for channels == nil || len(channels) == 0 { channels, err = api.GetTvChannels() if err != nil { logger.Error("[Pt1Recorder] Failed to get channels: %v", err) time.Sleep(Pt1Config.FetchInterval) } else { logger.Info("[Pt1Recorder] Got %d channels. Start to check programs...", len(channels)) } } for _, ch := range channels { upcomming := pt1.recorder.Upcomming() now := time.Now() if upcomming.IsZero() || now.Add(pt1.pt1Config.ProgramCheckDuration*3).Before(upcomming) { // ok to launch recpt1 and dummy recording err = pt1.updatePrograms(ch) if err != nil { logger.Warn("[Pt1Recorder] Could not update the channel: %v - %s:%s", err, ch.Cid, ch.Name) } else { logger.Info("[Pt1Recorder] Updated channel: %s", ch.Name) } } else { logger.Warn("[Pt1Recorder] Could not use pt1 device so skipped to check channels: %s", ch.Name) } } time.Sleep(pt1.pt1Config.ProgramCheckInterval) } }
func NewRecordCtrl(rec Record) *RecordCtrl { return &RecordCtrl{ record: rec, state: RSWaiting, stopCh: make(chan bool, 1), logger: util.GetLogger(), } }
func (r *Pt1Record) Kill() { // send KILL if r.cmd != nil { util.GetLogger().Info("[recpt1][%s] Canceling the process.", r.Key()) r.signaled = true exec.Command("kill", "-9", strconv.Itoa(r.cmd.Process.Pid)).Run() } }
// Create a new Recorder instance. // receiver should be a channel to register the record func NewRecorder(receiver <-chan []Record) *Recorder { return &Recorder{ receiver: receiver, recorder: make(chan *RecordResult, 128), controls: make(map[string]*RecordCtrl), shouldStop: false, logger: util.GetLogger(), } }
func (pt1 *Pt1Recorder) updatePrograms(ch *tv.TvChannel) error { var stdout bytes.Buffer var stderr bytes.Buffer logger := util.GetLogger() d := int(pt1.pt1Config.ProgramCheckDuration.Seconds()) tspath := filepath.Join( pt1.pt1Config.StoragePath, fmt.Sprintf(".updateProgram.%s.ts", ch.Cid), ) jsonpath := filepath.Join( pt1.pt1Config.StoragePath, fmt.Sprintf(".updateProgram.%s.json", ch.Cid), ) // execute recpt1 args := []string{"--b25", "--strip", ch.Cid, fmt.Sprintf("%d", d), tspath} recpt1 := exec.Command(pt1.pt1Config.Recpt1Path, args...) recpt1.Stdout = &stdout recpt1.Stderr = &stderr err := recpt1.Run() if err != nil { logger.Warn("[Pt1Recorder] Could not execute recpt1: %v", err) logger.Warn("[CMD] %s %s", pt1.pt1Config.Recpt1Path, strings.Join(args, " ")) logger.Warn("[STDOUT]: %s", stdout.String()) logger.Warn("[STDERR]: %s", stderr.String()) return err } logger.Debug("[Pt1Recorder] Generated %s for updating programs.", tspath) // execute epgdump to generate json args = []string{"json", tspath, jsonpath} epgdump := exec.Command(pt1.pt1Config.EpgdumpPath, args...) err = epgdump.Run() if err != nil { logger.Warn("[Pt1Recorder] Could not execute epgdump: %v", err) return err } logger.Debug("[Pt1Recorder] Generated %s for updating programs.", jsonpath) // upload json data to server jsondata, err := ioutil.ReadFile(jsonpath) if err != nil { logger.Warn("[Pt1Recorder] Could not read the generated jsonfile on %s: %v", jsonpath, err) return err } resp, err := api.UploadPrograms(ch.Cid, bytes.NewBuffer(jsondata)) if err != nil { logger.Warn("[Pt1Recorder] Could not post the jsondata to the endpoint: %v", err) return err } else { logger.Info( "[Pt1Recorder] Uploaded %d programs, %d parse errors, %d database errors", len(resp["ids"]), len(resp["parse_errors"]), len(resp["database_errors"]), ) } return nil }
func (r *Pt1Record) Stop() error { // send TERM if r.IsRunning() { util.GetLogger().Info("[recpt1][%s] Stopping the process.", r.Key()) r.signaled = true err := exec.Command("kill", strconv.Itoa(r.cmd.Process.Pid)).Run() return err } return nil }
func (r *Pt1Record) Start() error { var err error logger := util.GetLogger() // make sure the directory exists if err = os.MkdirAll(r.DirectoryPath(), 0755); err != nil { return err } r.filepath = r.resolveFilePath() r.cmd = NewRecCommand(r.Recpt1Path, r.tvrecord.Cid, r.tvrecord.Sid, r.filepath) stdout, _ := r.cmd.StdoutPipe() stderr, _ := r.cmd.StderrPipe() err = r.cmd.Start() if err != nil { return err } logger.Info("[recpt1][%s] Started.", r.Key()) go pipeLogs(stderr, fmt.Sprintf("[recpt1][%s][stderr]", r.Key())) go pipeLogs(stdout, fmt.Sprintf("[recpt1][%s][stdout]", r.Key())) go func() { err := r.cmd.Wait() if err != nil { // failed. if r.signaled { logger.Info("[recpt1][%s] Stopped by signal: %v", r.Key(), err) } else { logger.Info("[recpt1][%s] Failed: %v", r.Key(), err) } } else { if r.cmd.ProcessState == nil { // could not started. } else { if r.cmd.ProcessState.Success() { logger.Info("[recpt1][%s] Completed successfully.", r.Key()) } else { // failed. if r.signaled { logger.Info("[recpt1][%s] Stopped by signal.", r.Key()) } else { logger.Info("[recpt1][%s] Failed.", r.Key()) } } } } r.cmd = nil r.signaled = false }() return nil }
func (pt1 *Pt1Recorder) subscribe() { logger := util.GetLogger() for { records, err := api.GetTvRecords() if err != nil { logger.Error("[Pt1Recorder] Failed to get records: %v", err) } else { logger.Debug("[Pt1Recorder] Got %d records from the server.", len(records)) list := make([]tv.Record, len(records)) for i, v := range records { list[i] = NewPt1Record(v, pt1.pt1Config) } pt1.receiver <- list } time.Sleep(pt1.pt1Config.FetchInterval) } }