예제 #1
0
파일: queue.go 프로젝트: pressly/qmd
func (qmd *Qmd) ListenQueue() {
	qmd.WaitListenQueue.Add(1)
	defer qmd.WaitListenQueue.Done()

	lg.Debug("Queue:\tListening")

	for {
		select {
		// Wait for some worker to become available.
		case worker := <-qmd.Workers:
			// Dequeue job or try again.
			job, err := qmd.Dequeue()
			if err != nil {
				qmd.Workers <- worker
				break
			}
			lg.Debugf("Queue:\tDequeued job %v", job.ID)
			// Send the job to the worker.
			worker <- job

		case <-qmd.ClosingListenQueue:
			lg.Debug("Queue:\tStopped listening")
			return
		}
	}
}
예제 #2
0
파일: cmd.go 프로젝트: pressly/qmd
func (cmd *Cmd) Kill() error {
	switch cmd.State {
	case Running:
		cmd.State = Terminated
		lg.Debugf("Cmd:\tKilling %v\n", cmd.JobID)
		pgid, err := syscall.Getpgid(cmd.Cmd.Process.Pid)
		if err != nil {
			// Fall-back on error. Kill the main process only.
			cmd.Cmd.Process.Kill()
			break
		}
		// Kill the whole process group.
		syscall.Kill(-pgid, 15)

	case Finished:
		lg.Debug("Cmd:\tKilling pgroup %v\n", cmd.JobID)
		pgid, err := syscall.Getpgid(cmd.Cmd.Process.Pid)
		if err != nil {
			break
		}
		// Make sure to kill the whole process group,
		// so there are no subprocesses left.
		syscall.Kill(-pgid, 15)

	case Initialized:
		// This one is tricky, as the cmd's Start() might have
		// been called and is already in progress, but the cmd's
		// state is not Running yet.
		usCallingStartOnce := false
		cmd.StartOnce.Do(func() {
			cmd.WaitOnce.Do(func() {
				cmd.State = Invalidated
				cmd.StatusCode = -2
				cmd.Err = errors.New("invalidated")
				lg.Debugf("Cmd: Invalidating %v\n", cmd.JobID)
				close(cmd.Finished)
			})
			close(cmd.Started)
			usCallingStartOnce = true
		})
		if !usCallingStartOnce {
			// It was cmd.Start() that called StartOnce.Do(), not us,
			// thus we need to wait for Started and try to Kill again:
			<-cmd.Started
			cmd.Kill()
		}
	}

	return cmd.Err
}
예제 #3
0
파일: qmd.go 프로젝트: pressly/qmd
func (qmd *Qmd) Close() {
	lg.Debug("Closing")

	qmd.Closing = true

	close(qmd.ClosingListenQueue)
	qmd.WaitListenQueue.Wait()

	close(qmd.ClosingWorkers)
	qmd.WaitWorkers.Wait()

	qmd.DB.Close()
	qmd.Queue.Close()
}
예제 #4
0
파일: scripts.go 프로젝트: pressly/qmd
// Update walks ScriptDir directory for shell scripts and updates the files cache.
func (s *Scripts) Update(dir string) error {
	info, err := os.Stat(dir)
	if err != nil {
		return errors.New("script_dir=\"" + dir + "\": no such directory")
	}
	if !info.IsDir() {
		return errors.New("script_dir=\"" + dir + "\": not a directory")
	}

	files := map[string]string{}
	if err := filepath.Walk(dir, func(file string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			if path.Ext(file) == ".sh" {
				rel, err := filepath.Rel(dir, file)
				if err != nil {
					return err
				}
				files[rel] = file
			}
		}
		return nil
	}); err != nil {
		return err
	}

	if len(files) == 0 {
		return errors.New("script_dir=\"" + dir + "\" is empty")
	}

	s.Lock()
	defer s.Unlock()

	if !reflect.DeepEqual(s.files, files) {
		lg.Debug("Scripts:	Loading new files from script_dir:")
		for rel, _ := range files {
			lg.Debugf("Scripts:	 - %v", rel)
		}
	}

	s.files = files
	return nil
}