Esempio n. 1
0
void StructuralStatsDatabase::display(OperationContext &context, ostream &out, const DictionaryDatabase *ddb) const
{
	Cursor myCursor(const_cast<DbWrapper&>(db_), getTxn(context), CURSOR_WRITE, 0);
	if(myCursor.error() != 0) throw XmlException(myCursor.error());

	NameID id1;
	NameID id2;
	StructuralStats stats;

	int err = 0;
	while((err = myCursor.get(context.key(), context.data(), DB_NEXT)) == 0) {
		id1.reset();
		id2.reset();
		unmarshalKey(context.key(), id1, id2);
		stats.reset();
		stats.unmarshal(context.data());

		if(ddb) out << ddb->lookupName(context, id1);
		else out << id1;

		if(id2 != 0) {
			if(ddb) out << " -> " << ddb->lookupName(context, id2);
			else out << " -> " << id2;
		}

		out << ": ";

		stats.display(out);

		out << endl;
	}
}
Esempio n. 2
0
int StructuralStatsDatabase::getStats(OperationContext &context, StructuralStats &stats) const
{
	Cursor myCursor(const_cast<DbWrapper&>(db_), getTxn(context), CURSOR_READ, 0);
	if(myCursor.error() != 0) return myCursor.error();

	StructuralStats current;

	// Loop over every node and every node's descendant information
	int err;
	while((err = myCursor.get(context.key(), context.data(), DB_NEXT)) == 0) {
		current.reset();
		current.unmarshal(context.data());
		stats.add(current);
	}

	if(err != DB_NOTFOUND && err != 0) return err;

	if(stats.sumSize_ == 0 && stats.numberOfNodes_ != 0) {
		// Fill in an estimate for the missing size values that you get with DLS
		stats.sumSize_ = NODE_SIZE * stats.numberOfNodes_;
		stats.sumChildSize_ = NODE_SIZE * stats.sumNumberOfChildren_;
		stats.sumDescendantSize_ = NODE_SIZE * stats.sumNumberOfDescendants_;
	}

	return 0;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
	}
	}
}
Esempio n. 6
0
// We assume that key has the correct endianness.
int IndexDatabase::getIndexEntry(OperationContext &context, const DbXmlDbt &key, IndexEntry &ie) const
{
	u_int32_t flags = (context.txn()) ? DB_READ_COMMITTED : 0;
	int err = get(context.txn(), &(const_cast<DbXmlDbt&>(key)), &context.data(), flags);
	if(err == 0) {
		ie.setThisFromDbt(context.data());
	}
	return err;
}
Esempio n. 7
0
int StructuralStatsDatabase::addStats(OperationContext &context, const StructuralStatsDatabase &sdb)
{
	Cursor myCursor(db_, getTxn(context), CURSOR_WRITE, 0);
	if(myCursor.error() != 0) return myCursor.error();

	Cursor sdbCursor(const_cast<DbWrapper&>(sdb.db_), sdb.getTxn(context), CURSOR_READ, 0);
	if(sdbCursor.error() != 0) return sdbCursor.error();

	int err = 0;
	StructuralStats stats;
	StructuralStats current;
	bool nodeStats;

	while((err = sdbCursor.get(context.key(), context.data(), DB_NEXT)) == 0) {

		stats.reset();
		nodeStats = stats.unmarshal(context.data());

		err = myCursor.get(context.key(), context.data(), DB_SET);
		if(err == DB_NOTFOUND) {
			stats.marshal(context.data(), nodeStats);
			err = myCursor.put(context.key(), context.data(), DB_KEYLAST);
		} else if(err == 0) {
			current.unmarshal(context.data());
			current.add(stats);
			current.marshal(context.data(), nodeStats);
			err = myCursor.put(context.key(), context.data(), DB_CURRENT);
		} else break;
	}

	if(err != DB_NOTFOUND) return err;

	return 0;
}
Esempio n. 8
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;
}
Esempio n. 9
0
int StructuralStatsDatabase::addStats(OperationContext &context, const StructuralStatsWriteCache &cache)
{
	Cursor myCursor(db_, getTxn(context), CURSOR_WRITE, 0);
	if(myCursor.error() != 0) return myCursor.error();

	int err = 0;
	StructuralStats current;

	StructuralStatsWriteCache::Map::const_iterator it = cache.cache_.begin();
	for(; err == 0 && it != cache.cache_.end(); ++it) {

		StructuralStatsWriteCache::InnerMap::const_iterator it2 = it->second.begin();
		for(; it2 != it->second.end(); ++it2) {

			marshalKey(it->first, it2->first, context.key());

			err = myCursor.get(context.key(), context.data(), DB_SET);
			if(err == DB_NOTFOUND) {
				it2->second.marshal(context.data(), it2->first == 0);
				err = myCursor.put(context.key(), context.data(), DB_KEYLAST);
			} else if(err == 0) {
				current.unmarshal(context.data());
				current.add(it2->second);
				current.marshal(context.data(), it2->first == 0);
				err = myCursor.put(context.key(), context.data(), DB_CURRENT);
			} else break;
		}
	}

	if(err != DB_NOTFOUND) return err;

	return 0;
}
Esempio n. 10
0
int StructuralStatsDatabase::subtractStats(OperationContext &context, const NameID &id1, const NameID &id2,
	const StructuralStats &stats)
{
	DBXML_ASSERT(id1 != 0 || id2 == 0);

	Cursor myCursor(const_cast<DbWrapper&>(db_), getTxn(context), CURSOR_WRITE, 0);
	if(myCursor.error() != 0) return myCursor.error();

	marshalKey(id1, id2, context.key());
	int err = myCursor.get(context.key(), context.data(), DB_SET);
	if(err != DB_NOTFOUND && err != 0) return err;

	StructuralStats current;

	if(err == DB_NOTFOUND) {
		current.subtract(stats);

		current.marshal(context.data(), id2 == 0);
		err = myCursor.put(context.key(), context.data(), DB_KEYLAST);
	} else {
		current.unmarshal(context.data());
		current.subtract(stats);

		current.marshal(context.data(), id2 == 0);
		err = myCursor.put(context.key(), context.data(), DB_CURRENT);
	}

	return err;
}
Esempio n. 11
0
int StructuralStatsDatabase::getStats(OperationContext &context, const NameID &id1, StructuralStats &stats) const
{
	if(id1 == 0) return getStats(context, stats);

	Cursor myCursor(const_cast<DbWrapper&>(db_), getTxn(context), CURSOR_READ, 0);
	if(myCursor.error() != 0) return myCursor.error();

	NameID cid1, cid2;
	StructuralStats current;

	// Find the node information
	marshalKey(id1, 0, context.key());
	int err = myCursor.get(context.key(), context.data(), DB_SET);
	if(err == DB_NOTFOUND) return getStats(context, stats);

	// Loop over the node information and all it's descendant information
	while(err == 0) {
		cid1.reset();
		unmarshalKey(context.key(), cid1, cid2);
		if(id1 != cid1) break;

		current.reset();
		current.unmarshal(context.data());
		stats.add(current);

		err = myCursor.get(context.key(), context.data(), DB_NEXT);
	}

	if(err != DB_NOTFOUND && err != 0) return err;

	if(stats.sumSize_ == 0 && stats.numberOfNodes_ != 0) {
		// Fill in an estimate for the missing size values that you get with DLS
		stats.sumSize_ = NODE_SIZE * stats.numberOfNodes_;
		stats.sumChildSize_ = NODE_SIZE * stats.sumNumberOfChildren_;
		stats.sumDescendantSize_ = NODE_SIZE * stats.sumNumberOfDescendants_;
	}

	return 0;
}
Esempio n. 12
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;
}
Esempio n. 13
0
int StructuralStatsDatabase::getStats(OperationContext &context, const NameID &id1, const NameID &id2,
	StructuralStats &stats) const
{
	if(id1 == 0) return getStats(context, stats);
	if(id2 == 0) return getStats(context, id1, stats);

	Cursor myCursor(const_cast<DbWrapper&>(db_), getTxn(context), CURSOR_READ, 0);
	if(myCursor.error() != 0) return myCursor.error();

	// Lookup the descendant information
	marshalKey(id1, id2, context.key());
	int err = myCursor.get(context.key(), context.data(), DB_SET);
	if(err == DB_NOTFOUND) return getStats(context, id1, stats);
	if(err != 0) return err;

	stats.unmarshal(context.data());

	// Lookup the node information
	marshalKey(id1, 0, context.key());
	err = myCursor.get(context.key(), context.data(), DB_SET);
	DBXML_ASSERT(err != DB_NOTFOUND);
	if(err != 0) return err;

	stats.unmarshal(context.data());

	if(stats.sumSize_ == 0 && stats.numberOfNodes_ != 0) {
		// Fill in an estimate for the missing size values that you get with DLS
		StructuralStats allStats;
		err = getStats(context, id1, allStats);
		if(err != 0) return err;

		stats.sumSize_ = allStats.sumSize_;
		stats.sumChildSize_ = allStats.sumChildSize_;
		stats.sumDescendantSize_ = allStats.sumDescendantSize_;
	}

	return 0;
}
Esempio n. 14
0
int SyntaxDatabase::updateStatistics(OperationContext &context, DbtIn &key, const KeyStatistics &statistics)
{
	Cursor cursor(*statistics_.get(), context.txn(), CURSOR_WRITE);
	int err = cursor.get(key, context.data(), DB_SET | (context.txn() ? DB_RMW : 0)); // could throw on error
	if (err == 0) {
		KeyStatistics existing;
		existing.setThisFromDbt(context.data());
		existing.add(statistics);
		existing.setDbtFromThis(context.data());
		err = cursor.put(key, context.data(), DB_CURRENT); // could throw on error
	} else if (err == DB_NOTFOUND) {
		statistics.setDbtFromThis(context.data());
		err = cursor.put(key, context.data(), DB_KEYFIRST); // could throw on error
	}
	return err;
}
Esempio n. 15
0
// mutex is locked if present and necessary
int DictionaryDatabase::defineName(OperationContext &context,
				   const Name &name, NameID &id)
{
	// Primary { id -> name\0uri\0 }
	// Secondary { name:uri -> id }
	id.reset();
	name.setDbtFromThis_PrimaryValue(context.data());
	int err = primary_->appendPrimary(context, id, context.data(), /*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(), context.data());
		id.setDbtFromThis(context.key());
		name.setDbtFromThis_SecondaryKey(context.data());
		Transaction *txn = getTxn(context);
		err = secondary_->put(txn, &context.data(), &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(&context.data(), 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;
}
Esempio n. 16
0
double IndexDatabase::percentage(OperationContext &context, Operation operation, Operation gto, Operation lto, const Key &key1, const Key &key2) const
{
	DbtOut &dbt1 = context.key();
	DbtOut &dbt2 = context.data();

	DB_KEY_RANGE krMin;
	getMinKeyDbt(key1, dbt1);
	key_range(context.txn(), &dbt1, &krMin, 0);

	DB_KEY_RANGE krMax;
	getMaxKeyDbt(key1, dbt1);
	key_range(context.txn(), &dbt1, &krMax, 0);

	// range is the % of the database keys that the keys for this index occupy.
	double range = krMax.less - krMin.less;
	double extent = 0.0;

	if (range > 0.0) {
		// extent is the % of the database keys that the keys for this index match this operation.
		DB_KEY_RANGE kr1;
		DB_KEY_RANGE kr2;

		switch(operation) {
		case DbWrapper::PREFIX: {
			key1.setDbtFromThis(dbt1);
			key_range(context.txn(), &dbt1, &kr1, 0);
			getNextKeyDbt(key1, dbt2);
			key_range(context.txn(), &dbt2, &kr2, 0);
			extent = kr2.less - kr1.less;
			break;
		}
		case DbWrapper::LTX:
		case DbWrapper::LTE: {
			key1.setDbtFromThis(dbt2);
			key_range(context.txn(), &dbt2, &kr2, 0);
			extent = kr2.less - krMin.less + (operation == DbWrapper::LTE ? kr2.equal : 0);
			break;
		}
		case DbWrapper::GTX:
		case DbWrapper::GTE: {
			key1.setDbtFromThis(dbt1);
			key_range(context.txn(), &dbt1, &kr1, 0);
			extent = krMax.less + krMax.equal - kr1.less + (operation == DbWrapper::GTX ? kr1.equal : 0);
			break;
		}
		case DbWrapper::RANGE: {
			key1.setDbtFromThis(dbt1);
			key_range(context.txn(), &dbt1, &kr1, 0);
			key2.setDbtFromThis(dbt2);
			key_range(context.txn(), &dbt2, &kr2, 0);
			extent = kr2.less - kr1.less + (lto == DbWrapper::LTE ? kr2.equal : 0) + (gto == DbWrapper::GTX ? kr1.equal : 0);
			break;
		}
		case DbWrapper::EQUALITY: {
			key1.setDbtFromThis(dbt2);
			key_range(context.txn(), &dbt2, &kr2, 0);
			extent = kr2.equal;
			break;
		}
		case DbWrapper::ALL: {
			extent = range;
			break;
		}
		default: {
			break;
		}
		}
	}

	// Return a small percentage in the case of a zero range or extent -
	// it's unlikely that zero is really the right answer
	if(range == 0 || extent == 0) return 0.001;

	// extent/range is the % of keys within this index that match this operation.
	return extent / range;
}