Beispiel #1
0
func (f *fileListener) Close() error {
	f.Lock()

	select {
	case <-f.stop:
		f.Unlock()
		return nil // Already stopped
	default:
		close(f.stop)
	}

	var firstErr error
	if firstErr = f.netListener.Close(); firstErr != nil {
		slog.Trace("Error closing file listener: %v", firstErr)
	}

	for conn := range f.connections {
		if err := conn.Close(); err != nil {
			if firstErr == nil {
				firstErr = err
			}
			slog.Trace("Error closing connection: %v", err)
		}
	}

	f.Unlock()
	f.wg.Wait()
	close(f.changes)

	return firstErr
}
Beispiel #2
0
// Collect file changes that happen FileChangeWindow ms from each
// other, and restart all nodes in the process tree that match
// features of the changed files.
func start(tree *processtree.ProcessTree, filesChanged chan string, done, quit chan bool) {
	for {
		select {
		case <-quit:
			done <- true
			return
		case file := <-filesChanged:
			changed := make(map[string]bool)
			changed[file] = true

			slog.Trace("Restarter got the first file of potentially many")
			deadline := time.After(FileChangeWindow)
			deadline_expired := false
			for !deadline_expired {
				select {
				case <-quit:
					done <- true
					return
				case file := <-filesChanged:
					changed[file] = true
				case <-deadline:
					deadline_expired = true
				}
			}
			slog.Trace("Restarter has gathered %d changed files", len(changed))
			go tree.RestartNodesWithFeatures(changed)
		}
	}
}
Beispiel #3
0
func (f *fileListener) handleConnection(conn net.Conn, ch chan string) {
	// Handle writes
	stop := make(chan struct{})
	go func() {
		for {
			select {
			case s := <-ch:
				conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
				if _, err := conn.Write([]byte(s + "\n")); err == io.EOF {
					return
				} else if err != nil {
					slog.Trace("Error writing to connection: %v", err)
				}
			case <-stop:
				return
			}
		}
	}()

	// Handle reads
	scanner := bufio.NewScanner(conn)
	for {
		if scanner.Scan() {
			f.changes <- scanner.Text()
		} else {
			if err := scanner.Err(); err != nil {
				select {
				case <-f.stop:
					break
				default:
					slog.Trace("Error reading from connection: %v", err)
				}
			}
			break
		}
	}

	f.Lock()
	defer f.Unlock()

	close(stop)
	delete(f.connections, conn)
	f.wg.Done()
}
Beispiel #4
0
// Collect file changes that happen FileChangeWindow ms from each
// other, and restart all nodes in the process tree that match
// features of the changed files.
func (r *restarter) start() {
	for {
		select {
		case <-r.quit:
			r.done <- true
			return
		case file := <-r.filesChanged:
			changed := make(map[string]bool)
			changed[file] = true

			slog.Trace("Restarter got the first file of potentially many")

			if r.gatherFiles(changed, time.After(FileChangeWindow)) {
				return
			}

			slog.Trace("Restarter has gathered %d changed files", len(changed))
			go r.tree.RestartNodesWithFeatures(changed)
		}
	}
}
Beispiel #5
0
func (s *SlaveNode) trace(format string, args ...interface{}) {
	if !slog.TraceEnabled() {
		return
	}

	_, file, line, _ := runtime.Caller(1)

	var prefix string
	if s.Pid != 0 {
		prefix = fmt.Sprintf("[%s:%d] %s/(%d)", file, line, s.Name, s.Pid)
	} else {
		prefix = fmt.Sprintf("[%s:%d] %s/(no PID)", file, line, s.Name)
	}
	new_args := make([]interface{}, len(args)+1)
	new_args[0] = prefix
	for i, v := range args {
		new_args[i+1] = v
	}
	slog.Trace("%s "+format, new_args...)
}
Beispiel #6
0
func (f *fileListener) serve() {
	var tempDelay time.Duration // how long to sleep on accept failure

	for {
		conn, err := f.netListener.Accept()
		if err != nil {
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				slog.Trace("filelistener: Accept error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue
			}

			select {
			case <-f.stop:
				return
			default:
				panic(err)
			}
		}

		ch := make(chan string)
		f.Lock()
		f.connections[conn] = ch
		f.wg.Add(1)
		f.Unlock()

		go f.handleConnection(conn, ch)
	}
}