Example #1
0
// Serve on a given port
//
// The server will log to the default logger and will gracefully terminate on
// receipt of an interrupt or kill signal.
//
// The following URLs are defined:
//    /
//    /healthz
//    /varz
//    /streamz
//    /birpc
//    /debug/pprof
//
// Setting port to 0 will start the server on an ephemeral port. The assigned
// port will be logged.
func ServeForever(port int) error {
	l, err := vnet.SignalListener(port)
	if err != nil {
		log.Errorf("govtil/net/server: failed to open port: %v", err)
		return err
	}
	return ServeListenerForever(l)
}
Example #2
0
// Split a WriteCloser into 'n' WriteClosers. When all returned WriteClosers
// have been Close()'d, then the underlying ReadCloser is also closed.
func SplitWriteCloser(wc io.WriteCloser, n uint) []io.WriteCloser {
	var r []io.WriteCloser
	c := make(chan wop)
	cg := new(sync.WaitGroup)
	cg.Add(int(n))
	for i := 0; i < int(n); i++ {
		wpx := &wproxy{
			i,
			c,
			make(chan rp),
			cg,
		}
		r = append(r, wpx)
	}

	// Closer
	go func() {
		cg.Wait()
		wc.Close()
	}()

	// Write pump
	wpump := func() {
		var err error
		defer func() {
			if err != nil && err != io.EOF {
				log.Errorf("govtil/io/multiplex: wpump error: %v", err)
			}
		}()

		enc := gob.NewEncoder(wc)
		for {
			w, ok := <-c
			if !ok {
				err = nil
				return
			}
			if err = enc.Encode(uint(w.id)); err != nil {
				w.c <- rp{0, err}
				err = nil
				continue
			}
			if err = enc.Encode(w.b); err != nil {
				w.c <- rp{0, err}
				err = nil
				continue
			}
			w.c <- rp{len(w.b), nil}
		}
	}

	go wpump()
	return r
}
Example #3
0
// ServeListenerForever is the same as ServeForever except it uses the specified
// listener. This is useful in testing when an ephemeral port should be used.
func ServeListenerForever(l net.Listener) error {
	// Wrap with logger
	handler := logginghandler.New(http.DefaultServeMux, log.GetVerbosity())

	_, aps, err := net.SplitHostPort(l.Addr().String())
	if err != nil {
		log.Errorf("govtil/net/server: failed to get port - %v", err)
	}
	log.Printf("govtil/net/server: starting on port %v", aps)

	// Serve
	err = http.Serve(l, handler)
	if err != nil {
		if vnet.SocketClosed(err) {
			err = nil // closed due to signal, no error
		} else {
			log.Errorf("govtil/net/server: %v", err)
		}
	}
	log.Println("govtil/net/server: Terminating")
	return err
}
Example #4
0
// Split a ReadCloser into 'n' ReadClosers. When all returned ReadClosers have
// been Close()'d, then the underlying ReadCloser is also closed.
func SplitReadCloser(rc io.ReadCloser, n uint) []io.ReadCloser {
	var r []io.ReadCloser
	var w []io.WriteCloser
	cg := new(sync.WaitGroup)
	cg.Add(int(n))
	for i := 0; i < int(n); i++ {
		rp, wp := io.Pipe()
		brp := bufio.NewReader(rp)
		w = append(w, wp)
		rpx := &rproxy{
			i,
			rp,
			brp,
			cg,
		}
		r = append(r, rpx)
	}

	// Closer
	go func() {
		cg.Wait()
		rc.Close()
	}()

	// Read pump
	rpump := func() {
		var err error
		defer func() {
			if err != nil && err != io.EOF {
				log.Errorf("govtil/io/multiplex: rpump error: %v", err)
			}
			for i := 0; i < len(w); i++ {
				w[i].Close()
			}
		}()

		dec := gob.NewDecoder(rc)
		var chno uint
		var d []byte
		for {
			if err = dec.Decode(&chno); err != nil {
				return
			}
			if err = dec.Decode(&d); err != nil {
				return
			}
			if _, err = w[chno].Write(d); err != nil {
				if err == io.ErrClosedPipe {
					// closed sub-channel, keep serving other sub-channels
					log.Debugf("govtil/io/multiplex: sub-channel closed, dumping payload of len %v", len(d))
					continue
				} else {
					// something wrong, stop
					log.Debugf("govtil/io/multiplex: failed to write received payload of length %v to pipe for channel %v", len(d), chno)
					return
				}
			}
		}
	}

	go rpump()
	return r
}