func TestQueryManager_Interrupt(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } closing := make(chan struct{}) qm := influxql.DefaultQueryManager(0) params := influxql.QueryParams{ Query: q, Database: `mydb`, InterruptCh: closing, } _, ch, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } close(closing) select { case <-ch: case <-time.After(100 * time.Millisecond): t.Error("interrupting the query did not close the channel after 100 milliseconds") } }
func TestQueryManager_KillQuery(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } qm := influxql.DefaultQueryManager(0) params := influxql.QueryParams{ Query: q, Database: `mydb`, } qid, ch, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } qm.KillQuery(qid) select { case <-ch: case <-time.After(100 * time.Millisecond): t.Error("detaching the query did not close the channel after 100 milliseconds") } if err := qm.KillQuery(qid); err == nil || err.Error() != fmt.Sprintf("no such query id: %d", qid) { t.Errorf("incorrect error detaching query, got %s", err) } }
func TestQueryManager_Close(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } qm := influxql.DefaultQueryManager(0) params := influxql.QueryParams{ Query: q, Database: `mydb`, } _, ch, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } qm.Close() select { case <-ch: case <-time.After(100 * time.Millisecond): t.Error("closing the query manager did not kill the query after 100 milliseconds") } _, _, err = qm.AttachQuery(¶ms) if err == nil || err != influxql.ErrQueryManagerShutdown { t.Errorf("unexpected error: %s", err) } }
func TestQueryManager_Queries(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } qm := influxql.DefaultQueryManager(0) params := influxql.QueryParams{ Query: q, Database: `mydb`, } qid, _, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } queries := qm.Queries() if len(queries) != 1 { t.Errorf("expected 1 query, got %d", len(queries)) } else { qi := queries[0] if qi.ID != qid { t.Errorf("query id: exp=%d got=%d", qid, qi.ID) } if qi.Query != `SELECT count(value) FROM cpu` { t.Errorf("query id: incorrect query string, got '%s'", qi.Query) } if qi.Database != "mydb" { t.Errorf("query id: incorrect database, got %s", qi.Database) } } qm.KillQuery(qid) queries = qm.Queries() if len(queries) != 0 { t.Errorf("expected 0 queries, got %d", len(queries)) } }
func TestQueryManager_AttachQuery(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } qm := influxql.DefaultQueryManager(0) params := influxql.QueryParams{ Query: q, Database: `mydb`, } qid, _, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } defer qm.KillQuery(qid) if qid != 1 { t.Errorf("incorrect query id: exp=1 got=%d", qid) } }
func TestQueryManager_Limit_ConcurrentQueries(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } qm := influxql.DefaultQueryManager(1) params := influxql.QueryParams{ Query: q, Database: `mydb`, } qid, _, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } defer qm.KillQuery(qid) _, _, err = qm.AttachQuery(¶ms) if err == nil || err != influxql.ErrMaxConcurrentQueriesReached { t.Errorf("unexpected error: %s", err) } }
func TestQueryManager_Limit_Timeout(t *testing.T) { q, err := influxql.ParseQuery(`SELECT count(value) FROM cpu`) if err != nil { t.Fatal(err) } qm := influxql.DefaultQueryManager(0) params := influxql.QueryParams{ Query: q, Database: `mydb`, Timeout: time.Nanosecond, } _, ch, err := qm.AttachQuery(¶ms) if err != nil { t.Fatal(err) } select { case <-ch: case <-time.After(time.Millisecond): t.Errorf("timeout has not killed the query") } }
// NewServer returns a new instance of Server built from a config. func NewServer(c *Config, buildInfo *BuildInfo) (*Server, error) { // We need to ensure that a meta directory always exists even if // we don't start the meta store. node.json is always stored under // the meta directory. if err := os.MkdirAll(c.Meta.Dir, 0777); err != nil { return nil, fmt.Errorf("mkdir all: %s", err) } // 0.10-rc1 and prior would sometimes put the node.json at the root // dir which breaks backup/restore and restarting nodes. This moves // the file from the root so it's always under the meta dir. oldPath := filepath.Join(filepath.Dir(c.Meta.Dir), "node.json") newPath := filepath.Join(c.Meta.Dir, "node.json") if _, err := os.Stat(oldPath); err == nil { if err := os.Rename(oldPath, newPath); err != nil { return nil, err } } _, err := influxdb.LoadNode(c.Meta.Dir) if err != nil { if !os.IsNotExist(err) { return nil, err } } // In 0.10.0 bind-address got moved to the top level. Check // The old location to keep things backwards compatible bind := c.BindAddress s := &Server{ buildInfo: *buildInfo, err: make(chan error), closing: make(chan struct{}), BindAddress: bind, MetaClient: meta.NewClient(c.Meta), Monitor: monitor.New(c.Monitor), reportingDisabled: c.ReportingDisabled, httpAPIAddr: c.HTTPD.BindAddress, httpUseTLS: c.HTTPD.HTTPSEnabled, tcpAddr: bind, config: c, } if err := s.MetaClient.Open(); err != nil { return nil, err } s.TSDBStore = tsdb.NewStore(c.Data.Dir) s.TSDBStore.EngineOptions.Config = c.Data // Copy TSDB configuration. s.TSDBStore.EngineOptions.EngineVersion = c.Data.Engine // Create the Subscriber service s.Subscriber = subscriber.NewService(c.Subscriber) // Initialize points writer. s.PointsWriter = cluster.NewPointsWriter() s.PointsWriter.WriteTimeout = time.Duration(c.Cluster.WriteTimeout) s.PointsWriter.TSDBStore = s.TSDBStore s.PointsWriter.Subscriber = s.Subscriber // Initialize query executor. s.QueryExecutor = cluster.NewQueryExecutor() s.QueryExecutor.MetaClient = s.MetaClient s.QueryExecutor.TSDBStore = s.TSDBStore s.QueryExecutor.Monitor = s.Monitor s.QueryExecutor.PointsWriter = s.PointsWriter s.QueryExecutor.QueryTimeout = time.Duration(c.Cluster.QueryTimeout) s.QueryExecutor.QueryManager = influxql.DefaultQueryManager(c.Cluster.MaxConcurrentQueries) s.QueryExecutor.MaxSelectSeriesN = c.Cluster.MaxSelectSeriesN if c.Data.QueryLogEnabled { s.QueryExecutor.LogOutput = os.Stderr } // Initialize the monitor s.Monitor.Version = s.buildInfo.Version s.Monitor.Commit = s.buildInfo.Commit s.Monitor.Branch = s.buildInfo.Branch s.Monitor.BuildTime = s.buildInfo.Time s.Monitor.PointsWriter = (*monitorPointsWriter)(s.PointsWriter) return s, nil }