func (this *InterpretedExecutor) executeInternal(optimalPlan *plan.Plan, q network.Query, timeoutStopChannel misc.StopChannel) { clog.To(executor.CHANNEL, "simple executor started") // first make the plan excutable executablePipeline, berr := this.xpipelinebuilder.Build(optimalPlan, q) if berr != nil { q.Response().SendError(query.NewError(berr, "")) return } root := executablePipeline.Root // create a stop channel stopChannel := make(misc.StopChannel) // set it on the query object, so HTTP layer can // stop us if the client goes away q.SetStopChannel(stopChannel) go root.Run(stopChannel) // now execute it var item *dparval.Value var obj interface{} sourceItemChannel, supportChannel := root.GetChannels() ok := true for ok { select { case item, ok = <-sourceItemChannel: if ok { ok = this.processItem(q, item) clog.To(executor.CHANNEL, "simple executor sent client item: %v", item) } case obj, ok = <-supportChannel: if ok { switch obj := obj.(type) { case query.Error: q.Response().SendError(obj) clog.To(executor.CHANNEL, "simple executor sent client error: %v", obj) if obj.IsFatal() { return } } } case _, ok = <-timeoutStopChannel: clog.To(executor.CHANNEL, "simple execution aborted, timeout") return } } q.Response().NoMoreResults() clog.To(executor.CHANNEL, "simple executor finished") }