/** * 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 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; }