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