Пример #1
0
int DictionaryDatabase::lookupNameFromID(OperationContext &context,
					 const NameID &id, Name &name) const
{
	int err = 0;
	nameId_t raw = id.raw() - 1; // id space is 1-based, not 0
	if (id == nidName_) {
		name = Name::dbxml_colon_name;
		return 0;
	} else if (id == nidRoot_) {
		name = Name::dbxml_colon_root;
		return 0;
	}
	
	if ((raw < DICTIONARY_RESERVE_SIZE) && usePreloads_) {
		name = preloadNames[raw];
	} else {
		err = lookupFromID(context, context.data(), id);
		if (err == 0) {
			name.setThisFromDbt(context.data());
		} else {
			name.reset();
		}
	}
	return err;
}
Пример #2
0
int DictionaryDatabase::lookupIDFromName(OperationContext &context,
					 const Name &name,
					 NameID &id, bool define)
{
	int err = 0;
	if (name == Name::dbxml_colon_name) {
		id = nidName_;
	} else if (name == Name::dbxml_colon_root) {
		id = nidRoot_;
	}
	if (id == 0) {
		MutexLock ml(mutex_);
		u_int32_t flags = (getTxn(context) && !define) ? DB_READ_COMMITTED : 0;
		name.setDbtFromThis_SecondaryKey(context.key());
		if (stringCacheLookup(context, context.key(), id))
			return 0;
		err = secondary_->get(getTxn(context), &context.key(), &context.data(), flags);
		if (err == 0) {
			id.setThisFromDbt(context.data());
			stringCache_.insert(&context.key(), id.raw());
		} else if (err == DB_NOTFOUND && define) {
			err = defineName(context, name, id); // define from name:uri
		} else {
			id.reset();
		}
	}
	return err;
}
Пример #3
0
// Basic lookup, returning a pointer that will be valid
// until this object is deleted.  Lookup does not require locking
// because entries are never removed, and they are only added
// at the beginning of the hash chain with a simple pointer update.
// A race condition could theoretically happen if a compiler reorders
// some of the code in insert
bool
DictionaryCache::lookup(OperationContext &context, const NameID &id,
			DbtOut &dbt, bool useDictionary)
{
	while (true) { // will only ever loop once
		nameId_t nid = id.raw();
		int bucket = hash(nid);
		DictionaryCacheEntry *current = htable_[bucket];
		while (current && (current->getNid() != nid))
			current = current->getNext();
		if (current) {
			dbt.set(current->getValue(), current->getLen());
			return true;
		}
		if (!useDictionary)
			return false;
		// read through the dictionary
		int ret = ddb_->lookupStringNameFromID(context, id, dbt);
		if (ret == 0) {
			DBXML_ASSERT(dbt.size);
			insert(nid, dbt);
		} else {
			// this should never happen, but if it does,
			// be silent (for now)
			return false;
		}
	}
}
Пример #4
0
// mutex is locked if present and necessary
int DictionaryDatabase::defineStringName(OperationContext &context,
					 const char *name, size_t namelen,
					 NameID &id)
{
	// Primary { id -> name\0 }
	// Secondary { name -> id }
	int err = 0;
	id.reset();
	DbtIn primaryData((void*)name, namelen + 1); // add null
	DbtIn secondaryKey((void*)name, namelen); // don't add null
	err = primary_->appendPrimary(context, id,
				      primaryData, /*no flags*/0);
	if (err == 0) {
		/* Cache after insert.  This prevents the cache from returning bad answers
		 * on a transaction abort, and speeds up access to newly inserted element
		 * and attribute names that are needed for indexing after an insert.  
		 */
		cache_.insert(id.raw(), primaryData);
		id.setDbtFromThis(context.key());
		Transaction *txn = getTxn(context);
		err = secondary_->put(txn, &secondaryKey,
				      &context.key(),
				      /*no flags*/0);
		if (err == 0) {
			/* Add to the transaction's string cache, that way if an abort occurs
			 * the values can be removed from the cache. 
			 */
			if (txn) { 
				DictionaryStringCache *dsc = txn->getStringCache(this, true);
				dsc->insert(&secondaryKey, id.raw());
			}
			if (Log::isLogEnabled(Log::C_DICTIONARY, Log::L_INFO)) {
				ostringstream oss;
				oss << "Define new name " << id << " -> " << name;
				Log::log(environment_, Log::C_DICTIONARY, Log::L_INFO,
					name_.c_str(),
					oss.str().c_str());
			}
		}
	}
	return err;
}
Пример #5
0
int DictionaryDatabase::lookupStringNameFromID(
	OperationContext &context,
	const NameID &id, DbtOut &dbt) const
{
	int err = 0;
	nameId_t raw = id.raw() - 1; // id space is 1-based, not 0
	if ((raw < DICTIONARY_RESERVE_SIZE) && usePreloads_) {
		const char *name = preloadNames[raw];
		dbt.set((const void *)name, ::strlen(name) + 1);
	} else
		err = lookupFromID(context, dbt, id);

	return err;
}
Пример #6
0
int DictionaryDatabase::lookupStringNameFromID(
	OperationContext &context,
	const NameID &id, const char **name) const
{
	int err = 0;
	nameId_t raw = id.raw() - 1; // id space is 1-based, not 0
	if ((raw < DICTIONARY_RESERVE_SIZE) && usePreloads_) {
		*name = preloadNames[raw];
	} else {
		err = lookupFromID(context, context.data(), id);
		if (err == 0)
			*name = (const char *)context.data().data;
	}

	return err;
}
Пример #7
0
// puts result in dbt, which may be context.data(), or may be user-provided
int DictionaryDatabase::lookupFromID(
	OperationContext &context, DbtOut &dbt,
	const NameID &id) const
{
	int err = 0;
	if (cache_.lookup(context, id, dbt, false))
		return 0;
	u_int32_t flags = (getTxn(context)) ? DB_READ_COMMITTED : 0;
	// primary key is the integer value of the id (database is
	// recno)
	id.setDbtFromThisAsId(context.key());
	MutexLock ml(mutex_);
	err = primary_->get(getTxn(context), &context.key(),
			    &dbt, flags);
	if (err == 0)
		cache_.insert(id.raw(), dbt);
	return err;
}
Пример #8
0
int DictionaryDatabase::lookupIDFromStringNameInternal(
	OperationContext &context,
	DbXmlDbt &dbt,
	NameID &id,
	bool define) const
{
	if (!dbt.size) {
		id.reset();
		return 0;
	}
	u_int32_t flags = (getTxn(context) && !define) ? DB_READ_COMMITTED : 0;
	if (stringCacheLookup(context, dbt, id))
			return 0;
	int err = secondary_->get(getTxn(context), &dbt,
				  &context.data(), flags);
	if (err == 0) {
		id.setThisFromDbt(context.data());
		stringCache_.insert(&dbt, id.raw());
	} else
		id.reset();
	return err;
}