// Distributes the query across the cluster and combines the results. Yields as they come in ensuring proper order. // TODO: make this work even if there is a downed server in the cluster func (self *CoordinatorImpl) DistributeQuery(user common.User, db string, query *parser.SelectQuery, localOnly bool, yield func(*protocol.Series) error) error { if self.clusterConfiguration.IsSingleServer() || localOnly { return self.datastore.ExecuteQuery(user, db, query, yield, nil) } servers, replicationFactor := self.clusterConfiguration.GetServersToMakeQueryTo(&db) id := atomic.AddUint32(&self.requestId, uint32(1)) userName := user.GetName() isDbUser := !user.IsClusterAdmin() responseChannels := make([]chan *protocol.Response, 0, len(servers)+1) queryString := query.GetQueryString() var localServerToQuery *serverToQuery for _, server := range servers { if server.server.Id == self.clusterConfiguration.localServerId { localServerToQuery = server } else { request := &protocol.Request{Type: &queryRequest, Query: &queryString, Id: &id, Database: &db, UserName: &userName, IsDbUser: &isDbUser} if server.ringLocationsToQuery != replicationFactor { r := server.ringLocationsToQuery request.RingLocationsToQuery = &r } responseChan := make(chan *protocol.Response, 3) server.server.MakeRequest(request, responseChan) responseChannels = append(responseChannels, responseChan) } } local := make(chan *protocol.Response) nextPointMap := make(map[string]*NextPoint) // TODO: this style of wrapping the series in response objects with the // last point time is duplicated in the request handler. Refactor... sendFromLocal := func(series *protocol.Series) error { response := createResponse(nextPointMap, series, nil) local <- response return nil } responseChannels = append(responseChannels, local) // TODO: wire up the willreturnsingleseries method and uncomment this line and delete the next one. // isSingleSeriesQuery := query.WillReturnSingleSeries() isSingleSeriesQuery := false go func() { var ringFilter func(database, series *string, time *int64) bool if replicationFactor != localServerToQuery.ringLocationsToQuery { ringFilter = self.clusterConfiguration.GetRingFilterFunction(db, localServerToQuery.ringLocationsToQuery) } self.datastore.ExecuteQuery(user, db, query, sendFromLocal, ringFilter) local <- &protocol.Response{Type: &endStreamResponse} close(local) }() self.streamResultsFromChannels(isSingleSeriesQuery, query.Ascending, responseChannels, yield) return nil }
func (s *RaftServer) runContinuousQuery(db string, query *parser.SelectQuery, start time.Time, end time.Time) { adminName := s.clusterConfig.GetClusterAdmins()[0] clusterAdmin := s.clusterConfig.GetClusterAdmin(adminName) intoClause := query.GetIntoClause() targetName := intoClause.Target.Name queryString := query.GetQueryStringWithTimesAndNoIntoClause(start, end) f := func(series *protocol.Series) error { return s.coordinator.InterpolateValuesAndCommit(query.GetQueryString(), db, series, targetName, true) } writer := NewContinuousQueryWriter(f) s.coordinator.RunQuery(clusterAdmin, db, queryString, writer) }
// Distributes the query across the cluster and combines the results. Yields as they come in ensuring proper order. // TODO: make this work even if there is a downed server in the cluster func (self *CoordinatorImpl) DistributeQuery(user common.User, db string, query *parser.SelectQuery, yield func(*protocol.Series) error) error { if self.clusterConfiguration.IsSingleServer() { return self.datastore.ExecuteQuery(user, db, query, yield, nil) } servers, replicationFactor := self.clusterConfiguration.GetServersToMakeQueryTo(self.localHostId, &db) queryString := query.GetQueryString() id := atomic.AddUint32(&self.requestId, uint32(1)) userName := user.GetName() responseChannels := make([]chan *protocol.Response, 0, len(servers)+1) var localServerToQuery *serverToQuery for _, server := range servers { if server.server.Id == self.localHostId { localServerToQuery = server } else { request := &protocol.Request{Type: &queryRequest, Query: &queryString, Id: &id, Database: &db, UserName: &userName} if server.ringLocationsToQuery != replicationFactor { r := server.ringLocationsToQuery request.RingLocationsToQuery = &r } responseChan := make(chan *protocol.Response, 3) server.server.protobufClient.MakeRequest(request, responseChan) responseChannels = append(responseChannels, responseChan) } } local := make(chan *protocol.Response) nextPointMap := make(map[string]*protocol.Point) // TODO: this style of wrapping the series in response objects with the // last point time is duplicated in the request handler. Refactor... sendFromLocal := func(series *protocol.Series) error { pointCount := len(series.Points) if pointCount == 0 { if nextPoint := nextPointMap[*series.Name]; nextPoint != nil { series.Points = append(series.Points, nextPoint) } local <- &protocol.Response{Type: &queryResponse, Series: series} return nil } oldNextPoint := nextPointMap[*series.Name] nextPoint := series.Points[pointCount-1] series.Points[pointCount-1] = nil if oldNextPoint != nil { copy(series.Points[1:], series.Points[0:]) series.Points[0] = oldNextPoint } else { series.Points = series.Points[:len(series.Points)-1] } response := &protocol.Response{Series: series, Type: &queryResponse} if nextPoint != nil { nextPointMap[*series.Name] = nextPoint response.NextPointTime = nextPoint.Timestamp } local <- response return nil } responseChannels = append(responseChannels, local) // TODO: wire up the willreturnsingleseries method and uncomment this line and delete the next one. // isSingleSeriesQuery := query.WillReturnSingleSeries() isSingleSeriesQuery := false go func() { var ringFilter func(database, series *string, time *int64) bool if replicationFactor != localServerToQuery.ringLocationsToQuery { ringFilter = self.clusterConfiguration.GetRingFilterFunction(db, localServerToQuery.ringLocationsToQuery) } self.datastore.ExecuteQuery(user, db, query, sendFromLocal, ringFilter) local <- &protocol.Response{Type: &endStreamResponse} close(local) }() self.streamResultsFromChannels(isSingleSeriesQuery, query.Ascending, responseChannels, yield) return nil }