Example #1
0
bool DecisionPointIterator::nextContainer(int contID, DynamicContext *context)
{
	DbXmlConfiguration *conf = GET_CONFIGURATION(context);

	{
		// Find the correct QueryPlan for the container
		//
		// Hold the compile time mutex whilst searching the linked list.
		// This stops the list from being modified by just-in-time
		// optimisation while we traverse it.
		//
		// (The mutex in the runtime configuration is the same as the
		// one from the compile time configuration.)
		MutexLock lock(conf->getMutex());
		while(list_ != 0 && list_->container->getContainerID() < contID) {
			list_ = list_->next;
		}
	}

	if(list_ == 0 || list_->container->getContainerID() != contID) {
		list_ = const_cast<DecisionPointQP*>(dp_)->justInTimeOptimize(contID, context);
	}
	AutoDecisionPointIteratorReset reset(conf, this);
	result_ = list_->qp->createNodeIterator(context);

	return true;
}
Example #2
0
DecisionPointQP::ListItem *DecisionPointQP::justInTimeOptimize(int contID, DynamicContext *context)
{
	// **** IMPORTANT - This algorithm is very carefully arranged to avoid
	// **** deadlocks and race-conditions. Don't rearrange things unless you
	// **** know what you are doing!
	
	// Get the runtime configuration
	DbXmlConfiguration *conf = GET_CONFIGURATION(context);

	// Lookup the container
	ScopedContainer scont((Manager&)conf->getManager(), contID, /*mustExist*/true);

	// Just-in-time optimise the QueryPlan, using a temporary memory manager for thread safety
	XPath2MemoryManagerImpl tmpMM;
	QueryPlan *qp;
	{
		AutoMemoryManagerReset resetMM(context, &tmpMM);

		qp = arg_->copy(&tmpMM);
		try {
			AutoDecisionPointReset reset(conf, this);
			justInTimeOptimize(qp, scont.get(), context);
		}
		catch(XmlException &e) {
			if(e.getQueryLine() == 0)
				e.setLocationInfo(this);
			throw;
		}
	}

	// Hold the compile time mutex whilst altering the query plan.
	// This protects the compile time XPath2MemoryManager as well
	// as the query plan itself.
	//
	// (The mutex in the runtime configuration is the same as the
	// one from the compile time configuration.)
	MutexLock lock(conf->getMutex());

	// Now we hold the lock, re-search qpList_ for the container,
	// in case someone beat us to creating it.
	DecisionPointQP::ListItem **li = &qpList_;
	while(*li != 0 && (*li)->container->getContainerID() < contID) {
		li = &(*li)->next;
	}

	if(*li == 0 || (*li)->container->getContainerID() != contID) {
		// Add the container to the compile time ReferenceMinder, in case it has been auto-opened
		if (contID > 0)
			compileTimeMinder_->addContainer(scont.getContainer());

		// Create a new ListItem and copy the optimised QueryPlan using the
		// compile time memory manager - so that they can both become a
		// permanent part of the query's AST
		XPath2MemoryManager *compile_mm = compileTimeContext_->getMemoryManager();
		DecisionPointQP::ListItem *newListItem = new (compile_mm) DecisionPointQP::ListItem(scont.get(), *li);
		newListItem->qp = qp->copy(compile_mm);
		newListItem->qp->staticTypingLite(compileTimeContext_);

		// Only add the new ListItem to the linked list once it is fully optimised
		// and ready to execute - otherwise another thread could come along and try
		// to use it.
		*li = newListItem;
	}
	else {
		// All our work was in vain! Someone beat us to creating a QueryPlan
		// for this container. Oh well, we'll just use the existing one then...
	}

	qp->release();
	return *li;
}