This file is indexed.

/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