github.com/m3db/m3@v1.5.0/src/query/executor/request.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package executor 22 23 import ( 24 "context" 25 "fmt" 26 27 "github.com/m3db/m3/src/query/models" 28 "github.com/m3db/m3/src/query/parser" 29 "github.com/m3db/m3/src/query/plan" 30 "github.com/m3db/m3/src/query/storage" 31 "github.com/m3db/m3/src/query/util/logging" 32 "github.com/m3db/m3/src/x/instrument" 33 "github.com/m3db/m3/src/x/opentracing" 34 35 "go.uber.org/zap" 36 ) 37 38 // State is the request state. 39 type State int 40 41 const ( 42 compiling State = iota 43 planning 44 executing 45 all 46 ) 47 48 func (s State) String() string { 49 switch s { 50 case compiling: 51 return "compiling" 52 case planning: 53 return "planning" 54 case executing: 55 return "executing" 56 case all: 57 return "all" 58 default: 59 return "unknown" 60 } 61 } 62 63 func (s State) durationString() string { 64 return fmt.Sprintf("%s_duration_seconds", s) 65 } 66 67 // Request represents a single request. 68 type Request struct { 69 engine *engine 70 params models.RequestParams 71 fetchOpts *storage.FetchOptions 72 instrumentOpts instrument.Options 73 } 74 75 func newRequest( 76 engine *engine, 77 params models.RequestParams, 78 fetchOpts *storage.FetchOptions, 79 instrumentOpts instrument.Options, 80 ) *Request { 81 return &Request{ 82 engine: engine, 83 params: params, 84 fetchOpts: fetchOpts, 85 instrumentOpts: instrumentOpts, 86 } 87 } 88 89 func (r *Request) compile(ctx context.Context, parser parser.Parser) (parser.Nodes, parser.Edges, error) { 90 sp, ctx := opentracing.StartSpanFromContext(ctx, "compile") 91 defer sp.Finish() 92 // TODO: Change DAG interface to take in a context 93 nodes, edges, err := parser.DAG() 94 if err != nil { 95 return nil, nil, err 96 } 97 98 if r.params.Debug { 99 logging.WithContext(ctx, r.instrumentOpts). 100 Info("compiling dag", zap.Any("nodes", nodes), zap.Any("edges", edges)) 101 } 102 103 return nodes, edges, nil 104 } 105 106 func (r *Request) plan(ctx context.Context, nodes parser.Nodes, edges parser.Edges) (plan.PhysicalPlan, error) { 107 sp, ctx := opentracing.StartSpanFromContext(ctx, "plan") 108 defer sp.Finish() 109 110 lp, err := plan.NewLogicalPlan(nodes, edges) 111 if err != nil { 112 return plan.PhysicalPlan{}, err 113 } 114 115 if r.params.Debug { 116 logging.WithContext(ctx, r.instrumentOpts). 117 Info("logical plan", zap.String("plan", lp.String())) 118 } 119 120 pp, err := plan.NewPhysicalPlan(lp, r.params) 121 if err != nil { 122 return plan.PhysicalPlan{}, err 123 } 124 125 if r.params.Debug { 126 logging.WithContext(ctx, r.instrumentOpts). 127 Info("physical plan", zap.String("plan", pp.String())) 128 } 129 130 return pp, nil 131 } 132 133 func (r *Request) generateExecutionState(ctx context.Context, pp plan.PhysicalPlan) (*ExecutionState, error) { 134 sp, ctx := opentracing.StartSpanFromContext(ctx, 135 "generate_execution_state") 136 defer sp.Finish() 137 138 state, err := GenerateExecutionState(pp, r.engine.opts.Store(), 139 r.fetchOpts, r.instrumentOpts) 140 // free up resources 141 if err != nil { 142 return nil, err 143 } 144 145 if r.params.Debug { 146 logging.WithContext(ctx, r.instrumentOpts). 147 Info("execution state", zap.String("state", state.String())) 148 } 149 150 return state, nil 151 }