/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * *************************************************************************************** */ package com.espertech.esper.core.context.mgr; import com.espertech.esper.client.EventBean; import com.espertech.esper.client.EventType; import com.espertech.esper.client.SafeIterator; import com.espertech.esper.client.context.*; import com.espertech.esper.core.context.factory.StatementAgentInstanceFactoryResult; import com.espertech.esper.core.context.stmt.AIRegistryAggregationMap; import com.espertech.esper.core.context.stmt.AIRegistryExprMap; import com.espertech.esper.core.context.stmt.StatementAIResourceRegistry; import com.espertech.esper.core.context.stmt.StatementAIResourceRegistryFactory; import com.espertech.esper.core.context.util.ContextControllerSelectorUtil; import com.espertech.esper.core.context.util.ContextDescriptor; import com.espertech.esper.core.context.util.ContextIteratorHandler; import com.espertech.esper.core.context.util.StatementAgentInstanceUtil; import com.espertech.esper.core.service.EPServicesContext; import com.espertech.esper.epl.expression.core.ExprValidationException; import com.espertech.esper.epl.spec.ContextDetailPartitionItem; import com.espertech.esper.event.MappedEventBean; import com.espertech.esper.filter.FilterFaultHandler; import com.espertech.esper.filter.FilterSpecCompiled; import com.espertech.esper.filter.FilterSpecLookupable; import com.espertech.esper.filter.FilterValueSetParam; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; public class ContextManagerNested implements ContextManager, ContextControllerLifecycleCallback, ContextIteratorHandler, FilterFaultHandler { private static final Logger log = LoggerFactory.getLogger(ContextManagerNested.class); private final String contextName; private final EPServicesContext servicesContext; private final ContextControllerFactory[] nestedContextFactories; private final Map<Integer, ContextControllerStatementDesc> statements = new LinkedHashMap<Integer, ContextControllerStatementDesc>(); // retain order of statement creation private final ContextDescriptor contextDescriptor; /** * The single root context. * This represents the context declared first. */ private ContextController rootContext; /** * Double-linked tree of sub-contexts. * An entry exists for all branches including the root. For example with 2 contexts declared this map has entries representing the root and all second-level sub-contexts. * For example with 3 contexts declared this map has entries for the root, second and third-level contexts. */ private final Map<ContextController, ContextControllerTreeEntry> subcontexts = new HashMap<ContextController, ContextControllerTreeEntry>(); private final ContextPartitionIdManager contextPartitionIdManager; public ContextManagerNested(ContextControllerFactoryServiceContext factoryServiceContext) throws ExprValidationException { this.contextName = factoryServiceContext.getContextName(); this.servicesContext = factoryServiceContext.getServicesContext(); this.contextPartitionIdManager = factoryServiceContext.getAgentInstanceContextCreate().getStatementContext().getContextControllerFactoryService().allocatePartitionIdMgr(contextName, factoryServiceContext.getAgentInstanceContextCreate().getStatementContext().getStatementId()); nestedContextFactories = factoryServiceContext.getAgentInstanceContextCreate().getStatementContext().getContextControllerFactoryService().getFactory(factoryServiceContext); StatementAIResourceRegistryFactory resourceRegistryFactory = new StatementAIResourceRegistryFactory() { public StatementAIResourceRegistry make() { return new StatementAIResourceRegistry(new AIRegistryAggregationMap(), new AIRegistryExprMap()); } }; Map<String, Object> contextProps = ContextPropertyEventType.getNestedTypeBase(); for (ContextControllerFactory factory : nestedContextFactories) { contextProps.put(factory.getFactoryContext().getContextName(), factory.getContextBuiltinProps()); } EventType contextPropsType = servicesContext.getEventAdapterService().createAnonymousMapType(contextName, contextProps, true); ContextPropertyRegistryImpl registry = new ContextPropertyRegistryImpl(Collections.<ContextDetailPartitionItem>emptyList(), contextPropsType); contextDescriptor = new ContextDescriptor(contextName, false, registry, resourceRegistryFactory, this, factoryServiceContext.getDetail()); } public Map<Integer, ContextControllerStatementDesc> getStatements() { return statements; } public ContextDescriptor getContextDescriptor() { return contextDescriptor; } public int getNumNestingLevels() { return nestedContextFactories.length; } public synchronized Iterator<EventBean> iterator(int statementId, ContextPartitionSelector selector) { AgentInstance[] instances = getAgentInstancesForStmt(statementId, selector); return new AgentInstanceArrayIterator(instances); } public synchronized SafeIterator<EventBean> safeIterator(int statementId, ContextPartitionSelector selector) { AgentInstance[] instances = getAgentInstancesForStmt(statementId, selector); return new AgentInstanceArraySafeIterator(instances); } public Collection<Integer> getAgentInstanceIds(ContextPartitionSelector contextPartitionSelector) { return getAgentInstancesForSelector(contextPartitionSelector); } public void importStartPaths(ContextControllerState state, AgentInstanceSelector agentInstanceSelector) { rootContext.importContextPartitions(state, 0, null, agentInstanceSelector); } protected static ContextPartitionIdentifier[] getTreeCompositeKey( ContextControllerFactory[] nestedContextFactories, Object initPartitionKey, ContextControllerTreeEntry treeEntry, Map<ContextController, ContextControllerTreeEntry> subcontexts) { int length = nestedContextFactories.length; ContextPartitionIdentifier[] keys = new ContextPartitionIdentifier[length]; keys[length - 1] = nestedContextFactories[length - 1].keyPayloadToIdentifier(initPartitionKey); keys[length - 2] = nestedContextFactories[length - 2].keyPayloadToIdentifier(treeEntry.getInitPartitionKey()); // get parent's parent if (length > 2) { ContextController parent = treeEntry.getParent(); ContextControllerTreeEntry parentEntry = subcontexts.get(parent); for (int i = 0; i < length - 2; i++) { keys[length - 2 - i] = nestedContextFactories[length - 2 - i].keyPayloadToIdentifier(parentEntry.getInitPartitionKey()); parent = parentEntry.getParent(); parentEntry = subcontexts.get(parent); } } return keys; } public ContextStatePathDescriptor extractPaths(ContextPartitionSelector selector) { ContextPartitionVisitorStateWithPath visitor = getContextPartitionPathsInternal(selector); return new ContextStatePathDescriptor(visitor.getStates(), visitor.getAgentInstanceInfo()); } public ContextStatePathDescriptor extractStopPaths(ContextPartitionSelector selector) { ContextPartitionVisitorStateWithPath visitor = getContextPartitionPathsInternal(selector); for (Map.Entry<ContextController, List<ContextPartitionVisitorStateWithPath.LeafDesc>> entry : visitor.getControllerAgentInstances().entrySet()) { ContextControllerTreeEntry treeEntry = subcontexts.get(entry.getKey()); for (ContextPartitionVisitorStateWithPath.LeafDesc leaf : entry.getValue()) { int agentInstanceId = leaf.getValue().getOptionalContextPartitionId(); ContextControllerTreeAgentInstanceList list = treeEntry.getAgentInstances().get(agentInstanceId); list.setState(ContextPartitionState.STOPPED); StatementAgentInstanceUtil.stopAgentInstances(list.getAgentInstances(), null, servicesContext, false, false); list.clearAgentInstances(); leaf.getValue().setState(ContextPartitionState.STOPPED); rootContext.getFactory().getFactoryContext().getStateCache().updateContextPath(contextName, leaf.getKey(), leaf.getValue()); } } return new ContextStatePathDescriptor(visitor.getStates(), visitor.getAgentInstanceInfo()); } public ContextStatePathDescriptor extractDestroyPaths(ContextPartitionSelector selector) { ContextPartitionVisitorStateWithPath visitor = getContextPartitionPathsInternal(selector); for (Map.Entry<ContextController, List<ContextPartitionVisitorStateWithPath.LeafDesc>> entry : visitor.getControllerAgentInstances().entrySet()) { ContextControllerTreeEntry treeEntry = subcontexts.get(entry.getKey()); for (ContextPartitionVisitorStateWithPath.LeafDesc leaf : entry.getValue()) { int agentInstanceId = leaf.getValue().getOptionalContextPartitionId(); ContextControllerTreeAgentInstanceList list = treeEntry.getAgentInstances().get(agentInstanceId); StatementAgentInstanceUtil.stopAgentInstances(list.getAgentInstances(), null, servicesContext, false, false); rootContext.getFactory().getFactoryContext().getStateCache().removeContextPath(contextName, leaf.getKey().getLevel(), leaf.getKey().getParentPath(), leaf.getKey().getSubPath()); ContextPartitionDescriptor descriptor = visitor.getAgentInstanceInfo().get(agentInstanceId); ContextPartitionIdentifierNested nestedIdent = (ContextPartitionIdentifierNested) descriptor.getIdentifier(); entry.getKey().deletePath(nestedIdent.getIdentifiers()[nestedContextFactories.length - 1]); } } return new ContextStatePathDescriptor(visitor.getStates(), visitor.getAgentInstanceInfo()); } public Map<Integer, ContextPartitionDescriptor> startPaths(ContextPartitionSelector selector) { ContextPartitionVisitorStateWithPath visitor = getContextPartitionPathsInternal(selector); for (Map.Entry<ContextController, List<ContextPartitionVisitorStateWithPath.LeafDesc>> entry : visitor.getControllerAgentInstances().entrySet()) { ContextControllerTreeEntry treeEntry = subcontexts.get(entry.getKey()); for (ContextPartitionVisitorStateWithPath.LeafDesc leaf : entry.getValue()) { int agentInstanceId = leaf.getValue().getOptionalContextPartitionId(); ContextControllerTreeAgentInstanceList list = treeEntry.getAgentInstances().get(agentInstanceId); if (list.getState() == ContextPartitionState.STARTED) { continue; } for (Map.Entry<Integer, ContextControllerStatementDesc> statement : statements.entrySet()) { AgentInstance instance = startStatement(agentInstanceId, statement.getValue(), rootContext, list.getInitPartitionKey(), list.getInitContextProperties(), false); list.getAgentInstances().add(instance); } list.setState(ContextPartitionState.STARTED); leaf.getValue().setState(ContextPartitionState.STARTED); rootContext.getFactory().getFactoryContext().getStateCache().updateContextPath(contextName, leaf.getKey(), leaf.getValue()); } } ContextManagerImpl.setState(visitor.getAgentInstanceInfo(), ContextPartitionState.STARTED); return visitor.getAgentInstanceInfo(); } public ContextPartitionVisitorStateWithPath getContextPartitionPathsInternal(ContextPartitionSelector selector) { ContextPartitionVisitorStateWithPath visitor = new ContextPartitionVisitorStateWithPath(nestedContextFactories, subcontexts); List<ContextPartitionSelector[]> selectors; if (selector instanceof ContextPartitionSelectorNested) { ContextPartitionSelectorNested nested = (ContextPartitionSelectorNested) selector; selectors = nested.getSelectors(); } else if (selector instanceof ContextPartitionSelectorAll) { ContextPartitionSelector[] all = new ContextPartitionSelector[getNumNestingLevels()]; Arrays.fill(all, selector); selectors = Collections.singletonList(all); } else { throw new IllegalArgumentException("Invalid selector for nested context"); } for (ContextPartitionSelector[] item : selectors) { recursivePopulateSelector(rootContext, 1, item, visitor); } return visitor; } public void addStatement(ContextControllerStatementBase statement, boolean isRecoveringResilient) throws ExprValidationException { // validation down the hierarchy ContextControllerStatementCtxCache[] caches = new ContextControllerStatementCtxCache[nestedContextFactories.length]; for (int i = 0; i < nestedContextFactories.length; i++) { ContextControllerFactory nested = nestedContextFactories[i]; caches[i] = nested.validateStatement(statement); } // save statement ContextControllerStatementDesc desc = new ContextControllerStatementDesc(statement, caches); statements.put(statement.getStatementContext().getStatementId(), desc); // activate if this is the first statement if (statements.size() == 1) { activate(); // this may itself trigger a callback } else { // activate statement in respect to existing context partitions for (Map.Entry<ContextController, ContextControllerTreeEntry> subcontext : subcontexts.entrySet()) { if (subcontext.getKey().getFactory().getFactoryContext().getNestingLevel() != nestedContextFactories.length) { continue; } if (subcontext.getValue().getAgentInstances() == null || subcontext.getValue().getAgentInstances().isEmpty()) { continue; } for (Map.Entry<Integer, ContextControllerTreeAgentInstanceList> entry : subcontext.getValue().getAgentInstances().entrySet()) { if (entry.getValue().getState() == ContextPartitionState.STARTED) { AgentInstance agentInstance = startStatement(entry.getKey(), desc, subcontext.getKey(), entry.getValue().getInitPartitionKey(), entry.getValue().getInitContextProperties(), isRecoveringResilient); entry.getValue().getAgentInstances().add(agentInstance); } } } } } public synchronized void stopStatement(String statementName, int statementId) { destroyStatement(statementName, statementId); } public synchronized void destroyStatement(String statementName, int statementId) { if (!statements.containsKey(statementId)) { return; } if (statements.size() == 1) { safeDestroy(); } else { removeStatement(statementId); } } public void safeDestroy() { if (rootContext != null) { recursiveDeactivateStop(rootContext, false, null); nestedContextFactories[0].getFactoryContext().getStateCache().removeContext(contextName); rootContext = null; statements.clear(); subcontexts.clear(); contextPartitionIdManager.clear(); } } public FilterSpecLookupable getFilterLookupable(EventType eventType) { throw new UnsupportedOperationException(); } public void contextPartitionNavigate(ContextControllerInstanceHandle existingHandle, ContextController originator, ContextControllerState controllerState, int exportedCPOrPathId, ContextInternalFilterAddendum filterAddendum, AgentInstanceSelector agentInstanceSelector, byte[] payload, boolean isRecoveringResilient) { ContextManagerNestedInstanceHandle nestedHandle = (ContextManagerNestedInstanceHandle) existingHandle; // detect non-leaf int nestingLevel = originator.getFactory().getFactoryContext().getNestingLevel(); // starts at 1 for root if (nestingLevel < nestedContextFactories.length) { nestedHandle.getController().importContextPartitions(controllerState, exportedCPOrPathId, filterAddendum, agentInstanceSelector); return; } ContextControllerTreeEntry entry = subcontexts.get(originator); if (entry == null) { return; } for (Map.Entry<Integer, ContextControllerTreeAgentInstanceList> cpEntry : entry.getAgentInstances().entrySet()) { if (cpEntry.getValue().getState() == ContextPartitionState.STOPPED) { cpEntry.getValue().setState(ContextPartitionState.STARTED); entry.getAgentInstances().clear(); for (Map.Entry<Integer, ContextControllerStatementDesc> statement : statements.entrySet()) { AgentInstance instance = startStatement(existingHandle.getContextPartitionOrPathId(), statement.getValue(), originator, cpEntry.getValue().getInitPartitionKey(), entry.getInitContextProperties(), false); cpEntry.getValue().getAgentInstances().add(instance); } ContextStatePathKey key = new ContextStatePathKey(nestedContextFactories.length, originator.getPathId(), existingHandle.getSubPathId()); ContextStatePathValue value = new ContextStatePathValue(existingHandle.getContextPartitionOrPathId(), payload, ContextPartitionState.STARTED); originator.getFactory().getFactoryContext().getStateCache().updateContextPath(contextName, key, value); } else { List<AgentInstance> removed = new ArrayList<AgentInstance>(2); List<AgentInstance> added = new ArrayList<AgentInstance>(2); List<AgentInstance> current = cpEntry.getValue().getAgentInstances(); for (AgentInstance agentInstance : current) { if (!agentInstanceSelector.select(agentInstance)) { continue; } // remove StatementAgentInstanceUtil.stopAgentInstanceRemoveResources(agentInstance, null, servicesContext, false, false); removed.add(agentInstance); // start ContextControllerStatementDesc statementDesc = statements.get(agentInstance.getAgentInstanceContext().getStatementId()); AgentInstance instance = startStatement(cpEntry.getKey(), statementDesc, originator, cpEntry.getValue().getInitPartitionKey(), entry.getInitContextProperties(), false); added.add(instance); if (controllerState.getPartitionImportCallback() != null) { controllerState.getPartitionImportCallback().existing(existingHandle.getContextPartitionOrPathId(), exportedCPOrPathId); } } current.removeAll(removed); current.addAll(added); } } } public synchronized ContextControllerInstanceHandle contextPartitionInstantiate( Integer optionalContextPartitionId, int subPathId, Integer importSubpathId, ContextController originator, EventBean optionalTriggeringEvent, Map<String, Object> optionalTriggeringPattern, Object partitionKey, Map<String, Object> contextProperties, ContextControllerState states, ContextInternalFilterAddendum filterAddendum, boolean isRecoveringResilient, ContextPartitionState state) { // detect non-leaf int nestingLevel = originator.getFactory().getFactoryContext().getNestingLevel(); // starts at 1 for root if (nestingLevel < nestedContextFactories.length) { // next sub-sontext ContextControllerFactory nextFactory = nestedContextFactories[originator.getFactory().getFactoryContext().getNestingLevel()]; ContextController nextContext = nextFactory.createNoCallback(subPathId, this); // link current context to sub-context ContextControllerTreeEntry branch = subcontexts.get(originator); if (branch.getChildContexts() == null) { branch.setChildContexts(new HashMap<Integer, ContextController>()); } branch.getChildContexts().put(subPathId, nextContext); // save child branch, linking sub-context to its parent ContextControllerTreeEntry entry = new ContextControllerTreeEntry(originator, null, partitionKey, contextProperties); subcontexts.put(nextContext, entry); // now post-initialize, this may actually call back nextContext.activate(optionalTriggeringEvent, optionalTriggeringPattern, states, filterAddendum, importSubpathId); if (log.isDebugEnabled()) { log.debug("Instantiating branch context path for " + contextName + " from level " + originator.getFactory().getFactoryContext().getNestingLevel() + "(" + originator.getFactory().getFactoryContext().getContextName() + ")" + " parentPath " + originator.getPathId() + " for level " + nextContext.getFactory().getFactoryContext().getNestingLevel() + "(" + nextContext.getFactory().getFactoryContext().getContextName() + ")" + " childPath " + subPathId ); } return new ContextManagerNestedInstanceHandle(subPathId, nextContext, subPathId, true, null); } // assign context id int assignedContextId; if (optionalContextPartitionId != null && !states.isImported()) { assignedContextId = optionalContextPartitionId; contextPartitionIdManager.addExisting(optionalContextPartitionId); } else { assignedContextId = contextPartitionIdManager.allocateId(); if (states != null && states.getPartitionImportCallback() != null && optionalContextPartitionId != null) { states.getPartitionImportCallback().allocated(assignedContextId, optionalContextPartitionId); } } if (log.isDebugEnabled()) { log.debug("Instantiating agent instance for " + contextName + " from level " + originator.getFactory().getFactoryContext().getNestingLevel() + "(" + originator.getFactory().getFactoryContext().getContextName() + ")" + " parentPath " + originator.getPathId() + " contextPartId " + assignedContextId); } // handle leaf creation List<AgentInstance> newInstances = new ArrayList<AgentInstance>(); if (state == ContextPartitionState.STARTED) { for (Map.Entry<Integer, ContextControllerStatementDesc> statementEntry : statements.entrySet()) { ContextControllerStatementDesc statementDesc = statementEntry.getValue(); AgentInstance instance = startStatement(assignedContextId, statementDesc, originator, partitionKey, contextProperties, isRecoveringResilient); newInstances.add(instance); } } // for all new contexts: evaluate this event for this statement if (optionalTriggeringEvent != null) { StatementAgentInstanceUtil.evaluateEventForStatement(servicesContext, optionalTriggeringEvent, optionalTriggeringPattern, newInstances); } // save leaf ContextControllerTreeEntry entry = subcontexts.get(originator); if (entry.getAgentInstances() == null) { entry.setAgentInstances(new LinkedHashMap<Integer, ContextControllerTreeAgentInstanceList>()); } long filterVersion = servicesContext.getFilterService().getFiltersVersion(); ContextControllerTreeAgentInstanceList agentInstanceList = new ContextControllerTreeAgentInstanceList(filterVersion, partitionKey, contextProperties, newInstances, state); entry.getAgentInstances().put(assignedContextId, agentInstanceList); return new ContextManagerNestedInstanceHandle(subPathId, originator, assignedContextId, false, agentInstanceList); } public synchronized boolean handleFilterFault(EventBean theEvent, long version) { for (Map.Entry<ContextController, ContextControllerTreeEntry> entry : subcontexts.entrySet()) { if (entry.getValue().getAgentInstances() != null) { StatementAgentInstanceUtil.handleFilterFault(theEvent, version, servicesContext, entry.getValue().getAgentInstances()); } } return false; } public ContextStateCache getContextStateCache() { return rootContext.getFactory().getStateCache(); } /** * Provides the sub-context that ends. */ public void contextPartitionTerminate(ContextControllerInstanceHandle contextNestedHandle, Map<String, Object> terminationProperties, boolean leaveLocksAcquired, List<AgentInstance> agentInstances) { ContextManagerNestedInstanceHandle handle = (ContextManagerNestedInstanceHandle) contextNestedHandle; if (handle.isBranch()) { ContextManagerNestedInstanceHandle branchHandle = handle; ContextController branch = branchHandle.getController(); recursiveDeactivateStop(branch, leaveLocksAcquired, agentInstances); if (log.isDebugEnabled()) { log.debug("Terminated context branch for " + contextName + " from level " + branch.getFactory().getFactoryContext().getNestingLevel() + "(" + branch.getFactory().getFactoryContext().getContextName() + ")" + " parentPath " + branch.getPathId()); } } else { ContextManagerNestedInstanceHandle leafHandle = handle; ContextController leaf = leafHandle.getController(); ContextControllerTreeEntry leafEntry = subcontexts.get(leaf); if (leafEntry != null) { // could be terminated earlier ContextControllerTreeAgentInstanceList ailist = leafEntry.getAgentInstances().get(leafHandle.getContextPartitionOrPathId()); if (ailist != null) { StatementAgentInstanceUtil.stopAgentInstances(ailist.getAgentInstances(), null, servicesContext, false, false); contextPartitionIdManager.removeId(leafHandle.getContextPartitionOrPathId()); ailist.getAgentInstances().clear(); } if (log.isDebugEnabled()) { log.debug("Terminated context leaf for " + contextName + " from level " + leaf.getFactory().getFactoryContext().getNestingLevel() + "(" + leaf.getFactory().getFactoryContext().getContextName() + ")" + " parentPath " + leaf.getPathId() + " contextPartId " + leafHandle.getContextPartitionOrPathId()); } } } } public synchronized Iterator<EventBean> iterator(int statementId) { AgentInstance[] instances = getAgentInstancesForStmt(statementId); return new AgentInstanceArrayIterator(instances); } public synchronized SafeIterator<EventBean> safeIterator(int statementId) { AgentInstance[] instances = getAgentInstancesForStmt(statementId); return new AgentInstanceArraySafeIterator(instances); } private AgentInstance startStatement(int contextId, ContextControllerStatementDesc statementDesc, ContextController originator, Object partitionKey, Map<String, Object> contextProperties, boolean isRecoveringResilient) { // build filters AgentInstanceFilterProxy proxy = getMergedFilterAddendums(statementDesc, originator, partitionKey, contextId); // build built-in context properties Map<String, Object> properties = ContextPropertyEventType.getNestedBeanBase(contextName, contextId); properties.put(nestedContextFactories[nestedContextFactories.length - 1].getFactoryContext().getContextName(), contextProperties); recursivePopulateBuiltinProps(originator, properties); properties.put(ContextPropertyEventType.PROP_CTX_NAME, contextName); properties.put(ContextPropertyEventType.PROP_CTX_ID, contextId); MappedEventBean contextBean = (MappedEventBean) servicesContext.getEventAdapterService().adapterForTypedMap(properties, contextDescriptor.getContextPropertyRegistry().getContextEventType()); // activate StatementAgentInstanceFactoryResult result = StatementAgentInstanceUtil.start(servicesContext, statementDesc.getStatement(), false, contextId, contextBean, proxy, isRecoveringResilient); return new AgentInstance(result.getStopCallback(), result.getAgentInstanceContext(), result.getFinalView()); } private void recursivePopulateBuiltinProps(ContextController originator, Map<String, Object> properties) { ContextControllerTreeEntry entry = subcontexts.get(originator); if (entry.getInitContextProperties() != null) { properties.put(entry.getParent().getFactory().getFactoryContext().getContextName(), entry.getInitContextProperties()); } if (entry.getParent() != null && entry.getParent().getFactory().getFactoryContext().getNestingLevel() > 1) { recursivePopulateBuiltinProps(entry.getParent(), properties); } } private AgentInstanceFilterProxy getMergedFilterAddendums(ContextControllerStatementDesc statement, ContextController originator, Object partitionKey, int contextId) { IdentityHashMap<FilterSpecCompiled, FilterValueSetParam[][]> result = new IdentityHashMap<FilterSpecCompiled, FilterValueSetParam[][]>(); originator.getFactory().populateFilterAddendums(result, statement, partitionKey, contextId); ContextControllerTreeEntry originatorEntry = subcontexts.get(originator); if (originatorEntry != null) { recursivePopulateFilterAddendum(statement, originatorEntry, contextId, result); } return new AgentInstanceFilterProxyImpl(result); } private void recursivePopulateFilterAddendum(ContextControllerStatementDesc statement, ContextControllerTreeEntry originatorEntry, int contextId, IdentityHashMap<FilterSpecCompiled, FilterValueSetParam[][]> result) { if (originatorEntry.getParent() == null) { return; } originatorEntry.getParent().getFactory().populateFilterAddendums(result, statement, originatorEntry.getInitPartitionKey(), contextId); ContextControllerTreeEntry parentEntry = subcontexts.get(originatorEntry.getParent()); if (parentEntry != null) { recursivePopulateFilterAddendum(statement, parentEntry, contextId, result); } } private void activate() { rootContext = nestedContextFactories[0].createNoCallback(0, this); subcontexts.put(rootContext, new ContextControllerTreeEntry(null, null, null, null)); rootContext.activate(null, null, null, null, null); } private void removeStatement(int statementId) { ContextControllerStatementDesc statementDesc = statements.get(statementId); if (statementDesc == null) { return; } for (Map.Entry<ContextController, ContextControllerTreeEntry> entry : subcontexts.entrySet()) { // ignore branches if (entry.getKey().getFactory().getFactoryContext().getNestingLevel() < nestedContextFactories.length) { continue; } if (entry.getValue().getAgentInstances() == null || entry.getValue().getAgentInstances().isEmpty()) { continue; } for (Map.Entry<Integer, ContextControllerTreeAgentInstanceList> contextPartitionEntry : entry.getValue().getAgentInstances().entrySet()) { Iterator<AgentInstance> instanceIt = contextPartitionEntry.getValue().getAgentInstances().iterator(); for (; instanceIt.hasNext(); ) { AgentInstance instance = instanceIt.next(); if (instance.getAgentInstanceContext().getStatementContext().getStatementId() != statementId) { continue; } StatementAgentInstanceUtil.stop(instance.getStopCallback(), instance.getAgentInstanceContext(), instance.getFinalView(), servicesContext, true, false, true); instanceIt.remove(); } } } statements.remove(statementId); } private void recursiveDeactivateStop(ContextController currentContext, boolean leaveLocksAcquired, List<AgentInstance> agentInstancesCollected) { // deactivate currentContext.deactivate(); // remove state ContextControllerTreeEntry entry = subcontexts.remove(currentContext); if (entry == null) { return; } // remove from parent ContextControllerTreeEntry parent = subcontexts.get(entry.getParent()); if (parent != null) { parent.getChildContexts().remove(currentContext.getPathId()); } // stop instances if (entry.getAgentInstances() != null) { for (Map.Entry<Integer, ContextControllerTreeAgentInstanceList> entryCP : entry.getAgentInstances().entrySet()) { StatementAgentInstanceUtil.stopAgentInstances(entryCP.getValue().getAgentInstances(), null, servicesContext, false, leaveLocksAcquired); if (agentInstancesCollected != null) { agentInstancesCollected.addAll(entryCP.getValue().getAgentInstances()); } contextPartitionIdManager.removeId(entryCP.getKey()); } } // deactivate child contexts if (entry.getChildContexts() == null || entry.getChildContexts().isEmpty()) { return; } for (ContextController inner : entry.getChildContexts().values()) { recursiveDeactivateStop(inner, leaveLocksAcquired, agentInstancesCollected); } } private AgentInstance[] getAgentInstancesForStmt(int statementId) { List<AgentInstance> instances = new ArrayList<AgentInstance>(); for (Map.Entry<ContextController, ContextControllerTreeEntry> subcontext : subcontexts.entrySet()) { if (subcontext.getKey().getFactory().getFactoryContext().getNestingLevel() != nestedContextFactories.length) { continue; } if (subcontext.getValue().getAgentInstances() == null || subcontext.getValue().getAgentInstances().isEmpty()) { continue; } for (Map.Entry<Integer, ContextControllerTreeAgentInstanceList> entry : subcontext.getValue().getAgentInstances().entrySet()) { for (AgentInstance ai : entry.getValue().getAgentInstances()) { if (ai.getAgentInstanceContext().getStatementContext().getStatementId() == statementId) { instances.add(ai); } } } } return instances.toArray(new AgentInstance[instances.size()]); } private AgentInstance[] getAgentInstancesForStmt(int statementId, ContextPartitionSelector selector) { Collection<Integer> agentInstanceIds = getAgentInstancesForSelector(selector); if (agentInstanceIds == null || agentInstanceIds.isEmpty()) { return new AgentInstance[0]; } List<AgentInstance> instances = new ArrayList<AgentInstance>(agentInstanceIds.size()); for (Map.Entry<ContextController, ContextControllerTreeEntry> subcontext : subcontexts.entrySet()) { if (subcontext.getKey().getFactory().getFactoryContext().getNestingLevel() != nestedContextFactories.length) { continue; } if (subcontext.getValue().getAgentInstances() == null || subcontext.getValue().getAgentInstances().isEmpty()) { continue; } for (Integer agentInstanceId : agentInstanceIds) { ContextControllerTreeAgentInstanceList instancesList = subcontext.getValue().getAgentInstances().get(agentInstanceId); if (instancesList != null) { Iterator<AgentInstance> instanceIt = instancesList.getAgentInstances().iterator(); for (; instanceIt.hasNext(); ) { AgentInstance instance = instanceIt.next(); if (instance.getAgentInstanceContext().getStatementContext().getStatementId() == statementId) { instances.add(instance); } } } } } return instances.toArray(new AgentInstance[instances.size()]); } private Collection<Integer> getAgentInstancesForSelector(ContextPartitionSelector selector) { if (selector instanceof ContextPartitionSelectorById) { ContextPartitionSelectorById byId = (ContextPartitionSelectorById) selector; Set<Integer> ids = byId.getContextPartitionIds(); if (ids == null || ids.isEmpty()) { return Collections.emptyList(); } ArrayList agentInstanceIds = new ArrayList<Integer>(ids); agentInstanceIds.retainAll(contextPartitionIdManager.getIds()); return agentInstanceIds; } else if (selector instanceof ContextPartitionSelectorAll) { return new ArrayList<Integer>(contextPartitionIdManager.getIds()); } else if (selector instanceof ContextPartitionSelectorNested) { ContextPartitionSelectorNested nested = (ContextPartitionSelectorNested) selector; ContextPartitionVisitorAgentInstanceIdWPath visitor = new ContextPartitionVisitorAgentInstanceIdWPath(nestedContextFactories.length); for (ContextPartitionSelector[] item : nested.getSelectors()) { recursivePopulateSelector(rootContext, 1, item, visitor); } return visitor.getAgentInstanceIds(); } throw ContextControllerSelectorUtil.getInvalidSelector(new Class[]{ContextPartitionSelectorNested.class}, selector, true); } private void recursivePopulateSelector(ContextController currentContext, int level, ContextPartitionSelector[] selectorStack, ContextPartitionVisitorWithPath visitor) { ContextControllerTreeEntry entry = subcontexts.get(currentContext); if (entry == null) { return; } ContextPartitionSelector selector = selectorStack[level - 1]; // handle branch if (level < nestedContextFactories.length) { visitor.resetSubPaths(); currentContext.visitSelectedPartitions(selector, visitor); Collection<Integer> selectedPaths = new ArrayList<Integer>(visitor.getSubpaths()); for (Integer path : selectedPaths) { ContextController controller = entry.getChildContexts().get(path); if (controller != null) { recursivePopulateSelector(controller, level + 1, selectorStack, visitor); } } } else { // handle leaf currentContext.visitSelectedPartitions(selector, visitor); } } }