int DocumentDatabase::removeContentAndIndex(const Document &document, UpdateContext &context, KeyStash &stash, bool updateStats) { Indexer &indexer = context.getIndexer(); OperationContext &oc = context.getOperationContext(); // Index the document IndexSpecification &index = context.getIndexSpecification(); index.set(Index::INDEXER_DELETE); indexer.indexMetaData(index, document, stash, /*checkModified*/false); ScopedPtr<NsPushEventSource> source(document.getContentAsEventSource( oc.txn(), /*needsValidation*/false, indexer.getContainer()->nodesIndexed())); if (source.get()) { indexer.initIndexContent(index, document.getID(), source.get(), stash, updateStats, false, /*isDelete*/true); source.get()->start(); } // Delete the content deleteID(oc, document.getID()); // a no-op document.getID().setDbtFromThis(oc.key()); int err = content_.del(oc.txn(), &oc.key(), 0); if (err == DB_NOTFOUND) err = 0; // no-content doc 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; }