// index_descriptor.cpp
/**
* 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 .
*
* 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.
*/
#pragma once
#include
#include "mongo/db/jsobj.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/util/stacktrace.h"
namespace mongo {
class IndexCatalog;
class IndexCatalogEntry;
class IndexCatalogEntryContainer;
/**
* A cache of information computed from the memory-mapped per-index data (OnDiskIndexData).
* Contains accessors for the various immutable index parameters, and an accessor for the
* mutable "head" pointer which is index-specific.
*
* All synchronization is the responsibility of the caller.
*/
class IndexDescriptor {
public:
/**
* OnDiskIndexData is a pointer to the memory mapped per-index data.
* infoObj is a copy of the index-describing BSONObj contained in the OnDiskIndexData.
*/
IndexDescriptor(Collection* collection, const std::string& accessMethodName, BSONObj infoObj)
: _magic(123987),
_collection(collection),
_accessMethodName(accessMethodName),
_infoObj(infoObj.getOwned()),
_numFields(infoObj.getObjectField("key").nFields()),
_keyPattern(infoObj.getObjectField("key").getOwned()),
_indexName(infoObj.getStringField("name")),
_parentNS(infoObj.getStringField("ns")),
_isIdIndex(isIdIndexPattern(_keyPattern)),
_sparse(infoObj["sparse"].trueValue()),
_unique(_isIdIndex || infoObj["unique"].trueValue()),
_partial(!infoObj["partialFilterExpression"].eoo()),
_cachedEntry(NULL) {
_indexNamespace = makeIndexNamespace(_parentNS, _indexName);
_version = 0;
BSONElement e = _infoObj["v"];
if (e.isNumber()) {
_version = e.numberInt();
}
}
~IndexDescriptor() {
_magic = 555;
}
//
// Information about the key pattern.
//
/**
* Return the user-provided index key pattern.
* Example: {geo: "2dsphere", nonGeo: 1}
* Example: {foo: 1, bar: -1}
*/
const BSONObj& keyPattern() const {
_checkOk();
return _keyPattern;
}
// How many fields do we index / are in the key pattern?
int getNumFields() const {
_checkOk();
return _numFields;
}
//
// Information about the index's namespace / collection.
//
// Return the name of the index.
const std::string& indexName() const {
_checkOk();
return _indexName;
}
// Return the name of the indexed collection.
const std::string& parentNS() const {
return _parentNS;
}
// Return the name of this index's storage area (database.table.$index)
const std::string& indexNamespace() const {
return _indexNamespace;
}
// Return the name of the access method we must use to access this index's data.
const std::string& getAccessMethodName() const {
return _accessMethodName;
}
//
// Properties every index has
//
// Return what version of index this is.
int version() const {
return _version;
}
// May each key only occur once?
bool unique() const {
return _unique;
}
// Is this index sparse?
bool isSparse() const {
return _sparse;
}
// Is this a partial index?
bool isPartial() const {
return _partial;
}
// Is this index multikey?
bool isMultikey(OperationContext* txn) const {
_checkOk();
return _collection->getIndexCatalog()->isMultikey(txn, this);
}
bool isIdIndex() const {
_checkOk();
return _isIdIndex;
}
//
// Properties that are Index-specific.
//
// Allow access to arbitrary fields in the per-index info object. Some indices stash
// index-specific data there.
BSONElement getInfoElement(const std::string& name) const {
return _infoObj[name];
}
//
// "Internals" of accessing the index, used by IndexAccessMethod(s).
//
// Return a (rather compact) std::string representation.
std::string toString() const {
_checkOk();
return _infoObj.toString();
}
// Return the info object.
const BSONObj& infoObj() const {
_checkOk();
return _infoObj;
}
// Both the collection and the catalog must outlive the IndexDescriptor
const Collection* getCollection() const {
return _collection;
}
const IndexCatalog* getIndexCatalog() const {
return _collection->getIndexCatalog();
}
bool areIndexOptionsEquivalent(const IndexDescriptor* other) const;
static bool isIdIndexPattern(const BSONObj& pattern) {
BSONObjIterator i(pattern);
BSONElement e = i.next();
//_id index must have form exactly {_id : 1} or {_id : -1}.
// Allows an index of form {_id : "hashed"} to exist but
// do not consider it to be the primary _id index
if (!(strcmp(e.fieldName(), "_id") == 0 && (e.numberInt() == 1 || e.numberInt() == -1)))
return false;
return i.next().eoo();
}
static std::string makeIndexNamespace(StringData ns, StringData name) {
return ns.toString() + ".$" + name.toString();
}
private:
void _checkOk() const;
int _magic;
// Related catalog information of the parent collection
Collection* _collection;
// What access method should we use for this index?
std::string _accessMethodName;
// The BSONObj describing the index. Accessed through the various members above.
const BSONObj _infoObj;
// --- cached data from _infoObj
int64_t _numFields; // How many fields are indexed?
BSONObj _keyPattern;
std::string _indexName;
std::string _parentNS;
std::string _indexNamespace;
bool _isIdIndex;
bool _sparse;
bool _unique;
bool _partial;
int _version;
// only used by IndexCatalogEntryContainer to do caching for perf
// users not allowed to touch, and not part of API
IndexCatalogEntry* _cachedEntry;
friend class IndexCatalog;
friend class IndexCatalogEntry;
friend class IndexCatalogEntryContainer;
};
} // namespace mongo