diff --git a/bench/client.go b/bench/client.go index 603e25cb2..101f62d4b 100644 --- a/bench/client.go +++ b/bench/client.go @@ -1,8 +1,9 @@ package bench import ( + "context" + "errors" "fmt" - "github.com/pilosa/pilosa" ) @@ -22,8 +23,9 @@ func roundRobinClient(hosts []string, agentNum int) (*pilosa.Client, error) { // HasClient provides a reusable component for Benchmark implementations which // provides the Init method, a ClientType argument and a cli internal variable. type HasClient struct { - client *pilosa.Client - ClientType string `json:"client-type"` + client *pilosa.Client + ClientType string `json:"client-type"` + ContentType string `json:"content-type"` } // Init for HasClient looks at the ClientType field and creates a pilosa client @@ -34,11 +36,32 @@ func (h *HasClient) Init(hosts []string, agentNum int) error { switch h.ClientType { case "single": h.client, err = firstHostClient(hosts) - return err case "round_robin": h.client, err = roundRobinClient(hosts, agentNum) - return err default: - return fmt.Errorf("Unsupported ClientType: %v", h.ClientType) + err = fmt.Errorf("Unsupported ClientType: %v", h.ClientType) + } + if err != nil { + return err + } + + switch h.ContentType { + case "protobuf": + return nil + case "pql": + return nil + default: + return fmt.Errorf("Unsupported ContentType: %v", h.ContentType) + + } +} + +func (h *HasClient) ExecuteQuery(contentType, db, query string, ctx context.Context) (interface{}, error) { + if contentType == "protobuf" { + return h.client.ExecuteQuery(ctx, db, query, true) + } else if contentType == "pql" { + return h.client.ExecutePQL(ctx, db, query) + } else { + return nil, errors.New("unsupport content type") } } diff --git a/bench/diagonal.go b/bench/diagonal.go index 4cb0e354c..393b732b3 100644 --- a/bench/diagonal.go +++ b/bench/diagonal.go @@ -57,6 +57,8 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + -content-type string + protobuf or pql `[1:] } @@ -71,6 +73,7 @@ func (b *DiagonalSetBits) ConsumeFlags(args []string) ([]string, error) { fs.IntVar(&b.Iterations, "iterations", 100, "") fs.StringVar(&b.DB, "db", "benchdb", "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/bench/multidb.go b/bench/multidb.go index 8ea8cd135..aa275ac17 100644 --- a/bench/multidb.go +++ b/bench/multidb.go @@ -49,6 +49,9 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + -content-type string + protobuf or pql + `[1:] } @@ -62,6 +65,7 @@ func (b *MultiDBSetBits) ConsumeFlags(args []string) ([]string, error) { fs.IntVar(&b.BaseProfileID, "base-profile-id", 0, "") fs.IntVar(&b.Iterations, "iterations", 100, "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/bench/random.go b/bench/random.go index e3e89400c..3bb74e886 100644 --- a/bench/random.go +++ b/bench/random.go @@ -65,6 +65,9 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + + -content-type string + protobuf or pql `[1:] } @@ -82,6 +85,7 @@ func (b *RandomSetBits) ConsumeFlags(args []string) ([]string, error) { fs.IntVar(&b.Iterations, "iterations", 100, "") fs.StringVar(&b.DB, "db", "benchdb", "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/bench/randquery.go b/bench/randquery.go index 11fa7016b..8bdc98e74 100644 --- a/bench/randquery.go +++ b/bench/randquery.go @@ -67,6 +67,9 @@ The following arguments are available: -client-type string Can be 'single' (all agents hitting one host) or 'round_robin' + + -content-type string + protobuf or pql `[1:] } @@ -86,6 +89,7 @@ func (b *RandomQuery) ConsumeFlags(args []string) ([]string, error) { var dbs string fs.StringVar(&dbs, "dbs", "benchdb", "") fs.StringVar(&b.ClientType, "client-type", "single", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err @@ -107,7 +111,7 @@ func (b *RandomQuery) Run(ctx context.Context) map[string]interface{} { for n := 0; n < b.Iterations; n++ { call := qm.Random(b.MaxN, b.MaxDepth, b.MaxArgs, uint64(b.BaseBitmapID), uint64(b.BitmapIDRange)) start = time.Now() - b.client.ExecuteQuery(ctx, b.DBs[n%len(b.DBs)], call.String(), true) + b.ExecuteQuery(b.ContentType, b.DBs[n%len(b.DBs)], call.String(), ctx) s.Add(time.Now().Sub(start)) } AddToResults(s, results) diff --git a/bench/zipf.go b/bench/zipf.go index 274f6f8ae..46832a75f 100644 --- a/bench/zipf.go +++ b/bench/zipf.go @@ -90,6 +90,9 @@ The following arguments are available: -operation string Can be 'set' or 'clear' + + -content-type string + protobuf or pql `[1:] } @@ -112,6 +115,7 @@ func (b *Zipf) ConsumeFlags(args []string) ([]string, error) { fs.Float64Var(&b.ProfileRatio, "profile-ratio", 0.25, "") fs.StringVar(&b.ClientType, "client-type", "single", "") fs.StringVar(&b.Operation, "operation", "set", "") + fs.StringVar(&b.ContentType, "content-type", "protobuf", "") if err := fs.Parse(args); err != nil { return nil, err diff --git a/client.go b/client.go index d26206022..5c24920ff 100644 --- a/client.go +++ b/client.go @@ -194,6 +194,38 @@ func (c *Client) ExecuteQuery(ctx context.Context, db, query string, allowRedire return qresp, nil } +// ExecutePQL executes query string against db on the server. +func (c *Client) ExecutePQL(ctx context.Context, db, query string) (interface{}, error) { + u := url.URL{ + Scheme: "http", + Host: c.host, + Path: "/query", + RawQuery: url.Values{ + "db": {db}, + }.Encode(), + } + + req, err := http.NewRequest("POST", u.String(), bytes.NewReader([]byte(query))) + if err != nil { + return nil, err + } + resp, err := c.HTTPClient.Do(req.WithContext(ctx)) + + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } else if resp.StatusCode != http.StatusOK { + return nil, errors.New(string(body)) + } + return string(body), nil + +} + // Import bulk imports bits for a single slice to a host. func (c *Client) Import(ctx context.Context, db, frame string, slice uint64, bits []Bit) error { if db == "" {