summaryrefslogtreecommitdiff
path: root/src/mongo/db/index/btree_interface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/index/btree_interface.cpp')
-rw-r--r--src/mongo/db/index/btree_interface.cpp235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/mongo/db/index/btree_interface.cpp b/src/mongo/db/index/btree_interface.cpp
new file mode 100644
index 00000000000..ace3d45ada8
--- /dev/null
+++ b/src/mongo/db/index/btree_interface.cpp
@@ -0,0 +1,235 @@
+/**
+ * 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/catalog/index_catalog_entry.h"
+#include "mongo/db/index/btree_interface.h"
+#include "mongo/db/pdfile.h"
+#include "mongo/db/structure/btree/btree.h"
+#include "mongo/db/structure/record_store.h"
+
+namespace mongo {
+
+ template <class Version>
+ class BtreeInterfaceImpl : public BtreeInterface {
+ public:
+ // typedef typename BucketBasics<Version>::VersionNode VersionNode;
+
+ virtual ~BtreeInterfaceImpl() { }
+
+ const BtreeBucket<Version>* getHeadBucket( const IndexCatalogEntry* entry ) const {
+ return getBucket( entry->head() );
+ }
+
+ const BtreeBucket<Version>* getBucket( const IndexCatalogEntry* entry,
+ const DiskLoc& loc ) const {
+ Record* record = entry->recordStore()->recordFor( loc );
+ return BtreeBucket<Version>::asVersion( record );
+ }
+
+ virtual int bt_insert(IndexCatalogEntry* btreeState,
+ const DiskLoc thisLoc,
+ const DiskLoc recordLoc,
+ const BSONObj& key,
+ bool dupsallowed,
+ bool toplevel) {
+ // FYI: toplevel has a default value of true in btree.h
+ return getBucket( btreeState, thisLoc )->bt_insert(btreeState,
+ thisLoc,
+ recordLoc,
+ key,
+ dupsallowed,
+ toplevel);
+ }
+
+ virtual bool unindex(IndexCatalogEntry* btreeState,
+ const DiskLoc thisLoc,
+ const BSONObj& key,
+ const DiskLoc recordLoc) {
+ return getBucket( btreeState, thisLoc )->unindex(btreeState,
+ thisLoc,
+ key,
+ recordLoc);
+ }
+
+ virtual DiskLoc locate(const IndexCatalogEntry* btreeState,
+ const DiskLoc& thisLoc,
+ const BSONObj& key,
+ int& pos,
+ bool& found,
+ const DiskLoc& recordLoc,
+ int direction) const {
+ // FYI: direction has a default of 1
+ return getBucket( btreeState, thisLoc )->locate(btreeState,
+ thisLoc,
+ key,
+ pos,
+ found,
+ recordLoc,
+ direction);
+ }
+
+ virtual bool wouldCreateDup(const IndexCatalogEntry* btreeState,
+ const DiskLoc& thisLoc,
+ const BSONObj& key,
+ const DiskLoc& self) const {
+ typename Version::KeyOwned ownedVersion(key);
+ return getBucket( btreeState, thisLoc )->wouldCreateDup(btreeState,
+ thisLoc,
+ ownedVersion,
+ self);
+ }
+
+ virtual void assertIfKeyTooLongAndNotIgnored(const IndexCatalogEntry* btreeState,
+ const DiskLoc& thisLoc,
+ const BSONObj& key) const {
+ typename Version::KeyOwned ownedVersion(key);
+ getBucket( btreeState, thisLoc )->assertIfKeyTooLongAndNotIgnored(btreeState,
+ ownedVersion);
+ }
+
+ virtual void customLocate(const IndexCatalogEntry* btreeState,
+ DiskLoc& locInOut,
+ int& keyOfs,
+ const BSONObj& keyBegin,
+ int keyBeginLen, bool afterVersion,
+ const vector<const BSONElement*>& keyEnd,
+ const vector<bool>& keyEndInclusive,
+ int direction,
+ pair<DiskLoc, int>& bestParent) const {
+ return BtreeBucket<Version>::customLocate(btreeState,
+ locInOut,
+ keyOfs,
+ keyBegin,
+ keyBeginLen, afterVersion,
+ keyEnd,
+ keyEndInclusive,
+ direction,
+ bestParent);
+ }
+
+ virtual void advanceTo(const IndexCatalogEntry* btreeState,
+ DiskLoc &thisLoc,
+ int &keyOfs,
+ const BSONObj &keyBegin,
+ int keyBeginLen,
+ bool afterVersion,
+ const vector<const BSONElement*>& keyEnd,
+ const vector<bool>& keyEndInclusive,
+ int direction) const {
+ return getBucket( btreeState, thisLoc )->advanceTo(btreeState,
+ thisLoc,
+ keyOfs,
+ keyBegin,
+ keyBeginLen,
+ afterVersion,
+ keyEnd,
+ keyEndInclusive,
+ direction);
+ }
+
+
+ virtual int nKeys(const IndexCatalogEntry* btreeState,
+ DiskLoc bucket ) {
+ return getBucket(btreeState,bucket)->nKeys();
+ }
+
+
+ virtual bool keyIsUsed(const IndexCatalogEntry* btreeState,
+ DiskLoc bucket, int keyOffset) const {
+ return getBucket(btreeState,bucket)->k(keyOffset).isUsed();
+ }
+
+ virtual BSONObj keyAt(const IndexCatalogEntry* btreeState,
+ DiskLoc bucket, int keyOffset) const {
+ verify(!bucket.isNull());
+ const BtreeBucket<Version> *b = getBucket(btreeState,bucket);
+ int n = b->getN();
+ if (n == b->INVALID_N_SENTINEL) {
+ throw UserException(deletedBucketCode, "keyAt bucket deleted");
+ }
+ dassert( n >= 0 && n < 10000 );
+ return keyOffset >= n ? BSONObj() : b->keyNode(keyOffset).key.toBson();
+ }
+
+ virtual DiskLoc recordAt(const IndexCatalogEntry* btreeState,
+ DiskLoc bucket, int keyOffset) const {
+ const BtreeBucket<Version> *b = getBucket(btreeState,bucket);
+ return b->keyNode(keyOffset).recordLoc;
+ }
+
+ virtual void keyAndRecordAt(const IndexCatalogEntry* btreeState,
+ DiskLoc bucket, int keyOffset, BSONObj* keyOut,
+ DiskLoc* recordOut) const {
+ verify(!bucket.isNull());
+ const BtreeBucket<Version> *b = getBucket(btreeState,bucket);
+
+ int n = b->getN();
+
+ // If n is 0xffff the bucket was deleted.
+ if (keyOffset < 0 || keyOffset >= n || n == 0xffff || !b->isUsed(keyOffset)) {
+ return;
+ }
+
+ if (keyOffset >= n) {
+ *keyOut = BSONObj();
+ *recordOut = DiskLoc();
+ } else {
+ *keyOut = b->keyNode(keyOffset).key.toBson();
+ *recordOut = b->keyNode(keyOffset).recordLoc;
+ }
+ }
+
+ virtual string dupKeyError(const IndexCatalogEntry* btreeState,
+ DiskLoc bucket,
+ const BSONObj& keyObj) const {
+ typename Version::KeyOwned key(keyObj);
+ return getBucket( btreeState, bucket )->dupKeyError(btreeState->descriptor(),
+ key);
+ }
+
+ virtual DiskLoc advance(const IndexCatalogEntry* btreeState,
+ const DiskLoc& thisLoc,
+ int& keyOfs,
+ int direction,
+ const char* caller) const {
+ return getBucket( btreeState, thisLoc )->advance(thisLoc, keyOfs, direction, caller);
+ }
+
+ virtual long long fullValidate(const IndexCatalogEntry* btreeState,
+ const DiskLoc& thisLoc,
+ const BSONObj& keyPattern) {
+ return getBucket( btreeState, thisLoc )->fullValidate(thisLoc, keyPattern);
+ }
+ };
+
+ BtreeInterfaceImpl<V0> interface_v0;
+ BtreeInterfaceImpl<V1> interface_v1;
+ BtreeInterface* BtreeInterface::interfaces[] = { &interface_v0, &interface_v1 };
+
+} // namespace mongo
+