/* * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.siddhi.core.query; import org.wso2.siddhi.core.config.ExecutionPlanContext; import org.wso2.siddhi.core.event.MetaComplexEvent; import org.wso2.siddhi.core.query.input.stream.StreamRuntime; import org.wso2.siddhi.core.query.output.callback.OutputCallback; import org.wso2.siddhi.core.query.output.callback.QueryCallback; import org.wso2.siddhi.core.query.output.ratelimit.OutputRateLimiter; import org.wso2.siddhi.core.query.selector.QuerySelector; import org.wso2.siddhi.core.stream.StreamJunction; import org.wso2.siddhi.core.util.lock.LockWrapper; import org.wso2.siddhi.core.util.parser.OutputParser; import org.wso2.siddhi.core.util.parser.helper.QueryParserHelper; import org.wso2.siddhi.query.api.annotation.Element; import org.wso2.siddhi.query.api.definition.StreamDefinition; import org.wso2.siddhi.query.api.exception.DuplicateAnnotationException; import org.wso2.siddhi.query.api.execution.query.Query; import org.wso2.siddhi.query.api.execution.query.input.stream.JoinInputStream; import org.wso2.siddhi.query.api.execution.query.input.stream.SingleInputStream; import org.wso2.siddhi.query.api.execution.query.input.stream.StateInputStream; import org.wso2.siddhi.query.api.util.AnnotationHelper; import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.ReentrantLock; /** * Query Runtime represent holder object for a single Siddhi query and holds all runtime objects related to that query. */ public class QueryRuntime { private final ExecutionPlanContext executionPlanContext; private StreamRuntime streamRuntime; private OutputRateLimiter outputRateLimiter; private String queryId; private Query query; private OutputCallback outputCallback; private boolean synchronised; private StreamDefinition outputStreamDefinition; private boolean toLocalStream; private QuerySelector selector; private MetaComplexEvent metaComplexEvent; public QueryRuntime(Query query, ExecutionPlanContext executionPlanContext, StreamRuntime streamRuntime, QuerySelector selector, OutputRateLimiter outputRateLimiter, OutputCallback outputCallback, MetaComplexEvent metaComplexEvent, boolean synchronised) { this.query = query; this.executionPlanContext = executionPlanContext; this.streamRuntime = streamRuntime; this.selector = selector; this.outputCallback = outputCallback; this.synchronised = synchronised; outputRateLimiter.setOutputCallback(outputCallback); setOutputRateLimiter(outputRateLimiter); setMetaComplexEvent(metaComplexEvent); setId(); init(); } private void setId() { try { Element element = AnnotationHelper.getAnnotationElement("info", "name", query.getAnnotations()); if (element != null) { queryId = element.getValue(); } } catch (DuplicateAnnotationException e) { throw new DuplicateAnnotationException(e.getMessage() + " for the same Query " + query.toString()); } if (queryId == null) { queryId = UUID.randomUUID().toString(); } } public String getQueryId() { return queryId; } public void addCallback(QueryCallback callback) { outputRateLimiter.addQueryCallback(callback); } public OutputRateLimiter getOutputRateManager() { return outputRateLimiter; } public StreamDefinition getOutputStreamDefinition() { return outputStreamDefinition; } public List<String> getInputStreamId() { return query.getInputStream().getAllStreamIds(); } public boolean isToLocalStream() { return toLocalStream; } public void setToLocalStream(boolean toLocalStream) { this.toLocalStream = toLocalStream; } public boolean isFromLocalStream() { if (query.getInputStream() instanceof SingleInputStream) { return ((SingleInputStream) query.getInputStream()).isInnerStream(); } else if (query.getInputStream() instanceof JoinInputStream) { return ((SingleInputStream) ((JoinInputStream) query.getInputStream()).getLeftInputStream()) .isInnerStream() || ((SingleInputStream) ((JoinInputStream) query.getInputStream()) .getRightInputStream()).isInnerStream(); } else if (query.getInputStream() instanceof StateInputStream) { for (String streamId : query.getInputStream().getAllStreamIds()) { if (streamId.startsWith("#")) { return true; } } } return false; } public QueryRuntime clone(String key, ConcurrentMap<String, StreamJunction> localStreamJunctionMap) { LockWrapper lockWrapper = null; if (synchronised) { lockWrapper = new LockWrapper(""); lockWrapper.setLock(new ReentrantLock()); } StreamRuntime clonedStreamRuntime = this.streamRuntime.clone(key); QuerySelector clonedSelector = this.selector.clone(key); OutputRateLimiter clonedOutputRateLimiter = outputRateLimiter.clone(key); clonedOutputRateLimiter.init(executionPlanContext, lockWrapper, queryId); QueryRuntime queryRuntime = new QueryRuntime(query, executionPlanContext, clonedStreamRuntime, clonedSelector, clonedOutputRateLimiter, outputCallback, this.metaComplexEvent, synchronised); QueryParserHelper.initStreamRuntime(clonedStreamRuntime, metaComplexEvent, lockWrapper, queryId); queryRuntime.queryId = this.queryId + key; queryRuntime.setToLocalStream(toLocalStream); if (!toLocalStream) { queryRuntime.outputRateLimiter.setOutputCallback(outputCallback); queryRuntime.outputCallback = this.outputCallback; } else { OutputCallback clonedQueryOutputCallback = OutputParser.constructOutputCallback(query.getOutputStream(), key, localStreamJunctionMap, outputStreamDefinition, executionPlanContext, queryId); queryRuntime.outputRateLimiter.setOutputCallback(clonedQueryOutputCallback); queryRuntime.outputCallback = clonedQueryOutputCallback; } return queryRuntime; } private void setOutputRateLimiter(OutputRateLimiter outputRateLimiter) { this.outputRateLimiter = outputRateLimiter; selector.setNextProcessor(outputRateLimiter); } public StreamRuntime getStreamRuntime() { return streamRuntime; } public MetaComplexEvent getMetaComplexEvent() { return metaComplexEvent; } private void setMetaComplexEvent(MetaComplexEvent metaComplexEvent) { outputStreamDefinition = metaComplexEvent.getOutputStreamDefinition(); this.metaComplexEvent = metaComplexEvent; } public Query getQuery() { return query; } public OutputCallback getOutputCallback() { return outputCallback; } public void init() { streamRuntime.setCommonProcessor(selector); } public QuerySelector getSelector() { return selector; } }