func (this *Server) getPrepared(request Request, namespace string) (*plan.Prepared, errors.Error) { prepared := request.Prepared() if prepared == nil { parse := time.Now() stmt, err := n1ql.ParseStatement(request.Statement()) if err != nil { return nil, errors.NewParseSyntaxError(err, "") } prep := time.Now() prepared, err = planner.BuildPrepared(stmt, this.datastore, this.systemstore, namespace, false) if err != nil { return nil, errors.NewPlanError(err, "") } if logging.LogLevel() >= logging.TRACE { request.Output().AddPhaseTime("plan", time.Since(prep)) request.Output().AddPhaseTime("parse", prep.Sub(parse)) } } if logging.LogLevel() >= logging.DEBUG { // log EXPLAIN for the request logExplain(prepared) } return prepared, nil }
func NewServer(store datastore.Datastore, config clustering.ConfigurationStore, acctng accounting.AccountingStore, namespace string, readonly bool, channel, plusChannel RequestChannel, servicers, plusServicers, maxParallelism int, timeout time.Duration, signature, metrics bool, enterprise bool) (*Server, errors.Error) { rv := &Server{ datastore: store, configstore: config, acctstore: acctng, namespace: namespace, readonly: readonly, channel: channel, plusChannel: plusChannel, signature: signature, timeout: timeout, metrics: metrics, done: make(chan bool), plusDone: make(chan bool), enterprise: enterprise, } // special case handling for the atomic specfic stuff atomic.StoreInt64(&rv.servicers, int64(servicers)) atomic.StoreInt64(&rv.plusServicers, int64(plusServicers)) store.SetLogLevel(logging.LogLevel()) rv.SetMaxParallelism(maxParallelism) sys, err := system.NewDatastore(store) if err != nil { return nil, err } rv.systemstore = sys return rv, nil }
func (this *Server) getPrepared(request Request, namespace string) (*plan.Prepared, errors.Error) { prepared := request.Prepared() if prepared == nil { parse := time.Now() stmt, err := n1ql.ParseStatement(request.Statement()) if err != nil { return nil, errors.NewParseSyntaxError(err, "") } prep := time.Now() prepared, err = planner.BuildPrepared(stmt, this.datastore, this.systemstore, namespace, false) if err != nil { return nil, errors.NewPlanError(err, "") } // In order to allow monitoring to track prepared statement executed through // N1QL "EXECUTE", set request.prepared - because, as of yet, it isn't! // // HACK ALERT - request does not currently track the request type // and even if it did, and prepared.(*plan.Prepared) is set, it // does not carry a name or text. // This should probably done in build.go and / or build_execute.go, // but for now this will do. exec, ok := stmt.(*algebra.Execute) if ok && exec.Prepared() != nil { prep, _ := plan.TrackPrepared(exec.Prepared()) request.SetPrepared(prep) } if logging.LogLevel() >= logging.TRACE { request.Output().AddPhaseTime("plan", time.Since(prep)) request.Output().AddPhaseTime("parse", prep.Sub(parse)) } } if logging.LogLevel() >= logging.DEBUG { // log EXPLAIN for the request logExplain(prepared) } return prepared, nil }
func NewBaseRequest(statement string, prepared *plan.Prepared, namedArgs map[string]value.Value, positionalArgs value.Values, namespace string, maxParallelism int, readonly, metrics, signature value.Tristate, consistency ScanConfiguration, client_id string, creds datastore.Credentials) *BaseRequest { rv := &BaseRequest{ statement: statement, prepared: prepared, namedArgs: namedArgs, positionalArgs: positionalArgs, namespace: namespace, maxParallelism: maxParallelism, readonly: readonly, signature: signature, metrics: metrics, consistency: consistency, credentials: creds, requestTime: time.Now(), serviceTime: time.Now(), state: RUNNING, errors: make(errors.ErrorChannel, _ERROR_CAP), warnings: make(errors.ErrorChannel, _ERROR_CAP), closeNotify: make(chan bool, 1), stopResult: make(chan bool, 1), stopExecute: make(chan bool, 1), } if maxParallelism <= 0 { maxParallelism = runtime.NumCPU() } rv.results = make(value.ValueChannel, maxParallelism) if logging.LogLevel() >= logging.TRACE { rv.phaseTimes = make(map[string]time.Duration, 8) } uuid, _ := util.UUID() rv.id = &requestIDImpl{id: uuid} rv.client_id = newClientContextIDImpl(client_id) return rv }
func (this *Server) serviceRequest(request Request) { defer func() { err := recover() if err != nil { buf := make([]byte, 1<<16) n := runtime.Stack(buf, false) s := string(buf[0:n]) logging.Severep("", logging.Pair{"panic", err}, logging.Pair{"stack", s}) os.Stderr.WriteString(s) os.Stderr.Sync() } }() request.Servicing() namespace := request.Namespace() if namespace == "" { namespace = this.namespace } prepared, err := this.getPrepared(request, namespace) if err != nil { request.Fail(err) } if (this.readonly || value.ToBool(request.Readonly())) && (prepared != nil && !prepared.Readonly()) { request.Fail(errors.NewServiceErrorReadonly("The server or request is read-only" + " and cannot accept this write statement.")) } if request.State() == FATAL { request.Failed(this) return } maxParallelism := request.MaxParallelism() if maxParallelism <= 0 { maxParallelism = this.MaxParallelism() } context := execution.NewContext(request.Id().String(), this.datastore, this.systemstore, namespace, this.readonly, maxParallelism, request.NamedArgs(), request.PositionalArgs(), request.Credentials(), request.ScanConsistency(), request.ScanVectorSource(), request.Output()) build := time.Now() operator, er := execution.Build(prepared, context) if er != nil { error, ok := er.(errors.Error) if ok { request.Fail(error) } else { request.Fail(errors.NewError(er, "")) } } if logging.LogLevel() >= logging.TRACE { request.Output().AddPhaseTime("instantiate", time.Since(build)) } if request.State() == FATAL { request.Failed(this) return } // Apply server execution timeout if this.Timeout() > 0 { timer := time.AfterFunc(this.Timeout(), func() { request.Expire() }) defer timer.Stop() } go request.Execute(this, prepared.Signature(), operator.StopChannel()) run := time.Now() operator.RunOnce(context, nil) if logging.LogLevel() >= logging.TRACE { request.Output().AddPhaseTime("run", time.Since(run)) logPhases(request) } }
func (this *Server) LogLevel() string { return logging.LogLevel().String() }
func (this *Server) Debug() bool { return logging.LogLevel() == logging.DEBUG }
func main() { HideConsole(true) defer HideConsole(false) // useful for getting list of go-routines go go_http.ListenAndServe("localhost:6060", nil) flag.Parse() if *LOGGER != "" { logger, _ := log_resolver.NewLogger(*LOGGER) if logger == nil { fmt.Printf("Invalid logger: %s\n", *LOGGER) os.Exit(1) } logging.SetLogger(logger) } if *DEBUG { logging.SetLevel(logging.DEBUG) } else { level := logging.INFO if *LOG_LEVEL != "" { lvl, ok := logging.ParseLevel(*LOG_LEVEL) if ok { level = lvl } } logging.SetLevel(level) } datastore, err := resolver.NewDatastore(*DATASTORE) if err != nil { logging.Errorp(err.Error()) os.Exit(1) } datastore_package.SetDatastore(datastore) configstore, err := config_resolver.NewConfigstore(*CONFIGSTORE) if err != nil { logging.Errorp("Could not connect to configstore", logging.Pair{"error", err}, ) } acctstore, err := acct_resolver.NewAcctstore(*ACCTSTORE) if err != nil { logging.Errorp("Could not connect to acctstore", logging.Pair{"error", err}, ) } else { // Create the metrics we are interested in accounting.RegisterMetrics(acctstore) // Make metrics available acctstore.MetricReporter().Start(1, 1) } channel := make(server.RequestChannel, *REQUEST_CAP) plusChannel := make(server.RequestChannel, *REQUEST_CAP) sys, err := system.NewDatastore(datastore) if err != nil { logging.Errorp(err.Error()) os.Exit(1) } server, err := server.NewServer(datastore, sys, configstore, acctstore, *NAMESPACE, *READONLY, channel, plusChannel, *SERVICERS, *PLUS_SERVICERS, *MAX_PARALLELISM, *TIMEOUT, *SIGNATURE, *METRICS, *ENTERPRISE) if err != nil { logging.Errorp(err.Error()) os.Exit(1) } datastore_package.SetSystemstore(server.Systemstore()) server.SetCpuProfile(*CPU_PROFILE) server.SetKeepAlive(*KEEP_ALIVE_LENGTH) server.SetMemProfile(*MEM_PROFILE) server.SetPipelineCap(*PIPELINE_CAP) server.SetPipelineBatch(*PIPELINE_BATCH) server.SetRequestSizeCap(*REQUEST_SIZE_CAP) server.SetScanCap(*SCAN_CAP) if server.Enterprise() && os.Getenv("GOMAXPROCS") == "" { runtime.GOMAXPROCS(runtime.NumCPU()) } if !server.Enterprise() { var numCPU int if os.Getenv("GOMAXPROCS") == "" { numCPU = runtime.NumCPU() } else { numCPU = runtime.GOMAXPROCS(0) } // Use at most 4 cpus in non-enterprise mode runtime.GOMAXPROCS(util.MinInt(numCPU, 4)) } go server.Serve() go server.PlusServe() logging.Infop("cbq-engine started", logging.Pair{"version", util.VERSION}, logging.Pair{"datastore", *DATASTORE}, logging.Pair{"max-concurrency", runtime.GOMAXPROCS(0)}, logging.Pair{"loglevel", logging.LogLevel().String()}, logging.Pair{"servicers", server.Servicers()}, logging.Pair{"plus-servicers", server.PlusServicers()}, logging.Pair{"pipeline-cap", server.PipelineCap()}, logging.Pair{"pipeline-batch", *PIPELINE_BATCH}, logging.Pair{"request-cap", *REQUEST_CAP}, logging.Pair{"request-size-cap", server.RequestSizeCap()}, logging.Pair{"timeout", server.Timeout()}, ) // Create http endpoint endpoint := http.NewServiceEndpoint(server, *STATIC_PATH, *METRICS, *HTTP_ADDR, *HTTPS_ADDR, *CERT_FILE, *KEY_FILE) er := endpoint.Listen() if er != nil { logging.Errorp("cbq-engine exiting with error", logging.Pair{"error", er}, logging.Pair{"HTTP_ADDR", *HTTP_ADDR}, ) os.Exit(1) } if server.Enterprise() && *CERT_FILE != "" && *KEY_FILE != "" { er := endpoint.ListenTLS() if er != nil { logging.Errorp("cbq-engine exiting with error", logging.Pair{"error", er}, logging.Pair{"HTTPS_ADDR", *HTTPS_ADDR}, ) os.Exit(1) } } signalCatcher(server, endpoint) }