// executeCmd interprets the given message as a *roachpb.BatchRequest and sends it // via the local sender. func (n *Node) executeCmd(argsI proto.Message) (proto.Message, error) { ba := argsI.(*roachpb.BatchRequest) var br *roachpb.BatchResponse opName := "node " + strconv.Itoa(int(n.Descriptor.NodeID)) // could save allocs here fail := func(err error) { br = &roachpb.BatchResponse{} br.Error = roachpb.NewError(err) } f := func() { sp, err := tracing.JoinOrNew(n.ctx.Tracer, ba.Trace, opName) if err != nil { fail(err) return } // If this is a snowball span, it gets special treatment: It skips the // regular tracing machinery, and we instead send the collected spans // back with the response. This is more expensive, but then again, // those are individual requests traced by users, so they can be. if sp.BaggageItem(tracing.Snowball) != "" { if sp, err = tracing.JoinOrNewSnowball(opName, ba.Trace, func(rawSpan basictracer.RawSpan) { encSp, err := tracing.EncodeRawSpan(&rawSpan, nil) if err != nil { log.Warning(err) } br.CollectedSpans = append(br.CollectedSpans, encSp) }); err != nil { fail(err) return } } defer sp.Finish() ctx := opentracing.ContextWithSpan((*Node)(n).context(), sp) tStart := time.Now() var pErr *roachpb.Error br, pErr = n.stores.Send(ctx, *ba) if pErr != nil { br = &roachpb.BatchResponse{} sp.LogEvent(fmt.Sprintf("error: %T", pErr.GetDetail())) } if br.Error != nil { panic(roachpb.ErrorUnexpectedlySet(n.stores, br)) } n.metrics.callComplete(time.Now().Sub(tStart), pErr) br.Error = pErr } if !n.stopper.RunTask(f) { return nil, util.Errorf("node %d stopped", n.Descriptor.NodeID) } return br, nil }
// reset creates a new Txn and initializes it using the session defaults. func (ts *txnState) reset(ctx context.Context, e *Executor, s *Session) { *ts = txnState{} ts.txn = client.NewTxn(ctx, *e.ctx.DB) ts.txn.Context = s.context ts.txn.Proto.Isolation = s.DefaultIsolationLevel ts.tr = s.Trace // Discard the old schemaChangers, if any. ts.schemaChangers = schemaChangerCollection{} if traceSQL { sp, err := tracing.JoinOrNewSnowball("coordinator", nil, func(sp basictracer.RawSpan) { ts.txn.CollectedSpans = append(ts.txn.CollectedSpans, sp) }) if err != nil { log.Warningf(ctx, "unable to create snowball tracer: %s", err) return } ts.txn.Context = opentracing.ContextWithSpan(ts.txn.Context, sp) ts.sp = sp } }
// Batch implements the roachpb.KVServer interface. func (n *Node) Batch(ctx context.Context, args *roachpb.BatchRequest) (*roachpb.BatchResponse, error) { // TODO(marc): this code is duplicated in kv/db.go, which should be fixed. // Also, grpc's authentication model (which gives credential access in the // request handler) doesn't really fit with the current design of the // security package (which assumes that TLS state is only given at connection // time) - that should be fixed. if peer, ok := peer.FromContext(ctx); ok { if tlsInfo, ok := peer.AuthInfo.(credentials.TLSInfo); ok { certUser, err := security.GetCertificateUser(&tlsInfo.State) if err != nil { return nil, err } if certUser != security.NodeUser { return nil, util.Errorf("user %s is not allowed", certUser) } } } var br *roachpb.BatchResponse opName := "node " + strconv.Itoa(int(n.Descriptor.NodeID)) // could save allocs here fail := func(err error) { br = &roachpb.BatchResponse{} br.Error = roachpb.NewError(err) } f := func() { sp, err := tracing.JoinOrNew(n.ctx.Tracer, args.Trace, opName) if err != nil { fail(err) return } // If this is a snowball span, it gets special treatment: It skips the // regular tracing machinery, and we instead send the collected spans // back with the response. This is more expensive, but then again, // those are individual requests traced by users, so they can be. if sp.BaggageItem(tracing.Snowball) != "" { sp.LogEvent("delegating to snowball tracing") sp.Finish() if sp, err = tracing.JoinOrNewSnowball(opName, args.Trace, func(rawSpan basictracer.RawSpan) { encSp, err := tracing.EncodeRawSpan(&rawSpan, nil) if err != nil { log.Warning(err) } br.CollectedSpans = append(br.CollectedSpans, encSp) }); err != nil { fail(err) return } } defer sp.Finish() traceCtx := opentracing.ContextWithSpan(n.context(ctx), sp) tStart := timeutil.Now() var pErr *roachpb.Error br, pErr = n.stores.Send(traceCtx, *args) if pErr != nil { br = &roachpb.BatchResponse{} log.Trace(traceCtx, fmt.Sprintf("error: %T", pErr.GetDetail())) } if br.Error != nil { panic(roachpb.ErrorUnexpectedlySet(n.stores, br)) } n.metrics.callComplete(timeutil.Since(tStart), pErr) br.Error = pErr } if !n.stopper.RunTask(f) { return nil, util.Errorf("node %d stopped", n.Descriptor.NodeID) } return br, nil }
// Explain executes the explain statement, providing debugging and analysis // info about a DELETE, INSERT, SELECT or UPDATE statement. // // Privileges: the same privileges as the statement being explained. func (p *planner) Explain(n *parser.Explain) (planNode, *roachpb.Error) { mode := explainNone if len(n.Options) == 1 { if strings.EqualFold(n.Options[0], "DEBUG") { mode = explainDebug } else if strings.EqualFold(n.Options[0], "TRACE") { mode = explainTrace } } else if len(n.Options) == 0 { mode = explainPlan } if mode == explainNone { return nil, roachpb.NewUErrorf("unsupported EXPLAIN options: %s", n) } if mode == explainTrace { var err error if p.txn.Trace, err = tracing.JoinOrNewSnowball("coordinator", nil, func(sp basictracer.RawSpan) { p.txn.CollectedSpans = append(p.txn.CollectedSpans, sp) }); err != nil { return nil, roachpb.NewError(err) } } plan, err := p.makePlan(n.Statement, false) if err != nil { return nil, err } switch mode { case explainDebug: plan, err = markDebug(plan, mode) if err != nil { return nil, roachpb.NewUErrorf("%v: %s", err, n) } // Wrap the plan in an explainDebugNode. return &explainDebugNode{plan}, nil case explainPlan: v := &valuesNode{} v.columns = []ResultColumn{ {Name: "Level", Typ: parser.DummyInt}, {Name: "Type", Typ: parser.DummyString}, {Name: "Description", Typ: parser.DummyString}, } populateExplain(v, plan, 0) return v, nil case explainTrace: plan, err = markDebug(plan, explainDebug) if err != nil { return nil, roachpb.NewUErrorf("%v: %s", err, n) } return (&sortNode{ ordering: []columnOrderInfo{{0, encoding.Ascending}, {1, encoding.Ascending}}, columns: traceColumns, }).wrap(&explainTraceNode{plan: plan, txn: p.txn}), nil default: return nil, roachpb.NewUErrorf("unsupported EXPLAIN mode: %d", mode) } }