/usr/include/mongo/db/btreecursor.h is in mongodb-dev 1:2.4.9-1ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | /**
* Copyright (C) 2008 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/>.
*/
#pragma once
#include "mongo/db/cursor.h"
#include "mongo/db/diskloc.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_details.h"
namespace mongo {
class FieldRangeVector;
class FieldRangeVectorIterator;
/**
* A Cursor class for btree iteration.
*
* A BtreeCursor iterates over all keys of a specified btree that are within the provided
* btree bounds, using the specified direction of traversal.
*
* Notes on specifying btree bounds:
*
* A BtreeCursor may be initialized with the 'startKey' and 'endKey' bounds of an interval of
* keys within a btree. A BtreeCursor may alternatively be initialized with a FieldRangeVector
* describing a list of intervals for every field of the btree index.
*
* Notes on inheritance:
*
* BtreeCursor is an abstract class. Btrees come in different versions, with different storage
* formats. The versions are v0 and v1 as of this writing. Member functions implemented in
* BtreeCursor are storage format agnostic. Classes derived from BtreeCursor implement the
* format specific bits.
*
* Notes on the yielding implementation:
*
* When an operation using a BtreeCursor yields the database mutex that locks the btree data
* structure, the btree may be modified. When the operation regains the database mutex, the
* BtreeCursor can relocate its position in the modified btree and continue iteration from that
* point.
*
* Before the database mutex is yielded, a BtreeCursor records its position (noteLoc()). A
* recorded btree position consists of a btree bucket, bucket key offset, and unique btree key.
*
* After the database mutex is regained, a BtreeCursor relocates its position (checkLoc()). To
* relocate a unique btree key, a BtreeCursor first checks the btree key at its recorded btree
* bucket and bucket key offset. If the key at that location does not match the recorded btree
* key, and a preceding offset also fails to match, the recorded key (or the next existing key
* following it) is located in the btree using binary search. If the recorded btree bucket is
* invalidated, the initial recorded bucket check is not attempted (see SERVER-4575).
*/
class BtreeCursor : public Cursor {
public:
virtual ~BtreeCursor();
/** Makes an appropriate subclass depending on the index version. */
static BtreeCursor* make( NamespaceDetails* namespaceDetails,
const IndexDetails& id,
const BSONObj& startKey,
const BSONObj& endKey,
bool endKeyInclusive,
int direction );
static BtreeCursor* make( NamespaceDetails* namespaceDetails,
const IndexDetails& id,
const shared_ptr<FieldRangeVector>& bounds,
int singleIntervalLimit,
int direction );
virtual bool ok() { return !bucket.isNull(); }
virtual bool advance();
virtual void noteLocation(); // updates keyAtKeyOfs...
virtual void checkLocation() = 0;
virtual bool supportGetMore() { return true; }
virtual bool supportYields() { return true; }
/**
* used for multikey index traversal to avoid sending back dups. see Matcher::matches().
* if a multikey index traversal:
* if loc has already been sent, returns true.
* otherwise, marks loc as sent.
* @return false if the loc has not been seen
*/
virtual bool getsetdup(DiskLoc loc) {
if( _multikey ) {
pair<set<DiskLoc>::iterator, bool> p = _dups.insert(loc);
return !p.second;
}
return false;
}
virtual bool modifiedKeys() const { return _multikey; }
virtual bool isMultiKey() const { return _multikey; }
/** returns BSONObj() if ofs is out of range */
virtual BSONObj keyAt(int ofs) const = 0;
virtual BSONObj currKey() const = 0;
virtual BSONObj indexKeyPattern() { return _order; }
virtual void aboutToDeleteBucket(const DiskLoc& b) {
if ( bucket == b )
keyOfs = -1;
}
virtual DiskLoc currLoc() = 0;
virtual DiskLoc refLoc() { return currLoc(); }
virtual Record* _current() { return currLoc().rec(); }
virtual BSONObj current() { return BSONObj::make(_current()); }
virtual string toString();
BSONObj prettyKey( const BSONObj& key ) const {
return key.replaceFieldNames( indexDetails.keyPattern() ).clientReadable();
}
virtual BSONObj prettyIndexBounds() const;
virtual CoveredIndexMatcher* matcher() const { return _matcher.get(); }
virtual bool currentMatches( MatchDetails* details = 0 );
virtual void setMatcher( shared_ptr<CoveredIndexMatcher> matcher ) { _matcher = matcher; }
virtual const Projection::KeyOnly* keyFieldsOnly() const { return _keyFieldsOnly.get(); }
virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly>& keyFieldsOnly ) {
_keyFieldsOnly = keyFieldsOnly;
}
virtual long long nscanned() { return _nscanned; }
/** for debugging only */
const DiskLoc getBucket() const { return bucket; }
int getKeyOfs() const { return keyOfs; }
// just for unit tests
virtual bool curKeyHasChild() = 0;
protected:
BtreeCursor( NamespaceDetails* nsd, int theIndexNo, const IndexDetails& idxDetails );
virtual void init( const BSONObj& startKey,
const BSONObj& endKey,
bool endKeyInclusive,
int direction );
virtual void init( const shared_ptr<FieldRangeVector>& bounds,
int singleIntervalLimit,
int direction );
/**
* Our btrees may (rarely) have "unused" keys when items are deleted.
* Skip past them.
*/
virtual bool skipUnusedKeys() = 0;
bool skipOutOfRangeKeysAndCheckEnd();
/**
* Attempt to locate the next btree key matching _bounds. This may mean advancing to the
* next successive key in the btree, or skipping to a new position in the btree. If an
* internal iteration cutoff is reached before a matching key is found, then the search for
* a matching key will be aborted, leaving the cursor pointing at a key that is not within
* bounds.
*/
void skipAndCheck();
void checkEnd();
/** selective audits on construction */
void audit();
virtual void _audit() = 0;
virtual DiskLoc _locate(const BSONObj& key, const DiskLoc& loc) = 0;
virtual DiskLoc _advance(const DiskLoc& thisLoc,
int& keyOfs,
int direction,
const char* caller) = 0;
virtual void _advanceTo(DiskLoc& thisLoc,
int& keyOfs,
const BSONObj& keyBegin,
int keyBeginLen,
bool afterKey,
const vector<const BSONElement*>& keyEnd,
const vector<bool>& keyEndInclusive,
const Ordering& order,
int direction ) = 0;
/** set initial bucket */
void initWithoutIndependentFieldRanges();
/** if afterKey is true, we want the first key with values of the keyBegin fields greater than keyBegin */
void advanceTo( const BSONObj& keyBegin,
int keyBeginLen,
bool afterKey,
const vector<const BSONElement*>& keyEnd,
const vector<bool>& keyEndInclusive );
// these are set in the construtor
NamespaceDetails* const d;
const int idxNo;
const IndexDetails& indexDetails;
// these are all set in init()
set<DiskLoc> _dups;
BSONObj startKey;
BSONObj endKey;
bool _endKeyInclusive;
bool _multikey; // this must be updated every getmore batch in case someone added a multikey
BSONObj _order; // this is the same as indexDetails.keyPattern()
Ordering _ordering;
DiskLoc bucket;
int keyOfs;
int _direction; // 1=fwd,-1=reverse
BSONObj keyAtKeyOfs; // so we can tell if things moved around on us between the query and the getMore call
DiskLoc locAtKeyOfs;
shared_ptr<FieldRangeVector> _bounds;
auto_ptr<FieldRangeVectorIterator> _boundsIterator;
bool _boundsMustMatch; // If iteration is aborted before a key matching _bounds is
// identified, the cursor may be left pointing at a key that is not
// within bounds (_bounds->matchesKey( currKey() ) may be false).
// _boundsMustMatch will be set to false accordingly.
shared_ptr<CoveredIndexMatcher> _matcher;
shared_ptr<Projection::KeyOnly> _keyFieldsOnly;
bool _independentFieldRanges;
long long _nscanned;
private:
void _finishConstructorInit();
static BtreeCursor* make( NamespaceDetails* nsd,
int idxNo,
const IndexDetails& indexDetails );
};
} // namespace mongo
|