// Ensure two handlers cannot be registered for the same header byte. func TestMux_Listen_ErrAlreadyRegistered(t *testing.T) { defer func() { if r := recover(); r != `listener already registered under header byte: 5` { t.Fatalf("unexpected recover: %#v", r) } }() // Register two listeners with the same header byte. mux := tcp.NewMux() mux.Listen(5) mux.Listen(5) }
func newService(cfg *meta.Config) *testService { // Open shared TCP connection. ln, err := net.Listen("tcp", cfg.BindAddress) if err != nil { panic(err) } // Multiplex listener. mux := tcp.NewMux() s := meta.NewService(cfg) s.RaftListener = mux.Listen(meta.MuxHeader) go mux.Serve(ln) return &testService{Service: s, ln: ln} }
func newTestWriteService(f func(shardID uint64, points []models.Point) error) testService { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } mux := tcp.NewMux() muxln := mux.Listen(cluster.MuxHeader) go mux.Serve(ln) s := testService{ ln: ln, muxln: muxln, } s.TSDBStore.WriteToShardFn = f s.responses = make(chan *serviceResponse, 1024) return s }
// MustOpenService returns a new, opened service. Panic on error. func MustOpenService() *Service { // Open randomly assigned port. ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { panic(err) } // Start muxer. mux := tcp.NewMux() // Create new service and attach mux'd listener. s := NewService() s.ln = ln s.Listener = mux.Listen(copier.MuxHeader) go mux.Serve(ln) if err := s.Open(); err != nil { panic(err) } return s }
// Open opens the meta and data store and all services. func (s *Server) Open() error { // Start profiling, if set. startProfile(s.CPUProfile, s.MemProfile) // Open shared TCP connection. ln, err := net.Listen("tcp", s.BindAddress) if err != nil { return fmt.Errorf("listen: %s", err) } s.Listener = ln // Multiplex listener. mux := tcp.NewMux() go mux.Serve(ln) // Append services. s.appendMonitorService() s.appendPrecreatorService(s.config.Precreator) s.appendSnapshotterService() s.appendAdminService(s.config.Admin) s.appendContinuousQueryService(s.config.ContinuousQuery) s.appendHTTPDService(s.config.HTTPD) s.appendRetentionPolicyService(s.config.Retention) for _, i := range s.config.GraphiteInputs { if err := s.appendGraphiteService(i); err != nil { return err } } for _, i := range s.config.CollectdInputs { s.appendCollectdService(i) } for _, i := range s.config.OpenTSDBInputs { if err := s.appendOpenTSDBService(i); err != nil { return err } } for _, i := range s.config.UDPInputs { s.appendUDPService(i) } s.Subscriber.MetaClient = s.MetaClient s.Subscriber.MetaClient = s.MetaClient s.PointsWriter.MetaClient = s.MetaClient s.Monitor.MetaClient = s.MetaClient s.SnapshotterService.Listener = mux.Listen(snapshotter.MuxHeader) // Configure logging for all services and clients. if s.config.Meta.LoggingEnabled { s.MetaClient.WithLogger(s.Logger) } s.TSDBStore.WithLogger(s.Logger) if s.config.Data.QueryLogEnabled { s.QueryExecutor.WithLogger(s.Logger) } s.PointsWriter.WithLogger(s.Logger) s.Subscriber.WithLogger(s.Logger) for _, svc := range s.Services { svc.WithLogger(s.Logger) } s.SnapshotterService.WithLogger(s.Logger) s.Monitor.WithLogger(s.Logger) // Open TSDB store. if err := s.TSDBStore.Open(); err != nil { return fmt.Errorf("open tsdb store: %s", err) } // Open the subcriber service if err := s.Subscriber.Open(); err != nil { return fmt.Errorf("open subscriber: %s", err) } // Open the points writer service if err := s.PointsWriter.Open(); err != nil { return fmt.Errorf("open points writer: %s", err) } for _, service := range s.Services { if err := service.Open(); err != nil { return fmt.Errorf("open service: %s", err) } } // Start the reporting service, if not disabled. if !s.reportingDisabled { go s.startServerReporting() } return nil }
// Open opens the meta and data store and all services. func (s *Server) Open() error { // Start profiling, if set. startProfile(s.CPUProfile, s.MemProfile) // Open shared TCP connection. ln, err := net.Listen("tcp", s.BindAddress) if err != nil { return fmt.Errorf("listen: %s", err) } s.Listener = ln // Multiplex listener. mux := tcp.NewMux() go mux.Serve(ln) // Append services. s.appendClusterService(s.config.Cluster) s.appendPrecreatorService(s.config.Precreator) s.appendSnapshotterService() s.appendCopierService() s.appendAdminService(s.config.Admin) s.appendContinuousQueryService(s.config.ContinuousQuery) s.appendHTTPDService(s.config.HTTPD) s.appendCollectdService(s.config.Collectd) if err := s.appendOpenTSDBService(s.config.OpenTSDB); err != nil { return err } for _, g := range s.config.UDPs { s.appendUDPService(g) } s.appendRetentionPolicyService(s.config.Retention) for _, g := range s.config.Graphites { if err := s.appendGraphiteService(g); err != nil { return err } } s.Subscriber.MetaClient = s.MetaClient s.Subscriber.MetaClient = s.MetaClient s.PointsWriter.MetaClient = s.MetaClient s.Monitor.MetaClient = s.MetaClient s.ClusterService.Listener = mux.Listen(cluster.MuxHeader) s.SnapshotterService.Listener = mux.Listen(snapshotter.MuxHeader) s.CopierService.Listener = mux.Listen(copier.MuxHeader) // Open TSDB store. if err := s.TSDBStore.Open(); err != nil { return fmt.Errorf("open tsdb store: %s", err) } // Open the subcriber service if err := s.Subscriber.Open(); err != nil { return fmt.Errorf("open subscriber: %s", err) } // Open the points writer service if err := s.PointsWriter.Open(); err != nil { return fmt.Errorf("open points writer: %s", err) } // Open the monitor service if err := s.Monitor.Open(); err != nil { return fmt.Errorf("open monitor: %v", err) } for _, service := range s.Services { if err := service.Open(); err != nil { return fmt.Errorf("open service: %s", err) } } // Start the reporting service, if not disabled. if !s.reportingDisabled { go s.startServerReporting() } return nil }
// Ensure the muxer can split a listener's connections across multiple listeners. func TestMux(t *testing.T) { if err := quick.Check(func(n uint8, msg []byte) bool { if testing.Verbose() { if len(msg) == 0 { log.Printf("n=%d, <no message>", n) } else { log.Printf("n=%d, hdr=%d, len=%d", n, msg[0], len(msg)) } } var wg sync.WaitGroup // Open single listener on random port. tcpListener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } defer tcpListener.Close() // Setup muxer & listeners. mux := tcp.NewMux() mux.Timeout = 200 * time.Millisecond if !testing.Verbose() { mux.Logger = log.New(ioutil.Discard, "", 0) } for i := uint8(0); i < n; i++ { ln := mux.Listen(byte(i)) wg.Add(1) go func(i uint8, ln net.Listener) { defer wg.Done() // Wait for a connection for this listener. conn, err := ln.Accept() if conn != nil { defer conn.Close() } // If there is no message or the header byte // doesn't match then expect close. if len(msg) == 0 || msg[0] != byte(i) { if err == nil || err.Error() != "network connection closed" { t.Fatalf("unexpected error: %s", err) } return } // If the header byte matches this listener // then expect a connection and read the message. var buf bytes.Buffer if _, err := io.CopyN(&buf, conn, int64(len(msg)-1)); err != nil { t.Fatal(err) } else if !bytes.Equal(msg[1:], buf.Bytes()) { t.Fatalf("message mismatch:\n\nexp=%x\n\ngot=%x\n\n", msg[1:], buf.Bytes()) } // Write response. if _, err := conn.Write([]byte("OK")); err != nil { t.Fatal(err) } }(i, ln) } // Begin serving from the listener. go mux.Serve(tcpListener) // Write message to TCP listener and read OK response. conn, err := net.Dial("tcp", tcpListener.Addr().String()) if err != nil { t.Fatal(err) } else if _, err = conn.Write(msg); err != nil { t.Fatal(err) } // Read the response into the buffer. var resp [2]byte _, err = io.ReadFull(conn, resp[:]) // If the message header is less than n then expect a response. // Otherwise we should get an EOF because the mux closed. if len(msg) > 0 && uint8(msg[0]) < n { if string(resp[:]) != `OK` { t.Fatalf("unexpected response: %s", resp[:]) } } else { if err == nil || (err != io.EOF && !(strings.Contains(err.Error(), "connection reset by peer") || strings.Contains(err.Error(), "closed by the remote host"))) { t.Fatalf("unexpected error: %s", err) } } // Close connection. if err := conn.Close(); err != nil { t.Fatal(err) } // Close original TCP listener and wait for all goroutines to close. tcpListener.Close() wg.Wait() return true }, nil); err != nil { t.Error(err) } }
// Open opens the meta and data store and all services. func (s *Server) Open() error { // Start profiling, if set. startProfile(s.CPUProfile, s.MemProfile) // Open shared TCP connection. ln, err := net.Listen("tcp", s.BindAddress) if err != nil { return fmt.Errorf("listen: %s", err) } s.Listener = ln // Multiplex listener. mux := tcp.NewMux() go mux.Serve(ln) if s.MetaService != nil { s.MetaService.RaftListener = mux.Listen(meta.MuxHeader) // Open meta service. if err := s.MetaService.Open(); err != nil { return fmt.Errorf("open meta service: %s", err) } go s.monitorErrorChan(s.MetaService.Err()) } // initialize MetaClient. if err = s.initializeMetaClient(); err != nil { return err } if s.TSDBStore != nil { // Append services. s.appendClusterService(s.config.Cluster) s.appendPrecreatorService(s.config.Precreator) s.appendSnapshotterService() s.appendCopierService() s.appendAdminService(s.config.Admin) s.appendContinuousQueryService(s.config.ContinuousQuery) s.appendHTTPDService(s.config.HTTPD) s.appendCollectdService(s.config.Collectd) if err := s.appendOpenTSDBService(s.config.OpenTSDB); err != nil { return err } for _, g := range s.config.UDPs { s.appendUDPService(g) } s.appendRetentionPolicyService(s.config.Retention) for _, g := range s.config.Graphites { if err := s.appendGraphiteService(g); err != nil { return err } } s.QueryExecutor.Node = s.Node s.Subscriber.MetaClient = s.MetaClient s.ShardWriter.MetaClient = s.MetaClient s.HintedHandoff.MetaClient = s.MetaClient s.Subscriber.MetaClient = s.MetaClient s.PointsWriter.MetaClient = s.MetaClient s.Monitor.MetaClient = s.MetaClient s.ClusterService.Listener = mux.Listen(cluster.MuxHeader) s.SnapshotterService.Listener = mux.Listen(snapshotter.MuxHeader) s.CopierService.Listener = mux.Listen(copier.MuxHeader) // Open TSDB store. if err := s.TSDBStore.Open(); err != nil { // Provide helpful error if user needs to upgrade shards to // tsm1. if serr, ok := err.(tsdb.ShardError); ok && serr.Err == tsdb.ErrUnknownEngineFormat { return influxdb.ErrUpgradeEngine } return fmt.Errorf("open tsdb store: %s", err) } // Open the hinted handoff service if err := s.HintedHandoff.Open(); err != nil { return fmt.Errorf("open hinted handoff: %s", err) } // Open the subcriber service if err := s.Subscriber.Open(); err != nil { return fmt.Errorf("open subscriber: %s", err) } // Open the points writer service if err := s.PointsWriter.Open(); err != nil { return fmt.Errorf("open points writer: %s", err) } // Open the monitor service if err := s.Monitor.Open(); err != nil { return fmt.Errorf("open monitor: %v", err) } for _, service := range s.Services { if err := service.Open(); err != nil { return fmt.Errorf("open service: %s", err) } } } // Start the reporting service, if not disabled. if !s.reportingDisabled { go s.startServerReporting() } return nil }