summaryrefslogtreecommitdiff
path: root/src/mongo/db/index
diff options
context:
space:
mode:
authorHari Khalsa <hkhalsa@10gen.com>2014-04-22 17:49:46 -0400
committerHari Khalsa <hkhalsa@10gen.com>2014-04-25 14:27:37 -0400
commit892eb99b4469e2d35570bbfd07f57b87fc2376e0 (patch)
treed667d7c92c8fa2b34365ad15773123c692068539 /src/mongo/db/index
parentece2f2e2b997eb5c21328966ce2ccff9bdfe4db2 (diff)
downloadmongo-892eb99b4469e2d35570bbfd07f57b87fc2376e0.tar.gz
SERVER-13084 migrate builder to new iface, some clean-up
Diffstat (limited to 'src/mongo/db/index')
-rw-r--r--src/mongo/db/index/btree_access_method.h5
-rw-r--r--src/mongo/db/index/btree_based_access_method.cpp299
-rw-r--r--src/mongo/db/index/btree_based_access_method.h7
-rw-r--r--src/mongo/db/index/btree_based_bulk_access_method.cpp210
-rw-r--r--src/mongo/db/index/btree_based_bulk_access_method.h140
-rw-r--r--src/mongo/db/index/hash_access_method.cpp1
6 files changed, 381 insertions, 281 deletions
diff --git a/src/mongo/db/index/btree_access_method.h b/src/mongo/db/index/btree_access_method.h
index dbe1a7980af..d40bc013767 100644
--- a/src/mongo/db/index/btree_access_method.h
+++ b/src/mongo/db/index/btree_access_method.h
@@ -31,10 +31,9 @@
#include <boost/scoped_ptr.hpp>
#include "mongo/base/status.h"
-#include "mongo/db/structure/btree/btree.h"
-#include "mongo/db/index/index_access_method.h"
-#include "mongo/db/index/btree_key_generator.h"
#include "mongo/db/index/btree_based_access_method.h"
+#include "mongo/db/index/btree_key_generator.h"
+#include "mongo/db/index/index_access_method.h"
#include "mongo/db/jsobj.h"
namespace mongo {
diff --git a/src/mongo/db/index/btree_based_access_method.cpp b/src/mongo/db/index/btree_based_access_method.cpp
index 11b4b92f9c2..ebd933cb0ac 100644
--- a/src/mongo/db/index/btree_based_access_method.cpp
+++ b/src/mongo/db/index/btree_based_access_method.cpp
@@ -34,6 +34,7 @@
#include "mongo/base/status.h"
#include "mongo/db/curop.h"
#include "mongo/db/extsort.h"
+#include "mongo/db/index/btree_based_bulk_access_method.h"
#include "mongo/db/index/btree_index_cursor.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/keypattern.h"
@@ -42,8 +43,6 @@
#include "mongo/db/pdfile_private.h"
#include "mongo/db/repl/is_master.h"
#include "mongo/db/repl/rs.h"
-#include "mongo/db/sort_phase_one.h"
-#include "mongo/db/structure/btree/btreebuilder.h"
#include "mongo/db/structure/btree/btree_interface.h"
#include "mongo/util/progress_meter.h"
@@ -189,22 +188,7 @@ namespace mongo {
}
Status BtreeBasedAccessMethod::initializeAsEmpty() {
- if ( !_btreeState->head().isNull() )
- return Status( ErrorCodes::InternalError, "index already initialized" );
-
- DiskLoc newHead;
- if ( 0 == _descriptor->version() ) {
- newHead = BtreeBucket<V0>::addBucket( _btreeState );
- }
- else if ( 1 == _descriptor->version() ) {
- newHead = BtreeBucket<V1>::addBucket( _btreeState );
- }
- else {
- return Status( ErrorCodes::InternalError, "invalid index number" );
- }
- _btreeState->setHead( newHead );
-
- return Status::OK();
+ return _newInterface->initAsEmpty();
}
Status BtreeBasedAccessMethod::touch(const BSONObj& obj) {
@@ -220,23 +204,26 @@ namespace mongo {
return Status::OK();
}
- DiskLoc BtreeBasedAccessMethod::findSingle( const BSONObj& key ) const {
- DiskLoc head = _btreeState->head();
- Record* record = _btreeState->recordStore()->recordFor( head );
+ DiskLoc BtreeBasedAccessMethod::findSingle(const BSONObj& key) const {
+ DiskLoc bucket;
+ int pos;
+
+ _newInterface->locate(key, minDiskLoc, 1, &bucket, &pos);
- if ( 0 == _descriptor->version() ) {
- return BtreeBucket<V0>::asVersion( record )->findSingle( _btreeState,
- _btreeState->head(),
- key );
+ // A null bucket means the key wasn't found (nor was anything found after it).
+ if (bucket.isNull()) {
+ return DiskLoc();
}
- if ( 1 == _descriptor->version() ) {
- return BtreeBucket<V1>::asVersion( record )->findSingle( _btreeState,
- _btreeState->head(),
- key );
+
+ // We found something but it could be a key after 'key'. Examine what we're pointing at.
+ if (0 != key.woCompare(_newInterface->getKey(bucket, pos), BSONObj(), false)) {
+ // If the keys don't match, return "not found."
+ return DiskLoc();
}
- verify( 0 );
- }
+ // Return the DiskLoc found.
+ return _newInterface->getDiskLoc(bucket, pos);
+ }
Status BtreeBasedAccessMethod::validate(int64_t* numKeys) {
// XXX: long long vs int64_t
@@ -284,7 +271,7 @@ namespace mongo {
Status BtreeBasedAccessMethod::update(const UpdateTicket& ticket, int64_t* numUpdated) {
if (!ticket._isValid) {
- return Status(ErrorCodes::InternalError, "Invalid updateticket in update");
+ return Status(ErrorCodes::InternalError, "Invalid UpdateTicket in update");
}
BtreeBasedPrivateUpdateData* data =
@@ -307,255 +294,25 @@ namespace mongo {
return Status::OK();
}
- // -------
-
- class BtreeBulk : public IndexAccessMethod {
- public:
- BtreeBulk( BtreeBasedAccessMethod* real ) {
- _real = real;
- }
-
- ~BtreeBulk() {}
-
- virtual Status insert(const BSONObj& obj,
- const DiskLoc& loc,
- const InsertDeleteOptions& options,
- int64_t* numInserted) {
- BSONObjSet keys;
- _real->getKeys(obj, &keys);
- _phase1.addKeys(keys, loc, false);
- if ( numInserted )
- *numInserted += keys.size();
- return Status::OK();
- }
-
- virtual Status remove(const BSONObj& obj,
- const DiskLoc& loc,
- const InsertDeleteOptions& options,
- int64_t* numDeleted) {
- return _notAllowed();
- }
-
- virtual Status validateUpdate(const BSONObj& from,
- const BSONObj& to,
- const DiskLoc& loc,
- const InsertDeleteOptions& options,
- UpdateTicket* ticket) {
- return _notAllowed();
- }
-
- virtual Status update(const UpdateTicket& ticket, int64_t* numUpdated) {
- return _notAllowed();
- }
-
- virtual Status newCursor(IndexCursor **out) const {
- return _notAllowed();
- }
-
- virtual Status initializeAsEmpty() {
- return _notAllowed();
- }
-
- virtual IndexAccessMethod* initiateBulk() {
- return NULL;
- }
-
- virtual Status commitBulk( IndexAccessMethod* bulk,
- bool mayInterrupt,
- std::set<DiskLoc>* dups ) {
- verify( this == bulk );
- return Status::OK();
- }
-
- virtual Status touch(const BSONObj& obj) {
- return _notAllowed();
- }
-
- virtual Status validate(int64_t* numKeys) {
- return _notAllowed();
- }
-
- // -------
-
- template< class V >
- void commit( set<DiskLoc>* dupsToDrop,
- CurOp* op,
- bool mayInterrupt ) {
-
- Timer timer;
-
- IndexCatalogEntry* entry = _real->_btreeState;
-
- bool dupsAllowed = !entry->descriptor()->unique() ||
- ignoreUniqueIndex(entry->descriptor());
- bool dropDups = entry->descriptor()->dropDups() || inDBRepair;
-
- BtreeBuilder<V> btBuilder(dupsAllowed, entry);
-
- BSONObj keyLast;
- scoped_ptr<BSONObjExternalSorter::Iterator> i( _phase1.sorter->iterator() );
-
- // verifies that pm and op refer to the same ProgressMeter
- ProgressMeter& pm = op->setMessage("Index Bulk Build: (2/3) btree bottom up",
- "Index: (2/3) BTree Bottom Up Progress",
- _phase1.nkeys,
- 10);
-
- while( i->more() ) {
- RARELY if ( mayInterrupt ) killCurrentOp.checkForInterrupt();
- ExternalSortDatum d = i->next();
-
- try {
- if ( !dupsAllowed && dropDups ) {
- LastError::Disabled led( lastError.get() );
- btBuilder.addKey(d.first, d.second);
- }
- else {
- btBuilder.addKey(d.first, d.second);
- }
- }
- catch( AssertionException& e ) {
- if ( dupsAllowed ) {
- // unknown exception??
- throw;
- }
-
- if (ErrorCodes::isInterruption(
- DBException::convertExceptionCode(e.getCode()))) {
- killCurrentOp.checkForInterrupt();
- }
-
- if ( ! dropDups )
- throw;
-
- /* we could queue these on disk, but normally there are very few dups,
- * so instead we keep in ram and have a limit.
- */
- if ( dupsToDrop ) {
- dupsToDrop->insert(d.second);
- uassert( 10092,
- "too may dups on index build with dropDups=true",
- dupsToDrop->size() < 1000000 );
- }
- }
- pm.hit();
- }
- pm.finished();
- op->setMessage("Index Bulk Build: (3/3) btree-middle",
- "Index: (3/3) BTree Middle Progress");
- LOG(timer.seconds() > 10 ? 0 : 1 ) << "\t done building bottom layer, going to commit";
- btBuilder.commit( mayInterrupt );
- if ( btBuilder.getn() != _phase1.nkeys && ! dropDups ) {
- warning() << "not all entries were added to the index, probably some "
- << "keys were too large" << endl;
- }
- }
-
- // -------
-
- Status _notAllowed() const {
- return Status( ErrorCodes::InternalError, "cannot use bulk for this yet" );
- }
-
- BtreeBasedAccessMethod* _real; // now owned here
- SortPhaseOne _phase1;
- };
-
- int oldCompare(const BSONObj& l,const BSONObj& r, const Ordering &o); // key.cpp
-
- class BtreeExternalSortComparisonV0 : public ExternalSortComparison {
- public:
- BtreeExternalSortComparisonV0(const BSONObj& ordering)
- : _ordering(Ordering::make(ordering)){
- }
-
- virtual ~BtreeExternalSortComparisonV0() { }
-
- virtual int compare(const ExternalSortDatum& l, const ExternalSortDatum& r) const {
- int x = oldCompare(l.first, r.first, _ordering);
- if (x) { return x; }
- return l.second.compare(r.second);
- }
- private:
- const Ordering _ordering;
- };
-
- class BtreeExternalSortComparisonV1 : public ExternalSortComparison {
- public:
- BtreeExternalSortComparisonV1(const BSONObj& ordering)
- : _ordering(Ordering::make(ordering)) {
- }
-
- virtual ~BtreeExternalSortComparisonV1() { }
-
- virtual int compare(const ExternalSortDatum& l, const ExternalSortDatum& r) const {
- int x = l.first.woCompare(r.first, _ordering, /*considerfieldname*/false);
- if (x) { return x; }
- return l.second.compare(r.second);
- }
- private:
- const Ordering _ordering;
- };
-
- ExternalSortComparison* BtreeBasedAccessMethod::getComparison(int version,
- const BSONObj& keyPattern) {
-
- if ( 0 == version ) {
- return new BtreeExternalSortComparisonV0( keyPattern );
- }
- else if ( 1 == version ) {
- return new BtreeExternalSortComparisonV1( keyPattern );
- }
- verify( 0 );
- return NULL;
- }
-
IndexAccessMethod* BtreeBasedAccessMethod::initiateBulk() {
+ // If there's already data in the index, don't do anything.
if (!_newInterface->isEmpty()) {
return NULL;
}
- auto_ptr<BtreeBulk> bulk( new BtreeBulk( this ) );
- bulk->_phase1.sortCmp.reset( getComparison( _descriptor->version(),
- _descriptor->keyPattern() ) );
-
- bulk->_phase1.sorter.reset( new BSONObjExternalSorter(bulk->_phase1.sortCmp.get()) );
- bulk->_phase1.sorter->hintNumObjects( _btreeState->collection()->numRecords() );
-
- return bulk.release();
+ return new BtreeBasedBulkAccessMethod(
+ this, _newInterface.get(), _descriptor, _btreeState->collection()->numRecords());
}
- Status BtreeBasedAccessMethod::commitBulk( IndexAccessMethod* bulkRaw,
- bool mayInterrupt,
- set<DiskLoc>* dupsToDrop ) {
-
+ Status BtreeBasedAccessMethod::commitBulk(IndexAccessMethod* bulkRaw,
+ bool mayInterrupt,
+ set<DiskLoc>* dupsToDrop) {
if (!_newInterface->isEmpty()) {
- return Status( ErrorCodes::InternalError, "trying to commit, but has data already" );
- }
-
- {
- DiskLoc oldHead = _btreeState->head();
- _btreeState->setHead( DiskLoc() );
- _btreeState->recordStore()->deleteRecord( oldHead );
+ return Status(ErrorCodes::InternalError, "trying to commit but has data already");
}
- string ns = _btreeState->collection()->ns().ns();
-
- BtreeBulk* bulk = static_cast<BtreeBulk*>( bulkRaw );
- if ( bulk->_phase1.multi )
- _btreeState->setMultikey();
-
- bulk->_phase1.sorter->sort( false );
-
- if ( _descriptor->version() == 0 )
- bulk->commit<V0>( dupsToDrop, cc().curop(), mayInterrupt );
- else if ( _descriptor->version() == 1 )
- bulk->commit<V1>( dupsToDrop, cc().curop(), mayInterrupt );
- else
- return Status( ErrorCodes::InternalError, "bad btree version" );
-
- return Status::OK();
+ BtreeBasedBulkAccessMethod* bulk = static_cast<BtreeBasedBulkAccessMethod*>(bulkRaw);
+ return bulk->commit(dupsToDrop, cc().curop(), mayInterrupt);
}
-
} // namespace mongo
diff --git a/src/mongo/db/index/btree_based_access_method.h b/src/mongo/db/index/btree_based_access_method.h
index f75d63ed042..5d5dab921dc 100644
--- a/src/mongo/db/index/btree_based_access_method.h
+++ b/src/mongo/db/index/btree_based_access_method.h
@@ -40,7 +40,6 @@
namespace mongo {
- class BtreeBulk;
class ExternalSortComparison;
/**
@@ -96,13 +95,9 @@ namespace mongo {
// XXX: consider migrating callers to use IndexCursor instead
virtual DiskLoc findSingle( const BSONObj& key ) const;
- // exposed for testing, used for bulk commit
- static ExternalSortComparison* getComparison(int version,
- const BSONObj& keyPattern);
-
protected:
// Friends who need getKeys.
- friend class BtreeBulk;
+ friend class BtreeBasedBulkAccessMethod;
// See below for body.
class BtreeBasedPrivateUpdateData;
diff --git a/src/mongo/db/index/btree_based_bulk_access_method.cpp b/src/mongo/db/index/btree_based_bulk_access_method.cpp
new file mode 100644
index 00000000000..b812c4d5999
--- /dev/null
+++ b/src/mongo/db/index/btree_based_bulk_access_method.cpp
@@ -0,0 +1,210 @@
+/**
+* Copyright (C) 2013 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#include "mongo/db/index/btree_based_bulk_access_method.h"
+
+#include "mongo/db/kill_current_op.h"
+#include "mongo/db/pdfile_private.h" // This is for inDBRepair.
+#include "mongo/db/repl/rs.h" // This is for ignoreUniqueIndex.
+#include "mongo/util/progress_meter.h"
+
+namespace mongo {
+
+ //
+ // Comparison for external sorter interface
+ //
+
+ // Defined in db/structure/btree/key.cpp
+ // XXX TODO: rename to something more descriptive, etc. etc.
+ int oldCompare(const BSONObj& l,const BSONObj& r, const Ordering &o);
+
+ class BtreeExternalSortComparisonV0 : public ExternalSortComparison {
+ public:
+ BtreeExternalSortComparisonV0(const BSONObj& ordering)
+ : _ordering(Ordering::make(ordering)){
+ }
+
+ virtual ~BtreeExternalSortComparisonV0() { }
+
+ virtual int compare(const ExternalSortDatum& l, const ExternalSortDatum& r) const {
+ int x = oldCompare(l.first, r.first, _ordering);
+ if (x) { return x; }
+ return l.second.compare(r.second);
+ }
+ private:
+ const Ordering _ordering;
+ };
+
+ class BtreeExternalSortComparisonV1 : public ExternalSortComparison {
+ public:
+ BtreeExternalSortComparisonV1(const BSONObj& ordering)
+ : _ordering(Ordering::make(ordering)) {
+ }
+
+ virtual ~BtreeExternalSortComparisonV1() { }
+
+ virtual int compare(const ExternalSortDatum& l, const ExternalSortDatum& r) const {
+ int x = l.first.woCompare(r.first, _ordering, /*considerfieldname*/false);
+ if (x) { return x; }
+ return l.second.compare(r.second);
+ }
+ private:
+ const Ordering _ordering;
+ };
+
+ // static
+ ExternalSortComparison* BtreeBasedBulkAccessMethod::getComparison(int version, const BSONObj& keyPattern) {
+ if (0 == version) {
+ return new BtreeExternalSortComparisonV0(keyPattern);
+ }
+ else if (1 == version) {
+ return new BtreeExternalSortComparisonV1(keyPattern);
+ }
+ verify( 0 );
+ return NULL;
+ }
+
+ BtreeBasedBulkAccessMethod::BtreeBasedBulkAccessMethod(BtreeBasedAccessMethod* real,
+ transition::BtreeInterface* interface,
+ const IndexDescriptor* descriptor,
+ int numRecords) {
+
+ _real = real;
+ _interface = interface;
+
+ _docsInserted = 0;
+ _keysInserted = 0;
+ _isMultiKey = false;
+
+ _sortCmp.reset(getComparison(descriptor->version(), descriptor->keyPattern()));
+ _sorter.reset(new BSONObjExternalSorter(_sortCmp.get()));
+ _sorter->hintNumObjects(numRecords);
+ }
+
+ Status BtreeBasedBulkAccessMethod::insert(const BSONObj& obj,
+ const DiskLoc& loc,
+ const InsertDeleteOptions& options,
+ int64_t* numInserted) {
+ BSONObjSet keys;
+ _real->getKeys(obj, &keys);
+
+ _isMultiKey = _isMultiKey || (keys.size() > 1);
+
+ for (BSONObjSet::iterator it = keys.begin(); it != keys.end(); ++it) {
+ // False is for mayInterrupt.
+ _sorter->add(*it, loc, false);
+ _keysInserted++;
+ }
+
+ _docsInserted++;
+
+ if (NULL != numInserted) {
+ *numInserted += keys.size();
+ }
+
+ return Status::OK();
+ }
+
+ Status BtreeBasedBulkAccessMethod::commit(set<DiskLoc>* dupsToDrop, CurOp* op, bool mayInterrupt) {
+ DiskLoc oldHead = _real->_btreeState->head();
+ // XXX: do we expect the tree to be empty but have a head set? Looks like so from old code.
+ invariant(!oldHead.isNull());
+ _real->_btreeState->setHead(DiskLoc());
+ _real->_btreeState->recordStore()->deleteRecord(oldHead);
+
+ if (_isMultiKey) {
+ _real->_btreeState->setMultikey();
+ }
+
+ _sorter->sort(false);
+
+ Timer timer;
+ IndexCatalogEntry* entry = _real->_btreeState;
+
+ bool dupsAllowed = !entry->descriptor()->unique()
+ || ignoreUniqueIndex(entry->descriptor());
+
+ bool dropDups = entry->descriptor()->dropDups() || inDBRepair;
+
+ scoped_ptr<BSONObjExternalSorter::Iterator> i(_sorter->iterator());
+
+ // verifies that pm and op refer to the same ProgressMeter
+ ProgressMeter& pm = op->setMessage("Index Bulk Build: (2/3) btree bottom up",
+ "Index: (2/3) BTree Bottom Up Progress",
+ _keysInserted,
+ 10);
+
+ scoped_ptr<transition::BtreeBuilderInterface> builder;
+ builder.reset(_interface->getBulkBuilder(dupsAllowed));
+
+ while (i->more()) {
+ // Get the next datum and add it to the builder.
+ ExternalSortDatum d = i->next();
+ Status status = builder->addKey(d.first, d.second);
+
+ if (!status.isOK()) {
+ if (ErrorCodes::DuplicateKey != status.code()) {
+ return status;
+ }
+
+ // If we're here it's a duplicate key.
+ if (dropDups) {
+ static const size_t kMaxDupsToStore = 1000000;
+ dupsToDrop->insert(d.second);
+ if (dupsToDrop->size() > kMaxDupsToStore) {
+ return Status(ErrorCodes::InternalError,
+ "Too many dups on index build with dropDups = true");
+ }
+ }
+ else if (!dupsAllowed) {
+ return status;
+ }
+ }
+
+ // If we're here either it's a dup and we're cool with it or the addKey went just
+ // fine.
+ pm.hit();
+ }
+
+ pm.finished();
+
+ op->setMessage("Index Bulk Build: (3/3) btree-middle",
+ "Index: (3/3) BTree Middle Progress");
+
+ LOG(timer.seconds() > 10 ? 0 : 1 ) << "\t done building bottom layer, going to commit";
+
+ unsigned long long keysCommit = builder->commit(mayInterrupt);
+
+ if (!dropDups && (keysCommit != _keysInserted)) {
+ warning() << "not all entries were added to the index, probably some "
+ << "keys were too large" << endl;
+ }
+ return Status::OK();
+ }
+
+} // namespace mongo
diff --git a/src/mongo/db/index/btree_based_bulk_access_method.h b/src/mongo/db/index/btree_based_bulk_access_method.h
new file mode 100644
index 00000000000..16e72cfc60f
--- /dev/null
+++ b/src/mongo/db/index/btree_based_bulk_access_method.h
@@ -0,0 +1,140 @@
+/**
+* Copyright (C) 2013 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* As a special exception, the copyright holders give permission to link the
+* code of portions of this program with the OpenSSL library under certain
+* conditions as described in each individual source file and distribute
+* linked combinations including the program with the OpenSSL library. You
+* must comply with the GNU Affero General Public License in all respects for
+* all of the code used other than as permitted herein. If you modify file(s)
+* with this exception, you may extend this exception to your version of the
+* file(s), but you are not obligated to do so. If you do not wish to do so,
+* delete this exception statement from your version. If you delete this
+* exception statement from all source files in the program, then also delete
+* it in the license file.
+*/
+
+#include <set>
+#include <vector>
+
+#include "mongo/base/error_codes.h"
+#include "mongo/base/status.h"
+#include "mongo/db/curop.h"
+#include "mongo/db/extsort.h"
+#include "mongo/db/index/btree_based_access_method.h"
+#include "mongo/db/index/index_access_method.h"
+#include "mongo/db/index/index_descriptor.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/structure/btree/btree_interface.h"
+
+namespace mongo {
+
+ class BtreeBasedBulkAccessMethod : public IndexAccessMethod {
+ public:
+ BtreeBasedBulkAccessMethod(BtreeBasedAccessMethod* real,
+ transition::BtreeInterface* interface,
+ const IndexDescriptor* descriptor,
+ int numRecords);
+
+ ~BtreeBasedBulkAccessMethod() {}
+
+ virtual Status insert(const BSONObj& obj,
+ const DiskLoc& loc,
+ const InsertDeleteOptions& options,
+ int64_t* numInserted);
+
+ Status commit(std::set<DiskLoc>* dupsToDrop, CurOp* op, bool mayInterrupt);
+
+ // Exposed for testing.
+ static ExternalSortComparison* getComparison(int version, const BSONObj& keyPattern);
+
+ //
+ // Stuff below here is a no-op of one form or another.
+ //
+
+ virtual Status commitBulk(IndexAccessMethod* bulk,
+ bool mayInterrupt,
+ std::set<DiskLoc>* dups) {
+ verify(this == bulk);
+ return Status::OK();
+ }
+
+ virtual Status touch(const BSONObj& obj) {
+ return _notAllowed();
+ }
+
+ virtual Status validate(int64_t* numKeys) {
+ return _notAllowed();
+ }
+
+ virtual Status remove(const BSONObj& obj,
+ const DiskLoc& loc,
+ const InsertDeleteOptions& options,
+ int64_t* numDeleted) {
+ return _notAllowed();
+ }
+
+ virtual Status validateUpdate(const BSONObj& from,
+ const BSONObj& to,
+ const DiskLoc& loc,
+ const InsertDeleteOptions& options,
+ UpdateTicket* ticket) {
+ return _notAllowed();
+ }
+
+ virtual Status update(const UpdateTicket& ticket, int64_t* numUpdated) {
+ return _notAllowed();
+ }
+
+ virtual Status newCursor(IndexCursor **out) const {
+ return _notAllowed();
+ }
+
+ virtual Status initializeAsEmpty() {
+ return _notAllowed();
+ }
+
+ virtual IndexAccessMethod* initiateBulk() {
+ return NULL;
+ }
+
+ private:
+ Status _notAllowed() const {
+ return Status(ErrorCodes::InternalError, "cannot use bulk for this yet");
+ }
+
+ // Not owned here.
+ BtreeBasedAccessMethod* _real;
+
+ // Not owned here.
+ transition::BtreeInterface* _interface;
+
+ // The external sorter.
+ boost::scoped_ptr<BSONObjExternalSorter> _sorter;
+
+ // A comparison object required by the sorter.
+ boost::scoped_ptr<ExternalSortComparison> _sortCmp;
+
+ // How many docs are we indexing?
+ unsigned long long _docsInserted;
+
+ // And how many keys?
+ unsigned long long _keysInserted;
+
+ // Does any document have >1 key?
+ bool _isMultiKey;
+ };
+
+} // namespace mongo
diff --git a/src/mongo/db/index/hash_access_method.cpp b/src/mongo/db/index/hash_access_method.cpp
index 34729a1cf77..7457c68c085 100644
--- a/src/mongo/db/index/hash_access_method.cpp
+++ b/src/mongo/db/index/hash_access_method.cpp
@@ -26,7 +26,6 @@
* it in the license file.
*/
-#include "mongo/db/structure/btree/btree.h"
#include "mongo/db/hasher.h"
#include "mongo/db/index/expression_keys_private.h"
#include "mongo/db/index/expression_params.h"