/*
* 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.output.ratelimit.event;
import org.wso2.siddhi.core.event.ComplexEvent;
import org.wso2.siddhi.core.event.ComplexEventChunk;
import org.wso2.siddhi.core.event.GroupedComplexEvent;
import org.wso2.siddhi.core.query.output.ratelimit.OutputRateLimiter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementation of {@link OutputRateLimiter} which will collect pre-defined number of events and the emit only the
* first event. This implementation specifically handle queries with group by.
*/
public class FirstGroupByPerEventOutputRateLimiter extends OutputRateLimiter {
private final Integer value;
List<String> groupByKeys = new ArrayList<String>();
private String id;
private ComplexEventChunk<ComplexEvent> allComplexEventChunk;
private volatile int counter = 0;
public FirstGroupByPerEventOutputRateLimiter(String id, Integer value) {
this.id = id;
this.value = value;
allComplexEventChunk = new ComplexEventChunk<ComplexEvent>(false);
}
@Override
public OutputRateLimiter clone(String key) {
FirstGroupByPerEventOutputRateLimiter instance = new FirstGroupByPerEventOutputRateLimiter(id + key, value);
instance.setLatencyTracker(latencyTracker);
return instance;
}
@Override
public void process(ComplexEventChunk complexEventChunk) {
complexEventChunk.reset();
ArrayList<ComplexEventChunk<ComplexEvent>> outputEventChunks = new ArrayList<ComplexEventChunk<ComplexEvent>>();
synchronized (this) {
while (complexEventChunk.hasNext()) {
ComplexEvent event = complexEventChunk.next();
if (event.getType() == ComplexEvent.Type.CURRENT || event.getType() == ComplexEvent.Type.EXPIRED) {
complexEventChunk.remove();
GroupedComplexEvent groupedComplexEvent = ((GroupedComplexEvent) event);
if (!groupByKeys.contains(groupedComplexEvent.getGroupKey())) {
groupByKeys.add(groupedComplexEvent.getGroupKey());
allComplexEventChunk.add(groupedComplexEvent.getComplexEvent());
}
if (++counter == value) {
if (allComplexEventChunk.getFirst() != null) {
ComplexEventChunk<ComplexEvent> outputEventChunk = new ComplexEventChunk<ComplexEvent>
(complexEventChunk.isBatch());
outputEventChunk.add(allComplexEventChunk.getFirst());
outputEventChunks.add(outputEventChunk);
allComplexEventChunk.clear();
counter = 0;
groupByKeys.clear();
} else {
counter = 0;
groupByKeys.clear();
}
}
}
}
}
for (ComplexEventChunk eventChunk : outputEventChunks) {
sendToCallBacks(eventChunk);
}
}
@Override
public void start() {
//Nothing to start
}
@Override
public void stop() {
//Nothing to stop
}
@Override
public Map<String, Object> currentState() {
Map<String, Object> state = new HashMap<>();
state.put("Counter", counter);
state.put("GroupByKeys", groupByKeys);
state.put("AllComplexEventChunk", allComplexEventChunk.getFirst());
return state;
}
@Override
public void restoreState(Map<String, Object> state) {
counter = (int) state.get("Counter");
groupByKeys = (List<String>) state.get("GroupByKeys");
allComplexEventChunk.clear();
allComplexEventChunk.add((ComplexEvent) state.get("AllComplexEventChunk"));
}
}