public void closeLiveQuery(final InternalFactHandle factHandle) { try { startOperation(); this.ruleBase.readLock(); this.lock.lock(); final PropagationContext pCtx = new PropagationContextImpl( getNextPropagationIdCounter(), PropagationContext.INSERTION, null, null, factHandle, getEntryPoint()); if (this.ruleBase.getConfiguration().isPhreakEnabled()) { LeftInputAdapterNode lian = (LeftInputAdapterNode) factHandle.getFirstLeftTuple().getLeftTupleSink().getLeftTupleSource(); LiaNodeMemory lmem = (LiaNodeMemory) getNodeMemory((MemoryFactory) lian); SegmentMemory lsmem = lmem.getSegmentMemory(); LeftTuple childLeftTuple = factHandle.getFirstLeftTuple(); // there is only one, all other LTs are peers LeftInputAdapterNode.doDeleteObject( childLeftTuple, childLeftTuple.getPropagationContext(), lsmem, this, lian, false, lmem); List<PathMemory> rmems = lmem.getSegmentMemory().getPathMemories(); for (int i = 0, length = rmems.size(); i < length; i++) { PathMemory rm = rmems.get(i); RuleNetworkEvaluatorActivation evaluator = agenda.createRuleNetworkEvaluatorActivation( Integer.MAX_VALUE, rm, (TerminalNode) rm.getNetworkNode()); evaluator.evaluateNetwork(this, 0, -1); } } else { getEntryPointNode().retractQuery(factHandle, pCtx, this); pCtx.evaluateActionQueue(this); } getFactHandleFactory().destroyFactHandle(factHandle); } finally { this.lock.unlock(); this.ruleBase.readUnlock(); endOperation(); } }
public void execute(InternalWorkingMemory workingMemory) { DroolsQuery query = (DroolsQuery) factHandle.getObject(); RightTupleList rightTuples = query.getResultInsertRightTupleList(); query.setResultInsertRightTupleList( null); // null so further operations happen on a new stack element for (RightTuple rightTuple = rightTuples.getFirst(); rightTuple != null; ) { RightTuple tmp = (RightTuple) rightTuple.getNext(); rightTuples.remove(rightTuple); for (LeftTuple childLeftTuple = rightTuple.firstChild; childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getRightParentNext()) { node.getSinkPropagator() .doPropagateAssertLeftTuple( context, workingMemory, childLeftTuple, childLeftTuple.getLeftTupleSink()); } rightTuple = tmp; } // @FIXME, this should work, but it's closing needed fact handles // actually an evaluation 34 appears on the stack twice.... // if ( !node.isOpenQuery() ) { // workingMemory.getFactHandleFactory().destroyFactHandle( this.factHandle ); // } }
public void execute(InternalWorkingMemory workingMemory) { InternalFactHandle factHandle = (InternalFactHandle) leftTuple.getObject(); if (node.isOpenQuery()) { // iterate to the query terminal node, as the child leftTuples will get picked up there workingMemory .getEntryPointNode() .retractObject( factHandle, context, workingMemory .getObjectTypeConfigurationRegistry() .getObjectTypeConf(workingMemory.getEntryPoint(), factHandle.getObject()), workingMemory); // workingMemory.getFactHandleFactory().destroyFactHandle( factHandle ); } else { // get child left tuples, as there is no open query if (leftTuple.getFirstChild() != null) { node.getSinkPropagator().propagateRetractLeftTuple(leftTuple, context, workingMemory); } } }
public void execute(InternalWorkingMemory workingMemory) { DroolsQuery query = (DroolsQuery) factHandle.getObject(); RightTupleList rightTuples = query.getResultRetractRightTupleList(); query.setResultRetractRightTupleList( null); // null so further operations happen on a new stack element for (RightTuple rightTuple = rightTuples.getFirst(); rightTuple != null; ) { RightTuple tmp = (RightTuple) rightTuple.getNext(); rightTuples.remove(rightTuple); this.node .getSinkPropagator() .propagateRetractRightTuple(rightTuple, context, workingMemory); rightTuple = tmp; } }
public EqualityKey(final InternalFactHandle handle, final int status) { super((DefaultFactHandle) handle); this.hashCode = handle.getObjectHashCode(); this.status = status; }
/** Side-effects, will add the created key to the handle. */ private EqualityKey createEqualityKey(InternalFactHandle handle) { EqualityKey key = new EqualityKey(handle); handle.setEqualityKey(key); return key; }
protected void addPropertyChangeListener( final InternalFactHandle handle, final boolean dynamicFlag) { Object object = handle.getObject(); try { final Method method = object .getClass() .getMethod( "addPropertyChangeListener", NamedEntryPoint.ADD_REMOVE_PROPERTY_CHANGE_LISTENER_ARG_TYPES); method.invoke(object, this.addRemovePropertyChangeListenerArgs); if (dynamicFlag) { if (dynamicFacts == null) { dynamicFacts = new HashSet<InternalFactHandle>(); } dynamicFacts.add(handle); } } catch (final NoSuchMethodException e) { System.err.println( "Warning: Method addPropertyChangeListener not found" + " on the class " + object.getClass() + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object"); } catch (final IllegalArgumentException e) { System.err.println( "Warning: The addPropertyChangeListener method" + " on the class " + object.getClass() + " does not take" + " a simple PropertyChangeListener argument" + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object"); } catch (final IllegalAccessException e) { System.err.println( "Warning: The addPropertyChangeListener method" + " on the class " + object.getClass() + " is not public" + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object"); } catch (final InvocationTargetException e) { System.err.println( "Warning: The addPropertyChangeListener method" + " on the class " + object.getClass() + " threw an InvocationTargetException" + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object: " + e.getMessage()); } catch (final SecurityException e) { System.err.println( "Warning: The SecurityManager controlling the class " + object.getClass() + " did not allow the lookup of a" + " addPropertyChangeListener method" + " so Drools will be unable to process JavaBean" + " PropertyChangeEvents on the asserted Object: " + e.getMessage()); } }
public void retract( final org.drools.FactHandle factHandle, final boolean removeLogical, final boolean updateEqualsMap, final Rule rule, final Activation activation) throws FactException { if (factHandle == null) { throw new IllegalArgumentException("FactHandle cannot be null "); } try { this.ruleBase.readLock(); this.lock.lock(); this.wm.startOperation(); this.ruleBase.executeQueuedActions(); InternalFactHandle handle = (InternalFactHandle) factHandle; if (handle.getId() == -1) { // can't retract an already retracted handle return; } // the handle might have been disconnected, so reconnect if it has if (handle.isDisconnected()) { handle = this.objectStore.reconnect(handle); } if (handle.getEntryPoint() != this) { throw new IllegalArgumentException( "Invalid Entry Point. You updated the FactHandle on entry point '" + handle.getEntryPoint().getEntryPointId() + "' instead of '" + getEntryPointId() + "'"); } final Object object = handle.getObject(); final ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf(this.entryPoint, object); if (typeConf.isSupportsPropertyChangeListeners()) { removePropertyChangeListener(handle, true); } if (activation != null) { // release resources so that they can be GC'ed activation.getPropagationContext().releaseResources(); } final PropagationContext propagationContext = new PropagationContextImpl( this.wm.getNextPropagationIdCounter(), PropagationContext.RETRACTION, rule, (activation == null) ? null : activation.getTuple(), handle, this.wm.agenda.getActiveActivations(), this.wm.agenda.getDormantActivations(), this.entryPoint); this.entryPointNode.retractObject(handle, propagationContext, typeConf, this.wm); if (typeConf.isTMSEnabled()) { TruthMaintenanceSystem tms = wm.getTruthMaintenanceSystem(); // Update the equality key, which maintains a list of stated // FactHandles final EqualityKey key = handle.getEqualityKey(); // Its justified so attempt to remove any logical dependencies // for // the handle if (key.getStatus() == EqualityKey.JUSTIFIED) { tms.removeLogicalDependencies(handle); } key.removeFactHandle(handle); handle.setEqualityKey(null); // If the equality key is now empty, then remove it if (key.isEmpty()) { tms.remove(key); } } propagationContext.evaluateActionQueue(this.wm); this.wm.workingMemoryEventSupport.fireObjectRetracted( propagationContext, handle, object, this.wm); this.objectStore.removeHandle(handle); this.handleFactory.destroyFactHandle(handle); this.wm.executeQueuedActions(); if (rule == null) { // This is not needed for internal WM actions as the firing rule will unstage this.wm.getAgenda().unstageActivations(); } } finally { this.wm.endOperation(); this.lock.unlock(); this.ruleBase.readUnlock(); } }
public void update( org.drools.FactHandle factHandle, final Object object, final long mask, final Activation activation) throws FactException { try { this.ruleBase.readLock(); this.lock.lock(); this.wm.startOperation(); this.ruleBase.executeQueuedActions(); InternalFactHandle handle = (InternalFactHandle) factHandle; // the handle might have been disconnected, so reconnect if it has if (handle.isDisconnected()) { handle = this.objectStore.reconnect(factHandle); } final Object originalObject = handle.getObject(); if (handle.getEntryPoint() != this) { throw new IllegalArgumentException( "Invalid Entry Point. You updated the FactHandle on entry point '" + handle.getEntryPoint().getEntryPointId() + "' instead of '" + getEntryPointId() + "'"); } final ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf(this.entryPoint, object); // only needed if we maintain tms, but either way we must get it before we do the retract int status = -1; if (typeConf.isTMSEnabled()) { status = handle.getEqualityKey().getStatus(); } if (handle.getId() == -1 || object == null || (handle.isEvent() && ((EventFactHandle) handle).isExpired())) { // the handle is invalid, most likely already retracted, so return and we cannot assert a // null object return; } if (activation != null) { // release resources so that they can be GC'ed activation.getPropagationContext().releaseResources(); } if (originalObject != object || !AssertBehaviour.IDENTITY.equals( this.ruleBase.getConfiguration().getAssertBehaviour())) { this.objectStore.removeHandle(handle); // set anyway, so that it updates the hashCodes handle.setObject(object); this.objectStore.addHandle(handle, object); } if (typeConf.isTMSEnabled()) { // the hashCode and equality has changed, so we must update the // EqualityKey EqualityKey key = handle.getEqualityKey(); key.removeFactHandle(handle); TruthMaintenanceSystem tms = wm.getTruthMaintenanceSystem(); // If the equality key is now empty, then remove it if (key.isEmpty()) { tms.remove(key); } // now use an existing EqualityKey, if it exists, else create a new one key = tms.get(object); if (key == null) { key = new EqualityKey(handle, status); tms.put(key); } else { key.addFactHandle(handle); } handle.setEqualityKey(key); } this.handleFactory.increaseFactHandleRecency(handle); Rule rule = activation == null ? null : activation.getRule(); final PropagationContext propagationContext = new PropagationContextImpl( this.wm.getNextPropagationIdCounter(), PropagationContext.MODIFICATION, rule, (activation == null) ? null : activation.getTuple(), handle, this.wm.agenda.getActiveActivations(), this.wm.agenda.getDormantActivations(), entryPoint, mask); this.entryPointNode.modifyObject(handle, propagationContext, typeConf, this.wm); propagationContext.evaluateActionQueue(this.wm); this.wm.workingMemoryEventSupport.fireObjectUpdated( propagationContext, factHandle, originalObject, object, this.wm); this.wm.executeQueuedActions(); if (rule == null) { // This is not needed for internal WM actions as the firing rule will unstage this.wm.getAgenda().unstageActivations(); } } finally { this.wm.endOperation(); this.lock.unlock(); this.ruleBase.readUnlock(); } }
protected FactHandle insert( final Object object, final boolean dynamic, boolean logical, final Rule rule, final Activation activation) throws FactException { if (object == null) { // you cannot assert a null object return null; } try { this.wm.startOperation(); ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf(this.entryPoint, object); if (logical && !typeConf.isTMSEnabled()) { enableTMS(object, typeConf); } InternalFactHandle handle = null; if (this.wm.isSequential()) { handle = createHandle(object, typeConf); insert(handle, object, rule, activation, typeConf); return handle; } try { this.ruleBase.readLock(); this.lock.lock(); // check if the object already exists in the WM handle = this.objectStore.getHandleForObject(object); if (typeConf.isTMSEnabled()) { EqualityKey key; TruthMaintenanceSystem tms = wm.getTruthMaintenanceSystem(); if (handle == null) { // lets see if the object is already logical asserted key = tms.get(object); } else { // Object is already asserted, so check and possibly correct its // status and then return the handle key = handle.getEqualityKey(); if (key.getStatus() == EqualityKey.STATED) { // return null as you cannot justify a stated object. return handle; } if (!logical) { // this object was previously justified, so we have to override it to stated key.setStatus(EqualityKey.STATED); tms.removeLogicalDependencies(handle); } else { // this was object is already justified, so just add new logical dependency tms.addLogicalDependency( handle, activation, activation.getPropagationContext(), rule); } return handle; } // At this point we know the handle is null if (key == null) { handle = createHandle(object, typeConf); key = createEqualityKey(handle); tms.put(key); if (!logical) { key.setStatus(EqualityKey.STATED); } else { key.setStatus(EqualityKey.JUSTIFIED); tms.addLogicalDependency( handle, activation, activation.getPropagationContext(), rule); } } else if (!logical) { if (key.getStatus() == EqualityKey.JUSTIFIED) { // Its previous justified, so switch to stated and remove logical dependencies final InternalFactHandle justifiedHandle = key.getFactHandle(); tms.removeLogicalDependencies(justifiedHandle); if (this.wm.discardOnLogicalOverride) { // override, setting to new instance, and return // existing handle key.setStatus(EqualityKey.STATED); handle = key.getFactHandle(); if (AssertBehaviour.IDENTITY.equals( this.ruleBase.getConfiguration().getAssertBehaviour())) { // as assertMap may be using an "identity" // equality comparator, // we need to remove the handle from the map, // before replacing the object // and then re-add the handle. Otherwise we may // end up with a leak. this.objectStore.updateHandle(handle, object); } return handle; } else { // override, then instantiate new handle for // assertion key.setStatus(EqualityKey.STATED); handle = createHandle(object, typeConf); handle.setEqualityKey(key); key.addFactHandle(handle); } } else { handle = createHandle(object, typeConf); key.addFactHandle(handle); handle.setEqualityKey(key); } } else { if (key.getStatus() == EqualityKey.JUSTIFIED) { // only add as logical dependency if this wasn't previously stated tms.addLogicalDependency( key.getFactHandle(), activation, activation.getPropagationContext(), rule); return key.getFactHandle(); } else { // You cannot justify a previously stated equality equal object, so return null return null; } } } else { if (handle != null) { return handle; } handle = createHandle(object, typeConf); } // if the dynamic parameter is true or if the user declared the fact type with the meta tag: // @propertyChangeSupport if (dynamic || typeConf.isDynamic()) { addPropertyChangeListener(handle, dynamic); } insert(handle, object, rule, activation, typeConf); } finally { this.lock.unlock(); this.ruleBase.readUnlock(); } return handle; } finally { this.wm.endOperation(); } }
public void destroyFactHandle(final InternalFactHandle factHandle) { factHandle.invalidate(); }
public final void increaseFactHandleRecency(final InternalFactHandle factHandle) { factHandle.setRecency(this.counter.incrementAndGet()); }