public static void writeInitialFactHandleRightTuples(MarshallerWriteContext context) throws IOException { ObjectOutputStream stream = context.stream; InternalRuleBase ruleBase = context.ruleBase; ObjectTypeNode initialFactNode = ruleBase .getRete() .getEntryPointNode(EntryPoint.DEFAULT) .getObjectTypeNodes() .get(ClassObjectType.InitialFact_ObjectType); // do we write the fact to the objecttypenode memory if (initialFactNode != null) { ObjectHashSet initialFactMemory = (ObjectHashSet) context.wm.getNodeMemory(initialFactNode); if (initialFactMemory != null && !initialFactMemory.isEmpty()) { // context.out.println( "InitialFactMemory true int:" + initialFactNode.getId() ); stream.writeBoolean(true); stream.writeInt(initialFactNode.getId()); // context.out.println( "InitialFact RightTuples" ); writeRightTuples(context.wm.getInitialFactHandle(), context); } else { // context.out.println( "InitialFactMemory false " ); stream.writeBoolean(false); } } else { // context.out.println( "InitialFactMemory false " ); stream.writeBoolean(false); } }
/** * TMS will be automatically enabled when the first logical insert happens. * * <p>We will take all the already asserted objects of the same type and initialize the equality * map. * * @param object the logically inserted object. * @param conf the type's configuration. */ private void enableTMS(Object object, ObjectTypeConf conf) { final Rete source = this.ruleBase.getRete(); final ClassObjectType cot = new ClassObjectType(object.getClass()); final Map<ObjectType, ObjectTypeNode> map = source.getObjectTypeNodes(EntryPoint.DEFAULT); final ObjectTypeNode node = map.get(cot); final ObjectHashSet memory = ((ObjectTypeNodeMemory) this.wm.getNodeMemory(node)).memory; // All objects of this type that are already there were certainly stated, // since this method call happens at the first logical insert, for any given type. org.drools.core.util.Iterator it = memory.iterator(); for (Object obj = it.next(); obj != null; obj = it.next()) { org.drools.core.util.ObjectHashSet.ObjectEntry holder = (org.drools.core.util.ObjectHashSet.ObjectEntry) obj; InternalFactHandle handle = (InternalFactHandle) holder.getValue(); if (handle != null) { EqualityKey key = createEqualityKey(handle); key.setStatus(EqualityKey.STATED); this.wm.getTruthMaintenanceSystem().put(key); } } // Enable TMS for this type. conf.enableTMS(); }
public void dispose() { if (dynamicFacts != null) { // first we check for facts that were inserted into the working memory // using the old API and setting a per instance dynamic flag and remove the // session from the listeners list in the bean for (InternalFactHandle handle : dynamicFacts) { removePropertyChangeListener(handle, false); } dynamicFacts = null; } for (ObjectTypeConf conf : this.typeConfReg.values()) { // then, we check if any of the object types were configured using the // @propertyChangeSupport annotation, and clean them up if (conf.isDynamic() && conf.isSupportsPropertyChangeListeners()) { // it is enough to iterate the facts on the concrete object type nodes // only, as the facts will always be in their concrete object type nodes // even if they were also asserted into higher level OTNs as well ObjectTypeNode otn = conf.getConcreteObjectTypeNode(); final ObjectHashSet memory = ((ObjectTypeNodeMemory) this.getInternalWorkingMemory().getNodeMemory(otn)).memory; Iterator it = memory.iterator(); for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { InternalFactHandle handle = (InternalFactHandle) entry.getValue(); removePropertyChangeListener(handle, false); } } } }
/** * OTN needs to override remove to avoid releasing the node ID, since OTN are never removed from * the rulebase in the current implementation */ protected void doRemove( final RuleRemovalContext context, final ReteooBuilder builder, final BaseNode node, final InternalWorkingMemory[] workingMemories) { if (context.getCleanupAdapter() != null) { for (InternalWorkingMemory workingMemory : workingMemories) { CleanupAdapter adapter = context.getCleanupAdapter(); final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this); Iterator it = memory.iterator(); for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { InternalFactHandle handle = (InternalFactHandle) entry.getValue(); for (LeftTuple leftTuple = handle.getFirstLeftTuple(); leftTuple != null; leftTuple = leftTuple.getLeftParentNext()) { adapter.cleanUp(leftTuple, workingMemory); } } } context.setCleanupAdapter(null); } if (!node.isInUse()) { removeObjectSink((ObjectSink) node); } }
/** * When L&R Unlinking is enabled, updateSink() is used to populate a node's memory, but it has to * take into account if it's propagating. */ private void updateLRUnlinking( final ObjectSink sink, final PropagationContext context, final InternalWorkingMemory workingMemory) { final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this); Iterator it = memory.iterator(); InternalFactHandle ctxHandle = (InternalFactHandle) context.getFactHandle(); if (!context.isPropagating(this) || (context.isPropagating(this) && context.shouldPropagateAll())) { for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { // Assert everything sink.assertObject((InternalFactHandle) entry.getValue(), context, workingMemory); } } else { for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { InternalFactHandle handle = (InternalFactHandle) entry.getValue(); // Exclude the current fact propagation if (handle.getId() != ctxHandle.getId()) { sink.assertObject(handle, context, workingMemory); } } } }
/** * Propagate the <code>FactHandleimpl</code> through the <code>Rete</code> network. All <code> * FactHandleImpl</code> should be remembered in the node memory, so that later runtime rule * attachmnents can have the matched facts propagated to them. * * @param factHandle The fact handle. * @param object The object to assert. * @param workingMemory The working memory session. */ public void assertObject( final InternalFactHandle factHandle, final PropagationContext context, final InternalWorkingMemory workingMemory) { if (objectMemoryEnabled && !(queryNode && !((DroolsQuery) factHandle.getObject()).isOpen())) { final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this); memory.add(factHandle, false); } if (compiledNetwork != null) { compiledNetwork.assertObject(factHandle, context, workingMemory); } else { context.setCurrentPropagatingOTN(this); this.sink.propagateAssertObject(factHandle, context, workingMemory); } if (this.objectType.isEvent() && this.expirationOffset >= 0 && this.expirationOffset != Long.MAX_VALUE) { // schedule expiration WorkingMemoryReteExpireAction expire = new WorkingMemoryReteExpireAction(factHandle, this); TimerService clock = workingMemory.getTimerService(); long nextTimestamp = Math.max( clock.getCurrentTime() + this.expirationOffset, ((EventFactHandle) factHandle).getStartTimestamp() + this.expirationOffset); JobContext jobctx = new ExpireJobContext(expire, workingMemory); JobHandle handle = clock.scheduleJob(job, jobctx, new PointInTimeTrigger(nextTimestamp, null, null)); jobctx.setJobHandle(handle); } }
public static void readFactHandles(MarshallerReaderContext context, ObjectStore objectStore) throws IOException, ClassNotFoundException { ObjectInputStream stream = context.stream; InternalWorkingMemory wm = context.wm; int size = stream.readInt(); // load the handles InternalFactHandle[] handles = new InternalFactHandle[size]; for (int i = 0; i < size; i++) { InternalFactHandle handle = readFactHandle(context); context.handles.put(handle.getId(), handle); handles[i] = handle; if (handle.getObject() != null) { objectStore.addHandle(handle, handle.getObject()); } readRightTuples(handle, context); } readLeftTuples(context); // object store if (stream.readBoolean()) { readLeftTuples(context); // activation fact handles } // add handles to object type nodes for (InternalFactHandle factHandle : handles) { Object object = factHandle.getObject(); EntryPoint ep = ((InternalWorkingMemoryEntryPoint) factHandle.getEntryPoint()).getEntryPoint(); ObjectTypeConf typeConf = ((InternalWorkingMemoryEntryPoint) factHandle.getEntryPoint()) .getObjectTypeConfigurationRegistry() .getObjectTypeConf(ep, object); ObjectTypeNode[] cachedNodes = typeConf.getObjectTypeNodes(); for (int i = 0, length = cachedNodes.length; i < length; i++) { ObjectHashSet set = (ObjectHashSet) wm.getNodeMemory(cachedNodes[i]); set.add(factHandle, false); } } }
public void updateSink( final ObjectSink sink, final PropagationContext context, final InternalWorkingMemory workingMemory) { if (lrUnlinkingEnabled) { // Update sink taking into account L&R unlinking peculiarities updateLRUnlinking(sink, context, workingMemory); } else { // Regular updateSink final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this); Iterator it = memory.iterator(); for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) { sink.assertObject((InternalFactHandle) entry.getValue(), context, workingMemory); } } }
/** * Retract the <code>FactHandleimpl</code> from the <code>Rete</code> network. Also remove the * <code>FactHandleImpl</code> from the node memory. * * @param rightTuple The fact handle. * @param object The object to assert. * @param workingMemory The working memory session. */ public void retractObject( final InternalFactHandle factHandle, final PropagationContext context, final InternalWorkingMemory workingMemory) { if (objectMemoryEnabled && !(queryNode && !((DroolsQuery) factHandle.getObject()).isOpen())) { final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory(this); memory.remove(factHandle); } for (RightTuple rightTuple = factHandle.getFirstRightTuple(); rightTuple != null; rightTuple = (RightTuple) rightTuple.getHandleNext()) { rightTuple.getRightTupleSink().retractRightTuple(rightTuple, context, workingMemory); } factHandle.clearRightTuples(); for (LeftTuple leftTuple = factHandle.getFirstLeftTuple(); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getLeftParentNext()) { leftTuple.getLeftTupleSink().retractLeftTuple(leftTuple, context, workingMemory); } factHandle.clearLeftTuples(); }
public static ReteooStatefulSession readSession( ReteooStatefulSession session, DefaultAgenda agenda, long time, boolean multithread, MarshallerReaderContext context) throws IOException, ClassNotFoundException { if (session.getTimerService() instanceof PseudoClockScheduler) { PseudoClockScheduler clock = (PseudoClockScheduler) session.getTimerService(); clock.advanceTime(time, TimeUnit.MILLISECONDS); } // RuleFlowGroups need to reference the session for (RuleFlowGroup group : agenda.getRuleFlowGroupsMap().values()) { ((RuleFlowGroupImpl) group).setWorkingMemory(session); } context.wm = session; context.handles.put( context.wm.getInitialFactHandle().getId(), context.wm.getInitialFactHandle()); if (context.stream.readBoolean()) { InternalFactHandle initialFactHandle = context.wm.getInitialFactHandle(); int sinkId = context.stream.readInt(); ObjectTypeNode initialFactNode = (ObjectTypeNode) context.sinks.get(sinkId); if (initialFactNode == null) { // ------ START RANT ------ // The following code is as bad as it looks, but since I was so far // unable to convince Mark that creating OTNs on demand is really bad, // I have to continue doing it :) EntryPointNode defaultEPNode = context.ruleBase.getRete().getEntryPointNode(EntryPoint.DEFAULT); BuildContext buildContext = new BuildContext( context.ruleBase, context.ruleBase.getReteooBuilder().getIdGenerator()); buildContext.setPartitionId(RuleBasePartitionId.MAIN_PARTITION); buildContext.setObjectTypeNodeMemoryEnabled(true); initialFactNode = new ObjectTypeNode( sinkId, defaultEPNode, ClassObjectType.InitialFact_ObjectType, buildContext); // isn't contention something everybody loves? context.ruleBase.lock(); try { // Yeah, I know, because one session is being deserialized, we go and lock all of them... initialFactNode.attach(buildContext); } finally { context.ruleBase.unlock(); } // ------- END RANT ----- } ObjectHashSet initialFactMemory = (ObjectHashSet) context.wm.getNodeMemory(initialFactNode); initialFactMemory.add(initialFactHandle); readRightTuples(initialFactHandle, context); } while (context.readShort() == PersisterEnums.ENTRY_POINT) { String entryPointId = context.stream.readUTF(); WorkingMemoryEntryPoint wmep = context.wm.getEntryPoints().get(entryPointId); readFactHandles(context, ((NamedEntryPoint) wmep).getObjectStore()); } InternalFactHandle handle = context.wm.getInitialFactHandle(); while (context.stream.readShort() == PersisterEnums.LEFT_TUPLE) { LeftTupleSink sink = (LeftTupleSink) context.sinks.get(context.stream.readInt()); LeftTuple leftTuple = sink.createLeftTuple(handle, sink, true); readLeftTuple(leftTuple, context); } readPropagationContexts(context); readActivations(context); readActionQueue(context); readTruthMaintenanceSystem(context); if (processMarshaller != null) { processMarshaller.readProcessInstances(context); } else { short type = context.stream.readShort(); if (PersisterEnums.END != type) { throw new IllegalStateException( "No process marshaller, unable to unmarshall type: " + type); } } if (processMarshaller != null) { processMarshaller.readWorkItems(context); } else { short type = context.stream.readShort(); if (PersisterEnums.END != type) { throw new IllegalStateException( "No process marshaller, unable to unmarshall type: " + type); } } if (processMarshaller != null) { // This actually does ALL timers, due to backwards compatability issues // It will read in old JBPM binaries, but always write to the new binary format. processMarshaller.readProcessTimers(context); } else { short type = context.stream.readShort(); if (PersisterEnums.END != type) { throw new IllegalStateException( "No process marshaller, unable to unmarshall type: " + type); } } // no legacy jBPM timers, so handle locally while (context.readShort() == PersisterEnums.DEFAULT_TIMER) { InputMarshaller.readTimer(context); } if (multithread) { session.startPartitionManagers(); } return session; }