// // Upgrade implementation // // NsUpgradeReader // NsUpgradeReader::NsUpgradeReader( DbWrapper &db, const DocID &docId) : emptyElement_(false), db_(db), encStr_(0), standStr_(0), sniffStr_(0), xmlDecl_(-1), nsInfo_(0), id_(docId), doInit_(true), popElement_(false), entityCount_(0), current_(NULL), currentBuffer_(NULL), cursor_(db, 0, CURSOR_READ, 0), cursorFlags_(0), reuseList_(NULL), freeList_(NULL) { docId.setDbtFromThis(docKey_); initDocInfo(); // Old root nid format -- node ID 4 startBuf_[0] = 0x04; startBuf_[1] = 0; doElement(true /*start*/); }
virtual int seek(DocID &id) { if (last_ >= id) return next(id); id.setDbtFromThis(key_); // DB_SET_RANGE does >= get on the key (which is the id) int err = cursor_.get(key_, data_, DB_SET_RANGE); if(err == DB_NOTFOUND) { err = 0; done_ = true; id = 0; } else if(err == 0) { last_.setThisFromDbt(key_); DBXML_ASSERT(last_ >= id); id = last_; // let caller know where it landed } return err; }
// if toRemove is non-null, it specifies a list of Name IDs // to remove; otherwise remove all metadata for the target document int DocumentDatabase::removeMetaData(OperationContext &oc, const DocID &id, std::vector<NameID> *toRemove) { Cursor cursor(const_cast<SecondaryDatabase&>(secondary_), oc.txn(), CURSOR_WRITE, "DocumentMetaData_remove"); DbtIn none; none.set_flags(DB_DBT_PARTIAL); // Don't pull back the data. id.setDbtFromThis(oc.key()); DocID db_id; int err = cursor.get(oc.key(), none, DB_SET_RANGE); try { while(err == 0) { if (toRemove) { NameID nm_id; XmlValue::Type type; MetaDatum::decodeKeyDbt(oc.key(), db_id, nm_id, type); if ((id == db_id) && idInList(*toRemove, nm_id)) cursor.del(0); } else { db_id.setThisFromDbt(oc.key()); if (id == db_id) cursor.del(0); } if (id != db_id) // done with document? break; err = cursor.get(oc.key(), none, DB_NEXT); } } catch (...) { cursor.close(); throw; } if(err == DB_NOTFOUND) { err = 0; } cursor.close(); return err; }
virtual int next(DocID &id) { int err = 0; if(done_) { id = 0; } else { while((err = cursor_.get(key_, data_, cursorFlags_|DB_NEXT)) == 0) { id.setThisFromDbt(key_); if(id != last_) { last_ = id; break; } } if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { err = 0; done_ = true; id = 0; } } return err; }
int DocumentDatabase::updateContentAndIndex(Document &new_document, UpdateContext &context, KeyStash &stash, bool validate, bool updateStats) { OperationContext &oc = context.getOperationContext(); DocID id = new_document.getID(); Indexer &indexer = context.getIndexer(); IndexSpecification &index = context.getIndexSpecification(); int err = 0; bool resetId = false; // Add DB_RMW if transacted to reduce deadlocks u_int32_t flags = ((oc.txn() && !content_.isCDBEnv()) ? DB_RMW : 0); // Check to see if the old document exists, first // If ID is non-zero, let's trust it. If not, get by name. // Retrieve the old document XmlDocument old_document; if (id == 0) { // will throw if name is bad or doc doesn't exist err = indexer.getContainer()->getDocument( oc, new_document.getName(), old_document, flags); if (err == 0) { id = ((Document&)old_document).getID(); new_document.getIDToSet() = id; resetId = true; } } else { err = indexer.getContainer()->getDocument( oc, id, old_document, flags); } if(err != 0) return err; // Index the new document indexer.indexMetaData(index, new_document, stash, true); if(new_document.isContentModified()) { // Will need the Dbt later, so get it now. This also // allows the content to be used more than once in case // definitiveContent_ is INPUTSTREAM (void) new_document.getContentAsDbt(); // use private method that explicitly assumes Dbt content ScopedPtr<NsPushEventSource> source(new_document.dbt2events( oc.txn(), /*needsValidation*/validate, indexer.getContainer()->nodesIndexed())); if (source.get()) { indexer.initIndexContent(index, id, source.get(), stash, updateStats, true, /*isDelete*/false); source.get()->start(); } } // Set the modified flags of the old document to the same as the // new document, so that when we index, we only generate keys for // things that have actually changed. MetaData::const_iterator end = new_document.metaDataEnd(); for(MetaData::const_iterator i = new_document.metaDataBegin(); i != end; ++i) { if((*i)->isModified()) { const MetaDatum *md = ((Document&)old_document) .getMetaDataPtr((*i)->getName()); if(md != 0) const_cast<MetaDatum*>(md)->setModified(true); } } // Remove the index keys for the old document IndexSpecification delete_index(index); delete_index.set(Index::INDEXER_DELETE); indexer.indexMetaData(delete_index, old_document, stash, true); if(new_document.isContentModified()) { ScopedPtr<NsPushEventSource> source(((Document&)old_document). getContentAsEventSource( oc.txn(), /*needsValidation*/false, indexer.getContainer()->nodesIndexed())); if (source.get()) { indexer.initIndexContent(delete_index, id, source.get(), stash, updateStats, false, /*isDelete*/true); source.get()->start(); } } // Update the content if(new_document.isContentModified()) { OperationContext &oc = context.getOperationContext(); id.setDbtFromThis(oc.key()); DbXmlDbt *dbt = (DbXmlDbt*)new_document.getContentAsDbt(); err = addContent(oc.txn(), oc.key(),dbt, 0); } if(err == 0) new_document.setContentModified(false); if (resetId) new_document.getIDToSet() = 0; return err; }