func (s *Service) processCreateIteratorRequest(conn net.Conn) { defer conn.Close() var itr influxql.Iterator if err := func() error { // Parse request. var req CreateIteratorRequest if err := DecodeLV(conn, &req); err != nil { return err } // Collect iterator creators for each shard. ics := make([]influxql.IteratorCreator, 0, len(req.ShardIDs)) for _, shardID := range req.ShardIDs { ic := s.TSDBStore.ShardIteratorCreator(shardID) if ic == nil { return nil } ics = append(ics, ic) } // Generate a single iterator from all shards. i, err := influxql.IteratorCreators(ics).CreateIterator(req.Opt) if err != nil { return err } itr = i return nil }(); err != nil { itr.Close() s.Logger.Printf("error reading CreateIterator request: %s", err) EncodeTLV(conn, createIteratorResponseMessage, &CreateIteratorResponse{Err: err}) return } // Encode success response. if err := EncodeTLV(conn, createIteratorResponseMessage, &CreateIteratorResponse{}); err != nil { s.Logger.Printf("error writing CreateIterator response: %s", err) return } // Exit if no iterator was produced. if itr == nil { return } // Stream iterator to connection. if err := influxql.NewIteratorEncoder(conn).EncodeIterator(itr); err != nil { s.Logger.Printf("error encoding CreateIterator iterator: %s", err) return } }
// Ensure iterator can be encoded and decoded over a byte stream. func TestIterator_EncodeDecode(t *testing.T) { var buf bytes.Buffer // Create an iterator with several points & stats. itr := &FloatIterator{ Points: []influxql.FloatPoint{ {Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 0}, {Name: "mem", Tags: ParseTags("host=B"), Time: 1, Value: 10}, }, stats: influxql.IteratorStats{ SeriesN: 2, PointN: 0, }, } // Encode to the buffer. enc := influxql.NewIteratorEncoder(&buf) enc.StatsInterval = 100 * time.Millisecond if err := enc.EncodeIterator(itr); err != nil { t.Fatal(err) } // Decode from the buffer. dec, err := influxql.NewReaderIterator(&buf) if err != nil { t.Fatal(err) } // Initial stats should exist immediately. fdec := dec.(influxql.FloatIterator) if stats := fdec.Stats(); !reflect.DeepEqual(stats, influxql.IteratorStats{SeriesN: 2, PointN: 0}) { t.Fatalf("unexpected stats(initial): %#v", stats) } // Read both points. if p := fdec.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "cpu", Tags: ParseTags("host=A"), Time: 0, Value: 0}) { t.Fatalf("unexpected point(0); %#v", p) } else if p := fdec.Next(); !reflect.DeepEqual(p, &influxql.FloatPoint{Name: "mem", Tags: ParseTags("host=B"), Time: 1, Value: 10}) { t.Fatalf("unexpected point(1); %#v", p) } else if p := fdec.Next(); p != nil { t.Fatalf("unexpected point(eof); %#v", p) } }