* @return events
*/
public Collection<EventBean> snapshot(FilterSpecCompiled optionalFilter, Annotation[] annotations) {
// Determine virtual data window
VirtualDWView virtualDataWindow = null;
if (isVirtualDataWindow()) {
virtualDataWindow = getVirtualDataWindow();
}
if (optionalFilter == null || optionalFilter.getParameters().length == 0) {
if (virtualDataWindow != null) {
Pair<IndexMultiKey,EventTable> pair = virtualDataWindow.getFireAndForgetDesc(Collections.<String>emptySet(), Collections.<String>emptySet());
return virtualDataWindow.getFireAndForgetData(pair.getSecond(), new Object[0], new RangeIndexLookupValue[0], annotations);
}
return null;
}
// Determine what straight-equals keys and which ranges are available.
// Widening/Coercion is part of filter spec compile.
Set<String> keysAvailable = new HashSet<String>();
Set<String> rangesAvailable = new HashSet<String>();
for (FilterSpecParam param : optionalFilter.getParameters()) {
if (!(param instanceof FilterSpecParamConstant || param instanceof FilterSpecParamRange)) {
continue;
}
if (param.getFilterOperator() == FilterOperator.EQUAL || param.getFilterOperator() == FilterOperator.IS) {
keysAvailable.add(param.getLookupable().getExpression());
}
else if (param.getFilterOperator().isRangeOperator() ||
param.getFilterOperator().isInvertedRangeOperator() ||
param.getFilterOperator().isComparisonOperator()) {
rangesAvailable.add(param.getLookupable().getExpression());
}
else if (param.getFilterOperator().isRangeOperator()) {
rangesAvailable.add(param.getLookupable().getExpression());
}
}
// Find an index that matches the needs
Pair<IndexMultiKey, EventTableAndNamePair> tablePair;
if (virtualDataWindow != null) {
Pair<IndexMultiKey, EventTable> tablePairNoName = virtualDataWindow.getFireAndForgetDesc(keysAvailable, rangesAvailable);
tablePair = new Pair<IndexMultiKey, EventTableAndNamePair>(tablePairNoName.getFirst(), new EventTableAndNamePair(tablePairNoName.getSecond(), null));
}
else {
IndexHint indexHint = IndexHint.getIndexHint(annotations);
tablePair = indexRepository.findTable(keysAvailable, rangesAvailable, explicitIndexes, indexHint);
}
if (rootView.isQueryPlanLogging() && rootView.getQueryPlanLog().isInfoEnabled()) {
String prefix = "Fire-and-forget from window " + rootView.getEventType().getName() + " ";
String indexName = tablePair != null && tablePair.getSecond() != null ? tablePair.getSecond().getIndexName() : null;
String indexText = indexName != null ? "index " + indexName + " " : "full table scan ";
indexText += "(snapshot only, for join see separate query plan)";
if (tablePair == null) {
rootView.getQueryPlanLog().info(prefix + indexText);
}
else {
rootView.getQueryPlanLog().info(prefix + indexText + tablePair.getSecond().getEventTable().toQueryPlan());
}
QueryPlanIndexHook hook = QueryPlanIndexHookUtil.getHook(annotations);
if (hook != null) {
hook.fireAndForget(new QueryPlanIndexDescFAF(indexName, tablePair != null ?
tablePair.getSecond().getEventTable().getClass().getSimpleName() : null));
}
}
if (tablePair == null) {
return null; // indicates table scan
}
// Compile key index lookup values
String[] keyIndexProps = IndexedPropDesc.getIndexProperties(tablePair.getFirst().getHashIndexedProps());
Object[] keyValues = new Object[keyIndexProps.length];
for (int keyIndex = 0; keyIndex < keyIndexProps.length; keyIndex++) {
for (FilterSpecParam param : optionalFilter.getParameters()) {
if (param.getLookupable().getExpression().equals(keyIndexProps[keyIndex])) {
keyValues[keyIndex] = param.getFilterValue(null, agentInstanceContext);
break;
}
}
}
// Analyze ranges - these may include key lookup value (EQUALS semantics)
String[] rangeIndexProps = IndexedPropDesc.getIndexProperties(tablePair.getFirst().getRangeIndexedProps());
RangeIndexLookupValue[] rangeValues;
if (rangeIndexProps.length > 0) {
rangeValues = compileRangeLookupValues(rangeIndexProps, optionalFilter.getParameters());
}
else {
rangeValues = new RangeIndexLookupValue[0];
}
EventTable eventTable = tablePair.getSecond().getEventTable();
if (virtualDataWindow != null) {
return virtualDataWindow.getFireAndForgetData(eventTable, keyValues, rangeValues, annotations);
}
IndexMultiKey indexMultiKey = tablePair.getFirst();
Set<EventBean> result;
if (indexMultiKey.getHashIndexedProps().length > 0 && indexMultiKey.getRangeIndexedProps().length == 0) {