Пример #1
0
bool DictionaryDatabase::stringCacheLookup(OperationContext &context,
					   DbXmlDbt &dbt, NameID &id) const
{
	nameId_t *nid = 0;
	Transaction *txn = getTxn(context);
	if (txn) {
		DictionaryStringCache *dsc =
			txn->getStringCache(const_cast<DictionaryDatabase*>(this), false);
		if (dsc) {
			nid = dsc->lookup(&dbt);
			if (nid) {
				DbXmlDbt dbt((void *)nid, sizeof(nameId_t));
				id.setThisFromDbtAsId(dbt);
				return true;
			}
		}
	}
	nid = stringCache_.lookup(&dbt);
	if (nid) {
		DbXmlDbt tdbt((void *)nid, sizeof(nameId_t));
		id.setThisFromDbtAsId(tdbt);
		return true;
	}
	return false;
}
Пример #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
void DictionaryDatabase::display(OperationContext &context, ostream &out) const
{
	{
	Cursor myCursor(const_cast<PrimaryDatabase&>(*primary_.get()), getTxn(context), CURSOR_READ, 0);
	if(myCursor.error() != 0) throw XmlException(myCursor.error());

	int err = 0;
	NameID id;
	while((err = myCursor.get(context.key(), context.data(), DB_NEXT)) == 0) {
		id.setThisFromDbtAsId(context.key());
		Buffer val(context.data().data, context.data().size, true);
		out << id << " -> " << val.asString(true) << endl;
	}
	}
	{
	Cursor myCursor(const_cast<SecondaryDatabase&>(*secondary_.get()), getTxn(context), CURSOR_READ, 0);
	if(myCursor.error() != 0) throw XmlException(myCursor.error());

	int err = 0;
	NameID id;
	while((err = myCursor.get(context.key(), context.data(), DB_NEXT)) == 0) {
		Buffer val(context.key().data, context.key().size, true);
		id.setThisFromDbt(context.data());
		out << val.asString(true) << " -> " << id << endl;
	}
	}
}
Пример #4
0
static void unmarshalKey(const DbtOut &dbt, NameID &id1, NameID &id2)
{
	const xmlbyte_t *ptr = (const xmlbyte_t*)dbt.data;
	const xmlbyte_t *end = ptr + dbt.size;

	++ptr; // Skip the prefix
	if(ptr < end) ptr += id1.unmarshal(ptr);
	if(ptr < end) ptr += id2.unmarshal(ptr);
}
Пример #5
0
static void marshalKey(const NameID &id1, const NameID &id2, DbtOut &dbt)
{
	DBXML_ASSERT(id1 != 0 || id2 == 0);

	int size = 1;
	if(id1 != 0) size += id1.marshalSize();
	if(id2 != 0) size += id2.marshalSize();

	dbt.set(0, size);

	xmlbyte_t *ptr = (xmlbyte_t*)dbt.data;
	*ptr++ = KEY_PREFIX_BYTE;
	if(id1 != 0) ptr += id1.marshal(ptr);
	if(id2 != 0) ptr += id2.marshal(ptr);
}
Пример #6
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;
}
Пример #7
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;
		}
	}
}
Пример #8
0
int PrimaryDatabase::appendPrimary(OperationContext &context, NameID &id,
				   const DbXmlDbt &data, u_int32_t flags)
{
	int err = put(context.txn(), &context.key(), &(const_cast<DbXmlDbt&>(data)),
		      flags | DB_APPEND);
	if (err == 0)
		id.setThisFromDbtAsId(context.key());
	return err;
}
Пример #9
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
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;
}
Пример #14
0
// use DB prefix iterator to remove all index entries for the specified index.
// do both index and statistics databases.
// The prefix is <indexKeyPrefix>[<nameId>]
int SyntaxDatabase::removeIndex(OperationContext &context, const Index &index,
				const NameID &id)
{
	// key is <indexType><name ID>, which is one byte plus a marshaled integer.
	unsigned char keybuf[10];
	keybuf[0] = index.getKeyPrefix();
	u_int32_t sz = 1;
	if (id != 0) {
		// not a default index
		sz += id.marshal(keybuf+1);
	}
	int err = removeIndexEntries(context, *index_.get(), keybuf, sz);
	if (err == 0)
		err = removeIndexEntries(context, *statistics_.get(), keybuf, sz);
	return err;
}
Пример #15
0
int PrimaryDatabase::getPrimary(OperationContext &context, const NameID &id,
				DbtOut *data, u_int32_t flags) const
{
	id.setDbtFromThis(context.key());
	return get(context.txn(), &context.key(), data, flags);
}
Пример #16
0
int PrimaryDatabase::deletePrimary(OperationContext &context,
				   const NameID &id, u_int32_t flags)
{
	id.setDbtFromThis(context.key());
	return del(context.txn(), &context.key(), flags);
}
Пример #17
0
int PrimaryDatabase::putPrimary(OperationContext &context, const NameID &id,
				const DbXmlDbt &data, u_int32_t flags)
{
	id.setDbtFromThis(context.key());
	return put(context.txn(), &context.key(), &(const_cast<DbXmlDbt&>(data)), flags);
}