Ejemplo n.º 1
0
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
}
Ejemplo n.º 2
0
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
}
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
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
}
Ejemplo n.º 5
0
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)
	}
}
Ejemplo n.º 6
0
func (this *Server) LogLevel() string {
	return logging.LogLevel().String()
}
Ejemplo n.º 7
0
func (this *Server) Debug() bool {
	return logging.LogLevel() == logging.DEBUG
}
Ejemplo n.º 8
0
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)
}