| btree.h | | btree.h | |
| | | | |
| skipping to change at line 407 | | skipping to change at line 407 | |
| * - If key cannot fit in the bucket, the bucket will be packed an
d | | * - If key cannot fit in the bucket, the bucket will be packed an
d | |
| * the function will return false. | | * the function will return false. | |
| * Although this function is marked const, it modifies the underlyi
ng | | * Although this function is marked const, it modifies the underlyi
ng | |
| * btree representation through an optimized write intent mechanism
. | | * btree representation through an optimized write intent mechanism
. | |
| */ | | */ | |
| bool basicInsert(const DiskLoc thisLoc, int &keypos, const DiskLoc
recordLoc, const Key& key, const Ordering &order) const; | | bool basicInsert(const DiskLoc thisLoc, int &keypos, const DiskLoc
recordLoc, const Key& key, const Ordering &order) const; | |
| | | | |
| /** | | /** | |
| * Preconditions: | | * Preconditions: | |
| * - key / recordLoc are > all existing keys | | * - key / recordLoc are > all existing keys | |
|
| * - The keys in prevChild and their descendents are between all e
xisting | | * - The keys in prevChild and their descendants are between all e
xisting | |
| * keys and 'key'. | | * keys and 'key'. | |
| * Postconditions: | | * Postconditions: | |
| * - If there is space for key without packing, it is inserted as
the | | * - If there is space for key without packing, it is inserted as
the | |
| * last key with specified prevChild and true is returned. | | * last key with specified prevChild and true is returned. | |
| * Importantly, nextChild is not updated! | | * Importantly, nextChild is not updated! | |
| * - Otherwise false is returned and there is no change. | | * - Otherwise false is returned and there is no change. | |
| */ | | */ | |
| bool _pushBack(const DiskLoc recordLoc, const Key& key, const Order
ing &order, const DiskLoc prevChild); | | bool _pushBack(const DiskLoc recordLoc, const Key& key, const Order
ing &order, const DiskLoc prevChild); | |
| void pushBack(const DiskLoc recordLoc, const Key& key, const Orderi
ng &order, const DiskLoc prevChild) { | | void pushBack(const DiskLoc recordLoc, const Key& key, const Orderi
ng &order, const DiskLoc prevChild) { | |
| bool ok = _pushBack( recordLoc , key , order , prevChild ); | | bool ok = _pushBack( recordLoc , key , order , prevChild ); | |
| | | | |
| skipping to change at line 610 | | skipping to change at line 610 | |
| * pointer to. The pointer is cleared or removed explicitly, then the
data | | * pointer to. The pointer is cleared or removed explicitly, then the
data | |
| * it pointed to is cleaned up with a helper function. | | * it pointed to is cleaned up with a helper function. | |
| * | | * | |
| * TODO It might make sense to put some of these functions in a class | | * TODO It might make sense to put some of these functions in a class | |
| * representing a full btree instead of a single btree bucket. That wo
uld | | * representing a full btree instead of a single btree bucket. That wo
uld | |
| * allow us to use the const qualifier in a manner more consistent with | | * allow us to use the const qualifier in a manner more consistent with | |
| * standard usage. Right now the interface is for both a node and a tr
ee, | | * standard usage. Right now the interface is for both a node and a tr
ee, | |
| * so assignment of const is sometimes nonideal. | | * so assignment of const is sometimes nonideal. | |
| * | | * | |
| * TODO There are several cases in which the 'this' pointer is invalida
ted | | * TODO There are several cases in which the 'this' pointer is invalida
ted | |
|
| * as a result of deallocation. A seperate class representing a btree
would | | * as a result of deallocation. A separate class representing a btree
would | |
| * alleviate some fragile cases where the implementation must currently | | * alleviate some fragile cases where the implementation must currently | |
| * behave correctly if the 'this' pointer is suddenly invalidated by a | | * behave correctly if the 'this' pointer is suddenly invalidated by a | |
| * callee. | | * callee. | |
| */ | | */ | |
| template< class V > | | template< class V > | |
| class BtreeBucket : public BucketBasics<V> { | | class BtreeBucket : public BucketBasics<V> { | |
| friend class BtreeCursor; | | friend class BtreeCursor; | |
| friend struct IndexInsertionContinuationImpl<V>; | | friend struct IndexInsertionContinuationImpl<V>; | |
| public: | | public: | |
| // make compiler happy: | | // make compiler happy: | |
| | | | |
| skipping to change at line 1099 | | skipping to change at line 1099 | |
| virtual BSONObj current() { return BSONObj::make(_current()); } | | virtual BSONObj current() { return BSONObj::make(_current()); } | |
| virtual string toString(); | | virtual string toString(); | |
| | | | |
| BSONObj prettyKey( const BSONObj &key ) const { | | BSONObj prettyKey( const BSONObj &key ) const { | |
| return key.replaceFieldNames( indexDetails.keyPattern() ).clien
tReadable(); | | return key.replaceFieldNames( indexDetails.keyPattern() ).clien
tReadable(); | |
| } | | } | |
| | | | |
| virtual BSONObj prettyIndexBounds() const; | | virtual BSONObj prettyIndexBounds() const; | |
| | | | |
| virtual CoveredIndexMatcher *matcher() const { return _matcher.get(
); } | | virtual CoveredIndexMatcher *matcher() const { return _matcher.get(
); } | |
|
| virtual shared_ptr< CoveredIndexMatcher > matcherPtr() const { retu
rn _matcher; } | | | |
| | | | |
| virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher
) { _matcher = matcher; } | | virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher
) { _matcher = matcher; } | |
| | | | |
| virtual const Projection::KeyOnly *keyFieldsOnly() const { return _
keyFieldsOnly.get(); } | | virtual const Projection::KeyOnly *keyFieldsOnly() const { return _
keyFieldsOnly.get(); } | |
| | | | |
| virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly
> &keyFieldsOnly ) { | | virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly
> &keyFieldsOnly ) { | |
| _keyFieldsOnly = keyFieldsOnly; | | _keyFieldsOnly = keyFieldsOnly; | |
| } | | } | |
| | | | |
| virtual long long nscanned() { return _nscanned; } | | virtual long long nscanned() { return _nscanned; } | |
| | | | |
End of changes. 3 change blocks. |
| 3 lines changed or deleted | | 2 lines changed or added | |
|
| chunk.h | | chunk.h | |
| | | | |
| skipping to change at line 80 | | skipping to change at line 80 | |
| // chunk boundary support | | // chunk boundary support | |
| // | | // | |
| | | | |
| const BSONObj& getMin() const { return _min; } | | const BSONObj& getMin() const { return _min; } | |
| const BSONObj& getMax() const { return _max; } | | const BSONObj& getMax() const { return _max; } | |
| | | | |
| // if min/max key is pos/neg infinity | | // if min/max key is pos/neg infinity | |
| bool minIsInf() const; | | bool minIsInf() const; | |
| bool maxIsInf() const; | | bool maxIsInf() const; | |
| | | | |
|
| bool contains( const BSONObj& obj ) const; | | // Returns true if this chunk contains the given point, and false o | |
| | | therwise | |
| | | // | |
| | | // Note: this function takes an extracted *key*, not an original do | |
| | | cument | |
| | | // (the point may be computed by, say, hashing a given field or pro | |
| | | jecting | |
| | | // to a subset of fields). | |
| | | bool containsPoint( const BSONObj& point ) const; | |
| | | | |
| string genID() const; | | string genID() const; | |
| static string genID( const string& ns , const BSONObj& min ); | | static string genID( const string& ns , const BSONObj& min ); | |
| | | | |
| // | | // | |
| // chunk version support | | // chunk version support | |
| // | | // | |
| | | | |
| void appendShortVersion( const char * name , BSONObjBuilder& b ) co
nst; | | void appendShortVersion( const char * name , BSONObjBuilder& b ) co
nst; | |
| | | | |
| ShardChunkVersion getLastmod() const { return _lastmod; } | | ShardChunkVersion getLastmod() const { return _lastmod; } | |
| void setLastmod( ShardChunkVersion v ) { _lastmod = v; } | | void setLastmod( ShardChunkVersion v ) { _lastmod = v; } | |
| | | | |
| // | | // | |
| // split support | | // split support | |
| // | | // | |
| | | | |
|
| long getBytesWritten() const { return _dataWritten; } | | | |
| // Const since _dataWritten is mutable and a heuristic | | | |
| // TODO: Split data tracking and chunk information | | | |
| void setBytesWritten( long bytesWritten ) const { _dataWritten = by | | | |
| tesWritten; } | | | |
| | | | |
| /** | | /** | |
| * if the amount of data written nears the max size of a shard | | * if the amount of data written nears the max size of a shard | |
| * then we check the real size, and if its too big, we split | | * then we check the real size, and if its too big, we split | |
| * @return if something was split | | * @return if something was split | |
| */ | | */ | |
| bool splitIfShould( long dataWritten ) const; | | bool splitIfShould( long dataWritten ) const; | |
| | | | |
| /** | | /** | |
| * Splits this chunk at a non-specificed split key to be chosen by
the mongod holding this chunk. | | * Splits this chunk at a non-specificed split key to be chosen by
the mongod holding this chunk. | |
| * | | * | |
| | | | |
| skipping to change at line 194 | | skipping to change at line 194 | |
| static int MaxObjectPerChunk; | | static int MaxObjectPerChunk; | |
| static bool ShouldAutoSplit; | | static bool ShouldAutoSplit; | |
| | | | |
| // | | // | |
| // accessors and helpers | | // accessors and helpers | |
| // | | // | |
| | | | |
| string toString() const; | | string toString() const; | |
| | | | |
| friend ostream& operator << (ostream& out, const Chunk& c) { return
(out << c.toString()); } | | friend ostream& operator << (ostream& out, const Chunk& c) { return
(out << c.toString()); } | |
|
| | | | |
| | | // chunk equality is determined by comparing the min and max bounds | |
| | | of the chunk | |
| bool operator==(const Chunk& s) const; | | bool operator==(const Chunk& s) const; | |
| bool operator!=(const Chunk& s) const { return ! ( *this == s ); } | | bool operator!=(const Chunk& s) const { return ! ( *this == s ); } | |
| | | | |
| string getns() const; | | string getns() const; | |
| const char * getNS() { return "config.chunks"; } | | const char * getNS() { return "config.chunks"; } | |
| Shard getShard() const { return _shard; } | | Shard getShard() const { return _shard; } | |
| const ChunkManager* getManager() const { return _manager; } | | const ChunkManager* getManager() const { return _manager; } | |
| | | | |
| private: | | private: | |
| | | | |
| | | | |
| skipping to change at line 220 | | skipping to change at line 222 | |
| Shard _shard; | | Shard _shard; | |
| ShardChunkVersion _lastmod; | | ShardChunkVersion _lastmod; | |
| mutable bool _jumbo; | | mutable bool _jumbo; | |
| | | | |
| // transient stuff | | // transient stuff | |
| | | | |
| mutable long _dataWritten; | | mutable long _dataWritten; | |
| | | | |
| // methods, etc.. | | // methods, etc.. | |
| | | | |
|
| /** | | /** Returns the highest or lowest existing value in the shard-key s | |
| | | pace. | |
| | | * Warning: this assumes that the shard key is not "special"- that | |
| | | is, the shardKeyPattern | |
| | | * is simply an ordered list of ascending/descending fiel | |
| | | d names. Examples: | |
| | | * {a : 1, b : -1} is not special. {a : "hashed"} is. | |
| | | * | |
| * if sort 1, return lowest key | | * if sort 1, return lowest key | |
| * if sort -1, return highest key | | * if sort -1, return highest key | |
| * will return empty object if have none | | * will return empty object if have none | |
| */ | | */ | |
| BSONObj _getExtremeKey( int sort ) const; | | BSONObj _getExtremeKey( int sort ) const; | |
| | | | |
| /** initializes _dataWritten with a random value so that a mongos r
estart wouldn't cause delay in splitting */ | | /** initializes _dataWritten with a random value so that a mongos r
estart wouldn't cause delay in splitting */ | |
| static long mkDataWritten(); | | static long mkDataWritten(); | |
| | | | |
| ShardKeyPattern skey() const; | | ShardKeyPattern skey() const; | |
| | | | |
| skipping to change at line 242 | | skipping to change at line 248 | |
| | | | |
| class ChunkRange { | | class ChunkRange { | |
| public: | | public: | |
| const ChunkManager* getManager() const { return _manager; } | | const ChunkManager* getManager() const { return _manager; } | |
| Shard getShard() const { return _shard; } | | Shard getShard() const { return _shard; } | |
| | | | |
| const BSONObj& getMin() const { return _min; } | | const BSONObj& getMin() const { return _min; } | |
| const BSONObj& getMax() const { return _max; } | | const BSONObj& getMax() const { return _max; } | |
| | | | |
| // clones of Chunk methods | | // clones of Chunk methods | |
|
| bool contains(const BSONObj& obj) const; | | // Returns true if this ChunkRange contains the given point, and fa | |
| | | lse otherwise | |
| | | // | |
| | | // Note: this function takes an extracted *key*, not an original do | |
| | | cument | |
| | | // (the point may be computed by, say, hashing a given field or pro | |
| | | jecting | |
| | | // to a subset of fields). | |
| | | bool containsPoint( const BSONObj& point ) const; | |
| | | | |
| ChunkRange(ChunkMap::const_iterator begin, const ChunkMap::const_it
erator end) | | ChunkRange(ChunkMap::const_iterator begin, const ChunkMap::const_it
erator end) | |
| : _manager(begin->second->getManager()) | | : _manager(begin->second->getManager()) | |
| , _shard(begin->second->getShard()) | | , _shard(begin->second->getShard()) | |
| , _min(begin->second->getMin()) | | , _min(begin->second->getMin()) | |
| , _max(boost::prior(end)->second->getMax()) { | | , _max(boost::prior(end)->second->getMax()) { | |
| verify( begin != end ); | | verify( begin != end ); | |
| | | | |
| DEV while (begin != end) { | | DEV while (begin != end) { | |
| verify(begin->second->getManager() == _manager); | | verify(begin->second->getManager() == _manager); | |
| | | | |
| skipping to change at line 360 | | skipping to change at line 371 | |
| const vector<Shard>* initShards, | | const vector<Shard>* initShards, | |
| vector<BSONObj>* splitPoints, | | vector<BSONObj>* splitPoints, | |
| vector<Shard>* shards ) const; | | vector<Shard>* shards ) const; | |
| | | | |
| // | | // | |
| // Methods to use once loaded / created | | // Methods to use once loaded / created | |
| // | | // | |
| | | | |
| int numChunks() const { return _chunkMap.size(); } | | int numChunks() const { return _chunkMap.size(); } | |
| | | | |
|
| ChunkPtr findChunk( const BSONObj& obj ) const; | | /** Given a document, returns the chunk which contains that documen | |
| | | t. | |
| | | * This works by extracting the shard key part of the given docume | |
| | | nt, then | |
| | | * calling findIntersectingChunk() on the extracted key. | |
| | | * | |
| | | * See also the description for findIntersectingChunk(). | |
| | | */ | |
| | | ChunkPtr findChunkForDoc( const BSONObj& doc ) const; | |
| | | | |
| | | /** Given a key that has been extracted from a document, returns th | |
| | | e | |
| | | * chunk that contains that key. | |
| | | * | |
| | | * For instance, to locate the chunk for document {a : "foo" , b : | |
| | | "bar"} | |
| | | * when the shard key is {a : "hashed"}, you can call | |
| | | * findChunkForDoc() on {a : "foo" , b : "bar"}, or | |
| | | * findIntersectingChunk() on {a : hash("foo") } | |
| | | */ | |
| | | ChunkPtr findIntersectingChunk( const BSONObj& point ) const; | |
| | | | |
| ChunkPtr findChunkOnServer( const Shard& shard ) const; | | ChunkPtr findChunkOnServer( const Shard& shard ) const; | |
| | | | |
| void getShardsForQuery( set<Shard>& shards , const BSONObj& query )
const; | | void getShardsForQuery( set<Shard>& shards , const BSONObj& query )
const; | |
| void getAllShards( set<Shard>& all ) const; | | void getAllShards( set<Shard>& all ) const; | |
| /** @param shards set to the shards covered by the interval [min, m
ax], see SERVER-4791 */ | | /** @param shards set to the shards covered by the interval [min, m
ax], see SERVER-4791 */ | |
| void getShardsForRange(set<Shard>& shards, const BSONObj& min, cons
t BSONObj& max, bool fullKeyReq = true) const; | | void getShardsForRange(set<Shard>& shards, const BSONObj& min, cons
t BSONObj& max, bool fullKeyReq = true) const; | |
| | | | |
| ChunkMap getChunkMap() const { return _chunkMap; } | | ChunkMap getChunkMap() const { return _chunkMap; } | |
| | | | |
| /** | | /** | |
| | | | |
| skipping to change at line 525 | | skipping to change at line 553 | |
| struct chunk_lock { | | struct chunk_lock { | |
| chunk_lock( const Chunk* c ){ | | chunk_lock( const Chunk* c ){ | |
| | | | |
| } | | } | |
| | | | |
| Chunk _c; | | Chunk _c; | |
| }; | | }; | |
| */ | | */ | |
| inline string Chunk::genID() const { return genID(_manager->getns(), _m
in); } | | inline string Chunk::genID() const { return genID(_manager->getns(), _m
in); } | |
| | | | |
|
| bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu | | bool setShardVersion( DBClientBase & conn, | |
| nkVersion version , bool authoritative , BSONObj& result ); | | const string& ns, | |
| | | ShardChunkVersion version, | |
| | | ChunkManagerPtr manager, | |
| | | bool authoritative, | |
| | | BSONObj& result ); | |
| | | | |
| } // namespace mongo | | } // namespace mongo | |
| | | | |
End of changes. 7 change blocks. |
| 12 lines changed or deleted | | 57 lines changed or added | |
|
| client.h | | client.h | |
| | | | |
| skipping to change at line 171 | | skipping to change at line 171 | |
| ~GodScope(); | | ~GodScope(); | |
| }; | | }; | |
| | | | |
| //static void assureDatabaseIsOpen(const string& ns, string path=db
path); | | //static void assureDatabaseIsOpen(const string& ns, string path=db
path); | |
| | | | |
| /** "read lock, and set my context, all in one operation" | | /** "read lock, and set my context, all in one operation" | |
| * This handles (if not recursively locked) opening an unopened da
tabase. | | * This handles (if not recursively locked) opening an unopened da
tabase. | |
| */ | | */ | |
| class ReadContext : boost::noncopyable { | | class ReadContext : boost::noncopyable { | |
| public: | | public: | |
|
| ReadContext(const string& ns, string path=dbpath, bool doauth=t
rue ); | | ReadContext(const std::string& ns, const std::string& path=dbpa
th, bool doauth=true ); | |
| Context& ctx() { return *c.get(); } | | Context& ctx() { return *c.get(); } | |
| private: | | private: | |
| scoped_ptr<Lock::DBRead> lk; | | scoped_ptr<Lock::DBRead> lk; | |
| scoped_ptr<Context> c; | | scoped_ptr<Context> c; | |
| }; | | }; | |
| | | | |
| /* Set database we want to use, then, restores when we finish (are
out of scope) | | /* Set database we want to use, then, restores when we finish (are
out of scope) | |
| Note this is also helpful if an exception happens as the state i
f fixed up. | | Note this is also helpful if an exception happens as the state i
f fixed up. | |
| */ | | */ | |
| class Context : boost::noncopyable { | | class Context : boost::noncopyable { | |
| public: | | public: | |
| /** this is probably what you want */ | | /** this is probably what you want */ | |
|
| Context(const string& ns, string path=dbpath, bool doauth=true,
bool doVersion=true ); | | Context(const string& ns, const std::string& path=dbpath, bool
doauth=true, bool doVersion=true ); | |
| | | | |
| /** note: this does not call finishInit -- i.e., does not call | | /** note: this does not call finishInit -- i.e., does not call | |
| shardVersionOk() for example. | | shardVersionOk() for example. | |
| see also: reset(). | | see also: reset(). | |
| */ | | */ | |
|
| Context( string ns , Database * db, bool doauth=true ); | | Context( const std::string& ns , Database * db, bool doauth=tru
e ); | |
| | | | |
| // used by ReadContext | | // used by ReadContext | |
| Context(const string& path, const string& ns, Database *db, boo
l doauth); | | Context(const string& path, const string& ns, Database *db, boo
l doauth); | |
| | | | |
| ~Context(); | | ~Context(); | |
| Client* getClient() const { return _client; } | | Client* getClient() const { return _client; } | |
| Database* db() const { return _db; } | | Database* db() const { return _db; } | |
| const char * ns() const { return _ns.c_str(); } | | const char * ns() const { return _ns.c_str(); } | |
| bool equals( const string& ns , const string& path=dbpath ) con
st { return _ns == ns && _path == path; } | | bool equals( const string& ns , const string& path=dbpath ) con
st { return _ns == ns && _path == path; } | |
| | | | |
| | | | |
| skipping to change at line 240 | | skipping to change at line 240 | |
| bool _justCreated; | | bool _justCreated; | |
| bool _doVersion; | | bool _doVersion; | |
| const string _ns; | | const string _ns; | |
| Database * _db; | | Database * _db; | |
| | | | |
| Timer _timer; | | Timer _timer; | |
| }; // class Client::Context | | }; // class Client::Context | |
| | | | |
| class WriteContext : boost::noncopyable { | | class WriteContext : boost::noncopyable { | |
| public: | | public: | |
|
| WriteContext(const string& ns, string path=dbpath, bool doauth=
true ); | | WriteContext(const string& ns, const std::string& path=dbpath,
bool doauth=true ); | |
| Context& ctx() { return _c; } | | Context& ctx() { return _c; } | |
| private: | | private: | |
| Lock::DBWrite _lk; | | Lock::DBWrite _lk; | |
| Context _c; | | Context _c; | |
| }; | | }; | |
| | | | |
| }; // class Client | | }; // class Client | |
| | | | |
| /** get the Client object for this thread. */ | | /** get the Client object for this thread. */ | |
| inline Client& cc() { | | inline Client& cc() { | |
| | | | |
End of changes. 4 change blocks. |
| 4 lines changed or deleted | | 4 lines changed or added | |
|
| clientcursor.h | | clientcursor.h | |
| | | | |
| skipping to change at line 41 | | skipping to change at line 41 | |
| #include "cursor.h" | | #include "cursor.h" | |
| #include "jsobj.h" | | #include "jsobj.h" | |
| #include "../util/net/message.h" | | #include "../util/net/message.h" | |
| #include "../util/net/listen.h" | | #include "../util/net/listen.h" | |
| #include "../util/background.h" | | #include "../util/background.h" | |
| #include "diskloc.h" | | #include "diskloc.h" | |
| #include "dbhelpers.h" | | #include "dbhelpers.h" | |
| #include "matcher.h" | | #include "matcher.h" | |
| #include "projection.h" | | #include "projection.h" | |
| #include "s/d_chunk_manager.h" | | #include "s/d_chunk_manager.h" | |
|
| | | #include "mongo/db/keypattern.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; | | typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; | |
| typedef long long CursorId; /* passed to the client so it can send back
on getMore */ | | typedef long long CursorId; /* passed to the client so it can send back
on getMore */ | |
| static const CursorId INVALID_CURSOR_ID = -1; // But see SERVER-5726. | | static const CursorId INVALID_CURSOR_ID = -1; // But see SERVER-5726. | |
| class Cursor; /* internal server cursor base class */ | | class Cursor; /* internal server cursor base class */ | |
| class ClientCursor; | | class ClientCursor; | |
| class ParsedQuery; | | class ParsedQuery; | |
| | | | |
| | | | |
| skipping to change at line 146 | | skipping to change at line 147 | |
| _id = c->_cursorid; | | _id = c->_cursorid; | |
| } | | } | |
| else { | | else { | |
| _c = 0; | | _c = 0; | |
| _id = INVALID_CURSOR_ID; | | _id = INVALID_CURSOR_ID; | |
| } | | } | |
| } | | } | |
| ~Holder() { | | ~Holder() { | |
| DESTRUCTOR_GUARD ( reset(); ); | | DESTRUCTOR_GUARD ( reset(); ); | |
| } | | } | |
|
| ClientCursor* get() { return _c; } | | | |
| operator bool() { return _c; } | | operator bool() { return _c; } | |
| ClientCursor * operator-> () { return _c; } | | ClientCursor * operator-> () { return _c; } | |
| const ClientCursor * operator-> () const { return _c; } | | const ClientCursor * operator-> () const { return _c; } | |
| /** Release ownership of the ClientCursor. */ | | /** Release ownership of the ClientCursor. */ | |
| void release() { | | void release() { | |
| _c = 0; | | _c = 0; | |
| _id = INVALID_CURSOR_ID; | | _id = INVALID_CURSOR_ID; | |
| } | | } | |
| private: | | private: | |
| ClientCursor *_c; | | ClientCursor *_c; | |
| | | | |
| skipping to change at line 294 | | skipping to change at line 294 | |
| BSONElement getFieldDotted( const string& name , BSONObj& holder ,
bool * fromKey = 0 ) ; | | BSONElement getFieldDotted( const string& name , BSONObj& holder ,
bool * fromKey = 0 ) ; | |
| | | | |
| /** extract items from object which match a pattern object. | | /** extract items from object which match a pattern object. | |
| * e.g., if pattern is { x : 1, y : 1 }, builds an object with | | * e.g., if pattern is { x : 1, y : 1 }, builds an object with | |
| * x and y elements of this object, if they are present. | | * x and y elements of this object, if they are present. | |
| * returns elements with original field names | | * returns elements with original field names | |
| * NOTE: copied from BSONObj::extractFields | | * NOTE: copied from BSONObj::extractFields | |
| */ | | */ | |
| BSONObj extractFields(const BSONObj &pattern , bool fillWithNull =
false) ; | | BSONObj extractFields(const BSONObj &pattern , bool fillWithNull =
false) ; | |
| | | | |
|
| | | /** Extract elements from the object this cursor currently points t | |
| | | o, using the expression | |
| | | * specified in KeyPattern. Will use a covered index if the one in | |
| | | this cursor is usable. | |
| | | * TODO: there are some cases where a covered index could be used | |
| | | but is not, for instance | |
| | | * if both this index and the keyPattern are {a : "hashed"} | |
| | | */ | |
| | | BSONObj extractKey( const KeyPattern& usingKeyPattern ) const; | |
| | | | |
| void fillQueryResultFromObj( BufBuilder &b, const MatchDetails* det
ails = NULL ) const; | | void fillQueryResultFromObj( BufBuilder &b, const MatchDetails* det
ails = NULL ) const; | |
| | | | |
| bool currentIsDup() { return _c->getsetdup( _c->currLoc() ); } | | bool currentIsDup() { return _c->getsetdup( _c->currLoc() ); } | |
| | | | |
| bool currentMatches() { | | bool currentMatches() { | |
| if ( ! _c->matcher() ) | | if ( ! _c->matcher() ) | |
| return true; | | return true; | |
| return _c->matcher()->matchesCurrent( _c.get() ); | | return _c->matcher()->matchesCurrent( _c.get() ); | |
| } | | } | |
| | | | |
| void setChunkManager( ShardChunkManagerPtr manager ){ _chunkManager
= manager; } | | void setChunkManager( ShardChunkManagerPtr manager ){ _chunkManager
= manager; } | |
| ShardChunkManagerPtr getChunkManager(){ return _chunkManager; } | | ShardChunkManagerPtr getChunkManager(){ return _chunkManager; } | |
| | | | |
| private: | | private: | |
| void setLastLoc_inlock(DiskLoc); | | void setLastLoc_inlock(DiskLoc); | |
| | | | |
| static ClientCursor* find_inlock(CursorId id, bool warn = true) { | | static ClientCursor* find_inlock(CursorId id, bool warn = true) { | |
| CCById::iterator it = clientCursorsById.find(id); | | CCById::iterator it = clientCursorsById.find(id); | |
| if ( it == clientCursorsById.end() ) { | | if ( it == clientCursorsById.end() ) { | |
|
| if ( warn ) | | if ( warn ) { | |
| OCCASIONALLY out() << "ClientCursor::find(): cursor not | | OCCASIONALLY out() << "ClientCursor::find(): cursor not | |
| found in map " << id << " (ok after a drop)\n"; | | found in map '" << id | |
| | | << "' (ok after a drop)" << endl; | |
| | | } | |
| return 0; | | return 0; | |
| } | | } | |
| return it->second; | | return it->second; | |
| } | | } | |
| | | | |
| /* call when cursor's location changes so that we can update the | | /* call when cursor's location changes so that we can update the | |
| cursorsbylocation map. if you are locked and internally iterating
, only | | cursorsbylocation map. if you are locked and internally iterating
, only | |
| need to call when you are ready to "unlock". | | need to call when you are ready to "unlock". | |
| */ | | */ | |
| void updateLocation(); | | void updateLocation(); | |
| | | | |
| skipping to change at line 384 | | skipping to change at line 393 | |
| static void idleTimeReport(unsigned millis); | | static void idleTimeReport(unsigned millis); | |
| | | | |
| static void appendStats( BSONObjBuilder& result ); | | static void appendStats( BSONObjBuilder& result ); | |
| static unsigned numCursors() { return clientCursorsById.size(); } | | static unsigned numCursors() { return clientCursorsById.size(); } | |
| static void informAboutToDeleteBucket(const DiskLoc& b); | | static void informAboutToDeleteBucket(const DiskLoc& b); | |
| static void aboutToDelete(const DiskLoc& dl); | | static void aboutToDelete(const DiskLoc& dl); | |
| static void find( const string& ns , set<CursorId>& all ); | | static void find( const string& ns , set<CursorId>& all ); | |
| | | | |
| private: // methods | | private: // methods | |
| | | | |
|
| // cursors normally timeout after an inactivy period to prevent exc
ess memory use | | // cursors normally timeout after an inactivity period to prevent e
xcess memory use | |
| // setting this prevents timeout of the cursor in question. | | // setting this prevents timeout of the cursor in question. | |
| void noTimeout() { _pinValue++; } | | void noTimeout() { _pinValue++; } | |
| | | | |
| CCByLoc& byLoc() { return _db->ccByLoc; } | | CCByLoc& byLoc() { return _db->ccByLoc; } | |
| | | | |
| Record* _recordForYield( RecordNeeds need ); | | Record* _recordForYield( RecordNeeds need ); | |
| | | | |
| private: | | private: | |
| | | | |
| CursorId _cursorid; | | CursorId _cursorid; | |
| | | | |
End of changes. 5 change blocks. |
| 5 lines changed or deleted | | 17 lines changed or added | |
|
| cmdline.h | | cmdline.h | |
| | | | |
| skipping to change at line 19 | | skipping to change at line 19 | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Affero General Public License for more details. | | * GNU Affero General Public License for more details. | |
| * | | * | |
| * You should have received a copy of the GNU Affero General Public Licen
se | | * You should have received a copy of the GNU Affero General Public Licen
se | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
|
| #include "mongo/pch.h" | | #include <string> | |
| #include "jsobj.h" | | #include <vector> | |
| | | | |
| | | #include "mongo/db/jsobj.h" | |
| | | #include "mongo/util/net/listen.h" | |
| | | | |
| namespace boost { | | namespace boost { | |
| namespace program_options { | | namespace program_options { | |
| class options_description; | | class options_description; | |
| class positional_options_description; | | class positional_options_description; | |
| class variables_map; | | class variables_map; | |
| } | | } | |
| } | | } | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| skipping to change at line 43 | | skipping to change at line 46 | |
| class SSLManager; | | class SSLManager; | |
| #endif | | #endif | |
| | | | |
| /* command line options | | /* command line options | |
| */ | | */ | |
| /* concurrency: OK/READ */ | | /* concurrency: OK/READ */ | |
| struct CmdLine { | | struct CmdLine { | |
| | | | |
| CmdLine(); | | CmdLine(); | |
| | | | |
|
| string binaryName; // mongod or mongos | | std::string binaryName; // mongod or mongos | |
| string cwd; // cwd of when process started | | std::string cwd; // cwd of when process started | |
| | | | |
| // this is suboptimal as someone could rename a binary. todo... | | // this is suboptimal as someone could rename a binary. todo... | |
| bool isMongos() const { return binaryName == "mongos"; } | | bool isMongos() const { return binaryName == "mongos"; } | |
| | | | |
| int port; // --port | | int port; // --port | |
| enum { | | enum { | |
| DefaultDBPort = 27017, | | DefaultDBPort = 27017, | |
| ConfigServerPort = 27019, | | ConfigServerPort = 27019, | |
| ShardServerPort = 27018 | | ShardServerPort = 27018 | |
| }; | | }; | |
| bool isDefaultPort() const { return port == DefaultDBPort; } | | bool isDefaultPort() const { return port == DefaultDBPort; } | |
| | | | |
|
| string bind_ip; // --bind_ip | | std::string bind_ip; // --bind_ip | |
| bool rest; // --rest | | bool rest; // --rest | |
| bool jsonp; // --jsonp | | bool jsonp; // --jsonp | |
| | | | |
|
| string _replSet; // --replSet[/<seedlist>] | | std::string _replSet; // --replSet[/<seedlist>] | |
| string ourSetName() const { | | std::string ourSetName() const { | |
| string setname; | | std::string setname; | |
| size_t sl = _replSet.find('/'); | | size_t sl = _replSet.find('/'); | |
|
| if( sl == string::npos ) | | if( sl == std::string::npos ) | |
| return _replSet; | | return _replSet; | |
| return _replSet.substr(0, sl); | | return _replSet.substr(0, sl); | |
| } | | } | |
| bool usingReplSets() const { return !_replSet.empty(); } | | bool usingReplSets() const { return !_replSet.empty(); } | |
| | | | |
|
| string rsIndexPrefetch;// --indexPrefetch | | std::string rsIndexPrefetch;// --indexPrefetch | |
| | | | |
| // for master/slave replication | | // for master/slave replication | |
|
| string source; // --source | | std::string source; // --source | |
| string only; // --only | | std::string only; // --only | |
| | | | |
| bool quiet; // --quiet | | bool quiet; // --quiet | |
| bool noTableScan; // --notablescan no table scans allowed | | bool noTableScan; // --notablescan no table scans allowed | |
| bool prealloc; // --noprealloc no preallocation of data fil
es | | bool prealloc; // --noprealloc no preallocation of data fil
es | |
| bool preallocj; // --nopreallocj no preallocation of journal
files | | bool preallocj; // --nopreallocj no preallocation of journal
files | |
| bool smallfiles; // --smallfiles allocate smaller data files | | bool smallfiles; // --smallfiles allocate smaller data files | |
| | | | |
| bool configsvr; // --configsvr | | bool configsvr; // --configsvr | |
| | | | |
| bool quota; // --quota | | bool quota; // --quota | |
| | | | |
| skipping to change at line 118 | | skipping to change at line 121 | |
| long long oplogSize; // --oplogSize | | long long oplogSize; // --oplogSize | |
| int defaultProfile; // --profile | | int defaultProfile; // --profile | |
| int slowMS; // --time in ms that is "slow" | | int slowMS; // --time in ms that is "slow" | |
| int defaultLocalThresholdMillis; // --localThreshold in ms to co
nsider a node local | | int defaultLocalThresholdMillis; // --localThreshold in ms to co
nsider a node local | |
| int pretouch; // --pretouch for replication application (e
xperimental) | | int pretouch; // --pretouch for replication application (e
xperimental) | |
| bool moveParanoia; // for move chunk paranoia | | bool moveParanoia; // for move chunk paranoia | |
| double syncdelay; // seconds between fsyncs | | double syncdelay; // seconds between fsyncs | |
| | | | |
| bool noUnixSocket; // --nounixsocket | | bool noUnixSocket; // --nounixsocket | |
| bool doFork; // --fork | | bool doFork; // --fork | |
|
| string socket; // UNIX domain socket directory | | std::string socket; // UNIX domain socket directory | |
| | | | |
| | | int maxConns; // Maximum number of simultaneous open conne | |
| | | ctions. | |
| | | | |
| | | std::string keyFile; // Path to keyfile, or empty if none. | |
| | | std::string pidFile; // Path to pid file, or empty if none. | |
| | | | |
|
| bool keyFile; | | std::string logpath; // Path to log file, if logging to a file; o | |
| | | therwise, empty. | |
| | | bool logAppend; // True if logging to a file in append mode. | |
| | | bool logWithSyslog; // True if logging to syslog; must not be se | |
| | | t if logpath is set. | |
| | | | |
| #ifndef _WIN32 | | #ifndef _WIN32 | |
| pid_t parentProc; // --fork pid of initial process | | pid_t parentProc; // --fork pid of initial process | |
| pid_t leaderProc; // --fork pid of leader process | | pid_t leaderProc; // --fork pid of leader process | |
| #endif | | #endif | |
| | | | |
| #ifdef MONGO_SSL | | #ifdef MONGO_SSL | |
| bool sslOnNormalPorts; // --sslOnNormalPorts | | bool sslOnNormalPorts; // --sslOnNormalPorts | |
|
| string sslPEMKeyFile; // --sslPEMKeyFile | | std::string sslPEMKeyFile; // --sslPEMKeyFile | |
| string sslPEMKeyPassword; // --sslPEMKeyPassword | | std::string sslPEMKeyPassword; // --sslPEMKeyPassword | |
| | | | |
| SSLManager* sslServerManager; // currently leaks on close | | SSLManager* sslServerManager; // currently leaks on close | |
| #endif | | #endif | |
| | | | |
| static void launchOk(); | | static void launchOk(); | |
| | | | |
| static void addGlobalOptions( boost::program_options::options_descr
iption& general , | | static void addGlobalOptions( boost::program_options::options_descr
iption& general , | |
| boost::program_options::options_descr
iption& hidden , | | boost::program_options::options_descr
iption& hidden , | |
| boost::program_options::options_descr
iption& ssl_options ); | | boost::program_options::options_descr
iption& ssl_options ); | |
| | | | |
| static void addWindowsOptions( boost::program_options::options_desc
ription& windows , | | static void addWindowsOptions( boost::program_options::options_desc
ription& windows , | |
| boost::program_options::options_desc
ription& hidden ); | | boost::program_options::options_desc
ription& hidden ); | |
| | | | |
|
| static void parseConfigFile( istream &f, stringstream &ss); | | static void parseConfigFile( istream &f, std::stringstream &ss); | |
| /** | | /** | |
| * @return true if should run program, false if should exit | | * @return true if should run program, false if should exit | |
| */ | | */ | |
|
| static bool store( int argc , char ** argv , | | static bool store( const std::vector<std::string>& argv, | |
| boost::program_options::options_description& vis
ible, | | boost::program_options::options_description& vis
ible, | |
| boost::program_options::options_description& hid
den, | | boost::program_options::options_description& hid
den, | |
| boost::program_options::positional_options_descr
iption& positional, | | boost::program_options::positional_options_descr
iption& positional, | |
| boost::program_options::variables_map &output ); | | boost::program_options::variables_map &output ); | |
| | | | |
|
| | | /** | |
| | | * Blot out sensitive fields in the argv array. | |
| | | */ | |
| | | static void censor(int argc, char** argv); | |
| | | static void censor(std::vector<std::string>* args); | |
| | | | |
| | | static BSONArray getArgvArray(); | |
| | | static BSONObj getParsedOpts(); | |
| | | | |
| time_t started; | | time_t started; | |
| }; | | }; | |
| | | | |
| // todo move to cmdline.cpp? | | // todo move to cmdline.cpp? | |
| inline CmdLine::CmdLine() : | | inline CmdLine::CmdLine() : | |
| port(DefaultDBPort), rest(false), jsonp(false), quiet(false), | | port(DefaultDBPort), rest(false), jsonp(false), quiet(false), | |
| noTableScan(false), prealloc(true), preallocj(true), smallfiles(siz
eof(int*) == 4), | | noTableScan(false), prealloc(true), preallocj(true), smallfiles(siz
eof(int*) == 4), | |
| configsvr(false), quota(false), quotaFiles(8), cpu(false), | | configsvr(false), quota(false), quotaFiles(8), cpu(false), | |
| durOptions(0), objcheck(false), oplogSize(0), defaultProfile(0), | | durOptions(0), objcheck(false), oplogSize(0), defaultProfile(0), | |
| slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara
noia( true ), | | slowMS(100), defaultLocalThresholdMillis(15), pretouch(0), movePara
noia( true ), | |
|
| syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp") | | syncdelay(60), noUnixSocket(false), doFork(0), socket("/tmp"), maxC | |
| | | onns(DEFAULT_MAX_CONN), | |
| | | logAppend(false), logWithSyslog(false) | |
| { | | { | |
| started = time(0); | | started = time(0); | |
| | | | |
| journalCommitInterval = 0; // 0 means use default | | journalCommitInterval = 0; // 0 means use default | |
| dur = false; | | dur = false; | |
| #if defined(_DURABLEDEFAULTON) | | #if defined(_DURABLEDEFAULTON) | |
| dur = true; | | dur = true; | |
| #endif | | #endif | |
| if( sizeof(void*) == 8 ) | | if( sizeof(void*) == 8 ) | |
| dur = true; | | dur = true; | |
| | | | |
| skipping to change at line 187 | | skipping to change at line 207 | |
| #endif | | #endif | |
| | | | |
| #ifdef MONGO_SSL | | #ifdef MONGO_SSL | |
| sslOnNormalPorts = false; | | sslOnNormalPorts = false; | |
| sslServerManager = 0; | | sslServerManager = 0; | |
| #endif | | #endif | |
| } | | } | |
| | | | |
| extern CmdLine cmdLine; | | extern CmdLine cmdLine; | |
| | | | |
|
| void setupLaunchSignals(); | | | |
| void setupCoreSignals(); | | | |
| | | | |
| string prettyHostName(); | | | |
| | | | |
| void printCommandLineOpts(); | | void printCommandLineOpts(); | |
| | | | |
| /** | | /** | |
| * used for setParameter command | | * used for setParameter command | |
| * so you can write validation code that lives with code using it | | * so you can write validation code that lives with code using it | |
| * rather than all in the command place | | * rather than all in the command place | |
| * also lets you have mongos or mongod specific code | | * also lets you have mongos or mongod specific code | |
| * without pulling it all sorts of things | | * without pulling it all sorts of things | |
| */ | | */ | |
| class ParameterValidator { | | class ParameterValidator { | |
| public: | | public: | |
|
| ParameterValidator( const string& name ); | | ParameterValidator( const std::string& name ); | |
| virtual ~ParameterValidator() {} | | virtual ~ParameterValidator() {} | |
| | | | |
|
| virtual bool isValid( BSONElement e , string& errmsg ) const = 0; | | virtual bool isValid( BSONElement e , std::string& errmsg ) const =
0; | |
| | | | |
|
| static ParameterValidator * get( const string& name ); | | static ParameterValidator * get( const std::string& name ); | |
| | | | |
| private: | | private: | |
|
| const string _name; | | const std::string _name; | |
| }; | | }; | |
| | | | |
| } | | } | |
| | | | |
End of changes. 19 change blocks. |
| 28 lines changed or deleted | | 47 lines changed or added | |
|
| connections.h | | connections.h | |
| | | | |
| skipping to change at line 44 | | skipping to change at line 44 | |
| { | | { | |
| ScopedConn c("foo.acme.com:9999"); | | ScopedConn c("foo.acme.com:9999"); | |
| c->runCommand(...); | | c->runCommand(...); | |
| } | | } | |
| | | | |
| throws exception on connect error (but fine to try again later with
a new | | throws exception on connect error (but fine to try again later with
a new | |
| scopedconn object for same host). | | scopedconn object for same host). | |
| */ | | */ | |
| class ScopedConn { | | class ScopedConn { | |
| public: | | public: | |
|
| | | // A flag to keep ScopedConns open when all other sockets are disco | |
| | | nnected | |
| | | static const unsigned keepOpen; | |
| | | | |
| /** throws assertions if connect failure etc. */ | | /** throws assertions if connect failure etc. */ | |
|
| ScopedConn(string hostport); | | ScopedConn(const std::string& hostport); | |
| ~ScopedConn() { | | ~ScopedConn() { | |
| // conLock releases... | | // conLock releases... | |
| } | | } | |
| void reconnect() { | | void reconnect() { | |
|
| connInfo->cc.reset(new DBClientConnection(true, 0, 10)); | | connInfo->cc.reset(new DBClientConnection(true, 0, connInfo->ge
tTimeout())); | |
| connInfo->cc->_logLevel = 2; | | connInfo->cc->_logLevel = 2; | |
| connInfo->connected = false; | | connInfo->connected = false; | |
| connect(); | | connect(); | |
| } | | } | |
| | | | |
|
| | | void setTimeout(time_t timeout) { | |
| | | connInfo->setTimeout(timeout); | |
| | | } | |
| | | | |
| /* If we were to run a query and not exhaust the cursor, future use
of the connection would be problematic. | | /* If we were to run a query and not exhaust the cursor, future use
of the connection would be problematic. | |
| So here what we do is wrapper known safe methods and not allow c
ursor-style queries at all. This makes | | So here what we do is wrapper known safe methods and not allow c
ursor-style queries at all. This makes | |
| ScopedConn limited in functionality but very safe. More non-cur
sor wrappers can be added here if needed. | | ScopedConn limited in functionality but very safe. More non-cur
sor wrappers can be added here if needed. | |
| */ | | */ | |
| bool runCommand(const string &dbname, | | bool runCommand(const string &dbname, | |
| const BSONObj& cmd, | | const BSONObj& cmd, | |
| BSONObj &info, | | BSONObj &info, | |
| int options=0, | | int options=0, | |
| const AuthenticationTable* auth=NULL) { | | const AuthenticationTable* auth=NULL) { | |
|
| return conn()->runCommand(dbname, cmd, info, options, auth); | | return conn()->runCommand(dbname, cmd, info, options, noauth ?
NULL : auth); | |
| } | | } | |
| unsigned long long count(const string &ns) { | | unsigned long long count(const string &ns) { | |
| return conn()->count(ns); | | return conn()->count(ns); | |
| } | | } | |
| BSONObj findOne(const string &ns, const Query& q, const BSONObj *fi
eldsToReturn = 0, int queryOptions = 0) { | | BSONObj findOne(const string &ns, const Query& q, const BSONObj *fi
eldsToReturn = 0, int queryOptions = 0) { | |
| return conn()->findOne(ns, q, fieldsToReturn, queryOptions); | | return conn()->findOne(ns, q, fieldsToReturn, queryOptions); | |
| } | | } | |
| | | | |
| private: | | private: | |
| auto_ptr<scoped_lock> connLock; | | auto_ptr<scoped_lock> connLock; | |
| static mongo::mutex mapMutex; | | static mongo::mutex mapMutex; | |
| struct ConnectionInfo { | | struct ConnectionInfo { | |
| mongo::mutex lock; | | mongo::mutex lock; | |
| scoped_ptr<DBClientConnection> cc; | | scoped_ptr<DBClientConnection> cc; | |
| bool connected; | | bool connected; | |
| ConnectionInfo() : lock("ConnectionInfo"), | | ConnectionInfo() : lock("ConnectionInfo"), | |
|
| cc(new DBClientConnection(/*reconnect*/ true | | cc(new DBClientConnection(/*reconnect*/ true, | |
| , 0, /*timeout*/ 10.0)), | | /*replicaSet*/ 0, | |
| connected(false) { | | /*timeout*/ ReplSetConfig::DEFAUL | |
| | | T_HB_TIMEOUT)), | |
| | | connected(false) { | |
| cc->_logLevel = 2; | | cc->_logLevel = 2; | |
| } | | } | |
|
| | | | |
| | | void tagPort() { | |
| | | MessagingPort& mp = cc->port(); | |
| | | mp.tag |= ScopedConn::keepOpen; | |
| | | } | |
| | | | |
| | | void setTimeout(time_t timeout) { | |
| | | _timeout = timeout; | |
| | | cc->setSoTimeout(_timeout); | |
| | | } | |
| | | | |
| | | int getTimeout() { | |
| | | return _timeout; | |
| | | } | |
| | | | |
| | | private: | |
| | | int _timeout; | |
| } *connInfo; | | } *connInfo; | |
| typedef map<string,ScopedConn::ConnectionInfo*> M; | | typedef map<string,ScopedConn::ConnectionInfo*> M; | |
| static M& _map; | | static M& _map; | |
| scoped_ptr<DBClientConnection>& conn() { return connInfo->cc; } | | scoped_ptr<DBClientConnection>& conn() { return connInfo->cc; } | |
| const string _hostport; | | const string _hostport; | |
| | | | |
| // we should already be locked... | | // we should already be locked... | |
| bool connect() { | | bool connect() { | |
| string err; | | string err; | |
| if (!connInfo->cc->connect(_hostport, err)) { | | if (!connInfo->cc->connect(_hostport, err)) { | |
| log() << "couldn't connect to " << _hostport << ": " << err <<
rsLog; | | log() << "couldn't connect to " << _hostport << ": " << err <<
rsLog; | |
| return false; | | return false; | |
| } | | } | |
| connInfo->connected = true; | | connInfo->connected = true; | |
|
| | | connInfo->tagPort(); | |
| | | | |
| // if we cannot authenticate against a member, then either its ke
y file | | // if we cannot authenticate against a member, then either its ke
y file | |
| // or our key file has to change. if our key file has to change,
we'll | | // or our key file has to change. if our key file has to change,
we'll | |
| // be rebooting. if their file has to change, they'll be rebooted
so the | | // be rebooting. if their file has to change, they'll be rebooted
so the | |
| // connection created above will go dead, reconnect, and reauth. | | // connection created above will go dead, reconnect, and reauth. | |
| if (!noauth) { | | if (!noauth) { | |
| if (!connInfo->cc->auth("local", | | if (!connInfo->cc->auth("local", | |
| internalSecurity.user, | | internalSecurity.user, | |
| internalSecurity.pwd, | | internalSecurity.pwd, | |
| err, | | err, | |
| | | | |
| skipping to change at line 122 | | skipping to change at line 149 | |
| return false; | | return false; | |
| } | | } | |
| connInfo->cc->setAuthenticationTable( | | connInfo->cc->setAuthenticationTable( | |
| AuthenticationTable::getInternalSecurityAuthenticatio
nTable() ); | | AuthenticationTable::getInternalSecurityAuthenticatio
nTable() ); | |
| } | | } | |
| | | | |
| return true; | | return true; | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| inline ScopedConn::ScopedConn(string hostport) : _hostport(hostport) { | | inline ScopedConn::ScopedConn(const std::string& hostport) : _hostport(
hostport) { | |
| bool first = false; | | bool first = false; | |
| { | | { | |
| scoped_lock lk(mapMutex); | | scoped_lock lk(mapMutex); | |
| connInfo = _map[_hostport]; | | connInfo = _map[_hostport]; | |
| if( connInfo == 0 ) { | | if( connInfo == 0 ) { | |
| connInfo = _map[_hostport] = new ConnectionInfo(); | | connInfo = _map[_hostport] = new ConnectionInfo(); | |
| first = true; | | first = true; | |
| connLock.reset( new scoped_lock(connInfo->lock) ); | | connLock.reset( new scoped_lock(connInfo->lock) ); | |
| } | | } | |
| } | | } | |
| | | | |
| skipping to change at line 148 | | skipping to change at line 175 | |
| } | | } | |
| | | | |
| connLock.reset( new scoped_lock(connInfo->lock) ); | | connLock.reset( new scoped_lock(connInfo->lock) ); | |
| if (connInfo->connected) { | | if (connInfo->connected) { | |
| return; | | return; | |
| } | | } | |
| | | | |
| // Keep trying to connect if we're not yet connected | | // Keep trying to connect if we're not yet connected | |
| connect(); | | connect(); | |
| } | | } | |
|
| | | | |
| } | | } | |
| | | | |
End of changes. 10 change blocks. |
| 8 lines changed or deleted | | 35 lines changed or added | |
|
| core.h | | core.h | |
| | | | |
| skipping to change at line 23 | | skipping to change at line 23 | |
| * GNU Affero General Public License for more details. | | * GNU Affero General Public License for more details. | |
| * | | * | |
| * You should have received a copy of the GNU Affero General Public Licen
se | | * You should have received a copy of the GNU Affero General Public Licen
se | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "mongo/pch.h" | | #include "mongo/pch.h" | |
| #include "../jsobj.h" | | #include "../jsobj.h" | |
|
| #include "shapes.h" | | | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| | | | |
| #ifndef M_PI | | #ifndef M_PI | |
| # define M_PI 3.14159265358979323846 | | # define M_PI 3.14159265358979323846 | |
| #endif | | #endif | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class GeoBitSets { | | class GeoBitSets { | |
| | | | |
| skipping to change at line 344 | | skipping to change at line 343 | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| GeoHash operator+( const char * s ) const { | | GeoHash operator+( const char * s ) const { | |
| GeoHash n = *this; | | GeoHash n = *this; | |
| n+=s; | | n+=s; | |
| return n; | | return n; | |
| } | | } | |
| | | | |
|
| GeoHash operator+( string s ) const { | | GeoHash operator+( const std::string& s ) const { | |
| return operator+( s.c_str() ); | | return operator+( s.c_str() ); | |
| } | | } | |
| | | | |
| void _fix() { | | void _fix() { | |
| static long long FULL = 0xFFFFFFFFFFFFFFFFLL; | | static long long FULL = 0xFFFFFFFFFFFFFFFFLL; | |
| long long mask = FULL << ( 64 - ( _bits * 2 ) ); | | long long mask = FULL << ( 64 - ( _bits * 2 ) ); | |
| _hash &= mask; | | _hash &= mask; | |
| } | | } | |
| | | | |
| void append( BSONObjBuilder& b , const char * name ) const { | | void append( BSONObjBuilder& b , const char * name ) const { | |
| | | | |
| skipping to change at line 404 | | skipping to change at line 403 | |
| } | | } | |
| | | | |
| class GeoConvert { | | class GeoConvert { | |
| public: | | public: | |
| virtual ~GeoConvert() {} | | virtual ~GeoConvert() {} | |
| | | | |
| virtual void unhash( const GeoHash& h , double& x , double& y ) con
st = 0; | | virtual void unhash( const GeoHash& h , double& x , double& y ) con
st = 0; | |
| virtual GeoHash hash( double x , double y ) const = 0; | | virtual GeoHash hash( double x , double y ) const = 0; | |
| }; | | }; | |
| | | | |
|
| | | class Point { | |
| | | public: | |
| | | | |
| | | Point( const GeoConvert * g , const GeoHash& hash ) { | |
| | | g->unhash( hash , _x , _y ); | |
| | | } | |
| | | | |
| | | explicit Point( const BSONElement& e ) { | |
| | | BSONObjIterator i(e.Obj()); | |
| | | _x = i.next().number(); | |
| | | _y = i.next().number(); | |
| | | } | |
| | | | |
| | | explicit Point( const BSONObj& o ) { | |
| | | BSONObjIterator i(o); | |
| | | _x = i.next().number(); | |
| | | _y = i.next().number(); | |
| | | } | |
| | | | |
| | | Point( double x , double y ) | |
| | | : _x( x ) , _y( y ) { | |
| | | } | |
| | | | |
| | | Point() : _x(0),_y(0) { | |
| | | } | |
| | | | |
| | | GeoHash hash( const GeoConvert * g ) { | |
| | | return g->hash( _x , _y ); | |
| | | } | |
| | | | |
| | | double distance( const Point& p ) const { | |
| | | double a = _x - p._x; | |
| | | double b = _y - p._y; | |
| | | | |
| | | // Avoid numerical error if possible... | |
| | | if( a == 0 ) return abs( _y - p._y ); | |
| | | if( b == 0 ) return abs( _x - p._x ); | |
| | | | |
| | | return sqrt( ( a * a ) + ( b * b ) ); | |
| | | } | |
| | | | |
| | | /** | |
| | | * Distance method that compares x or y coords when other direction | |
| | | is zero, | |
| | | * avoids numerical error when distances are very close to radius b | |
| | | ut axis-aligned. | |
| | | * | |
| | | * An example of the problem is: | |
| | | * (52.0 - 51.9999) - 0.0001 = 3.31965e-15 and 52.0 - 51.9999 > 0.0 | |
| | | 001 in double arithmetic | |
| | | * but: | |
| | | * 51.9999 + 0.0001 <= 52.0 | |
| | | * | |
| | | * This avoids some (but not all!) suprising results in $center que | |
| | | ries where points are | |
| | | * ( radius + center.x, center.y ) or vice-versa. | |
| | | */ | |
| | | bool distanceWithin( const Point& p, double radius ) const { | |
| | | double a = _x - p._x; | |
| | | double b = _y - p._y; | |
| | | | |
| | | if( a == 0 ) { | |
| | | // | |
| | | // Note: For some, unknown reason, when a 32-bit g++ optim | |
| | | izes this call, the sum is | |
| | | // calculated imprecisely. We need to force the compiler t | |
| | | o always evaluate it correctly, | |
| | | // hence the weirdness. | |
| | | // | |
| | | // On some 32-bit linux machines, removing the volatile key | |
| | | word or calculating the sum inline | |
| | | // will make certain geo tests fail. Of course this check | |
| | | will force volatile for all 32-bit systems, | |
| | | // not just affected systems. | |
| | | if( sizeof(void*) <= 4 ){ | |
| | | volatile double sum = _y > p._y ? p._y + radius : _y + | |
| | | radius; | |
| | | return _y > p._y ? sum >= _y : sum >= p._y; | |
| | | } | |
| | | else { | |
| | | // Original math, correct for most systems | |
| | | return _y > p._y ? p._y + radius >= _y : _y + radius >= | |
| | | p._y; | |
| | | } | |
| | | } | |
| | | if( b == 0 ) { | |
| | | if( sizeof(void*) <= 4 ){ | |
| | | volatile double sum = _x > p._x ? p._x + radius : _x + | |
| | | radius; | |
| | | return _x > p._x ? sum >= _x : sum >= p._x; | |
| | | } | |
| | | else { | |
| | | return _x > p._x ? p._x + radius >= _x : _x + radius >= | |
| | | p._x; | |
| | | } | |
| | | } | |
| | | | |
| | | return sqrt( ( a * a ) + ( b * b ) ) <= radius; | |
| | | } | |
| | | | |
| | | string toString() const { | |
| | | StringBuilder buf; | |
| | | buf << "(" << _x << "," << _y << ")"; | |
| | | return buf.str(); | |
| | | | |
| | | } | |
| | | | |
| | | double _x; | |
| | | double _y; | |
| | | }; | |
| | | | |
| extern const double EARTH_RADIUS_KM; | | extern const double EARTH_RADIUS_KM; | |
| extern const double EARTH_RADIUS_MILES; | | extern const double EARTH_RADIUS_MILES; | |
| | | | |
| // Technically lat/long bounds, not really tied to earth radius. | | // Technically lat/long bounds, not really tied to earth radius. | |
| inline void checkEarthBounds( Point p ) { | | inline void checkEarthBounds( Point p ) { | |
| uassert( 14808, str::stream() << "point " << p.toString() << " must
be in earth-like bounds of long : [-180, 180], lat : [-90, 90] ", | | uassert( 14808, str::stream() << "point " << p.toString() << " must
be in earth-like bounds of long : [-180, 180], lat : [-90, 90] ", | |
| p._x >= -180 && p._x <= 180 && p._y >= -90 && p._y <= 90 )
; | | p._x >= -180 && p._x <= 180 && p._y >= -90 && p._y <= 90 )
; | |
| } | | } | |
| | | | |
| inline double deg2rad(double deg) { return deg * (M_PI/180); } | | inline double deg2rad(double deg) { return deg * (M_PI/180); } | |
| | | | |
End of changes. 3 change blocks. |
| 2 lines changed or deleted | | 112 lines changed or added | |
|
| curop.h | | curop.h | |
| | | | |
| skipping to change at line 21 | | skipping to change at line 21 | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Affero General Public License for more details. | | * GNU Affero General Public License for more details. | |
| * | | * | |
| * You should have received a copy of the GNU Affero General Public Lice
nse | | * You should have received a copy of the GNU Affero General Public Lice
nse | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
|
| #include "namespace-inl.h" | | #include <vector> | |
| #include "client.h" | | | |
| #include "../bson/util/atomic_int.h" | | #include "mongo/bson/util/atomic_int.h" | |
| #include "../util/concurrency/spin_lock.h" | | #include "mongo/db/client.h" | |
| #include "../util/time_support.h" | | #include "mongo/db/namespace-inl.h" | |
| #include "../util/net/hostandport.h" | | #include "mongo/util/concurrency/spin_lock.h" | |
| #include "../util/progress_meter.h" | | #include "mongo/util/net/hostandport.h" | |
| | | #include "mongo/util/progress_meter.h" | |
| | | #include "mongo/util/time_support.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class CurOp; | | class CurOp; | |
| | | | |
| /* lifespan is different than CurOp because of recursives with DBDirect
Client */ | | /* lifespan is different than CurOp because of recursives with DBDirect
Client */ | |
| class OpDebug { | | class OpDebug { | |
| public: | | public: | |
| OpDebug() : ns(""){ reset(); } | | OpDebug() : ns(""){ reset(); } | |
| | | | |
| void reset(); | | void reset(); | |
| | | | |
| string report( const CurOp& curop ) const; | | string report( const CurOp& curop ) const; | |
|
| void append( const CurOp& curop, BSONObjBuilder& b ) const; | | | |
| | | /** | |
| | | * Appends stored data and information from curop to the builder. | |
| | | * | |
| | | * @param curop information about the current operation which will | |
| | | be | |
| | | * use to append data to the builder. | |
| | | * @param builder the BSON builder to use for appending data. Data | |
| | | can | |
| | | * still be appended even if this method returns false. | |
| | | * @param maxSize the maximum allowed combined size for the query o | |
| | | bject | |
| | | * and update object | |
| | | * | |
| | | * @return false if the sum of the sizes for the query object and u | |
| | | pdate | |
| | | * object exceeded maxSize | |
| | | */ | |
| | | bool append(const CurOp& curop, BSONObjBuilder& builder, size_t max | |
| | | Size) const; | |
| | | | |
| // ------------------- | | // ------------------- | |
| | | | |
| StringBuilder extra; // weird things we need to fix later | | StringBuilder extra; // weird things we need to fix later | |
| | | | |
| // basic options | | // basic options | |
| int op; | | int op; | |
| bool iscommand; | | bool iscommand; | |
| Namespace ns; | | Namespace ns; | |
| BSONObj query; | | BSONObj query; | |
| | | | |
| skipping to change at line 103 | | skipping to change at line 119 | |
| } | | } | |
| | | | |
| void reset( int sz = 0 ) { | | void reset( int sz = 0 ) { | |
| _lock.lock(); | | _lock.lock(); | |
| _reset( sz ); | | _reset( sz ); | |
| _lock.unlock(); | | _lock.unlock(); | |
| } | | } | |
| | | | |
| void set( const BSONObj& o ) { | | void set( const BSONObj& o ) { | |
| scoped_spinlock lk(_lock); | | scoped_spinlock lk(_lock); | |
|
| size_t sz = o.objsize(); | | int sz = o.objsize(); | |
| if ( sz > sizeof(_buf) ) { | | if ( sz > (int) sizeof(_buf) ) { | |
| _reset(TOO_BIG_SENTINEL); | | _reset(TOO_BIG_SENTINEL); | |
| } | | } | |
| else { | | else { | |
| memcpy(_buf, o.objdata(), sz ); | | memcpy(_buf, o.objdata(), sz ); | |
| } | | } | |
| } | | } | |
| | | | |
| int size() const { return *_size; } | | int size() const { return *_size; } | |
| bool have() const { return size() > 0; } | | bool have() const { return size() > 0; } | |
| | | | |
| | | | |
| skipping to change at line 154 | | skipping to change at line 170 | |
| | | | |
| /* Current operation (for the current Client). | | /* Current operation (for the current Client). | |
| an embedded member of Client class, and typically used from within t
he mutex there. | | an embedded member of Client class, and typically used from within t
he mutex there. | |
| */ | | */ | |
| class CurOp : boost::noncopyable { | | class CurOp : boost::noncopyable { | |
| public: | | public: | |
| CurOp( Client * client , CurOp * wrapped = 0 ); | | CurOp( Client * client , CurOp * wrapped = 0 ); | |
| ~CurOp(); | | ~CurOp(); | |
| | | | |
| bool haveQuery() const { return _query.have(); } | | bool haveQuery() const { return _query.have(); } | |
|
| BSONObj query() { return _query.get(); } | | BSONObj query() const { return _query.get(); } | |
| void appendQuery( BSONObjBuilder& b , const StringData& name ) cons
t { _query.append( b , name ); } | | void appendQuery( BSONObjBuilder& b , const StringData& name ) cons
t { _query.append( b , name ); } | |
| | | | |
| void ensureStarted(); | | void ensureStarted(); | |
| bool isStarted() const { return _start > 0; } | | bool isStarted() const { return _start > 0; } | |
| void enter( Client::Context * context ); | | void enter( Client::Context * context ); | |
| void leave( Client::Context * context ); | | void leave( Client::Context * context ); | |
| void reset(); | | void reset(); | |
| void reset( const HostAndPort& remote, int op ); | | void reset( const HostAndPort& remote, int op ); | |
| void markCommand() { _command = true; } | | void markCommand() { _command = true; } | |
| OpDebug& debug() { return _debug; } | | OpDebug& debug() { return _debug; } | |
| | | | |
| skipping to change at line 209 | | skipping to change at line 225 | |
| int elapsedSeconds() { return elapsedMillis() / 1000; } | | int elapsedSeconds() { return elapsedMillis() / 1000; } | |
| void setQuery(const BSONObj& query) { _query.set( query ); } | | void setQuery(const BSONObj& query) { _query.set( query ); } | |
| Client * getClient() const { return _client; } | | Client * getClient() const { return _client; } | |
| BSONObj info(); | | BSONObj info(); | |
| BSONObj infoNoauth(); | | BSONObj infoNoauth(); | |
| string getRemoteString( bool includePort = true ) { return _remote.
toString(includePort); } | | string getRemoteString( bool includePort = true ) { return _remote.
toString(includePort); } | |
| ProgressMeter& setMessage( const char * msg , unsigned long long pr
ogressMeterTotal = 0 , int secondsBetween = 3 ); | | ProgressMeter& setMessage( const char * msg , unsigned long long pr
ogressMeterTotal = 0 , int secondsBetween = 3 ); | |
| string getMessage() const { return _message.toString(); } | | string getMessage() const { return _message.toString(); } | |
| ProgressMeter& getProgressMeter() { return _progressMeter; } | | ProgressMeter& getProgressMeter() { return _progressMeter; } | |
| CurOp *parent() const { return _wrapped; } | | CurOp *parent() const { return _wrapped; } | |
|
| void kill() { _killed = true; } | | void kill(bool* pNotifyFlag = NULL); | |
| bool killed() const { return _killed; } | | bool killPending() const { return _killPending.load(); } | |
| void yielded() { _numYields++; } | | void yielded() { _numYields++; } | |
| int numYields() const { return _numYields; } | | int numYields() const { return _numYields; } | |
| void suppressFromCurop() { _suppressFromCurop = true; } | | void suppressFromCurop() { _suppressFromCurop = true; } | |
| | | | |
| long long getExpectedLatencyMs() const { return _expectedLatencyMs;
} | | long long getExpectedLatencyMs() const { return _expectedLatencyMs;
} | |
| void setExpectedLatencyMs( long long latency ) { _expectedLatencyMs
= latency; } | | void setExpectedLatencyMs( long long latency ) { _expectedLatencyMs
= latency; } | |
| | | | |
| void recordGlobalTime( long long micros ) const; | | void recordGlobalTime( long long micros ) const; | |
| | | | |
| const LockStat& lockStat() const { return _lockStat; } | | const LockStat& lockStat() const { return _lockStat; } | |
| LockStat& lockStat() { return _lockStat; } | | LockStat& lockStat() { return _lockStat; } | |
|
| | | | |
| | | void setKillWaiterFlags(); | |
| private: | | private: | |
| friend class Client; | | friend class Client; | |
| void _reset(); | | void _reset(); | |
| | | | |
| static AtomicUInt _nextOpNum; | | static AtomicUInt _nextOpNum; | |
| Client * _client; | | Client * _client; | |
| CurOp * _wrapped; | | CurOp * _wrapped; | |
| unsigned long long _start; | | unsigned long long _start; | |
| unsigned long long _end; | | unsigned long long _end; | |
| bool _active; | | bool _active; | |
| | | | |
| skipping to change at line 243 | | skipping to change at line 261 | |
| int _op; | | int _op; | |
| bool _command; | | bool _command; | |
| int _dbprofile; // 0=off, 1=slow, 2=all | | int _dbprofile; // 0=off, 1=slow, 2=all | |
| AtomicUInt _opNum; // todo: simple being "unsigned" m
ay make more sense here | | AtomicUInt _opNum; // todo: simple being "unsigned" m
ay make more sense here | |
| char _ns[Namespace::MaxNsLen+2]; | | char _ns[Namespace::MaxNsLen+2]; | |
| HostAndPort _remote; // CAREFUL here with thread safety | | HostAndPort _remote; // CAREFUL here with thread safety | |
| CachedBSONObj _query; // CachedBSONObj is thread safe | | CachedBSONObj _query; // CachedBSONObj is thread safe | |
| OpDebug _debug; | | OpDebug _debug; | |
| ThreadSafeString _message; | | ThreadSafeString _message; | |
| ProgressMeter _progressMeter; | | ProgressMeter _progressMeter; | |
|
| volatile bool _killed; | | AtomicInt32 _killPending; | |
| int _numYields; | | int _numYields; | |
| LockStat _lockStat; | | LockStat _lockStat; | |
|
| | | // _notifyList is protected by the global killCurrentOp's mtx. | |
| | | std::vector<bool*> _notifyList; | |
| | | | |
| // this is how much "extra" time a query might take | | // this is how much "extra" time a query might take | |
| // a writebacklisten for example will block for 30s | | // a writebacklisten for example will block for 30s | |
| // so this should be 30000 in that case | | // so this should be 30000 in that case | |
| long long _expectedLatencyMs; | | long long _expectedLatencyMs; | |
|
| | | | |
| }; | | }; | |
|
| | | | |
| /* _globalKill: we are shutting down | | | |
| otherwise kill attribute set on specified CurOp | | | |
| this class does not handle races between interruptJs and the checkFo | | | |
| rInterrupt functions - those must be | | | |
| handled by the client of this class | | | |
| */ | | | |
| extern class KillCurrentOp { | | | |
| public: | | | |
| void killAll(); | | | |
| void kill(AtomicUInt i); | | | |
| | | | |
| /** @return true if global interrupt and should terminate the opera | | | |
| tion */ | | | |
| bool globalInterruptCheck() const { return _globalKill; } | | | |
| | | | |
| /** | | | |
| * @param heedMutex if true and have a write lock, won't kill op si | | | |
| nce it might be unsafe | | | |
| */ | | | |
| void checkForInterrupt( bool heedMutex = true ); | | | |
| | | | |
| /** @return "" if not interrupted. otherwise, you should stop. */ | | | |
| const char *checkForInterruptNoAssert(); | | | |
| | | | |
| private: | | | |
| void interruptJs( AtomicUInt *op ); | | | |
| volatile bool _globalKill; | | | |
| } killCurrentOp; | | | |
| | | | |
| } | | } | |
| | | | |
End of changes. 10 change blocks. |
| 45 lines changed or deleted | | 39 lines changed or added | |
|
| cursor.h | | cursor.h | |
| | | | |
| skipping to change at line 189 | | skipping to change at line 189 | |
| | | | |
| // The implementation may return different matchers depending on th
e | | // The implementation may return different matchers depending on th
e | |
| // position of the cursor. If matcher() is nonzero at the start, | | // position of the cursor. If matcher() is nonzero at the start, | |
| // matcher() should be checked each time advance() is called. | | // matcher() should be checked each time advance() is called. | |
| // Implementations which generate their own matcher should return t
his | | // Implementations which generate their own matcher should return t
his | |
| // to avoid a matcher being set manually. | | // to avoid a matcher being set manually. | |
| // Note that the return values differ subtly here | | // Note that the return values differ subtly here | |
| | | | |
| // Used when we want fast matcher lookup | | // Used when we want fast matcher lookup | |
| virtual CoveredIndexMatcher *matcher() const { return 0; } | | virtual CoveredIndexMatcher *matcher() const { return 0; } | |
|
| // Used when we need to share this matcher with someone else | | | |
| virtual shared_ptr< CoveredIndexMatcher > matcherPtr() const { retu | | | |
| rn shared_ptr< CoveredIndexMatcher >(); } | | | |
| | | | |
| virtual bool currentMatches( MatchDetails *details = 0 ) { | | virtual bool currentMatches( MatchDetails *details = 0 ) { | |
| return !matcher() || matcher()->matchesCurrent( this, details )
; | | return !matcher() || matcher()->matchesCurrent( this, details )
; | |
| } | | } | |
| | | | |
| // A convenience function for setting the value of matcher() manual
ly | | // A convenience function for setting the value of matcher() manual
ly | |
| // so it may be accessed later. Implementations which must generat
e | | // so it may be accessed later. Implementations which must generat
e | |
| // their own matcher() should assert here. | | // their own matcher() should assert here. | |
| virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher
) { | | virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher
) { | |
| massert( 13285, "manual matcher config not allowed", false ); | | massert( 13285, "manual matcher config not allowed", false ); | |
| | | | |
| skipping to change at line 267 | | skipping to change at line 265 | |
| if ( !curr.isNull() || !last.isNull() ) | | if ( !curr.isNull() || !last.isNull() ) | |
| tailable_ = true; | | tailable_ = true; | |
| } | | } | |
| virtual bool tailable() { return tailable_; } | | virtual bool tailable() { return tailable_; } | |
| virtual bool getsetdup(DiskLoc loc) { return false; } | | virtual bool getsetdup(DiskLoc loc) { return false; } | |
| virtual bool isMultiKey() const { return false; } | | virtual bool isMultiKey() const { return false; } | |
| virtual bool modifiedKeys() const { return false; } | | virtual bool modifiedKeys() const { return false; } | |
| virtual bool supportGetMore() { return true; } | | virtual bool supportGetMore() { return true; } | |
| virtual bool supportYields() { return true; } | | virtual bool supportYields() { return true; } | |
| virtual CoveredIndexMatcher *matcher() const { return _matcher.get(
); } | | virtual CoveredIndexMatcher *matcher() const { return _matcher.get(
); } | |
|
| virtual shared_ptr< CoveredIndexMatcher > matcherPtr() const { retu
rn _matcher; } | | | |
| virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher
) { _matcher = matcher; } | | virtual void setMatcher( shared_ptr< CoveredIndexMatcher > matcher
) { _matcher = matcher; } | |
| virtual const Projection::KeyOnly *keyFieldsOnly() const { return _
keyFieldsOnly.get(); } | | virtual const Projection::KeyOnly *keyFieldsOnly() const { return _
keyFieldsOnly.get(); } | |
| virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly
> &keyFieldsOnly ) { | | virtual void setKeyFieldsOnly( const shared_ptr<Projection::KeyOnly
> &keyFieldsOnly ) { | |
| _keyFieldsOnly = keyFieldsOnly; | | _keyFieldsOnly = keyFieldsOnly; | |
| } | | } | |
| virtual long long nscanned() { return _nscanned; } | | virtual long long nscanned() { return _nscanned; } | |
| | | | |
| protected: | | protected: | |
| DiskLoc curr, last; | | DiskLoc curr, last; | |
| const AdvanceStrategy *s; | | const AdvanceStrategy *s; | |
| | | | |
End of changes. 2 change blocks. |
| 4 lines changed or deleted | | 0 lines changed or added | |
|
| d_chunk_manager.h | | d_chunk_manager.h | |
| | | | |
| skipping to change at line 65 | | skipping to change at line 65 | |
| * @param ns namespace for the collections whose chunks we're inter
ested | | * @param ns namespace for the collections whose chunks we're inter
ested | |
| * @param shardName name of the shard that this chunk matcher shoul
d track | | * @param shardName name of the shard that this chunk matcher shoul
d track | |
| * | | * | |
| * This constructor throws if collection is dropped/malformed and o
n connectivity errors | | * This constructor throws if collection is dropped/malformed and o
n connectivity errors | |
| */ | | */ | |
| static ShardChunkManager* make( const string& configServer , const
string& ns , const string& shardName, ShardChunkManagerPtr oldManager = Sha
rdChunkManagerPtr() ); | | static ShardChunkManager* make( const string& configServer , const
string& ns , const string& shardName, ShardChunkManagerPtr oldManager = Sha
rdChunkManagerPtr() ); | |
| | | | |
| /** | | /** | |
| * Same as the regular constructor but used in unittest (no access
to configDB required). | | * Same as the regular constructor but used in unittest (no access
to configDB required). | |
| * | | * | |
|
| * @param collectionDoc simulates config.collection's entry for one
colleciton | | * @param collectionDoc simulates config.collection's entry for one
collection | |
| * @param chunksDocs simulates config.chunks' entries for one colle
ction's shard | | * @param chunksDocs simulates config.chunks' entries for one colle
ction's shard | |
| */ | | */ | |
| ShardChunkManager( const BSONObj& collectionDoc , const BSONArray&
chunksDoc ); | | ShardChunkManager( const BSONObj& collectionDoc , const BSONArray&
chunksDoc ); | |
| | | | |
| ~ShardChunkManager() {} | | ~ShardChunkManager() {} | |
| | | | |
| /** | | /** | |
| * Generates a new manager based on 'this's state minus a given chu
nk. | | * Generates a new manager based on 'this's state minus a given chu
nk. | |
| * | | * | |
| * @param min max chunk boundaries for the chunk to subtract | | * @param min max chunk boundaries for the chunk to subtract | |
| | | | |
| skipping to change at line 108 | | skipping to change at line 108 | |
| */ | | */ | |
| ShardChunkManager* cloneSplit( const BSONObj& min , const BSONObj&
max , const vector<BSONObj>& splitKeys , | | ShardChunkManager* cloneSplit( const BSONObj& min , const BSONObj&
max , const vector<BSONObj>& splitKeys , | |
| const ShardChunkVersion& version ); | | const ShardChunkVersion& version ); | |
| | | | |
| /** | | /** | |
| * Checks whether a document belongs to this shard. | | * Checks whether a document belongs to this shard. | |
| * | | * | |
| * @param obj document containing sharding keys (and, optionally, o
ther attributes) | | * @param obj document containing sharding keys (and, optionally, o
ther attributes) | |
| * @return true if shards hold the object | | * @return true if shards hold the object | |
| */ | | */ | |
|
| bool belongsToMe( const BSONObj& obj ) const; | | bool belongsToMe( const BSONObj& doc ) const; | |
| | | | |
| /** | | /** | |
|
| * Checks whether a document belongs to this shard. | | * Checks whether the document currently pointed to by this cursor | |
| | | belongs to this shard. | |
| | | * This version of the function will use a covered index if there i | |
| | | s one in the cursor. | |
| * | | * | |
|
| * @param obj document containing sharding keys (and, optionally, o
ther attributes) | | * @param cc cursor pointing to an object | |
| * @return true if shards hold the object | | * @return true if shards hold the object | |
| */ | | */ | |
| bool belongsToMe( ClientCursor* cc ) const; | | bool belongsToMe( ClientCursor* cc ) const; | |
| | | | |
| /** | | /** | |
| * Given a chunk's min key (or empty doc), gets the boundary of the
chunk following that one (the first). | | * Given a chunk's min key (or empty doc), gets the boundary of the
chunk following that one (the first). | |
| * | | * | |
| * @param lookupKey is the min key for a previously obtained chunk
or the empty document | | * @param lookupKey is the min key for a previously obtained chunk
or the empty document | |
| * @param foundMin IN/OUT min for chunk following the one starting
at lookupKey | | * @param foundMin IN/OUT min for chunk following the one starting
at lookupKey | |
| * @param foundMax IN/OUT max for the above chunk | | * @param foundMax IN/OUT max for the above chunk | |
| | | | |
| skipping to change at line 140 | | skipping to change at line 141 | |
| ShardChunkVersion getVersion() const { return _version; } | | ShardChunkVersion getVersion() const { return _version; } | |
| ShardChunkVersion getCollVersion() const { return _collVersion; } | | ShardChunkVersion getCollVersion() const { return _collVersion; } | |
| BSONObj getKey() const { return _key.getOwned(); } | | BSONObj getKey() const { return _key.getOwned(); } | |
| unsigned getNumChunks() const { return _chunksMap.size(); } | | unsigned getNumChunks() const { return _chunksMap.size(); } | |
| | | | |
| string toString() const; | | string toString() const; | |
| private: | | private: | |
| void _init( const string& configServer , const string& ns , const s
tring& shardName, ShardChunkManagerPtr oldManager = ShardChunkManagerPtr()
); | | void _init( const string& configServer , const string& ns , const s
tring& shardName, ShardChunkManagerPtr oldManager = ShardChunkManagerPtr()
); | |
| | | | |
| /** | | /** | |
|
| * @same as belongsToMe to but key has to be the shard key | | * @same as belongsToMe but point is the extracted shard key | |
| */ | | */ | |
|
| bool _belongsToMe( const BSONObj& key ) const; | | bool _belongsToMe( const BSONObj& point ) const; | |
| | | | |
| ShardChunkVersion _collVersion; | | ShardChunkVersion _collVersion; | |
| // highest ShardChunkVersion for which this ShardChunkManager's inf
ormation is accurate | | // highest ShardChunkVersion for which this ShardChunkManager's inf
ormation is accurate | |
| ShardChunkVersion _version; | | ShardChunkVersion _version; | |
| | | | |
| // key pattern for chunks under this range | | // key pattern for chunks under this range | |
| BSONObj _key; | | BSONObj _key; | |
| | | | |
| // a map from a min key into the chunk's (or range's) max boundary | | // a map from a min key into the chunk's (or range's) max boundary | |
| typedef map< BSONObj, BSONObj , BSONObjCmp > RangeMap; | | typedef map< BSONObj, BSONObj , BSONObjCmp > RangeMap; | |
| | | | |
End of changes. 6 change blocks. |
| 6 lines changed or deleted | | 9 lines changed or added | |
|
| d_logic.h | | d_logic.h | |
| | | | |
| skipping to change at line 47 | | skipping to change at line 47 | |
| // -------------- | | // -------------- | |
| | | | |
| class ShardingState { | | class ShardingState { | |
| public: | | public: | |
| ShardingState(); | | ShardingState(); | |
| | | | |
| bool enabled() const { return _enabled; } | | bool enabled() const { return _enabled; } | |
| const string& getConfigServer() const { return _configServer; } | | const string& getConfigServer() const { return _configServer; } | |
| void enable( const string& server ); | | void enable( const string& server ); | |
| | | | |
|
| // Initialize sharding state and begin authenticating outgoing conn | | | |
| ections and handling | | | |
| // shard versions. If this is not run before sharded operations oc | | | |
| cur auth will not work | | | |
| // and versions will not be tracked. | | | |
| static void initialize(const string& server); | | | |
| | | | |
| void gotShardName( const string& name ); | | void gotShardName( const string& name ); | |
| void gotShardHost( string host ); | | void gotShardHost( string host ); | |
| | | | |
| string getShardName() { return _shardName; } | | string getShardName() { return _shardName; } | |
| string getShardHost() { return _shardHost; } | | string getShardHost() { return _shardHost; } | |
| | | | |
| /** Reverts back to a state where this mongod is not sharded. */ | | /** Reverts back to a state where this mongod is not sharded. */ | |
| void resetShardingState(); | | void resetShardingState(); | |
| | | | |
| // versioning support | | // versioning support | |
| | | | |
| skipping to change at line 89 | | skipping to change at line 84 | |
| * @param ns the collection to be dropped | | * @param ns the collection to be dropped | |
| */ | | */ | |
| void resetVersion( const string& ns ); | | void resetVersion( const string& ns ); | |
| | | | |
| /** | | /** | |
| * Requests to access a collection at a certain version. If the col
lection's manager is not at that version it | | * Requests to access a collection at a certain version. If the col
lection's manager is not at that version it | |
| * will try to update itself to the newest version. The request is
only granted if the version is the current or | | * will try to update itself to the newest version. The request is
only granted if the version is the current or | |
| * the newest one. | | * the newest one. | |
| * | | * | |
| * @param ns collection to be accessed | | * @param ns collection to be accessed | |
|
| * @param version (IN) the client belive this collection is on and
(OUT) the version the manager is actually in | | * @param version (IN) the client believe this collection is on and
(OUT) the version the manager is actually in | |
| * @return true if the access can be allowed at the provided versio
n | | * @return true if the access can be allowed at the provided versio
n | |
| */ | | */ | |
| bool trySetVersion( const string& ns , ConfigVersion& version ); | | bool trySetVersion( const string& ns , ConfigVersion& version ); | |
| | | | |
| void appendInfo( BSONObjBuilder& b ); | | void appendInfo( BSONObjBuilder& b ); | |
| | | | |
| // querying support | | // querying support | |
| | | | |
| bool needShardChunkManager( const string& ns ) const; | | bool needShardChunkManager( const string& ns ) const; | |
| ShardChunkManagerPtr getShardChunkManager( const string& ns ); | | ShardChunkManagerPtr getShardChunkManager( const string& ns ); | |
| | | | |
| skipping to change at line 171 | | skipping to change at line 166 | |
| // map from a namespace into the ensemble of chunk ranges that are
stored in this mongod | | // map from a namespace into the ensemble of chunk ranges that are
stored in this mongod | |
| // a ShardChunkManager carries all state we need for a collection a
t this shard, including its version information | | // a ShardChunkManager carries all state we need for a collection a
t this shard, including its version information | |
| typedef map<string,ShardChunkManagerPtr> ChunkManagersMap; | | typedef map<string,ShardChunkManagerPtr> ChunkManagersMap; | |
| ChunkManagersMap _chunks; | | ChunkManagersMap _chunks; | |
| }; | | }; | |
| | | | |
| extern ShardingState shardingState; | | extern ShardingState shardingState; | |
| | | | |
| /** | | /** | |
| * one per connection from mongos | | * one per connection from mongos | |
|
| * holds version state for each namesapce | | * holds version state for each namespace | |
| */ | | */ | |
| class ShardedConnectionInfo { | | class ShardedConnectionInfo { | |
| public: | | public: | |
| ShardedConnectionInfo(); | | ShardedConnectionInfo(); | |
| | | | |
| const OID& getID() const { return _id; } | | const OID& getID() const { return _id; } | |
| bool hasID() const { return _id.isSet(); } | | bool hasID() const { return _id.isSet(); } | |
| void setID( const OID& id ); | | void setID( const OID& id ); | |
| | | | |
| const ConfigVersion getVersion( const string& ns ) const; | | const ConfigVersion getVersion( const string& ns ) const; | |
| | | | |
End of changes. 3 change blocks. |
| 9 lines changed or deleted | | 2 lines changed or added | |
|
| dbclient_rs.h | | dbclient_rs.h | |
| | | | |
| skipping to change at line 41 | | skipping to change at line 41 | |
| | | | |
| class ReplicaSetMonitor; | | class ReplicaSetMonitor; | |
| class TagSet; | | class TagSet; | |
| typedef shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr; | | typedef shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr; | |
| typedef pair<set<string>,set<int> > NodeDiff; | | typedef pair<set<string>,set<int> > NodeDiff; | |
| | | | |
| /** | | /** | |
| * manages state about a replica set for client | | * manages state about a replica set for client | |
| * keeps tabs on whose master and what slaves are up | | * keeps tabs on whose master and what slaves are up | |
| * can hand a slave to someone for SLAVE_OK | | * can hand a slave to someone for SLAVE_OK | |
|
| * one instace per process per replica set | | * one instance per process per replica set | |
| * TODO: we might be able to use a regular Node * to avoid _lock | | * TODO: we might be able to use a regular Node * to avoid _lock | |
| */ | | */ | |
| class ReplicaSetMonitor { | | class ReplicaSetMonitor { | |
| public: | | public: | |
| | | | |
| typedef boost::function1<void,const ReplicaSetMonitor*> ConfigChang
eHook; | | typedef boost::function1<void,const ReplicaSetMonitor*> ConfigChang
eHook; | |
| | | | |
| /** | | /** | |
| * Data structure for keeping track of the states of individual rep
lica | | * Data structure for keeping track of the states of individual rep
lica | |
| * members. This class is not thread-safe so proper measures should
be taken | | * members. This class is not thread-safe so proper measures should
be taken | |
| | | | |
| skipping to change at line 150 | | skipping to change at line 150 | |
| * @param preference the read mode to use | | * @param preference the read mode to use | |
| * @param tags the tags used for filtering nodes | | * @param tags the tags used for filtering nodes | |
| * @param localThresholdMillis the exclusive upper bound of ping ti
me to be | | * @param localThresholdMillis the exclusive upper bound of ping ti
me to be | |
| * considered as a local node. Local nodes are favored over non
-local | | * considered as a local node. Local nodes are favored over non
-local | |
| * nodes if multiple nodes matches the other criteria. | | * nodes if multiple nodes matches the other criteria. | |
| * @param lastHost the host used in the last successful request. Th
is is used for | | * @param lastHost the host used in the last successful request. Th
is is used for | |
| * selecting a different node as much as possible, by doing a s
imple round | | * selecting a different node as much as possible, by doing a s
imple round | |
| * robin, starting from the node next to this lastHost. This wi
ll be overwritten | | * robin, starting from the node next to this lastHost. This wi
ll be overwritten | |
| * with the newly chosen host if not empty, not primary and whe
n preference | | * with the newly chosen host if not empty, not primary and whe
n preference | |
| * is not Nearest. | | * is not Nearest. | |
|
| * @param isPrimarySelected out parameter that is set to true if th | | | |
| e returned host | | | |
| * is a primary. Cannot be NULL and valid only if returned host | | | |
| is not empty. | | | |
| * | | * | |
| * @return the host object of the node selected. If none of the nod
es are | | * @return the host object of the node selected. If none of the nod
es are | |
| * eligible, returns an empty host. | | * eligible, returns an empty host. | |
| */ | | */ | |
| static HostAndPort selectNode(const std::vector<Node>& nodes, | | static HostAndPort selectNode(const std::vector<Node>& nodes, | |
| ReadPreference preference, | | ReadPreference preference, | |
| TagSet* tags, | | TagSet* tags, | |
| int localThresholdMillis, | | int localThresholdMillis, | |
|
| HostAndPort* lastHost, | | HostAndPort* lastHost); | |
| bool* isPrimarySelected); | | | |
| | | | |
| /** | | /** | |
| * Selects the right node given the nodes to pick from and the pref
erence. This | | * Selects the right node given the nodes to pick from and the pref
erence. This | |
| * will also attempt to refresh the local view of the replica set c
onfiguration | | * will also attempt to refresh the local view of the replica set c
onfiguration | |
| * if the primary node needs to be returned but is not currently av
ailable (except | | * if the primary node needs to be returned but is not currently av
ailable (except | |
| * for ReadPrefrence_Nearest). | | * for ReadPrefrence_Nearest). | |
| * | | * | |
|
| * @param preference the read mode to use. | | * @param preference the read mode to use | |
| * @param tags the tags used for filtering nodes. | | * @param tags the tags used for filtering nodes | |
| * @param isPrimarySelected out parameter that is set to true if th | | | |
| e returned host | | | |
| * is a primary. Cannot be NULL and valid only if returned host | | | |
| is not empty. | | | |
| * | | * | |
| * @return the host object of the node selected. If none of the nod
es are | | * @return the host object of the node selected. If none of the nod
es are | |
| * eligible, returns an empty host. | | * eligible, returns an empty host. | |
| */ | | */ | |
| HostAndPort selectAndCheckNode(ReadPreference preference, | | HostAndPort selectAndCheckNode(ReadPreference preference, | |
|
| TagSet* tags, | | TagSet* tags); | |
| bool* isPrimarySelected); | | | |
| | | | |
| /** | | /** | |
| * Creates a new ReplicaSetMonitor, if it doesn't already exist. | | * Creates a new ReplicaSetMonitor, if it doesn't already exist. | |
| */ | | */ | |
| static void createIfNeeded( const string& name , const vector<HostA
ndPort>& servers ); | | static void createIfNeeded( const string& name , const vector<HostA
ndPort>& servers ); | |
| | | | |
| /** | | /** | |
| * gets a cached Monitor per name. If the monitor is not found and
createFromSeed is false, | | * gets a cached Monitor per name. If the monitor is not found and
createFromSeed is false, | |
| * it will return none. If createFromSeed is true, it will try to l
ook up the last known | | * it will return none. If createFromSeed is true, it will try to l
ook up the last known | |
| * servers list for this set and will create a new monitor using th
at as the seed list. | | * servers list for this set and will create a new monitor using th
at as the seed list. | |
| | | | |
| skipping to change at line 563 | | skipping to change at line 557 | |
| * operation. | | * operation. | |
| */ | | */ | |
| static const size_t MAX_RETRY; | | static const size_t MAX_RETRY; | |
| | | | |
| // Throws a DBException if the monitor doesn't exist and there isn'
t a cached seed to use. | | // Throws a DBException if the monitor doesn't exist and there isn'
t a cached seed to use. | |
| ReplicaSetMonitorPtr _getMonitor() const; | | ReplicaSetMonitorPtr _getMonitor() const; | |
| | | | |
| string _setName; | | string _setName; | |
| | | | |
| HostAndPort _masterHost; | | HostAndPort _masterHost; | |
|
| // Note: reason why this is a shared_ptr is because we want _lastSl | | scoped_ptr<DBClientConnection> _master; | |
| aveOkConn to | | | |
| // keep a reference of the _master connection when it selected a pr | | | |
| imary node. | | | |
| // This is because the primary connection is special in mongos - it | | | |
| is the only | | | |
| // connection that is versioned. | | | |
| // WARNING: do not assign this variable (which will increment the i | | | |
| nternal ref | | | |
| // counter) to any other variable other than _lastSlaveOkConn. | | | |
| boost::shared_ptr<DBClientConnection> _master; | | | |
| | | | |
| // Last used host in a slaveOk query (can be a primary) | | // Last used host in a slaveOk query (can be a primary) | |
| HostAndPort _lastSlaveOkHost; | | HostAndPort _lastSlaveOkHost; | |
| // Last used connection in a slaveOk query (can be a primary) | | // Last used connection in a slaveOk query (can be a primary) | |
|
| boost::shared_ptr<DBClientConnection> _lastSlaveOkConn; | | scoped_ptr<DBClientConnection> _lastSlaveOkConn; | |
| | | | |
| double _so_timeout; | | double _so_timeout; | |
| | | | |
| /** | | /** | |
| * for storing authentication info | | * for storing authentication info | |
| * fields are exactly for DBClientConnection::auth | | * fields are exactly for DBClientConnection::auth | |
| */ | | */ | |
| struct AuthInfo { | | struct AuthInfo { | |
| // Default constructor provided only to make it compatible with
std::map::operator[] | | // Default constructor provided only to make it compatible with
std::map::operator[] | |
| AuthInfo(): digestPassword(false) { } | | AuthInfo(): digestPassword(false) { } | |
| | | | |
End of changes. 7 change blocks. |
| 27 lines changed or deleted | | 7 lines changed or added | |
|
| dbclientinterface.h | | dbclientinterface.h | |
| | | | |
| skipping to change at line 28 | | skipping to change at line 28 | |
| * limitations under the License. | | * limitations under the License. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "mongo/pch.h" | | #include "mongo/pch.h" | |
| | | | |
| #include "mongo/client/authlevel.h" | | #include "mongo/client/authlevel.h" | |
| #include "mongo/client/authentication_table.h" | | #include "mongo/client/authentication_table.h" | |
| #include "mongo/db/jsobj.h" | | #include "mongo/db/jsobj.h" | |
|
| #include "mongo/platform/atomic_word.h" | | | |
| #include "mongo/util/net/message.h" | | #include "mongo/util/net/message.h" | |
| #include "mongo/util/net/message_port.h" | | #include "mongo/util/net/message_port.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| /** the query field 'options' can have these bits set: */ | | /** the query field 'options' can have these bits set: */ | |
| enum QueryOptions { | | enum QueryOptions { | |
| /** Tailable means cursor is not closed when the last data is retri
eved. rather, the cursor marks | | /** Tailable means cursor is not closed when the last data is retri
eved. rather, the cursor marks | |
| the final object's position. you can resume using the cursor la
ter, from where it was located, | | the final object's position. you can resume using the cursor la
ter, from where it was located, | |
| if more data were received. Set on dbQuery and dbGetMore. | | if more data were received. Set on dbQuery and dbGetMore. | |
| | | | |
| skipping to change at line 60 | | skipping to change at line 59 | |
| // findingStart mode is used to find the first operation of interes
t when | | // findingStart mode is used to find the first operation of interes
t when | |
| // we are scanning through a repl log. For efficiency in the commo
n case, | | // we are scanning through a repl log. For efficiency in the commo
n case, | |
| // where the first operation of interest is closer to the tail than
the head, | | // where the first operation of interest is closer to the tail than
the head, | |
| // we start from the tail of the log and work backwards until we fi
nd the | | // we start from the tail of the log and work backwards until we fi
nd the | |
| // first operation of interest. Then we scan forward from that fir
st operation, | | // first operation of interest. Then we scan forward from that fir
st operation, | |
| // actually returning results to the client. During the findingSta
rt phase, | | // actually returning results to the client. During the findingSta
rt phase, | |
| // we release the db mutex occasionally to avoid blocking the db pr
ocess for | | // we release the db mutex occasionally to avoid blocking the db pr
ocess for | |
| // an extended period of time. | | // an extended period of time. | |
| QueryOption_OplogReplay = 1 << 3, | | QueryOption_OplogReplay = 1 << 3, | |
| | | | |
|
| /** The server normally times out idle cursors after an inactivy pe
riod to prevent excess memory uses | | /** The server normally times out idle cursors after an inactivity
period to prevent excess memory uses | |
| Set this option to prevent that. | | Set this option to prevent that. | |
| */ | | */ | |
| QueryOption_NoCursorTimeout = 1 << 4, | | QueryOption_NoCursorTimeout = 1 << 4, | |
| | | | |
| /** Use with QueryOption_CursorTailable. If we are at the end of t
he data, block for a while rather | | /** Use with QueryOption_CursorTailable. If we are at the end of t
he data, block for a while rather | |
| than returning no data. After a timeout period, we do return as
normal. | | than returning no data. After a timeout period, we do return as
normal. | |
| */ | | */ | |
| QueryOption_AwaitData = 1 << 5, | | QueryOption_AwaitData = 1 << 5, | |
| | | | |
| /** Stream the data down full blast in multiple "more" packages, on
the assumption that the client | | /** Stream the data down full blast in multiple "more" packages, on
the assumption that the client | |
| | | | |
| skipping to change at line 250 | | skipping to change at line 249 | |
| string toString() const { return _string; } | | string toString() const { return _string; } | |
| | | | |
| DBClientBase* connect( string& errmsg, double socketTimeout = 0 ) c
onst; | | DBClientBase* connect( string& errmsg, double socketTimeout = 0 ) c
onst; | |
| | | | |
| string getSetName() const { return _setName; } | | string getSetName() const { return _setName; } | |
| | | | |
| vector<HostAndPort> getServers() const { return _servers; } | | vector<HostAndPort> getServers() const { return _servers; } | |
| | | | |
| ConnectionType type() const { return _type; } | | ConnectionType type() const { return _type; } | |
| | | | |
|
| /** | | | |
| * This returns true if this and other point to the same logical en | | | |
| tity. | | | |
| * For single nodes, thats the same address. | | | |
| * For replica sets, thats just the same replica set name. | | | |
| * For pair (deprecated) or sync cluster connections, that's the sa | | | |
| me hosts in any ordering. | | | |
| */ | | | |
| bool sameLogicalEndpoint( const ConnectionString& other ) const; | | | |
| | | | |
| static ConnectionString parse( const string& url , string& errmsg )
; | | static ConnectionString parse( const string& url , string& errmsg )
; | |
| | | | |
| static string typeToString( ConnectionType type ); | | static string typeToString( ConnectionType type ); | |
| | | | |
| // | | // | |
| // Allow overriding the default connection behavior | | // Allow overriding the default connection behavior | |
| // This is needed for some tests, which otherwise would fail becaus
e they are unable to contact | | // This is needed for some tests, which otherwise would fail becaus
e they are unable to contact | |
| // the correct servers. | | // the correct servers. | |
| // | | // | |
| | | | |
| | | | |
| skipping to change at line 864 | | skipping to change at line 855 | |
| /** Create an index if it does not already exist. | | /** Create an index if it does not already exist. | |
| ensureIndex calls are remembered so it is safe/fast to call thi
s function many | | ensureIndex calls are remembered so it is safe/fast to call thi
s function many | |
| times in your code. | | times in your code. | |
| @param ns collection to be indexed | | @param ns collection to be indexed | |
| @param keys the "key pattern" for the index. e.g., { name : 1 } | | @param keys the "key pattern" for the index. e.g., { name : 1 } | |
| @param unique if true, indicates that key uniqueness should be e
nforced for this index | | @param unique if true, indicates that key uniqueness should be e
nforced for this index | |
| @param name if not specified, it will be created from the keys a
utomatically (which is recommended) | | @param name if not specified, it will be created from the keys a
utomatically (which is recommended) | |
| @param cache if set to false, the index cache for the connection
won't remember this call | | @param cache if set to false, the index cache for the connection
won't remember this call | |
| @param background build index in the background (see mongodb doc
s/wiki for details) | | @param background build index in the background (see mongodb doc
s/wiki for details) | |
| @param v index version. leave at default value. (unit tests set
this parameter.) | | @param v index version. leave at default value. (unit tests set
this parameter.) | |
|
| | | @param ttl. The value of how many seconds before data should be
removed from a collection. | |
| @return whether or not sent message to db. | | @return whether or not sent message to db. | |
| should be true on first call, false on subsequent unless reset
IndexCache was called | | should be true on first call, false on subsequent unless reset
IndexCache was called | |
| */ | | */ | |
|
| virtual bool ensureIndex( const string &ns , BSONObj keys , bool un | | virtual bool ensureIndex( const string &ns, | |
| ique = false, const string &name = "", | | BSONObj keys, | |
| bool cache = true, bool background = fals | | bool unique = false, | |
| e, int v = -1 ); | | const string &name = "", | |
| | | bool cache = true, | |
| | | bool background = false, | |
| | | int v = -1, | |
| | | int ttl = 0 ); | |
| /** | | /** | |
| clears the index cache, so the subsequent call to ensureIndex fo
r any index will go to the server | | clears the index cache, so the subsequent call to ensureIndex fo
r any index will go to the server | |
| */ | | */ | |
| virtual void resetIndexCache(); | | virtual void resetIndexCache(); | |
| | | | |
| virtual auto_ptr<DBClientCursor> getIndexes( const string &ns ); | | virtual auto_ptr<DBClientCursor> getIndexes( const string &ns ); | |
| | | | |
| virtual void dropIndex( const string& ns , BSONObj keys ); | | virtual void dropIndex( const string& ns , BSONObj keys ); | |
| virtual void dropIndex( const string& ns , const string& indexName
); | | virtual void dropIndex( const string& ns , const string& indexName
); | |
| | | | |
| | | | |
| skipping to change at line 930 | | skipping to change at line 927 | |
| bool _haveCachedAvailableOptions; | | bool _haveCachedAvailableOptions; | |
| AuthenticationTable _authTable; | | AuthenticationTable _authTable; | |
| bool _hasAuthentication; | | bool _hasAuthentication; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| abstract class that implements the core db operations | | abstract class that implements the core db operations | |
| */ | | */ | |
| class DBClientBase : public DBClientWithCommands, public DBConnector { | | class DBClientBase : public DBClientWithCommands, public DBConnector { | |
| protected: | | protected: | |
|
| static AtomicInt64 ConnectionIdSequence; | | | |
| long long _connectionId; // unique connection id for this connectio | | | |
| n | | | |
| WriteConcern _writeConcern; | | WriteConcern _writeConcern; | |
|
| | | | |
| public: | | public: | |
| DBClientBase() { | | DBClientBase() { | |
| _writeConcern = W_NORMAL; | | _writeConcern = W_NORMAL; | |
|
| _connectionId = ConnectionIdSequence.fetchAndAdd(1); | | | |
| } | | } | |
| | | | |
|
| long long getConnectionId() const { return _connectionId; } | | | |
| | | | |
| WriteConcern getWriteConcern() const { return _writeConcern; } | | WriteConcern getWriteConcern() const { return _writeConcern; } | |
| void setWriteConcern( WriteConcern w ) { _writeConcern = w; } | | void setWriteConcern( WriteConcern w ) { _writeConcern = w; } | |
| | | | |
| /** send a query to the database. | | /** send a query to the database. | |
| @param ns namespace to query, format is <dbname>.<collectname>[.<c
ollectname>]* | | @param ns namespace to query, format is <dbname>.<collectname>[.<c
ollectname>]* | |
| @param query query to perform on the collection. this is a BSONOb
j (binary JSON) | | @param query query to perform on the collection. this is a BSONOb
j (binary JSON) | |
| You may format as | | You may format as | |
| { query: { ... }, orderby: { ... } } | | { query: { ... }, orderby: { ... } } | |
| to specify a sort order. | | to specify a sort order. | |
| @param nToReturn n to return (i.e., limit). 0 = unlimited | | @param nToReturn n to return (i.e., limit). 0 = unlimited | |
| | | | |
| skipping to change at line 1148 | | skipping to change at line 1141 | |
| | | | |
| string getServerAddress() const { return _serverString; } | | string getServerAddress() const { return _serverString; } | |
| | | | |
| virtual void killCursor( long long cursorID ); | | virtual void killCursor( long long cursorID ); | |
| virtual bool callRead( Message& toSend , Message& response ) { retu
rn call( toSend , response ); } | | virtual bool callRead( Message& toSend , Message& response ) { retu
rn call( toSend , response ); } | |
| virtual void say( Message &toSend, bool isRetry = false , string *
actualServer = 0 ); | | virtual void say( Message &toSend, bool isRetry = false , string *
actualServer = 0 ); | |
| virtual bool recv( Message& m ); | | virtual bool recv( Message& m ); | |
| virtual void checkResponse( const char *data, int nReturned, bool*
retry = NULL, string* host = NULL ); | | virtual void checkResponse( const char *data, int nReturned, bool*
retry = NULL, string* host = NULL ); | |
| virtual bool call( Message &toSend, Message &response, bool assertO
k = true , string * actualServer = 0 ); | | virtual bool call( Message &toSend, Message &response, bool assertO
k = true , string * actualServer = 0 ); | |
| virtual ConnectionString::ConnectionType type() const { return Conn
ectionString::MASTER; } | | virtual ConnectionString::ConnectionType type() const { return Conn
ectionString::MASTER; } | |
|
| void setSoTimeout(double to) { _so_timeout = to; } | | void setSoTimeout(double timeout); | |
| double getSoTimeout() const { return _so_timeout; } | | double getSoTimeout() const { return _so_timeout; } | |
| | | | |
| virtual bool lazySupported() const { return true; } | | virtual bool lazySupported() const { return true; } | |
| | | | |
| static int getNumConnections() { | | static int getNumConnections() { | |
| return _numConnections; | | return _numConnections; | |
| } | | } | |
| | | | |
| static void setLazyKillCursor( bool lazy ) { _lazyKillCursor = lazy
; } | | static void setLazyKillCursor( bool lazy ) { _lazyKillCursor = lazy
; } | |
| static bool getLazyKillCursor() { return _lazyKillCursor; } | | static bool getLazyKillCursor() { return _lazyKillCursor; } | |
| | | | |
End of changes. 10 change blocks. |
| 24 lines changed or deleted | | 12 lines changed or added | |
|
| document_source.h | | document_source.h | |
| | | | |
| skipping to change at line 622 | | skipping to change at line 622 | |
| | | | |
| Accumulators become fields in the Documents that result from | | Accumulators become fields in the Documents that result from | |
| grouping. Each unique group document must have it's own | | grouping. Each unique group document must have it's own | |
| accumulator; the accumulator factory is used to create that. | | accumulator; the accumulator factory is used to create that. | |
| | | | |
| @param fieldName the name the accumulator result will have in the | | @param fieldName the name the accumulator result will have in the | |
| result documents | | result documents | |
| @param pAccumulatorFactory used to create the accumulator for the | | @param pAccumulatorFactory used to create the accumulator for the | |
| group field | | group field | |
| */ | | */ | |
|
| void addAccumulator(string fieldName, | | void addAccumulator(const std::string& fieldName, | |
| intrusive_ptr<Accumulator> (*pAccumulatorFactor
y)( | | intrusive_ptr<Accumulator> (*pAccumulatorFactor
y)( | |
| const intrusive_ptr<ExpressionContext> &), | | const intrusive_ptr<ExpressionContext> &), | |
| const intrusive_ptr<Expression> &pExpression); | | const intrusive_ptr<Expression> &pExpression); | |
| | | | |
| /** | | /** | |
| Create a grouping DocumentSource from BSON. | | Create a grouping DocumentSource from BSON. | |
| | | | |
| This is a convenience method that uses the above, and operates on | | This is a convenience method that uses the above, and operates on | |
| a BSONElement that has been deteremined to be an Object with an | | a BSONElement that has been deteremined to be an Object with an | |
| element named $group. | | element named $group. | |
| | | | |
| skipping to change at line 955 | | skipping to change at line 955 | |
| }; | | }; | |
| | | | |
| typedef vector<intrusive_ptr<Document> > VectorType; | | typedef vector<intrusive_ptr<Document> > VectorType; | |
| VectorType documents; | | VectorType documents; | |
| | | | |
| VectorType::iterator docIterator; | | VectorType::iterator docIterator; | |
| intrusive_ptr<Document> pCurrent; | | intrusive_ptr<Document> pCurrent; | |
| }; | | }; | |
| | | | |
| class DocumentSourceLimit : | | class DocumentSourceLimit : | |
|
| public SplittableDocumentSource { | | public DocumentSource { | |
| public: | | public: | |
| // virtuals from DocumentSource | | // virtuals from DocumentSource | |
| virtual ~DocumentSourceLimit(); | | virtual ~DocumentSourceLimit(); | |
| virtual bool eof(); | | virtual bool eof(); | |
| virtual bool advance(); | | virtual bool advance(); | |
| virtual intrusive_ptr<Document> getCurrent(); | | virtual intrusive_ptr<Document> getCurrent(); | |
| virtual const char *getSourceName() const; | | virtual const char *getSourceName() const; | |
| virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou
rce); | | virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou
rce); | |
| | | | |
| virtual GetDepsReturn getDependencies(set<string>& deps) const { | | virtual GetDepsReturn getDependencies(set<string>& deps) const { | |
| | | | |
| skipping to change at line 978 | | skipping to change at line 978 | |
| | | | |
| /** | | /** | |
| Create a new limiting DocumentSource. | | Create a new limiting DocumentSource. | |
| | | | |
| @param pExpCtx the expression context for the pipeline | | @param pExpCtx the expression context for the pipeline | |
| @returns the DocumentSource | | @returns the DocumentSource | |
| */ | | */ | |
| static intrusive_ptr<DocumentSourceLimit> create( | | static intrusive_ptr<DocumentSourceLimit> create( | |
| const intrusive_ptr<ExpressionContext> &pExpCtx); | | const intrusive_ptr<ExpressionContext> &pExpCtx); | |
| | | | |
|
| // Virtuals for SplittableDocumentSource | | | |
| // Need to run on rounter. Running on shard as well is an optimizat | | | |
| ion. | | | |
| virtual intrusive_ptr<DocumentSource> getShardSource() { return thi | | | |
| s; } | | | |
| virtual intrusive_ptr<DocumentSource> getRouterSource() { return th | | | |
| is; } | | | |
| | | | |
| long long getLimit() const { return limit; } | | | |
| void setLimit(long long newLimit) { limit = newLimit; } | | | |
| | | | |
| /** | | /** | |
| Create a limiting DocumentSource from BSON. | | Create a limiting DocumentSource from BSON. | |
| | | | |
| This is a convenience method that uses the above, and operates on | | This is a convenience method that uses the above, and operates on | |
| a BSONElement that has been deteremined to be an Object with an | | a BSONElement that has been deteremined to be an Object with an | |
| element named $limit. | | element named $limit. | |
| | | | |
| @param pBsonElement the BSONELement that defines the limit | | @param pBsonElement the BSONELement that defines the limit | |
| @param pExpCtx the expression context | | @param pExpCtx the expression context | |
| @returns the grouping DocumentSource | | @returns the grouping DocumentSource | |
| | | | |
| skipping to change at line 1017 | | skipping to change at line 1009 | |
| private: | | private: | |
| DocumentSourceLimit( | | DocumentSourceLimit( | |
| const intrusive_ptr<ExpressionContext> &pExpCtx); | | const intrusive_ptr<ExpressionContext> &pExpCtx); | |
| | | | |
| long long limit; | | long long limit; | |
| long long count; | | long long count; | |
| intrusive_ptr<Document> pCurrent; | | intrusive_ptr<Document> pCurrent; | |
| }; | | }; | |
| | | | |
| class DocumentSourceSkip : | | class DocumentSourceSkip : | |
|
| public SplittableDocumentSource { | | public DocumentSource { | |
| public: | | public: | |
| // virtuals from DocumentSource | | // virtuals from DocumentSource | |
| virtual ~DocumentSourceSkip(); | | virtual ~DocumentSourceSkip(); | |
| virtual bool eof(); | | virtual bool eof(); | |
| virtual bool advance(); | | virtual bool advance(); | |
| virtual intrusive_ptr<Document> getCurrent(); | | virtual intrusive_ptr<Document> getCurrent(); | |
| virtual const char *getSourceName() const; | | virtual const char *getSourceName() const; | |
| virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou
rce); | | virtual bool coalesce(const intrusive_ptr<DocumentSource> &pNextSou
rce); | |
| | | | |
| virtual GetDepsReturn getDependencies(set<string>& deps) const { | | virtual GetDepsReturn getDependencies(set<string>& deps) const { | |
| | | | |
| skipping to change at line 1040 | | skipping to change at line 1032 | |
| | | | |
| /** | | /** | |
| Create a new skipping DocumentSource. | | Create a new skipping DocumentSource. | |
| | | | |
| @param pExpCtx the expression context | | @param pExpCtx the expression context | |
| @returns the DocumentSource | | @returns the DocumentSource | |
| */ | | */ | |
| static intrusive_ptr<DocumentSourceSkip> create( | | static intrusive_ptr<DocumentSourceSkip> create( | |
| const intrusive_ptr<ExpressionContext> &pExpCtx); | | const intrusive_ptr<ExpressionContext> &pExpCtx); | |
| | | | |
|
| // Virtuals for SplittableDocumentSource | | | |
| // Need to run on rounter. Can't run on shards. | | | |
| virtual intrusive_ptr<DocumentSource> getShardSource() { return NUL | | | |
| L; } | | | |
| virtual intrusive_ptr<DocumentSource> getRouterSource() { return th | | | |
| is; } | | | |
| | | | |
| long long getSkip() const { return skip; } | | | |
| void setSkip(long long newSkip) { skip = newSkip; } | | | |
| | | | |
| /** | | /** | |
| Create a skipping DocumentSource from BSON. | | Create a skipping DocumentSource from BSON. | |
| | | | |
| This is a convenience method that uses the above, and operates on | | This is a convenience method that uses the above, and operates on | |
| a BSONElement that has been deteremined to be an Object with an | | a BSONElement that has been deteremined to be an Object with an | |
| element named $skip. | | element named $skip. | |
| | | | |
| @param pBsonElement the BSONELement that defines the skip | | @param pBsonElement the BSONELement that defines the skip | |
| @param pExpCtx the expression context | | @param pExpCtx the expression context | |
| @returns the grouping DocumentSource | | @returns the grouping DocumentSource | |
| | | | |
End of changes. 5 change blocks. |
| 24 lines changed or deleted | | 3 lines changed or added | |
|
| dur.h | | dur.h | |
| // @file dur.h durability support | | // @file dur.h durability support | |
| | | | |
|
| | | /** | |
| | | * Copyright (C) 2009 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 Licen | |
| | | se | |
| | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "diskloc.h" | | #include "diskloc.h" | |
| #include "mongommf.h" | | #include "mongommf.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class NamespaceDetails; | | class NamespaceDetails; | |
| | | | |
| void mongoAbort(const char *msg); | | void mongoAbort(const char *msg); | |
| | | | |
| skipping to change at line 37 | | skipping to change at line 53 | |
| | | | |
| class DurableInterface : boost::noncopyable { | | class DurableInterface : boost::noncopyable { | |
| public: | | public: | |
| virtual ~DurableInterface() { log() << "ERROR warning ~DurableI
nterface not intended to be called" << endl; } | | virtual ~DurableInterface() { log() << "ERROR warning ~DurableI
nterface not intended to be called" << endl; } | |
| | | | |
| /** Declare that a file has been created | | /** Declare that a file has been created | |
| Normally writes are applied only after journaling, for safe
ty. But here the file | | Normally writes are applied only after journaling, for safe
ty. But here the file | |
| is created first, and the journal will just replay the crea
tion if the create didn't | | is created first, and the journal will just replay the crea
tion if the create didn't | |
| happen because of crashing. | | happen because of crashing. | |
| */ | | */ | |
|
| virtual void createdFile(string filename, unsigned long long le
n) = 0; | | virtual void createdFile(const std::string& filename, unsigned
long long len) = 0; | |
| | | | |
| /** Declarations of write intent. | | /** Declarations of write intent. | |
| | | | |
| Use these methods to declare "i'm about to write to x and i
t should be logged for redo." | | Use these methods to declare "i'm about to write to x and i
t should be logged for redo." | |
| | | | |
| Failure to call writing...() is checked in _DEBUG mode by u
sing a read only mapped view | | Failure to call writing...() is checked in _DEBUG mode by u
sing a read only mapped view | |
| (i.e., you'll segfault if the code is covered in that situa
tion). The _DEBUG check doesn't | | (i.e., you'll segfault if the code is covered in that situa
tion). The _DEBUG check doesn't | |
| verify that your length is correct though. | | verify that your length is correct though. | |
| */ | | */ | |
| | | | |
| | | | |
| skipping to change at line 98 | | skipping to change at line 114 | |
| | | | |
| Do not use this. Use commitIfNeeded() instead. | | Do not use this. Use commitIfNeeded() instead. | |
| | | | |
| @return true if --dur is on. | | @return true if --dur is on. | |
| @return false if --dur is off. (in which case there is acti
on) | | @return false if --dur is off. (in which case there is acti
on) | |
| */ | | */ | |
| virtual bool commitNow() = 0; | | virtual bool commitNow() = 0; | |
| | | | |
| /** Commit if enough bytes have been modified. Current threshol
d is 50MB | | /** Commit if enough bytes have been modified. Current threshol
d is 50MB | |
| | | | |
|
| The idea is that long running write operations that dont yi
eld | | The idea is that long running write operations that don't y
ield | |
| (like creating an index or update with $atomic) can call th
is | | (like creating an index or update with $atomic) can call th
is | |
| whenever the db is in a sane state and it will prevent comm
its | | whenever the db is in a sane state and it will prevent comm
its | |
| from growing too large. | | from growing too large. | |
| @return true if commited | | @return true if commited | |
| */ | | */ | |
| virtual bool commitIfNeeded(bool force=false) = 0; | | virtual bool commitIfNeeded(bool force=false) = 0; | |
| | | | |
| /** @return true if time to commit but does NOT do a commit */ | | /** @return true if time to commit but does NOT do a commit */ | |
| virtual bool aCommitIsNeeded() const = 0; | | virtual bool aCommitIsNeeded() const = 0; | |
| | | | |
| | | | |
| skipping to change at line 171 | | skipping to change at line 187 | |
| // these need to be able to enable/disable Durability | | // these need to be able to enable/disable Durability | |
| friend void startup(); | | friend void startup(); | |
| friend class TempDisableDurability; | | friend class TempDisableDurability; | |
| }; // class DurableInterface | | }; // class DurableInterface | |
| | | | |
| class NonDurableImpl : public DurableInterface { | | class NonDurableImpl : public DurableInterface { | |
| void* writingPtr(void *x, unsigned len); | | void* writingPtr(void *x, unsigned len); | |
| void* writingAtOffset(void *buf, unsigned ofs, unsigned len) {
return buf; } | | void* writingAtOffset(void *buf, unsigned ofs, unsigned len) {
return buf; } | |
| void* writingRangesAtOffsets(void *buf, const vector< pair< lon
g long, unsigned > > &ranges) { return buf; } | | void* writingRangesAtOffsets(void *buf, const vector< pair< lon
g long, unsigned > > &ranges) { return buf; } | |
| void declareWriteIntent(void *, unsigned); | | void declareWriteIntent(void *, unsigned); | |
|
| void createdFile(string filename, unsigned long long len) { } | | void createdFile(const std::string& filename, unsigned long lon
g len) { } | |
| bool awaitCommit() { return false; } | | bool awaitCommit() { return false; } | |
| bool commitNow() { return false; } | | bool commitNow() { return false; } | |
| bool commitIfNeeded(bool) { return false; } | | bool commitIfNeeded(bool) { return false; } | |
| bool aCommitIsNeeded() const { return false; } | | bool aCommitIsNeeded() const { return false; } | |
| void syncDataAndTruncateJournal() {} | | void syncDataAndTruncateJournal() {} | |
| }; | | }; | |
| | | | |
| class DurableImpl : public DurableInterface { | | class DurableImpl : public DurableInterface { | |
| bool _aCommitIsNeeded(); | | bool _aCommitIsNeeded(); | |
| void* writingPtr(void *x, unsigned len); | | void* writingPtr(void *x, unsigned len); | |
| void* writingAtOffset(void *buf, unsigned ofs, unsigned len); | | void* writingAtOffset(void *buf, unsigned ofs, unsigned len); | |
| void* writingRangesAtOffsets(void *buf, const vector< pair< lon
g long, unsigned > > &ranges); | | void* writingRangesAtOffsets(void *buf, const vector< pair< lon
g long, unsigned > > &ranges); | |
| void declareWriteIntent(void *, unsigned); | | void declareWriteIntent(void *, unsigned); | |
|
| void createdFile(string filename, unsigned long long len); | | void createdFile(const std::string& filename, unsigned long lon
g len); | |
| bool awaitCommit(); | | bool awaitCommit(); | |
| bool commitNow(); | | bool commitNow(); | |
| bool aCommitIsNeeded() const; | | bool aCommitIsNeeded() const; | |
| bool commitIfNeeded(bool); | | bool commitIfNeeded(bool); | |
| void syncDataAndTruncateJournal(); | | void syncDataAndTruncateJournal(); | |
| }; | | }; | |
| | | | |
| } // namespace dur | | } // namespace dur | |
| | | | |
| inline dur::DurableInterface& getDur() { return dur::DurableInterface::
getDur(); } | | inline dur::DurableInterface& getDur() { return dur::DurableInterface::
getDur(); } | |
| | | | |
End of changes. 5 change blocks. |
| 4 lines changed or deleted | | 22 lines changed or added | |
|
| dur_recover.h | | dur_recover.h | |
| // @file dur.h durability support | | // @file dur.h durability support | |
| | | | |
|
| | | /** | |
| | | * Copyright (C) 2009 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 Licen | |
| | | se | |
| | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
|
| #include "dur_journalformat.h" | | #include <boost/filesystem/operations.hpp> | |
| #include "../util/concurrency/mutex.h" | | #include <list> | |
| #include "../util/file.h" | | | |
| | | #include "mongo/db/dur_journalformat.h" | |
| | | #include "mongo/util/concurrency/mutex.h" | |
| | | #include "mongo/util/file.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| class MongoMMF; | | class MongoMMF; | |
| | | | |
| namespace dur { | | namespace dur { | |
| struct ParsedJournalEntry; | | struct ParsedJournalEntry; | |
| | | | |
| /** call go() to execute a recovery from existing journal files. | | /** call go() to execute a recovery from existing journal files. | |
| */ | | */ | |
| class RecoveryJob : boost::noncopyable { | | class RecoveryJob : boost::noncopyable { | |
|
| | | static class Last { | |
| | | public: | |
| | | Last(); | |
| | | MongoMMF* newEntry(const ParsedJournalEntry&, RecoveryJob&) | |
| | | ; | |
| | | private: | |
| | | MongoMMF *mmf; | |
| | | string dbName; | |
| | | int fileNo; | |
| | | } last; | |
| public: | | public: | |
| RecoveryJob() : _lastDataSyncedFromLastRun(0), | | RecoveryJob() : _lastDataSyncedFromLastRun(0), | |
| _mx("recovery"), _recovering(false) { _lastSeqMentionedInCo
nsoleLog = 1; } | | _mx("recovery"), _recovering(false) { _lastSeqMentionedInCo
nsoleLog = 1; } | |
| void go(vector<boost::filesystem::path>& files); | | void go(vector<boost::filesystem::path>& files); | |
| ~RecoveryJob(); | | ~RecoveryJob(); | |
| | | | |
| /** @param data data between header and footer. compressed if r
ecovering. */ | | /** @param data data between header and footer. compressed if r
ecovering. */ | |
| void processSection(const JSectHeader *h, const void *data, uns
igned len, const JSectFooter *f); | | void processSection(const JSectHeader *h, const void *data, uns
igned len, const JSectFooter *f); | |
| | | | |
| void close(); // locks and calls _close() | | void close(); // locks and calls _close() | |
| | | | |
| static RecoveryJob & get() { return _instance; } | | static RecoveryJob & get() { return _instance; } | |
| private: | | private: | |
|
| void write(const ParsedJournalEntry& entry, MongoMMF* mmf); // | | void write(Last& last, const ParsedJournalEntry& entry); // act | |
| actually writes to the file | | ually writes to the file | |
| void applyEntry(const ParsedJournalEntry& entry, bool apply, bo | | void applyEntry(Last& last, const ParsedJournalEntry& entry, bo | |
| ol dump, MongoMMF* mmf); | | ol apply, bool dump); | |
| void applyEntries(const vector<ParsedJournalEntry> &entries); | | void applyEntries(const vector<ParsedJournalEntry> &entries); | |
| bool processFileBuffer(const void *, unsigned len); | | bool processFileBuffer(const void *, unsigned len); | |
| bool processFile(boost::filesystem::path journalfile); | | bool processFile(boost::filesystem::path journalfile); | |
| void _close(); // doesn't lock | | void _close(); // doesn't lock | |
| MongoMMF* getMongoMMF(const ParsedJournalEntry& entry); | | MongoMMF* getMongoMMF(const ParsedJournalEntry& entry); | |
| | | | |
| list<boost::shared_ptr<MongoMMF> > _mmfs; | | list<boost::shared_ptr<MongoMMF> > _mmfs; | |
| | | | |
| unsigned long long _lastDataSyncedFromLastRun; | | unsigned long long _lastDataSyncedFromLastRun; | |
| unsigned long long _lastSeqMentionedInConsoleLog; | | unsigned long long _lastSeqMentionedInConsoleLog; | |
| | | | |
End of changes. 4 change blocks. |
| 7 lines changed or deleted | | 38 lines changed or added | |
|
| expression.h | | expression.h | |
| | | | |
| skipping to change at line 64 | | skipping to change at line 64 | |
| virtual intrusive_ptr<Expression> optimize() = 0; | | virtual intrusive_ptr<Expression> optimize() = 0; | |
| | | | |
| /** | | /** | |
| Add this expression's field dependencies to the set | | Add this expression's field dependencies to the set | |
| | | | |
| Expressions are trees, so this is often recursive. | | Expressions are trees, so this is often recursive. | |
| | | | |
| @param deps output parameter | | @param deps output parameter | |
| @param path path to self if all ancestors are ExpressionObjects. | | @param path path to self if all ancestors are ExpressionObjects. | |
| Top-level ExpressionObject gets pointer to empty vec
tor. | | Top-level ExpressionObject gets pointer to empty vec
tor. | |
|
| If any other Expression is an ancestor {a:1} object | | If any other Expression is an ancestor, or in other | |
| aren't allowed, so they get NULL | | cases | |
| | | where {a:1} inclusion objects aren't allowed, they g | |
| | | et | |
| | | NULL. | |
| */ | | */ | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const = 0; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const = 0; | |
| | | | |
| /** simple expressions are just inclusion exclusion as supported by
ExpressionObject */ | | /** simple expressions are just inclusion exclusion as supported by
ExpressionObject */ | |
| virtual bool isSimple() { return false; } | | virtual bool isSimple() { return false; } | |
| | | | |
| /* | | /* | |
| Evaluate the Expression using the given document as input. | | Evaluate the Expression using the given document as input. | |
| | | | |
| @returns the computed value | | @returns the computed value | |
| | | | |
| skipping to change at line 97 | | skipping to change at line 97 | |
| substituted inline. | | substituted inline. | |
| | | | |
| @param pBuilder the builder to add the expression to | | @param pBuilder the builder to add the expression to | |
| @param fieldName the name the object should be given | | @param fieldName the name the object should be given | |
| @param requireExpression specify true if the value must appear | | @param requireExpression specify true if the value must appear | |
| as an expression; this is used by DocumentSources like | | as an expression; this is used by DocumentSources like | |
| $project which distinguish between field inclusion and virtual | | $project which distinguish between field inclusion and virtual | |
| field specification; See ExpressionConstant. | | field specification; See ExpressionConstant. | |
| */ | | */ | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const = 0; | | bool requireExpression) const = 0; | |
| | | | |
| /* | | /* | |
| Add the Expression (and any descendant Expressions) into a BSON | | Add the Expression (and any descendant Expressions) into a BSON | |
| array that is under construction. | | array that is under construction. | |
| | | | |
| Unevaluated Expressions always materialize as objects. Evaluatio
n | | Unevaluated Expressions always materialize as objects. Evaluatio
n | |
| may produce a scalar or another object, either of which will be | | may produce a scalar or another object, either of which will be | |
| substituted inline. | | substituted inline. | |
| | | | |
| | | | |
| skipping to change at line 224 | | skipping to change at line 224 | |
| typedef vector<intrusive_ptr<Expression> > ExpressionVector; | | typedef vector<intrusive_ptr<Expression> > ExpressionVector; | |
| | | | |
| }; | | }; | |
| | | | |
| class ExpressionNary : | | class ExpressionNary : | |
| public Expression { | | public Expression { | |
| public: | | public: | |
| // virtuals from Expression | | // virtuals from Expression | |
| virtual intrusive_ptr<Expression> optimize(); | | virtual intrusive_ptr<Expression> optimize(); | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const; | | bool requireExpression) const; | |
| virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | | virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | |
| | | | |
| /* | | /* | |
| Add an operand to the n-ary expression. | | Add an operand to the n-ary expression. | |
| | | | |
| @param pExpression the expression to add | | @param pExpression the expression to add | |
| */ | | */ | |
| virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n); | | virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n); | |
| | | | |
| skipping to change at line 365 | | skipping to change at line 365 | |
| class ExpressionCoerceToBool : | | class ExpressionCoerceToBool : | |
| public Expression { | | public Expression { | |
| public: | | public: | |
| // virtuals from ExpressionNary | | // virtuals from ExpressionNary | |
| virtual ~ExpressionCoerceToBool(); | | virtual ~ExpressionCoerceToBool(); | |
| virtual intrusive_ptr<Expression> optimize(); | | virtual intrusive_ptr<Expression> optimize(); | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | |
| virtual intrusive_ptr<const Value> evaluate( | | virtual intrusive_ptr<const Value> evaluate( | |
| const intrusive_ptr<Document> &pDocument) const; | | const intrusive_ptr<Document> &pDocument) const; | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const; | | bool requireExpression) const; | |
| virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | | virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | |
| | | | |
| static intrusive_ptr<ExpressionCoerceToBool> create( | | static intrusive_ptr<ExpressionCoerceToBool> create( | |
| const intrusive_ptr<Expression> &pExpression); | | const intrusive_ptr<Expression> &pExpression); | |
| | | | |
| private: | | private: | |
| ExpressionCoerceToBool(const intrusive_ptr<Expression> &pExpression
); | | ExpressionCoerceToBool(const intrusive_ptr<Expression> &pExpression
); | |
| | | | |
| intrusive_ptr<Expression> pExpression; | | intrusive_ptr<Expression> pExpression; | |
| | | | |
| skipping to change at line 394 | | skipping to change at line 394 | |
| virtual intrusive_ptr<const Value> evaluate( | | virtual intrusive_ptr<const Value> evaluate( | |
| const intrusive_ptr<Document> &pDocument) const; | | const intrusive_ptr<Document> &pDocument) const; | |
| virtual const char *getOpName() const; | | virtual const char *getOpName() const; | |
| virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n); | | virtual void addOperand(const intrusive_ptr<Expression> &pExpressio
n); | |
| | | | |
| /* | | /* | |
| Shorthands for creating various comparisons expressions. | | Shorthands for creating various comparisons expressions. | |
| Provide for conformance with the uniform function pointer signatu
re | | Provide for conformance with the uniform function pointer signatu
re | |
| required for parsing. | | required for parsing. | |
| | | | |
|
| These create a particular comparision operand, without any | | These create a particular comparison operand, without any | |
| operands. Those must be added via ExpressionNary::addOperand(). | | operands. Those must be added via ExpressionNary::addOperand(). | |
| */ | | */ | |
| static intrusive_ptr<ExpressionNary> createCmp(); | | static intrusive_ptr<ExpressionNary> createCmp(); | |
| static intrusive_ptr<ExpressionNary> createEq(); | | static intrusive_ptr<ExpressionNary> createEq(); | |
| static intrusive_ptr<ExpressionNary> createNe(); | | static intrusive_ptr<ExpressionNary> createNe(); | |
| static intrusive_ptr<ExpressionNary> createGt(); | | static intrusive_ptr<ExpressionNary> createGt(); | |
| static intrusive_ptr<ExpressionNary> createGte(); | | static intrusive_ptr<ExpressionNary> createGte(); | |
| static intrusive_ptr<ExpressionNary> createLt(); | | static intrusive_ptr<ExpressionNary> createLt(); | |
| static intrusive_ptr<ExpressionNary> createLte(); | | static intrusive_ptr<ExpressionNary> createLte(); | |
| | | | |
| | | | |
| skipping to change at line 439 | | skipping to change at line 439 | |
| public Expression { | | public Expression { | |
| public: | | public: | |
| // virtuals from Expression | | // virtuals from Expression | |
| virtual ~ExpressionConstant(); | | virtual ~ExpressionConstant(); | |
| virtual intrusive_ptr<Expression> optimize(); | | virtual intrusive_ptr<Expression> optimize(); | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | |
| virtual intrusive_ptr<const Value> evaluate( | | virtual intrusive_ptr<const Value> evaluate( | |
| const intrusive_ptr<Document> &pDocument) const; | | const intrusive_ptr<Document> &pDocument) const; | |
| virtual const char *getOpName() const; | | virtual const char *getOpName() const; | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const; | | bool requireExpression) const; | |
| virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | | virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | |
| | | | |
| static intrusive_ptr<ExpressionConstant> createFromBsonElement( | | static intrusive_ptr<ExpressionConstant> createFromBsonElement( | |
| BSONElement *pBsonElement); | | BSONElement *pBsonElement); | |
| static intrusive_ptr<ExpressionConstant> create( | | static intrusive_ptr<ExpressionConstant> create( | |
| const intrusive_ptr<const Value> &pValue); | | const intrusive_ptr<const Value> &pValue); | |
| | | | |
| /* | | /* | |
| Get the constant value represented by this Expression. | | Get the constant value represented by this Expression. | |
| | | | |
| skipping to change at line 536 | | skipping to change at line 536 | |
| class ExpressionFieldPath : | | class ExpressionFieldPath : | |
| public Expression { | | public Expression { | |
| public: | | public: | |
| // virtuals from Expression | | // virtuals from Expression | |
| virtual ~ExpressionFieldPath(); | | virtual ~ExpressionFieldPath(); | |
| virtual intrusive_ptr<Expression> optimize(); | | virtual intrusive_ptr<Expression> optimize(); | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | |
| virtual intrusive_ptr<const Value> evaluate( | | virtual intrusive_ptr<const Value> evaluate( | |
| const intrusive_ptr<Document> &pDocument) const; | | const intrusive_ptr<Document> &pDocument) const; | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const; | | bool requireExpression) const; | |
| virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | | virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | |
| | | | |
| /* | | /* | |
| Create a field path expression. | | Create a field path expression. | |
| | | | |
| Evaluation will extract the value associated with the given field | | Evaluation will extract the value associated with the given field | |
| path from the source document. | | path from the source document. | |
| | | | |
| @param fieldPath the field path string, without any leading docum
ent | | @param fieldPath the field path string, without any leading docum
ent | |
| | | | |
| skipping to change at line 605 | | skipping to change at line 605 | |
| class ExpressionFieldRange : | | class ExpressionFieldRange : | |
| public Expression { | | public Expression { | |
| public: | | public: | |
| // virtuals from expression | | // virtuals from expression | |
| virtual ~ExpressionFieldRange(); | | virtual ~ExpressionFieldRange(); | |
| virtual intrusive_ptr<Expression> optimize(); | | virtual intrusive_ptr<Expression> optimize(); | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | |
| virtual intrusive_ptr<const Value> evaluate( | | virtual intrusive_ptr<const Value> evaluate( | |
| const intrusive_ptr<Document> &pDocument) const; | | const intrusive_ptr<Document> &pDocument) const; | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const; | | bool requireExpression) const; | |
| virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | | virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | |
| virtual void toMatcherBson(BSONObjBuilder *pBuilder) const; | | virtual void toMatcherBson(BSONObjBuilder *pBuilder) const; | |
| | | | |
| /* | | /* | |
| Create a field range expression. | | Create a field range expression. | |
| | | | |
| Field ranges are meant to match up with classic Matcher semantics
, | | Field ranges are meant to match up with classic Matcher semantics
, | |
| and therefore are conjunctions. For example, these appear in | | and therefore are conjunctions. For example, these appear in | |
| mongo shell predicates in one of these forms: | | mongo shell predicates in one of these forms: | |
| | | | |
| skipping to change at line 814 | | skipping to change at line 814 | |
| }; | | }; | |
| | | | |
| class ExpressionObject : | | class ExpressionObject : | |
| public Expression { | | public Expression { | |
| public: | | public: | |
| // virtuals from Expression | | // virtuals from Expression | |
| virtual ~ExpressionObject(); | | virtual ~ExpressionObject(); | |
| virtual intrusive_ptr<Expression> optimize(); | | virtual intrusive_ptr<Expression> optimize(); | |
| virtual bool isSimple(); | | virtual bool isSimple(); | |
| virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | | virtual void addDependencies(set<string>& deps, vector<string>* pat
h=NULL) const; | |
|
| | | /** Only evaluates non inclusion expressions. For inclusions, use
addToDocument(). */ | |
| virtual intrusive_ptr<const Value> evaluate( | | virtual intrusive_ptr<const Value> evaluate( | |
| const intrusive_ptr<Document> &pDocument) const; | | const intrusive_ptr<Document> &pDocument) const; | |
| virtual void addToBsonObj( | | virtual void addToBsonObj( | |
|
| BSONObjBuilder *pBuilder, string fieldName, | | BSONObjBuilder *pBuilder, const std::string& fieldName, | |
| bool requireExpression) const; | | bool requireExpression) const; | |
| virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | | virtual void addToBsonArray(BSONArrayBuilder *pBuilder) const; | |
| | | | |
| /* | | /* | |
| evaluate(), but return a Document instead of a Value-wrapped | | evaluate(), but return a Document instead of a Value-wrapped | |
| Document. | | Document. | |
| | | | |
| @param pDocument the input Document | | @param pDocument the input Document | |
| @returns the result document | | @returns the result document | |
| */ | | */ | |
| | | | |
End of changes. 10 change blocks. |
| 11 lines changed or deleted | | 14 lines changed or added | |
|
| grid.h | | grid.h | |
| | | | |
| skipping to change at line 48 | | skipping to change at line 48 | |
| /** | | /** | |
| * gets the config the db. | | * gets the config the db. | |
| * will return an empty DBConfig if not in db already | | * will return an empty DBConfig if not in db already | |
| */ | | */ | |
| DBConfigPtr getDBConfig( string ns , bool create=true , const strin
g& shardNameHint="" ); | | DBConfigPtr getDBConfig( string ns , bool create=true , const strin
g& shardNameHint="" ); | |
| | | | |
| /** | | /** | |
| * removes db entry. | | * removes db entry. | |
| * on next getDBConfig call will fetch from db | | * on next getDBConfig call will fetch from db | |
| */ | | */ | |
|
| void removeDB( string db ); | | void removeDB( const std::string& db ); | |
| | | | |
| /** | | /** | |
| * removes db entry - only this DBConfig object will be removed, | | * removes db entry - only this DBConfig object will be removed, | |
| * other DBConfigs which may have been created in the meantime wil
l not be harmed | | * other DBConfigs which may have been created in the meantime wil
l not be harmed | |
| * on next getDBConfig call will fetch from db | | * on next getDBConfig call will fetch from db | |
| * | | * | |
| * Using this method avoids race conditions where multiple threads
detect a database | | * Using this method avoids race conditions where multiple threads
detect a database | |
| * reload has failed. | | * reload has failed. | |
| * | | * | |
| * Example : N threads receive version exceptions and dbConfig.rel
oad(), while | | * Example : N threads receive version exceptions and dbConfig.rel
oad(), while | |
| | | | |
| skipping to change at line 79 | | skipping to change at line 79 | |
| */ | | */ | |
| bool allowLocalHost() const; | | bool allowLocalHost() const; | |
| | | | |
| /** | | /** | |
| * @param whether to allow shards and config servers to use 'localh
ost' in address | | * @param whether to allow shards and config servers to use 'localh
ost' in address | |
| */ | | */ | |
| void setAllowLocalHost( bool allow ); | | void setAllowLocalHost( bool allow ); | |
| | | | |
| /** | | /** | |
| * | | * | |
|
| * addShard will create a new shard in the grid. It expects a mongo
d process to be runing | | * addShard will create a new shard in the grid. It expects a mongo
d process to be running | |
| * on the provided address. Adding a shard that is a replica set is
supported. | | * on the provided address. Adding a shard that is a replica set is
supported. | |
| * | | * | |
|
| * @param name is an optional string with the name of the shard. if
ommited, grid will | | * @param name is an optional string with the name of the shard. if
omitted, grid will | |
| * generate one and update the parameter. | | * generate one and update the parameter. | |
| * @param servers is the connection string of the shard being added | | * @param servers is the connection string of the shard being added | |
| * @param maxSize is the optional space quota in bytes. Zeros means
there's no limitation to | | * @param maxSize is the optional space quota in bytes. Zeros means
there's no limitation to | |
| * space usage | | * space usage | |
| * @param errMsg is the error description in case the operation fai
led. | | * @param errMsg is the error description in case the operation fai
led. | |
| * @return true if shard was successfully added. | | * @return true if shard was successfully added. | |
| */ | | */ | |
| bool addShard( string* name , const ConnectionString& servers , lon
g long maxSize , string& errMsg ); | | bool addShard( string* name , const ConnectionString& servers , lon
g long maxSize , string& errMsg ); | |
| | | | |
| /** | | /** | |
| | | | |
| skipping to change at line 109 | | skipping to change at line 109 | |
| */ | | */ | |
| bool shouldBalance( const string& ns = "", BSONObj* balancerDocOut
= 0 ) const; | | bool shouldBalance( const string& ns = "", BSONObj* balancerDocOut
= 0 ) const; | |
| | | | |
| /** | | /** | |
| * | | * | |
| * Obtain grid configuration and settings data. | | * Obtain grid configuration and settings data. | |
| * | | * | |
| * @param name identifies a particular type of configuration data. | | * @param name identifies a particular type of configuration data. | |
| * @return a BSON object containing the requested data. | | * @return a BSON object containing the requested data. | |
| */ | | */ | |
|
| BSONObj getConfigSetting( string name ) const; | | BSONObj getConfigSetting( const std::string& name ) const; | |
| | | | |
| unsigned long long getNextOpTime() const; | | unsigned long long getNextOpTime() const; | |
| | | | |
| void flushConfig(); | | void flushConfig(); | |
| | | | |
| // exposed methods below are for testing only | | // exposed methods below are for testing only | |
| | | | |
| /** | | /** | |
| * @param balancerDoc bson that may contain a window of time for th
e balancer to work | | * @param balancerDoc bson that may contain a window of time for th
e balancer to work | |
| * format { ... , activeWindow: { start: "8:30" , stop: "19:
00" } , ... } | | * format { ... , activeWindow: { start: "8:30" , stop: "19:
00" } , ... } | |
| | | | |
End of changes. 4 change blocks. |
| 4 lines changed or deleted | | 4 lines changed or added | |
|
| hostandport.h | | hostandport.h | |
| | | | |
| skipping to change at line 20 | | skipping to change at line 20 | |
| * | | * | |
| * Unless required by applicable law or agreed to in writing, software | | * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | | * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed. | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed. | |
| * See the License for the specific language governing permissions and | | * See the License for the specific language governing permissions and | |
| * limitations under the License. | | * limitations under the License. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
|
| #include "mongo/db/cmdline.h" | | #include "sock.h" | |
| #include "mongo/util/mongoutils/str.h" | | #include "../../db/cmdline.h" | |
| #include "mongo/util/net/sock.h" | | #include "../mongoutils/str.h" | |
| #include "mongo/bson/util/builder.h" | | | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| using namespace mongoutils; | | using namespace mongoutils; | |
| | | | |
| /** helper for manipulating host:port connection endpoints. | | /** helper for manipulating host:port connection endpoints. | |
| */ | | */ | |
| struct HostAndPort { | | struct HostAndPort { | |
| HostAndPort() : _port(-1) { } | | HostAndPort() : _port(-1) { } | |
| | | | |
| /** From a string hostname[:portnumber] | | /** From a string hostname[:portnumber] | |
| Throws user assertion if bad config string or bad port #. | | Throws user assertion if bad config string or bad port #. | |
| */ | | */ | |
|
| HostAndPort(string s); | | HostAndPort(const std::string& s); | |
| | | | |
| /** @param p port number. -1 is ok to use default. */ | | /** @param p port number. -1 is ok to use default. */ | |
|
| HostAndPort(string h, int p /*= -1*/) : _host(h), _port(p) { | | HostAndPort(const std::string& h, int p /*= -1*/) : _host(h), _port
(p) { | |
| verify( !str::startsWith(h, '#') ); | | verify( !str::startsWith(h, '#') ); | |
| } | | } | |
| | | | |
| HostAndPort(const SockAddr& sock ) : _host( sock.getAddr() ) , _por
t( sock.getPort() ) { } | | HostAndPort(const SockAddr& sock ) : _host( sock.getAddr() ) , _por
t( sock.getPort() ) { } | |
| | | | |
| static HostAndPort me(); | | static HostAndPort me(); | |
| | | | |
| bool operator<(const HostAndPort& r) const { | | bool operator<(const HostAndPort& r) const { | |
| string h = host(); | | string h = host(); | |
| string rh = r.host(); | | string rh = r.host(); | |
| | | | |
| skipping to change at line 76 | | skipping to change at line 75 | |
| | | | |
| bool isLocalHost() const; | | bool isLocalHost() const; | |
| | | | |
| /** | | /** | |
| * @param includePort host:port if true, host otherwise | | * @param includePort host:port if true, host otherwise | |
| */ | | */ | |
| string toString( bool includePort=true ) const; | | string toString( bool includePort=true ) const; | |
| | | | |
| operator string() const { return toString(); } | | operator string() const { return toString(); } | |
| | | | |
|
| void append( StringBuilder& ss ) const; | | | |
| | | | |
| bool empty() const { | | bool empty() const { | |
| return _host.empty() && _port < 0; | | return _host.empty() && _port < 0; | |
| } | | } | |
| string host() const { | | string host() const { | |
| return _host; | | return _host; | |
| } | | } | |
| int port() const { | | int port() const { | |
| if (hasPort()) | | if (hasPort()) | |
| return _port; | | return _port; | |
| return CmdLine::DefaultDBPort; | | return CmdLine::DefaultDBPort; | |
| | | | |
| skipping to change at line 128 | | skipping to change at line 125 | |
| } | | } | |
| } | | } | |
| | | | |
| string h = getHostName(); | | string h = getHostName(); | |
| verify( !h.empty() ); | | verify( !h.empty() ); | |
| verify( h != "localhost" ); | | verify( h != "localhost" ); | |
| return HostAndPort(h, cmdLine.port); | | return HostAndPort(h, cmdLine.port); | |
| } | | } | |
| | | | |
| inline string HostAndPort::toString( bool includePort ) const { | | inline string HostAndPort::toString( bool includePort ) const { | |
|
| if ( ! includePort ) | | string h = host(); | |
| return host(); | | | |
| | | | |
| StringBuilder ss; | | | |
| append( ss ); | | | |
| return ss.str(); | | | |
| } | | | |
| | | | |
| inline void HostAndPort::append( StringBuilder& ss ) const { | | | |
| ss << host(); | | | |
| | | | |
| int p = port(); | | int p = port(); | |
| | | | |
|
| | | if ( ! includePort ) | |
| | | return h; | |
| | | | |
| | | stringstream ss; | |
| | | ss << h; | |
| if ( p != -1 ) { | | if ( p != -1 ) { | |
| ss << ':'; | | ss << ':'; | |
| #if defined(_DEBUG) | | #if defined(_DEBUG) | |
| if( p >= 44000 && p < 44100 ) { | | if( p >= 44000 && p < 44100 ) { | |
| log() << "warning: special debug port 44xxx used" << endl; | | log() << "warning: special debug port 44xxx used" << endl; | |
| ss << p+1; | | ss << p+1; | |
| } | | } | |
| else | | else | |
| ss << p; | | ss << p; | |
| #else | | #else | |
| ss << p; | | ss << p; | |
| #endif | | #endif | |
| } | | } | |
|
| | | return ss.str(); | |
| } | | } | |
| | | | |
| inline bool HostAndPort::isLocalHost() const { | | inline bool HostAndPort::isLocalHost() const { | |
| string _host = host(); | | string _host = host(); | |
| return ( _host == "localhost" | | return ( _host == "localhost" | |
| || startsWith(_host.c_str(), "127.") | | || startsWith(_host.c_str(), "127.") | |
| || _host == "::1" | | || _host == "::1" | |
| || _host == "anonymous unix socket" | | || _host == "anonymous unix socket" | |
| || _host.c_str()[0] == '/' // unix socket | | || _host.c_str()[0] == '/' // unix socket | |
| ); | | ); | |
| | | | |
| skipping to change at line 183 | | skipping to change at line 175 | |
| _host = string(p,colon-p); | | _host = string(p,colon-p); | |
| _port = port; | | _port = port; | |
| } | | } | |
| else { | | else { | |
| // no port specified. | | // no port specified. | |
| _host = p; | | _host = p; | |
| _port = -1; | | _port = -1; | |
| } | | } | |
| } | | } | |
| | | | |
|
| inline HostAndPort::HostAndPort(string s) { | | inline HostAndPort::HostAndPort(const std::string& s) { | |
| init(s.c_str()); | | init(s.c_str()); | |
| } | | } | |
| | | | |
| } | | } | |
| | | | |
End of changes. 8 change blocks. |
| 21 lines changed or deleted | | 13 lines changed or added | |
|
| html.h | | html.h | |
| // @file html.h | | // @file html.h | |
| | | | |
|
| | | /** | |
| | | * Copyright (C) 2012 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 Licen | |
| | | se | |
| | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| /* Things in the mongoutils namespace | | /* Things in the mongoutils namespace | |
| (1) are not database specific, rather, true utilities | | (1) are not database specific, rather, true utilities | |
| (2) are cross platform | | (2) are cross platform | |
| (3) may require boost headers, but not libs | | (3) may require boost headers, but not libs | |
| (4) are clean and easy to use in any c++ project without pulling in lots
of other stuff | | (4) are clean and easy to use in any c++ project without pulling in lots
of other stuff | |
| */ | | */ | |
| | | | |
|
| /* Copyright 2010 10gen Inc. | | | |
| * | | | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | | | |
| * you may not use this file except in compliance with the License. | | | |
| * You may obtain a copy of the License at | | | |
| * | | | |
| * http://www.apache.org/licenses/LICENSE-2.0 | | | |
| * | | | |
| * Unless required by applicable law or agreed to in writing, software | | | |
| * distributed under the License is distributed on an "AS IS" BASIS, | | | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli | | | |
| ed. | | | |
| * See the License for the specific language governing permissions and | | | |
| * limitations under the License. | | | |
| */ | | | |
| | | | |
| #include <sstream> | | #include <sstream> | |
| | | | |
| namespace mongoutils { | | namespace mongoutils { | |
| | | | |
| namespace html { | | namespace html { | |
| | | | |
| using namespace std; | | using namespace std; | |
| | | | |
| inline string _end() { return "</body></html>"; } | | inline string _end() { return "</body></html>"; } | |
| inline string _table() { return "</table>\n\n"; } | | inline string _table() { return "</table>\n\n"; } | |
| inline string _tr() { return "</tr>\n"; } | | inline string _tr() { return "</tr>\n"; } | |
| | | | |
| inline string tr() { return "<tr>"; } | | inline string tr() { return "<tr>"; } | |
|
| inline string tr(string a, string b) { | | inline string tr(const std::string& a, const std::string& b) { | |
| stringstream ss; | | stringstream ss; | |
| ss << "<tr><td>" << a << "</td><td>" << b << "</td></tr>\n"; | | ss << "<tr><td>" << a << "</td><td>" << b << "</td></tr>\n"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| template <class T> | | template <class T> | |
| inline string td(T x) { | | inline string td(T x) { | |
| stringstream ss; | | stringstream ss; | |
| ss << "<td>" << x << "</td>"; | | ss << "<td>" << x << "</td>"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
|
| inline string td(string x) { | | inline string td(const std::string& x) { | |
| return "<td>" + x + "</td>"; | | return "<td>" + x + "</td>"; | |
| } | | } | |
|
| inline string th(string x) { | | inline string th(const std::string& x) { | |
| return "<th>" + x + "</th>"; | | return "<th>" + x + "</th>"; | |
| } | | } | |
| | | | |
| inline void tablecell( stringstream& ss , bool b ) { | | inline void tablecell( stringstream& ss , bool b ) { | |
| ss << "<td>" << (b ? "<b>X</b>" : "") << "</td>"; | | ss << "<td>" << (b ? "<b>X</b>" : "") << "</td>"; | |
| } | | } | |
| | | | |
| template< typename T> | | template< typename T> | |
| inline void tablecell( stringstream& ss , const T& t ) { | | inline void tablecell( stringstream& ss , const T& t ) { | |
| ss << "<td>" << t << "</td>"; | | ss << "<td>" << t << "</td>"; | |
| | | | |
| skipping to change at line 83 | | skipping to change at line 84 | |
| ss << "<tr>"; | | ss << "<tr>"; | |
| while( *headers ) { | | while( *headers ) { | |
| ss << "<th>" << *headers << "</th>"; | | ss << "<th>" << *headers << "</th>"; | |
| headers++; | | headers++; | |
| } | | } | |
| ss << "</tr>\n"; | | ss << "</tr>\n"; | |
| } | | } | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| | | | |
|
| inline string start(string title) { | | inline string start(const std::string& title) { | |
| stringstream ss; | | stringstream ss; | |
| ss << "<html><head>\n<title>"; | | ss << "<html><head>\n<title>"; | |
| ss << title; | | ss << title; | |
| ss << "</title>\n"; | | ss << "</title>\n"; | |
| | | | |
| ss << "<style type=\"text/css\" media=\"screen\">" | | ss << "<style type=\"text/css\" media=\"screen\">" | |
| "body { font-family: helvetica, arial, san-serif }\n" | | "body { font-family: helvetica, arial, san-serif }\n" | |
| "table { border-collapse:collapse; border-color:#999; margin
-top:.5em }\n" | | "table { border-collapse:collapse; border-color:#999; margin
-top:.5em }\n" | |
| "th { background-color:#bbb; color:#000 }\n" | | "th { background-color:#bbb; color:#000 }\n" | |
| "td,th { padding:.25em }\n" | | "td,th { padding:.25em }\n" | |
| "</style>\n"; | | "</style>\n"; | |
| | | | |
| ss << "</head>\n<body>\n"; | | ss << "</head>\n<body>\n"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| | | | |
|
| inline string red(string contentHtml, bool color=true) { | | inline string red(const std::string& contentHtml, bool color=true)
{ | |
| if( !color ) return contentHtml; | | if( !color ) return contentHtml; | |
| stringstream ss; | | stringstream ss; | |
| ss << "<span style=\"color:#A00;\">" << contentHtml << "</span>
"; | | ss << "<span style=\"color:#A00;\">" << contentHtml << "</span>
"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
|
| inline string grey(string contentHtml, bool color=true) { | | inline string grey(const std::string& contentHtml, bool color=true)
{ | |
| if( !color ) return contentHtml; | | if( !color ) return contentHtml; | |
| stringstream ss; | | stringstream ss; | |
| ss << "<span style=\"color:#888;\">" << contentHtml << "</span>
"; | | ss << "<span style=\"color:#888;\">" << contentHtml << "</span>
"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
|
| inline string blue(string contentHtml, bool color=true) { | | inline string blue(const std::string& contentHtml, bool color=true)
{ | |
| if( !color ) return contentHtml; | | if( !color ) return contentHtml; | |
| stringstream ss; | | stringstream ss; | |
| ss << "<span style=\"color:#00A;\">" << contentHtml << "</span>
"; | | ss << "<span style=\"color:#00A;\">" << contentHtml << "</span>
"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
|
| inline string yellow(string contentHtml, bool color=true) { | | inline string yellow(const std::string& contentHtml, bool color=tru
e) { | |
| if( !color ) return contentHtml; | | if( !color ) return contentHtml; | |
| stringstream ss; | | stringstream ss; | |
| ss << "<span style=\"color:#A80;\">" << contentHtml << "</span>
"; | | ss << "<span style=\"color:#A80;\">" << contentHtml << "</span>
"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
|
| inline string green(string contentHtml, bool color=true) { | | inline string green(const std::string& contentHtml, bool color=true
) { | |
| if( !color ) return contentHtml; | | if( !color ) return contentHtml; | |
| stringstream ss; | | stringstream ss; | |
| ss << "<span style=\"color:#0A0;\">" << contentHtml << "</span>
"; | | ss << "<span style=\"color:#0A0;\">" << contentHtml << "</span>
"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| | | | |
|
| inline string p(string contentHtml) { | | inline string p(const std::string& contentHtml) { | |
| stringstream ss; | | stringstream ss; | |
| ss << "<p>" << contentHtml << "</p>\n"; | | ss << "<p>" << contentHtml << "</p>\n"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| | | | |
|
| inline string h2(string contentHtml) { | | inline string h2(const std::string& contentHtml) { | |
| stringstream ss; | | stringstream ss; | |
| ss << "<h2>" << contentHtml << "</h2>\n"; | | ss << "<h2>" << contentHtml << "</h2>\n"; | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| | | | |
| /* does NOT escape the strings. */ | | /* does NOT escape the strings. */ | |
|
| inline string a(string href, string title="", string contentHtml = | | inline string a(const std::string& href, | |
| "") { | | const std::string& title="", | |
| | | const std::string& contentHtml = "") { | |
| stringstream ss; | | stringstream ss; | |
| ss << "<a"; | | ss << "<a"; | |
| if( !href.empty() ) ss << " href=\"" << href << '"'; | | if( !href.empty() ) ss << " href=\"" << href << '"'; | |
| if( !title.empty() ) ss << " title=\"" << title << '"'; | | if( !title.empty() ) ss << " title=\"" << title << '"'; | |
| ss << '>'; | | ss << '>'; | |
| if( !contentHtml.empty() ) { | | if( !contentHtml.empty() ) { | |
| ss << contentHtml << "</a>"; | | ss << contentHtml << "</a>"; | |
| } | | } | |
| return ss.str(); | | return ss.str(); | |
| } | | } | |
| | | | |
End of changes. 14 change blocks. |
| 29 lines changed or deleted | | 32 lines changed or added | |
|
| listen.h | | listen.h | |
| | | | |
| skipping to change at line 21 | | skipping to change at line 21 | |
| * Unless required by applicable law or agreed to in writing, software | | * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | | * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed. | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed. | |
| * See the License for the specific language governing permissions and | | * See the License for the specific language governing permissions and | |
| * limitations under the License. | | * limitations under the License. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "sock.h" | | #include "sock.h" | |
|
| | | #include "mongo/platform/atomic_word.h" | |
| #include "mongo/util/concurrency/ticketholder.h" | | #include "mongo/util/concurrency/ticketholder.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| const int DEFAULT_MAX_CONN = 20000; | | const int DEFAULT_MAX_CONN = 20000; | |
| const int MAX_MAX_CONN = 20000; | | const int MAX_MAX_CONN = 20000; | |
| | | | |
| class MessagingPort; | | class MessagingPort; | |
| | | | |
| class Listener : boost::noncopyable { | | class Listener : boost::noncopyable { | |
| | | | |
| skipping to change at line 97 | | skipping to change at line 98 | |
| /** | | /** | |
| * @return true iff everything went ok | | * @return true iff everything went ok | |
| */ | | */ | |
| bool _setupSockets( const vector<SockAddr>& mine , vector<SOCKET>&
socks ); | | bool _setupSockets( const vector<SockAddr>& mine , vector<SOCKET>&
socks ); | |
| | | | |
| void _logListen( int port , bool ssl ); | | void _logListen( int port , bool ssl ); | |
| | | | |
| static const Listener* _timeTracker; | | static const Listener* _timeTracker; | |
| | | | |
| virtual bool useUnixSockets() const { return false; } | | virtual bool useUnixSockets() const { return false; } | |
|
| | | | |
| | | public: | |
| | | /** the "next" connection number. every connection to this process | |
| | | has a unique number */ | |
| | | static AtomicInt64 globalConnectionNumber; | |
| | | | |
| | | /** keeps track of how many allowed connections there are and how m | |
| | | any are being used*/ | |
| | | static TicketHolder globalTicketHolder; | |
| | | | |
| | | /** makes sure user input is sane */ | |
| | | static void checkTicketNumbers(); | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * keep track of elapsed time | | * keep track of elapsed time | |
| * after a set amount of time, tells you to do something | | * after a set amount of time, tells you to do something | |
| * only in this file because depends on Listener | | * only in this file because depends on Listener | |
| */ | | */ | |
| class ElapsedTracker { | | class ElapsedTracker { | |
| public: | | public: | |
| ElapsedTracker( int hitsBetweenMarks , int msBetweenMarks ) | | ElapsedTracker( int hitsBetweenMarks , int msBetweenMarks ) | |
| | | | |
| skipping to change at line 155 | | skipping to change at line 166 | |
| public: | | public: | |
| ListeningSockets() | | ListeningSockets() | |
| : _mutex("ListeningSockets") | | : _mutex("ListeningSockets") | |
| , _sockets( new set<int>() ) | | , _sockets( new set<int>() ) | |
| , _socketPaths( new set<string>() ) | | , _socketPaths( new set<string>() ) | |
| { } | | { } | |
| void add( int sock ) { | | void add( int sock ) { | |
| scoped_lock lk( _mutex ); | | scoped_lock lk( _mutex ); | |
| _sockets->insert( sock ); | | _sockets->insert( sock ); | |
| } | | } | |
|
| void addPath( string path ) { | | void addPath( const std::string& path ) { | |
| scoped_lock lk( _mutex ); | | scoped_lock lk( _mutex ); | |
| _socketPaths->insert( path ); | | _socketPaths->insert( path ); | |
| } | | } | |
| void remove( int sock ) { | | void remove( int sock ) { | |
| scoped_lock lk( _mutex ); | | scoped_lock lk( _mutex ); | |
| _sockets->erase( sock ); | | _sockets->erase( sock ); | |
| } | | } | |
| void closeAll() { | | void closeAll() { | |
| set<int>* sockets; | | set<int>* sockets; | |
| set<string>* paths; | | set<string>* paths; | |
| | | | |
| skipping to change at line 195 | | skipping to change at line 206 | |
| } | | } | |
| } | | } | |
| static ListeningSockets* get(); | | static ListeningSockets* get(); | |
| private: | | private: | |
| mongo::mutex _mutex; | | mongo::mutex _mutex; | |
| set<int>* _sockets; | | set<int>* _sockets; | |
| set<string>* _socketPaths; // for unix domain sockets | | set<string>* _socketPaths; // for unix domain sockets | |
| static ListeningSockets* _instance; | | static ListeningSockets* _instance; | |
| }; | | }; | |
| | | | |
|
| extern TicketHolder connTicketHolder; | | | |
| | | | |
| } | | } | |
| | | | |
End of changes. 4 change blocks. |
| 3 lines changed or deleted | | 14 lines changed or added | |
|
| log.h | | log.h | |
| | | | |
| skipping to change at line 41 | | skipping to change at line 41 | |
| #include "mongo/util/exit_code.h" | | #include "mongo/util/exit_code.h" | |
| | | | |
| #ifndef _WIN32 | | #ifndef _WIN32 | |
| #include <syslog.h> | | #include <syslog.h> | |
| #endif | | #endif | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| enum ExitCode; | | enum ExitCode; | |
| | | | |
|
| // using negative numbers so these are always less than ::mongo::loglev | | enum LogLevel { LL_DEBUG , LL_INFO , LL_NOTICE , LL_WARNING , LL_ERROR | |
| el (see MONGO_LOG) | | , LL_SEVERE }; | |
| enum LogLevel { LL_DEBUG=-1000 , LL_INFO , LL_NOTICE , LL_WARNING , LL | | | |
| _ERROR , LL_SEVERE }; | | | |
| | | | |
| inline const char * logLevelToString( LogLevel l ) { | | inline const char * logLevelToString( LogLevel l ) { | |
| switch ( l ) { | | switch ( l ) { | |
| case LL_DEBUG: | | case LL_DEBUG: | |
| case LL_INFO: | | case LL_INFO: | |
| case LL_NOTICE: | | case LL_NOTICE: | |
| return ""; | | return ""; | |
| case LL_WARNING: | | case LL_WARNING: | |
| return "warning" ; | | return "warning" ; | |
| case LL_ERROR: | | case LL_ERROR: | |
| | | | |
| skipping to change at line 98 | | skipping to change at line 97 | |
| LabeledLevel operator+( int i ) const { | | LabeledLevel operator+( int i ) const { | |
| return LabeledLevel( _label, _level + i ); | | return LabeledLevel( _label, _level + i ); | |
| } | | } | |
| | | | |
| LabeledLevel operator+( const char* label ) const { | | LabeledLevel operator+( const char* label ) const { | |
| if( _label == "" ) | | if( _label == "" ) | |
| return LabeledLevel( label, _level ); | | return LabeledLevel( label, _level ); | |
| return LabeledLevel( _label + string("::") + label, _level ); | | return LabeledLevel( _label + string("::") + label, _level ); | |
| } | | } | |
| | | | |
|
| LabeledLevel operator+( string& label ) const { | | LabeledLevel operator+( const std::string& label ) const { | |
| return LabeledLevel( _label + string("::") + label, _level ); | | return LabeledLevel( _label + string("::") + label, _level ); | |
| } | | } | |
| | | | |
| LabeledLevel operator-( int i ) const { | | LabeledLevel operator-( int i ) const { | |
| return LabeledLevel( _label, _level - i ); | | return LabeledLevel( _label, _level - i ); | |
| } | | } | |
| | | | |
| const string& getLabel() const { return _label; } | | const string& getLabel() const { return _label; } | |
| int getLevel() const { return _level; } | | int getLevel() const { return _level; } | |
| | | | |
| private: | | private: | |
| string _label; | | string _label; | |
| int _level; | | int _level; | |
| }; | | }; | |
| | | | |
|
| inline bool operator<( const LabeledLevel& ll, const int i ) { return l | | | |
| l.getLevel() < i; } | | | |
| inline bool operator<( const int i, const LabeledLevel& ll ) { return i | | | |
| < ll.getLevel(); } | | | |
| inline bool operator>( const LabeledLevel& ll, const int i ) { return l | | | |
| l.getLevel() > i; } | | | |
| inline bool operator>( const int i, const LabeledLevel& ll ) { return i | | | |
| > ll.getLevel(); } | | | |
| inline bool operator<=( const LabeledLevel& ll, const int i ) { return | | | |
| ll.getLevel() <= i; } | | | |
| inline bool operator<=( const int i, const LabeledLevel& ll ) { return | | | |
| i <= ll.getLevel(); } | | | |
| inline bool operator>=( const LabeledLevel& ll, const int i ) { return | | | |
| ll.getLevel() >= i; } | | | |
| inline bool operator>=( const int i, const LabeledLevel& ll ) { return | | | |
| i >= ll.getLevel(); } | | | |
| inline bool operator==( const LabeledLevel& ll, const int i ) { return | | | |
| ll.getLevel() == i; } | | | |
| inline bool operator==( const int i, const LabeledLevel& ll ) { return | | | |
| i == ll.getLevel(); } | | | |
| | | | |
| class LazyString { | | class LazyString { | |
| public: | | public: | |
| virtual ~LazyString() {} | | virtual ~LazyString() {} | |
| virtual string val() const = 0; | | virtual string val() const = 0; | |
| }; | | }; | |
| | | | |
| // Utility class for stringifying object only when val() called. | | // Utility class for stringifying object only when val() called. | |
| template< class T > | | template< class T > | |
| class LazyStringImpl : public LazyString { | | class LazyStringImpl : public LazyString { | |
| public: | | public: | |
| | | | |
| skipping to change at line 344 | | skipping to change at line 332 | |
| globalTees->push_back( t ); | | globalTees->push_back( t ); | |
| } | | } | |
| | | | |
| void removeGlobalTee( Tee * tee ); | | void removeGlobalTee( Tee * tee ); | |
| | | | |
| void indentInc(){ indent++; } | | void indentInc(){ indent++; } | |
| void indentDec(){ indent--; } | | void indentDec(){ indent--; } | |
| int getIndent() const { return indent; } | | int getIndent() const { return indent; } | |
| | | | |
| private: | | private: | |
|
| | | static boost::thread_specific_ptr<Logstream> tsp; | |
| Logstream() { | | Logstream() { | |
| indent = 0; | | indent = 0; | |
| _init(); | | _init(); | |
| } | | } | |
| void _init() { | | void _init() { | |
| ss.str(""); | | ss.str(""); | |
| logLevel = LL_INFO; | | logLevel = LL_INFO; | |
| } | | } | |
| public: | | public: | |
| static Logstream& get(); | | static Logstream& get(); | |
| | | | |
| skipping to change at line 390 | | skipping to change at line 379 | |
| set tlogLevel to -1 to suppress tlog() output in a test program. */ | | set tlogLevel to -1 to suppress tlog() output in a test program. */ | |
| Nullstream& tlog( int level = 0 ); | | Nullstream& tlog( int level = 0 ); | |
| | | | |
| // log if debug build or if at a certain level | | // log if debug build or if at a certain level | |
| inline Nullstream& dlog( int level ) { | | inline Nullstream& dlog( int level ) { | |
| if ( level <= logLevel || DEBUG_BUILD ) | | if ( level <= logLevel || DEBUG_BUILD ) | |
| return Logstream::get().prolog(); | | return Logstream::get().prolog(); | |
| return nullstream; | | return nullstream; | |
| } | | } | |
| | | | |
|
| #define MONGO_LOG(level) \ | | inline Nullstream& log( int level ) { | |
| ( MONGO_likely( ::mongo::logLevel < (level) ) ) \ | | | |
| ? ::mongo::nullstream : ::mongo::logWithLevel(level) | | | |
| #define LOG MONGO_LOG | | | |
| | | | |
| inline Nullstream& log() { | | | |
| return Logstream::get().prolog(); | | | |
| } | | | |
| | | | |
| // Use MONGO_LOG() instead of this | | | |
| inline Nullstream& logWithLevel( int level ) { | | | |
| if ( level > logLevel ) | | if ( level > logLevel ) | |
| return nullstream; | | return nullstream; | |
| return Logstream::get().prolog(); | | return Logstream::get().prolog(); | |
| } | | } | |
| | | | |
|
| inline Nullstream& logWithLevel( LogLevel l ) { | | #define MONGO_LOG(level) if ( MONGO_likely(logLevel < (level)) ) { } else l | |
| | | og( level ) | |
| | | #define LOG MONGO_LOG | |
| | | | |
| | | inline Nullstream& log( LogLevel l ) { | |
| return Logstream::get().prolog().setLogLevel( l ); | | return Logstream::get().prolog().setLogLevel( l ); | |
| } | | } | |
| | | | |
|
| inline Nullstream& logWithLevel( const LabeledLevel& ll ) { | | inline Nullstream& log( const LabeledLevel& ll ) { | |
| Nullstream& stream = logWithLevel( ll.getLevel() ); | | Nullstream& stream = log( ll.getLevel() ); | |
| if( ll.getLabel() != "" ) | | if( ll.getLabel() != "" ) | |
| stream << "[" << ll.getLabel() << "] "; | | stream << "[" << ll.getLabel() << "] "; | |
| return stream; | | return stream; | |
| } | | } | |
| | | | |
|
| | | inline Nullstream& log() { | |
| | | return Logstream::get().prolog(); | |
| | | } | |
| | | | |
| inline Nullstream& error() { | | inline Nullstream& error() { | |
|
| return logWithLevel( LL_ERROR ); | | return log( LL_ERROR ); | |
| } | | } | |
| | | | |
| inline Nullstream& warning() { | | inline Nullstream& warning() { | |
|
| return logWithLevel( LL_WARNING ); | | return log( LL_WARNING ); | |
| } | | } | |
| | | | |
| /* default impl returns "" -- mongod overrides */ | | /* default impl returns "" -- mongod overrides */ | |
| extern const char * (*getcurns)(); | | extern const char * (*getcurns)(); | |
| | | | |
| inline Nullstream& problem( int level = 0 ) { | | inline Nullstream& problem( int level = 0 ) { | |
| if ( level > logLevel ) | | if ( level > logLevel ) | |
| return nullstream; | | return nullstream; | |
| Logstream& l = Logstream::get().prolog(); | | Logstream& l = Logstream::get().prolog(); | |
| l << ' ' << getcurns() << ' '; | | l << ' ' << getcurns() << ' '; | |
| | | | |
End of changes. 10 change blocks. |
| 42 lines changed or deleted | | 18 lines changed or added | |
|
| matcher.h | | matcher.h | |
| | | | |
| skipping to change at line 25 | | skipping to change at line 25 | |
| * GNU Affero General Public License for more details. | | * GNU Affero General Public License for more details. | |
| * | | * | |
| * You should have received a copy of the GNU Affero General Public Licen
se | | * You should have received a copy of the GNU Affero General Public Licen
se | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "jsobj.h" | | #include "jsobj.h" | |
| #include "pcrecpp.h" | | #include "pcrecpp.h" | |
|
| #include "geo/shapes.h" | | | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class Cursor; | | class Cursor; | |
| class CoveredIndexMatcher; | | class CoveredIndexMatcher; | |
| class ElementMatcher; | | class ElementMatcher; | |
| class Matcher; | | class Matcher; | |
| class FieldRangeVector; | | class FieldRangeVector; | |
| | | | |
| class RegexMatcher { | | class RegexMatcher { | |
| public: | | public: | |
|
| | | /** | |
| | | * Maximum pattern size which pcre v8.3 can do matches correctly wi | |
| | | th | |
| | | * LINK_SIZE define macro set to 2 @ pcre's config.h (based on | |
| | | * experiments) | |
| | | */ | |
| | | static const size_t MaxPatternSize = 32764; | |
| | | | |
| const char *_fieldName; | | const char *_fieldName; | |
| const char *_regex; | | const char *_regex; | |
| const char *_flags; | | const char *_flags; | |
| string _prefix; | | string _prefix; | |
| shared_ptr< pcrecpp::RE > _re; | | shared_ptr< pcrecpp::RE > _re; | |
| bool _isNot; | | bool _isNot; | |
| RegexMatcher() : _isNot() {} | | RegexMatcher() : _isNot() {} | |
| }; | | }; | |
| | | | |
|
| class GeoMatcher { | | | |
| private: | | | |
| GeoMatcher(const string& field) : _isBox(false), _isCircle(false), | | | |
| _isPolygon(false), | | | |
| _fieldName(field) {} | | | |
| bool _isBox; | | | |
| Box _box; | | | |
| | | | |
| bool _isCircle; | | | |
| Point _center; | | | |
| double _radius; | | | |
| | | | |
| bool _isPolygon; | | | |
| Polygon _polygon; | | | |
| | | | |
| string _fieldName; | | | |
| public: | | | |
| const string& getFieldName() const { return _fieldName; } | | | |
| | | | |
| static GeoMatcher makeBox(const string& field, const BSONObj &min, | | | |
| const BSONObj &max) { | | | |
| GeoMatcher m(field); | | | |
| m._isBox = true; | | | |
| uassert(16470, "Malformed coord: " + min.toString(), pointFrom( | | | |
| min, &m._box._min)); | | | |
| uassert(16471, "Malformed coord: " + max.toString(), pointFrom( | | | |
| max, &m._box._max)); | | | |
| return m; | | | |
| } | | | |
| | | | |
| static GeoMatcher makeCircle(const string& field, const BSONObj &ce | | | |
| nter, double rad) { | | | |
| GeoMatcher m(field); | | | |
| m._isCircle = true; | | | |
| uassert(16472, "Malformed coord: " + center.toString(), pointFr | | | |
| om(center, &m._center)); | | | |
| m._radius = rad; | | | |
| return m; | | | |
| } | | | |
| | | | |
| static GeoMatcher makePolygon(const string& field, const BSONObj &p | | | |
| oly) { | | | |
| GeoMatcher m(field); | | | |
| vector<Point> points; | | | |
| | | | |
| m._isPolygon = true; | | | |
| BSONObjIterator coordIt(poly); | | | |
| while (coordIt.more()) { | | | |
| BSONElement coord = coordIt.next(); | | | |
| const BSONObj& obj = coord.Obj(); | | | |
| Point p; | | | |
| uassert(16480, "Malformed coord: " + obj.toString(), pointF | | | |
| rom(obj, &p)); | | | |
| points.push_back(p); | | | |
| } | | | |
| m._polygon = Polygon(points); | | | |
| return m; | | | |
| } | | | |
| | | | |
| bool containsPoint(Point p) const { | | | |
| if (_isBox) { | | | |
| return _box.inside(p, 0); | | | |
| } else if (_isCircle) { | | | |
| return _center.distance(p) <= _radius; | | | |
| } else if (_isPolygon) { | | | |
| return _polygon.contains(p); | | | |
| } else { | | | |
| return false; | | | |
| } | | | |
| } | | | |
| | | | |
| string toString() const { | | | |
| stringstream ss; | | | |
| if (_isBox) { | | | |
| ss << "GeoMatcher Box: " << _box.toString(); | | | |
| } else if (_isCircle) { | | | |
| ss << "GeoMatcher Circle @ " << _center.toString() << " r = | | | |
| " << _radius; | | | |
| } else { | | | |
| ss << "GeoMatcher UNKNOWN"; | | | |
| } | | | |
| return ss.str(); | | | |
| } | | | |
| | | | |
| static bool pointFrom(const BSONObj o, Point *p) { | | | |
| BSONObjIterator i(o); | | | |
| if (!i.more()) { return false; } | | | |
| BSONElement xe = i.next(); | | | |
| if (!i.more()) { return false; } | | | |
| BSONElement ye = i.next(); | | | |
| if (!xe.isNumber() || !ye.isNumber()) { return false; } | | | |
| p->_x = xe.number(); | | | |
| p->_y = ye.number(); | | | |
| return true; | | | |
| } | | | |
| }; | | | |
| | | | |
| struct element_lt { | | struct element_lt { | |
| bool operator()(const BSONElement& l, const BSONElement& r) const { | | bool operator()(const BSONElement& l, const BSONElement& r) const { | |
| int x = (int) l.canonicalType() - (int) r.canonicalType(); | | int x = (int) l.canonicalType() - (int) r.canonicalType(); | |
| if ( x < 0 ) return true; | | if ( x < 0 ) return true; | |
| else if ( x > 0 ) return false; | | else if ( x > 0 ) return false; | |
| return compareElementValues(l,r) < 0; | | return compareElementValues(l,r) < 0; | |
| } | | } | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| | | | |
| skipping to change at line 358 | | skipping to change at line 276 | |
| bool _haveNeg; | | bool _haveNeg; | |
| | | | |
| /* $atomic - if true, a multi document operation (some removes, upd
ates) | | /* $atomic - if true, a multi document operation (some removes, upd
ates) | |
| should be done atomically. in that case, we do not yi
eld - | | should be done atomically. in that case, we do not yi
eld - | |
| i.e. we stay locked the whole time. | | i.e. we stay locked the whole time. | |
| http://dochub.mongodb.org/core/remove | | http://dochub.mongodb.org/core/remove | |
| */ | | */ | |
| bool _atomic; | | bool _atomic; | |
| | | | |
| vector<RegexMatcher> _regexs; | | vector<RegexMatcher> _regexs; | |
|
| vector<GeoMatcher> _geo; | | | |
| | | | |
| // so we delete the mem when we're done: | | // so we delete the mem when we're done: | |
| vector< shared_ptr< BSONObjBuilder > > _builders; | | vector< shared_ptr< BSONObjBuilder > > _builders; | |
| list< shared_ptr< Matcher > > _andMatchers; | | list< shared_ptr< Matcher > > _andMatchers; | |
| list< shared_ptr< Matcher > > _orMatchers; | | list< shared_ptr< Matcher > > _orMatchers; | |
| list< shared_ptr< Matcher > > _norMatchers; | | list< shared_ptr< Matcher > > _norMatchers; | |
| | | | |
| friend class CoveredIndexMatcher; | | friend class CoveredIndexMatcher; | |
| }; | | }; | |
| | | | |
| | | | |
End of changes. 4 change blocks. |
| 99 lines changed or deleted | | 8 lines changed or added | |
|
| mmap.h | | mmap.h | |
| | | | |
| skipping to change at line 54 | | skipping to change at line 54 | |
| | | | |
| /** era changes anytime memory maps come and go. thus you can use
this as a cheap way to check | | /** era changes anytime memory maps come and go. thus you can use
this as a cheap way to check | |
| if nothing has changed since the last time you locked. Of cour
se you must be shared locked | | if nothing has changed since the last time you locked. Of cour
se you must be shared locked | |
| at the time of this call, otherwise someone could be in progres
s. | | at the time of this call, otherwise someone could be in progres
s. | |
| | | | |
| This is used for yielding; see PageFaultException::touch(). | | This is used for yielding; see PageFaultException::touch(). | |
| */ | | */ | |
| static unsigned getEra() { return era; } | | static unsigned getEra() { return era; } | |
| | | | |
| static void assertExclusivelyLocked() { mmmutex.assertExclusivelyLo
cked(); } | | static void assertExclusivelyLocked() { mmmutex.assertExclusivelyLo
cked(); } | |
|
| | | static void assertAtLeastReadLocked() { mmmutex.assertAtLeastReadLo
cked(); } | |
| }; | | }; | |
| | | | |
| class LockMongoFilesExclusive { | | class LockMongoFilesExclusive { | |
| RWLockRecursive::Exclusive lk; | | RWLockRecursive::Exclusive lk; | |
| public: | | public: | |
| LockMongoFilesExclusive() : lk(LockMongoFilesShared::mmmutex) { | | LockMongoFilesExclusive() : lk(LockMongoFilesShared::mmmutex) { | |
| LockMongoFilesShared::era++; | | LockMongoFilesShared::era++; | |
| } | | } | |
| }; | | }; | |
| | | | |
| | | | |
| skipping to change at line 82 | | skipping to change at line 83 | |
| }; | | }; | |
| | | | |
| virtual ~MongoFile() {} | | virtual ~MongoFile() {} | |
| | | | |
| enum Options { | | enum Options { | |
| SEQUENTIAL = 1, // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on win
dows | | SEQUENTIAL = 1, // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on win
dows | |
| READONLY = 2 // not contractually guaranteed, but if specifi
ed the impl has option to fault writes | | READONLY = 2 // not contractually guaranteed, but if specifi
ed the impl has option to fault writes | |
| }; | | }; | |
| | | | |
| /** @param fun is called for each MongoFile. | | /** @param fun is called for each MongoFile. | |
|
| calledl from within a mutex that MongoFile uses. so be careful
not to deadlock. | | called from within a mutex that MongoFile uses. so be careful n
ot to deadlock. | |
| */ | | */ | |
| template < class F > | | template < class F > | |
| static void forEach( F fun ); | | static void forEach( F fun ); | |
| | | | |
| /** note: you need to be in mmmutex when using this. forEach (above
) handles that for you automatically. | | /** note: you need to be in mmmutex when using this. forEach (above
) handles that for you automatically. | |
| */ | | */ | |
|
| static set<MongoFile*>& getAllFiles() { return mmfiles; } | | static set<MongoFile*>& getAllFiles(); | |
| | | | |
| // callbacks if you need them | | // callbacks if you need them | |
| static void (*notifyPreFlush)(); | | static void (*notifyPreFlush)(); | |
| static void (*notifyPostFlush)(); | | static void (*notifyPostFlush)(); | |
| | | | |
| static int flushAll( bool sync ); // returns n flushed | | static int flushAll( bool sync ); // returns n flushed | |
| static long long totalMappedLength(); | | static long long totalMappedLength(); | |
| static void closeAllFiles( stringstream &message ); | | static void closeAllFiles( stringstream &message ); | |
| | | | |
| virtual bool isMongoMMF() { return false; } | | virtual bool isMongoMMF() { return false; } | |
| | | | |
| string filename() const { return _filename; } | | string filename() const { return _filename; } | |
|
| void setFilename(string fn); | | void setFilename(const std::string& fn); | |
| | | | |
| private: | | private: | |
| string _filename; | | string _filename; | |
| static int _flushAll( bool sync ); // returns n flushed | | static int _flushAll( bool sync ); // returns n flushed | |
| protected: | | protected: | |
| virtual void close() = 0; | | virtual void close() = 0; | |
| virtual void flush(bool sync) = 0; | | virtual void flush(bool sync) = 0; | |
| /** | | /** | |
| * returns a thread safe object that you can call flush on | | * returns a thread safe object that you can call flush on | |
| * Flushable has to fail nicely if the underlying object gets kille
d | | * Flushable has to fail nicely if the underlying object gets kille
d | |
| | | | |
| skipping to change at line 126 | | skipping to change at line 127 | |
| void created(); /* subclass must call after create */ | | void created(); /* subclass must call after create */ | |
| | | | |
| /* subclass must call in destructor (or at close). | | /* subclass must call in destructor (or at close). | |
| removes this from pathToFile and other maps | | removes this from pathToFile and other maps | |
| safe to call more than once, albeit might be wasted work | | safe to call more than once, albeit might be wasted work | |
| ideal to call close to the close, if the close is well before ob
ject destruction | | ideal to call close to the close, if the close is well before ob
ject destruction | |
| */ | | */ | |
| void destroyed(); | | void destroyed(); | |
| | | | |
| virtual unsigned long long length() const = 0; | | virtual unsigned long long length() const = 0; | |
|
| | | | |
| static set<MongoFile*> mmfiles; | | | |
| public: | | | |
| static map<string,MongoFile*> pathToFile; | | | |
| }; | | }; | |
| | | | |
| /** look up a MMF by filename. scoped mutex locking convention. | | /** look up a MMF by filename. scoped mutex locking convention. | |
| example: | | example: | |
| MMFFinderByName finder; | | MMFFinderByName finder; | |
| MongoMMF *a = finder.find("file_name_a"); | | MongoMMF *a = finder.find("file_name_a"); | |
| MongoMMF *b = finder.find("file_name_b"); | | MongoMMF *b = finder.find("file_name_b"); | |
| */ | | */ | |
| class MongoFileFinder : boost::noncopyable { | | class MongoFileFinder : boost::noncopyable { | |
| public: | | public: | |
|
| MongoFileFinder() { } | | | |
| | | | |
| /** @return The MongoFile object associated with the specified file
name. If no file is open | | /** @return The MongoFile object associated with the specified file
name. If no file is open | |
| with the specified name, returns null. | | with the specified name, returns null. | |
| */ | | */ | |
|
| MongoFile* findByPath(string path) { | | MongoFile* findByPath(const std::string& path) const; | |
| map<string,MongoFile*>::iterator i = MongoFile::pathToFile.find | | | |
| (path); | | | |
| return i == MongoFile::pathToFile.end() ? NULL : i->second; | | | |
| } | | | |
| | | | |
| private: | | private: | |
| LockMongoFilesShared _lk; | | LockMongoFilesShared _lk; | |
| }; | | }; | |
| | | | |
| class MemoryMappedFile : public MongoFile { | | class MemoryMappedFile : public MongoFile { | |
| protected: | | protected: | |
| virtual void* viewForFlushing() { | | virtual void* viewForFlushing() { | |
| if( views.size() == 0 ) | | if( views.size() == 0 ) | |
| return 0; | | return 0; | |
| | | | |
| skipping to change at line 188 | | skipping to change at line 180 | |
| | | | |
| /* Creates with length if DNE, otherwise uses existing file length, | | /* Creates with length if DNE, otherwise uses existing file length, | |
| passed length. | | passed length. | |
| @param options MongoFile::Options bits | | @param options MongoFile::Options bits | |
| */ | | */ | |
| void* map(const char *filename, unsigned long long &length, int opt
ions = 0 ); | | void* map(const char *filename, unsigned long long &length, int opt
ions = 0 ); | |
| | | | |
| /* Create. Must not exist. | | /* Create. Must not exist. | |
| @param zero fill file with zeros when true | | @param zero fill file with zeros when true | |
| */ | | */ | |
|
| void* create(string filename, unsigned long long len, bool zero); | | void* create(const std::string& filename, unsigned long long len, b
ool zero); | |
| | | | |
| void flush(bool sync); | | void flush(bool sync); | |
| virtual Flushable * prepareFlush(); | | virtual Flushable * prepareFlush(); | |
| | | | |
| long shortLength() const { return (long) len; } | | long shortLength() const { return (long) len; } | |
| unsigned long long length() const { return len; } | | unsigned long long length() const { return len; } | |
| HANDLE getFd() const { return fd; } | | HANDLE getFd() const { return fd; } | |
| /** create a new view with the specified properties. | | /** create a new view with the specified properties. | |
| automatically cleaned up upon close/destruction of the MemoryMa
ppedFile object. | | automatically cleaned up upon close/destruction of the MemoryMa
ppedFile object. | |
| */ | | */ | |
| | | | |
| skipping to change at line 240 | | skipping to change at line 232 | |
| /** close the current private view and open a new replacement */ | | /** close the current private view and open a new replacement */ | |
| void* remapPrivateView(void *oldPrivateAddr); | | void* remapPrivateView(void *oldPrivateAddr); | |
| }; | | }; | |
| | | | |
| typedef MemoryMappedFile MMF; | | typedef MemoryMappedFile MMF; | |
| | | | |
| /** p is called from within a mutex that MongoFile uses. so be careful
not to deadlock. */ | | /** p is called from within a mutex that MongoFile uses. so be careful
not to deadlock. */ | |
| template < class F > | | template < class F > | |
| inline void MongoFile::forEach( F p ) { | | inline void MongoFile::forEach( F p ) { | |
| LockMongoFilesShared lklk; | | LockMongoFilesShared lklk; | |
|
| for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.e | | const set<MongoFile*>& mmfiles = MongoFile::getAllFiles(); | |
| nd(); i++ ) | | for ( set<MongoFile*>::const_iterator i = mmfiles.begin(); i != mmf | |
| | | iles.end(); i++ ) | |
| p(*i); | | p(*i); | |
| } | | } | |
| | | | |
| #if defined(_WIN32) | | #if defined(_WIN32) | |
| class ourbitset { | | class ourbitset { | |
| volatile unsigned bits[MemoryMappedFile::NChunks]; // volatile as w
e are doing double check locking | | volatile unsigned bits[MemoryMappedFile::NChunks]; // volatile as w
e are doing double check locking | |
| public: | | public: | |
| ourbitset() { | | ourbitset() { | |
| memset((void*) bits, 0, sizeof(bits)); | | memset((void*) bits, 0, sizeof(bits)); | |
| } | | } | |
| | | | |
End of changes. 9 change blocks. |
| 17 lines changed or deleted | | 9 lines changed or added | |
|
| namespace_details.h | | namespace_details.h | |
| | | | |
| skipping to change at line 22 | | skipping to change at line 22 | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Affero General Public License for more details. | | * GNU Affero General Public License for more details. | |
| * | | * | |
| * You should have received a copy of the GNU Affero General Public Licen
se | | * You should have received a copy of the GNU Affero General Public Licen
se | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "mongo/pch.h" | | #include "mongo/pch.h" | |
|
| | | | |
| #include "mongo/db/d_concurrency.h" | | #include "mongo/db/d_concurrency.h" | |
| #include "mongo/db/diskloc.h" | | #include "mongo/db/diskloc.h" | |
| #include "mongo/db/index.h" | | #include "mongo/db/index.h" | |
| #include "mongo/db/jsobj.h" | | #include "mongo/db/jsobj.h" | |
| #include "mongo/db/mongommf.h" | | #include "mongo/db/mongommf.h" | |
| #include "mongo/db/namespace.h" | | #include "mongo/db/namespace.h" | |
|
| | | #include "mongo/db/namespacestring.h" | |
| #include "mongo/db/queryoptimizercursor.h" | | #include "mongo/db/queryoptimizercursor.h" | |
| #include "mongo/db/querypattern.h" | | #include "mongo/db/querypattern.h" | |
|
| | | #include "mongo/platform/unordered_map.h" | |
| #include "mongo/util/hashtab.h" | | #include "mongo/util/hashtab.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| class Database; | | class Database; | |
| | | | |
| /** @return true if a client can modify this namespace even though it i
s under ".system." | | /** @return true if a client can modify this namespace even though it i
s under ".system." | |
| For example <dbname>.system.users is ok for regular clients to upda
te. | | For example <dbname>.system.users is ok for regular clients to upda
te. | |
| @param write used when .system.js | | @param write used when .system.js | |
| */ | | */ | |
| bool legalClientSystemNS( const string& ns , bool write ); | | bool legalClientSystemNS( const string& ns , bool write ); | |
| | | | |
| skipping to change at line 421 | | skipping to change at line 422 | |
| these are things we know / compute about a namespace that are transi
ent -- things | | these are things we know / compute about a namespace that are transi
ent -- things | |
| we don't actually store in the .ns file. so mainly caching of frequ
ently used | | we don't actually store in the .ns file. so mainly caching of frequ
ently used | |
| information. | | information. | |
| | | | |
| CAUTION: Are you maintaining this properly on a collection drop()?
A dropdatabase()? Be careful. | | CAUTION: Are you maintaining this properly on a collection drop()?
A dropdatabase()? Be careful. | |
| The current field "allIndexKeys" may have too many keys in
it on such an occurrence; | | The current field "allIndexKeys" may have too many keys in
it on such an occurrence; | |
| as currently used that does not cause anything terrible to
happen. | | as currently used that does not cause anything terrible to
happen. | |
| | | | |
| todo: cleanup code, need abstractions and separation | | todo: cleanup code, need abstractions and separation | |
| */ | | */ | |
|
| // todo: multiple db's with the same name (repairDatbase) is not handle
d herein. that may be | | // todo: multiple db's with the same name (repairDatabase) is not handl
ed herein. that may be | |
| // the way to go, if not used by repair, but need some sort of en
forcement / asserts. | | // the way to go, if not used by repair, but need some sort of en
forcement / asserts. | |
| class NamespaceDetailsTransient : boost::noncopyable { | | class NamespaceDetailsTransient : boost::noncopyable { | |
| BOOST_STATIC_ASSERT( sizeof(NamespaceDetails) == 496 ); | | BOOST_STATIC_ASSERT( sizeof(NamespaceDetails) == 496 ); | |
| | | | |
| //Database *database; | | //Database *database; | |
| const string _ns; | | const string _ns; | |
| void reset(); | | void reset(); | |
|
| static std::map< string, shared_ptr< NamespaceDetailsTransient > >
_nsdMap; | | | |
| | | | |
|
| NamespaceDetailsTransient(Database*,const char *ns); | | // < db -> < fullns -> NDT > > | |
| | | typedef unordered_map< string, shared_ptr<NamespaceDetailsTransient | |
| | | > > CMap; | |
| | | typedef unordered_map< string, CMap*, NamespaceDBHash, NamespaceDBE | |
| | | quals > DMap; | |
| | | static DMap _nsdMap; | |
| | | | |
| | | NamespaceDetailsTransient(Database*,const string& ns); | |
| public: | | public: | |
| ~NamespaceDetailsTransient(); | | ~NamespaceDetailsTransient(); | |
| void addedIndex() { reset(); } | | void addedIndex() { reset(); } | |
| void deletedIndex() { reset(); } | | void deletedIndex() { reset(); } | |
|
| /* Drop cached information on all namespaces beginning with the spe | | | |
| cified prefix. | | /** | |
| Can be useful as index namespaces share the same start as the re | | * reset stats for a given collection | |
| gular collection. | | */ | |
| SLOW - sequential scan of all NamespaceDetailsTransient objects | | static void resetCollection(const string& ns ); | |
| */ | | | |
| static void clearForPrefix(const char *prefix); | | /** | |
| static void eraseForPrefix(const char *prefix); | | * remove entry for a collection | |
| | | */ | |
| | | static void eraseCollection(const string& ns); | |
| | | | |
| | | /** | |
| | | * remove all entries for db | |
| | | */ | |
| | | static void eraseDB(const string& db); | |
| | | | |
| /** | | /** | |
| * @return a cursor interface to the query optimizer. The implemen
tation may utilize a | | * @return a cursor interface to the query optimizer. The implemen
tation may utilize a | |
| * single query plan or interleave results from multiple query plan
s before settling on a | | * single query plan or interleave results from multiple query plan
s before settling on a | |
| * single query plan. Note that the schema of currKey() documents,
indexKeyPattern(), the | | * single query plan. Note that the schema of currKey() documents,
indexKeyPattern(), the | |
| * matcher(), and the isMultiKey() nature of the cursor may change
over the course of | | * matcher(), and the isMultiKey() nature of the cursor may change
over the course of | |
| * iteration. | | * iteration. | |
| * | | * | |
| * @param query - Query used to select indexes and populate matcher
s; not copied if unowned | | * @param query - Query used to select indexes and populate matcher
s; not copied if unowned | |
| * (see bsonobj.h). | | * (see bsonobj.h). | |
| | | | |
| skipping to change at line 538 | | skipping to change at line 553 | |
| verify( spec._finishedInit ); | | verify( spec._finishedInit ); | |
| } | | } | |
| } | | } | |
| return spec; | | return spec; | |
| } | | } | |
| | | | |
| /* query cache (for query optimizer) ------------------------------
------- */ | | /* query cache (for query optimizer) ------------------------------
------- */ | |
| private: | | private: | |
| int _qcWriteCount; | | int _qcWriteCount; | |
| map<QueryPattern,CachedQueryPlan> _qcCache; | | map<QueryPattern,CachedQueryPlan> _qcCache; | |
|
| static NamespaceDetailsTransient& make_inlock(const char *ns); | | static NamespaceDetailsTransient& make_inlock(const string& ns); | |
| | | static CMap& get_cmap_inlock(const string& ns); | |
| public: | | public: | |
| static SimpleMutex _qcMutex; | | static SimpleMutex _qcMutex; | |
| | | | |
| /* you must be in the qcMutex when calling this. | | /* you must be in the qcMutex when calling this. | |
| A NamespaceDetailsTransient object will not go out of scope on y
ou if you are | | A NamespaceDetailsTransient object will not go out of scope on y
ou if you are | |
| d.dbMutex.atLeastReadLocked(), so you do't have to stay locked. | | d.dbMutex.atLeastReadLocked(), so you do't have to stay locked. | |
| Creates a NamespaceDetailsTransient before returning if one DNE. | | Creates a NamespaceDetailsTransient before returning if one DNE. | |
| todo: avoid creating too many on erroneous ns queries. | | todo: avoid creating too many on erroneous ns queries. | |
| */ | | */ | |
|
| static NamespaceDetailsTransient& get_inlock(const char *ns); | | static NamespaceDetailsTransient& get_inlock(const string& ns); | |
| | | | |
| static NamespaceDetailsTransient& get(const char *ns) { | | static NamespaceDetailsTransient& get(const char *ns) { | |
| // todo : _qcMutex will create bottlenecks in our parallelism | | // todo : _qcMutex will create bottlenecks in our parallelism | |
| SimpleMutex::scoped_lock lk(_qcMutex); | | SimpleMutex::scoped_lock lk(_qcMutex); | |
| return get_inlock(ns); | | return get_inlock(ns); | |
| } | | } | |
| | | | |
| void clearQueryCache() { | | void clearQueryCache() { | |
| _qcCache.clear(); | | _qcCache.clear(); | |
| _qcWriteCount = 0; | | _qcWriteCount = 0; | |
| | | | |
| skipping to change at line 577 | | skipping to change at line 593 | |
| CachedQueryPlan cachedQueryPlanForPattern( const QueryPattern &patt
ern ) { | | CachedQueryPlan cachedQueryPlanForPattern( const QueryPattern &patt
ern ) { | |
| return _qcCache[ pattern ]; | | return _qcCache[ pattern ]; | |
| } | | } | |
| void registerCachedQueryPlanForPattern( const QueryPattern &pattern
, | | void registerCachedQueryPlanForPattern( const QueryPattern &pattern
, | |
| const CachedQueryPlan &cache
dQueryPlan ) { | | const CachedQueryPlan &cache
dQueryPlan ) { | |
| _qcCache[ pattern ] = cachedQueryPlan; | | _qcCache[ pattern ] = cachedQueryPlan; | |
| } | | } | |
| | | | |
| }; /* NamespaceDetailsTransient */ | | }; /* NamespaceDetailsTransient */ | |
| | | | |
|
| inline NamespaceDetailsTransient& NamespaceDetailsTransient::get_inlock | | inline NamespaceDetailsTransient& NamespaceDetailsTransient::get_inlock | |
| (const char *ns) { | | (const string& ns) { | |
| std::map< string, shared_ptr< NamespaceDetailsTransient > >::iterat | | CMap& m = get_cmap_inlock(ns); | |
| or i = _nsdMap.find(ns); | | CMap::iterator i = m.find( ns ); | |
| if( i != _nsdMap.end() && | | if ( i != m.end() && | |
| i->second.get() ) { // could be null ptr from clearForPrefix | | i->second.get() ) { // could be null ptr from clearForPrefix | |
| return *i->second; | | return *i->second; | |
| } | | } | |
| return make_inlock(ns); | | return make_inlock(ns); | |
| } | | } | |
| | | | |
| /* NamespaceIndex is the ".ns" file you see in the data directory. It
is the "system catalog" | | /* NamespaceIndex is the ".ns" file you see in the data directory. It
is the "system catalog" | |
| if you will: at least the core parts. (Additional info in system.*
collections.) | | if you will: at least the core parts. (Additional info in system.*
collections.) | |
| */ | | */ | |
| class NamespaceIndex { | | class NamespaceIndex { | |
| public: | | public: | |
| | | | |
End of changes. 10 change blocks. |
| 20 lines changed or deleted | | 35 lines changed or added | |
|
| oplog.h | | oplog.h | |
| | | | |
| skipping to change at line 63 | | skipping to change at line 63 | |
| void logKeepalive(); | | void logKeepalive(); | |
| | | | |
| /** puts obj in the oplog as a comment (a no-op). Just for diags. | | /** puts obj in the oplog as a comment (a no-op). Just for diags. | |
| convention is | | convention is | |
| { msg : "text", ... } | | { msg : "text", ... } | |
| */ | | */ | |
| void logOpComment(const BSONObj& obj); | | void logOpComment(const BSONObj& obj); | |
| | | | |
| void oplogCheckCloseDatabase( Database * db ); | | void oplogCheckCloseDatabase( Database * db ); | |
| | | | |
|
| extern int __findingStartInitialTimeout; // configurable for testing | | | |
| | | | |
| class QueryPlan; | | class QueryPlan; | |
| | | | |
| /** Implements an optimized procedure for finding the first op in the o
plog. */ | | /** Implements an optimized procedure for finding the first op in the o
plog. */ | |
| class FindingStartCursor { | | class FindingStartCursor { | |
| public: | | public: | |
| | | | |
| /** | | /** | |
| * The cursor will attempt to find the first op in the oplog matchi
ng the | | * The cursor will attempt to find the first op in the oplog matchi
ng the | |
| * 'ts' field of the qp's query. | | * 'ts' field of the qp's query. | |
| */ | | */ | |
| | | | |
| skipping to change at line 112 | | skipping to change at line 110 | |
| } | | } | |
| | | | |
| /** | | /** | |
| * @return a BasicCursor constructed using a FindingStartCursor wit
h the provided query and | | * @return a BasicCursor constructed using a FindingStartCursor wit
h the provided query and | |
| * order parameters. | | * order parameters. | |
| * @yields the db lock. | | * @yields the db lock. | |
| * @asserts on yield recovery failure. | | * @asserts on yield recovery failure. | |
| */ | | */ | |
| static shared_ptr<Cursor> getCursor( const char *ns, const BSONObj
&query, const BSONObj &order ); | | static shared_ptr<Cursor> getCursor( const char *ns, const BSONObj
&query, const BSONObj &order ); | |
| | | | |
|
| | | /** | |
| | | * @return the first record of the first nonempty extent preceding | |
| | | the extent containing | |
| | | * @param rec, or DiskLoc() if there is no such record or the b | |
| | | eginning of the | |
| | | * collection is reached. | |
| | | * public for testing | |
| | | */ | |
| | | DiskLoc prevExtentFirstLoc( const DiskLoc& rec ) const; | |
| | | | |
| | | /** For testing only. */ | |
| | | | |
| | | static int getInitialTimeout() { return _initialTimeout; } | |
| | | static void setInitialTimeout( int timeout ) { _initialTimeout = ti | |
| | | meout; } | |
| | | | |
| private: | | private: | |
| FindingStartCursor( const QueryPlan &qp ); | | FindingStartCursor( const QueryPlan &qp ); | |
| void init(); | | void init(); | |
| | | | |
| enum FindingStartMode { Initial, FindExtent, InExtent }; | | enum FindingStartMode { Initial, FindExtent, InExtent }; | |
| const QueryPlan &_qp; | | const QueryPlan &_qp; | |
| bool _findingStart; | | bool _findingStart; | |
| FindingStartMode _findingStartMode; | | FindingStartMode _findingStartMode; | |
| auto_ptr< CoveredIndexMatcher > _matcher; | | auto_ptr< CoveredIndexMatcher > _matcher; | |
| Timer _findingStartTimer; | | Timer _findingStartTimer; | |
| ClientCursor::Holder _findingStartCursor; | | ClientCursor::Holder _findingStartCursor; | |
| shared_ptr<Cursor> _c; | | shared_ptr<Cursor> _c; | |
| ClientCursor::YieldData _yieldData; | | ClientCursor::YieldData _yieldData; | |
|
| | | static int _initialTimeout; | |
| | | | |
| | | /** @return the first record of the extent containing @param rec. * | |
| | | / | |
| DiskLoc extentFirstLoc( const DiskLoc &rec ); | | DiskLoc extentFirstLoc( const DiskLoc &rec ); | |
| | | | |
|
| DiskLoc prevExtentFirstLoc( const DiskLoc &rec ); | | | |
| void createClientCursor( const DiskLoc &startLoc = DiskLoc() ); | | void createClientCursor( const DiskLoc &startLoc = DiskLoc() ); | |
| void destroyClientCursor() { | | void destroyClientCursor() { | |
| _findingStartCursor.reset( 0 ); | | _findingStartCursor.reset( 0 ); | |
| } | | } | |
| bool firstDocMatchesOrEmpty() const; | | bool firstDocMatchesOrEmpty() const; | |
| }; | | }; | |
| | | | |
| class Sync { | | class Sync { | |
| protected: | | protected: | |
| string hn; | | string hn; | |
| | | | |
End of changes. 4 change blocks. |
| 3 lines changed or deleted | | 20 lines changed or added | |
|
| pdfile.h | | pdfile.h | |
| | | | |
| skipping to change at line 51 | | skipping to change at line 51 | |
| // pdfile versions | | // pdfile versions | |
| const int PDFILE_VERSION = 4; | | const int PDFILE_VERSION = 4; | |
| const int PDFILE_VERSION_MINOR = 5; | | const int PDFILE_VERSION_MINOR = 5; | |
| | | | |
| class DataFileHeader; | | class DataFileHeader; | |
| class Extent; | | class Extent; | |
| class Record; | | class Record; | |
| class Cursor; | | class Cursor; | |
| class OpDebug; | | class OpDebug; | |
| | | | |
|
| void dropDatabase(string db); | | void dropDatabase(const std::string& db); | |
| bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles
OnFailure = false, bool backupOriginalFiles = false); | | bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles
OnFailure = false, bool backupOriginalFiles = false); | |
| | | | |
| /* low level - only drops this ns */ | | /* low level - only drops this ns */ | |
| void dropNS(const string& dropNs); | | void dropNS(const string& dropNs); | |
| | | | |
| /* deletes this ns, indexes and cursors */ | | /* deletes this ns, indexes and cursors */ | |
| void dropCollection( const string &name, string &errmsg, BSONObjBuilder
&result ); | | void dropCollection( const string &name, string &errmsg, BSONObjBuilder
&result ); | |
| bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForRe
plication, bool *deferIdIndex = 0); | | bool userCreateNS(const char *ns, BSONObj j, string& err, bool logForRe
plication, bool *deferIdIndex = 0); | |
| shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order,
const DiskLoc &startLoc=DiskLoc()); | | shared_ptr<Cursor> findTableScan(const char *ns, const BSONObj& order,
const DiskLoc &startLoc=DiskLoc()); | |
| | | | |
| | | | |
| skipping to change at line 159 | | skipping to change at line 159 | |
| no _id field check | | no _id field check | |
| */ | | */ | |
| Record* fast_oplog_insert(NamespaceDetails *d, const char *ns, int
len); | | Record* fast_oplog_insert(NamespaceDetails *d, const char *ns, int
len); | |
| | | | |
| static Extent* getExtent(const DiskLoc& dl); | | static Extent* getExtent(const DiskLoc& dl); | |
| static Record* getRecord(const DiskLoc& dl); | | static Record* getRecord(const DiskLoc& dl); | |
| static DeletedRecord* makeDeletedRecord(const DiskLoc& dl, int len)
; | | static DeletedRecord* makeDeletedRecord(const DiskLoc& dl, int len)
; | |
| | | | |
| void deleteRecord(const char *ns, Record *todelete, const DiskLoc&
dl, bool cappedOK = false, bool noWarn = false, bool logOp=false); | | void deleteRecord(const char *ns, Record *todelete, const DiskLoc&
dl, bool cappedOK = false, bool noWarn = false, bool logOp=false); | |
| | | | |
|
| | | void deleteRecord(NamespaceDetails* d, const char *ns, Record *tode | |
| | | lete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false, bool l | |
| | | ogOp=false); | |
| | | | |
| /* does not clean up indexes, etc. : just deletes the record in the
pdfile. use deleteRecord() to unindex */ | | /* does not clean up indexes, etc. : just deletes the record in the
pdfile. use deleteRecord() to unindex */ | |
| void _deleteRecord(NamespaceDetails *d, const char *ns, Record *tod
elete, const DiskLoc& dl); | | void _deleteRecord(NamespaceDetails *d, const char *ns, Record *tod
elete, const DiskLoc& dl); | |
| | | | |
| private: | | private: | |
| vector<MongoDataFile *> files; | | vector<MongoDataFile *> files; | |
| }; | | }; | |
| | | | |
| extern DataFileMgr theDataFileMgr; | | extern DataFileMgr theDataFileMgr; | |
| | | | |
| #pragma pack(1) | | #pragma pack(1) | |
| | | | |
| skipping to change at line 287 | | skipping to change at line 289 | |
| static bool likelyInPhysicalMemory( const char* data ); | | static bool likelyInPhysicalMemory( const char* data ); | |
| | | | |
| static bool blockCheckSupported(); | | static bool blockCheckSupported(); | |
| | | | |
| /** | | /** | |
| * this adds stats about page fault exceptions currently | | * this adds stats about page fault exceptions currently | |
| * specically how many times we call _accessing where the record is
not in memory | | * specically how many times we call _accessing where the record is
not in memory | |
| * and how many times we throw a PageFaultException | | * and how many times we throw a PageFaultException | |
| */ | | */ | |
| static void appendStats( BSONObjBuilder& b ); | | static void appendStats( BSONObjBuilder& b ); | |
|
| | | | |
| | | static void appendWorkingSetInfo( BSONObjBuilder& b ); | |
| private: | | private: | |
| | | | |
| int _netLength() const { return _lengthWithHeaders - HeaderSize; } | | int _netLength() const { return _lengthWithHeaders - HeaderSize; } | |
| | | | |
| /** | | /** | |
| * call this when accessing a field which could hit disk | | * call this when accessing a field which could hit disk | |
| */ | | */ | |
| void _accessing() const; | | void _accessing() const; | |
| | | | |
| int _lengthWithHeaders; | | int _lengthWithHeaders; | |
| | | | |
End of changes. 3 change blocks. |
| 1 lines changed or deleted | | 7 lines changed or added | |
|
| query.h | | query.h | |
| | | | |
| skipping to change at line 50 | | skipping to change at line 50 | |
| | | | |
| /** Exception indicating that a query should be retried from the beginn
ing. */ | | /** Exception indicating that a query should be retried from the beginn
ing. */ | |
| class QueryRetryException : public DBException { | | class QueryRetryException : public DBException { | |
| public: | | public: | |
| QueryRetryException() : DBException( "query retry exception" , 1608
3 ) { | | QueryRetryException() : DBException( "query retry exception" , 1608
3 ) { | |
| return; | | return; | |
| massert( 16083, "reserve 16083", true ); // Reserve 16083. | | massert( 16083, "reserve 16083", true ); // Reserve 16083. | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | /** Metadata about matching and loading a single candidate result docum | |
| | | ent from a Cursor. */ | |
| | | struct ResultDetails { | |
| | | ResultDetails(); | |
| | | MatchDetails matchDetails; // Details on how the Matcher matched th | |
| | | e query. | |
| | | bool match; // Matched the query, was not a dup, was | |
| | | not skipped etc. | |
| | | bool orderedMatch; // _match and belonged to an ordered que | |
| | | ry plan. | |
| | | bool loadedRecord; // Record was loaded (to match or return | |
| | | the document). | |
| | | bool chunkSkip; // Did not belong to an owned chunk rang | |
| | | e. | |
| | | }; | |
| | | | |
| /** Interface for recording events that contribute to explain results.
*/ | | /** Interface for recording events that contribute to explain results.
*/ | |
| class ExplainRecordingStrategy { | | class ExplainRecordingStrategy { | |
| public: | | public: | |
| ExplainRecordingStrategy( const ExplainQueryInfo::AncillaryInfo &an
cillaryInfo ); | | ExplainRecordingStrategy( const ExplainQueryInfo::AncillaryInfo &an
cillaryInfo ); | |
| virtual ~ExplainRecordingStrategy() {} | | virtual ~ExplainRecordingStrategy() {} | |
| /** Note information about a single query plan. */ | | /** Note information about a single query plan. */ | |
| virtual void notePlan( bool scanAndOrder, bool indexOnly ) {} | | virtual void notePlan( bool scanAndOrder, bool indexOnly ) {} | |
| /** Note an iteration of the query. */ | | /** Note an iteration of the query. */ | |
|
| virtual void noteIterate( bool match, bool orderedMatch, bool loade | | virtual void noteIterate( const ResultDetails& resultDetails ) {} | |
| dRecord, | | | |
| bool chunkSkip ) {} | | | |
| /** Note that the query yielded. */ | | /** Note that the query yielded. */ | |
| virtual void noteYield() {} | | virtual void noteYield() {} | |
| /** @return number of ordered matches noted. */ | | /** @return number of ordered matches noted. */ | |
| virtual long long orderedMatches() const { return 0; } | | virtual long long orderedMatches() const { return 0; } | |
| /** @return ExplainQueryInfo for a complete query. */ | | /** @return ExplainQueryInfo for a complete query. */ | |
| shared_ptr<ExplainQueryInfo> doneQueryInfo(); | | shared_ptr<ExplainQueryInfo> doneQueryInfo(); | |
| protected: | | protected: | |
| /** @return ExplainQueryInfo for a complete query, to be implemente
d by subclass. */ | | /** @return ExplainQueryInfo for a complete query, to be implemente
d by subclass. */ | |
| virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo() = 0; | | virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo() = 0; | |
| private: | | private: | |
| | | | |
| skipping to change at line 86 | | skipping to change at line 95 | |
| NoExplainStrategy(); | | NoExplainStrategy(); | |
| private: | | private: | |
| /** @asserts always. */ | | /** @asserts always. */ | |
| virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo(); | | virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo(); | |
| }; | | }; | |
| | | | |
| class MatchCountingExplainStrategy : public ExplainRecordingStrategy { | | class MatchCountingExplainStrategy : public ExplainRecordingStrategy { | |
| public: | | public: | |
| MatchCountingExplainStrategy( const ExplainQueryInfo::AncillaryInfo
&ancillaryInfo ); | | MatchCountingExplainStrategy( const ExplainQueryInfo::AncillaryInfo
&ancillaryInfo ); | |
| protected: | | protected: | |
|
| virtual void _noteIterate( bool match, bool orderedMatch, bool load | | virtual void _noteIterate( const ResultDetails& resultDetails ) = 0 | |
| edRecord, | | ; | |
| bool chunkSkip ) = 0; | | | |
| private: | | private: | |
|
| virtual void noteIterate( bool match, bool orderedMatch, bool loade | | virtual void noteIterate( const ResultDetails& resultDetails ); | |
| dRecord, | | | |
| bool chunkSkip ); | | | |
| virtual long long orderedMatches() const { return _orderedMatches;
} | | virtual long long orderedMatches() const { return _orderedMatches;
} | |
| long long _orderedMatches; | | long long _orderedMatches; | |
| }; | | }; | |
| | | | |
| /** Record explain events for a simple cursor representing a single cla
use and plan. */ | | /** Record explain events for a simple cursor representing a single cla
use and plan. */ | |
| class SimpleCursorExplainStrategy : public MatchCountingExplainStrategy
{ | | class SimpleCursorExplainStrategy : public MatchCountingExplainStrategy
{ | |
| public: | | public: | |
| SimpleCursorExplainStrategy( const ExplainQueryInfo::AncillaryInfo
&ancillaryInfo, | | SimpleCursorExplainStrategy( const ExplainQueryInfo::AncillaryInfo
&ancillaryInfo, | |
| const shared_ptr<Cursor> &cursor ); | | const shared_ptr<Cursor> &cursor ); | |
| private: | | private: | |
| virtual void notePlan( bool scanAndOrder, bool indexOnly ); | | virtual void notePlan( bool scanAndOrder, bool indexOnly ); | |
|
| virtual void _noteIterate( bool match, bool orderedMatch, bool load | | virtual void _noteIterate( const ResultDetails& resultDetails ); | |
| edRecord, | | | |
| bool chunkSkip ); | | | |
| virtual void noteYield(); | | virtual void noteYield(); | |
| virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo(); | | virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo(); | |
| shared_ptr<Cursor> _cursor; | | shared_ptr<Cursor> _cursor; | |
| shared_ptr<ExplainSinglePlanQueryInfo> _explainInfo; | | shared_ptr<ExplainSinglePlanQueryInfo> _explainInfo; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Record explain events for a QueryOptimizerCursor, which may record s
ome explain information | | * Record explain events for a QueryOptimizerCursor, which may record s
ome explain information | |
| * for multiple clauses and plans through an internal implementation. | | * for multiple clauses and plans through an internal implementation. | |
| */ | | */ | |
| class QueryOptimizerCursorExplainStrategy : public MatchCountingExplain
Strategy { | | class QueryOptimizerCursorExplainStrategy : public MatchCountingExplain
Strategy { | |
| public: | | public: | |
| QueryOptimizerCursorExplainStrategy( const ExplainQueryInfo::Ancill
aryInfo &ancillaryInfo, | | QueryOptimizerCursorExplainStrategy( const ExplainQueryInfo::Ancill
aryInfo &ancillaryInfo, | |
| const shared_ptr<QueryOptimizer
Cursor> &cursor ); | | const shared_ptr<QueryOptimizer
Cursor> &cursor ); | |
| private: | | private: | |
|
| virtual void _noteIterate( bool match, bool orderedMatch, bool load | | virtual void _noteIterate( const ResultDetails& resultDetails ); | |
| edRecord, | | | |
| bool chunkSkip ); | | | |
| virtual void noteYield(); | | virtual void noteYield(); | |
| virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo(); | | virtual shared_ptr<ExplainQueryInfo> _doneQueryInfo(); | |
| shared_ptr<QueryOptimizerCursor> _cursor; | | shared_ptr<QueryOptimizerCursor> _cursor; | |
| }; | | }; | |
| | | | |
| /** Interface for building a query response in a supplied BufBuilder. *
/ | | /** Interface for building a query response in a supplied BufBuilder. *
/ | |
| class ResponseBuildStrategy { | | class ResponseBuildStrategy { | |
| public: | | public: | |
| /** | | /** | |
| * @param queryPlan must be supplied if @param cursor is not a Quer
yOptimizerCursor and | | * @param queryPlan must be supplied if @param cursor is not a Quer
yOptimizerCursor and | |
| * results must be sorted or read with a covered index. | | * results must be sorted or read with a covered index. | |
| */ | | */ | |
| ResponseBuildStrategy( const ParsedQuery &parsedQuery, const shared
_ptr<Cursor> &cursor, | | ResponseBuildStrategy( const ParsedQuery &parsedQuery, const shared
_ptr<Cursor> &cursor, | |
| BufBuilder &buf ); | | BufBuilder &buf ); | |
| virtual ~ResponseBuildStrategy() {} | | virtual ~ResponseBuildStrategy() {} | |
| /** | | /** | |
| * Handle the current iterate of the supplied cursor as a (possibly
duplicate) match. | | * Handle the current iterate of the supplied cursor as a (possibly
duplicate) match. | |
| * @return true if a match is found. | | * @return true if a match is found. | |
|
| * @param orderedMatch set if it is an ordered match. | | * @param resultDetails details of how the result is matched and lo
aded. | |
| */ | | */ | |
|
| virtual bool handleMatch( bool& orderedMatch, MatchDetails& details
) = 0; | | virtual bool handleMatch( ResultDetails* resultDetails ) = 0; | |
| | | | |
| /** | | /** | |
| * Write all matches into the buffer, overwriting existing data. | | * Write all matches into the buffer, overwriting existing data. | |
| * @return number of matches written, or -1 if no op. | | * @return number of matches written, or -1 if no op. | |
| */ | | */ | |
| virtual int rewriteMatches() { return -1; } | | virtual int rewriteMatches() { return -1; } | |
| /** @return the number of matches that have been written to the buf
fer. */ | | /** @return the number of matches that have been written to the buf
fer. */ | |
| virtual int bufferedMatches() const = 0; | | virtual int bufferedMatches() const = 0; | |
| /** | | /** | |
| * Callback when enough results have been read for the first batch,
with potential handoff | | * Callback when enough results have been read for the first batch,
with potential handoff | |
| * to getMore. | | * to getMore. | |
| */ | | */ | |
| virtual void finishedFirstBatch() {} | | virtual void finishedFirstBatch() {} | |
| /** Reset the buffer. */ | | /** Reset the buffer. */ | |
| void resetBuf(); | | void resetBuf(); | |
| protected: | | protected: | |
| /** | | /** | |
| * Return the document for the current iterate. Implements the $re
turnKey option. | | * Return the document for the current iterate. Implements the $re
turnKey option. | |
|
| * @param allowCovered - enable covered index support. | | * @param allowCovered enable covered index support. | |
| | | * @param resultDetails details of how the result is loaded. | |
| */ | | */ | |
|
| BSONObj current( bool allowCovered ) const; | | BSONObj current( bool allowCovered, ResultDetails* resultDetails )
const; | |
| const ParsedQuery &_parsedQuery; | | const ParsedQuery &_parsedQuery; | |
| shared_ptr<Cursor> _cursor; | | shared_ptr<Cursor> _cursor; | |
| shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor; | | shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor; | |
| BufBuilder &_buf; | | BufBuilder &_buf; | |
| }; | | }; | |
| | | | |
| /** Build strategy for a cursor returning in order results. */ | | /** Build strategy for a cursor returning in order results. */ | |
| class OrderedBuildStrategy : public ResponseBuildStrategy { | | class OrderedBuildStrategy : public ResponseBuildStrategy { | |
| public: | | public: | |
| OrderedBuildStrategy( const ParsedQuery &parsedQuery, const shared_
ptr<Cursor> &cursor, | | OrderedBuildStrategy( const ParsedQuery &parsedQuery, const shared_
ptr<Cursor> &cursor, | |
| BufBuilder &buf ); | | BufBuilder &buf ); | |
|
| virtual bool handleMatch( bool& orderedMatch, MatchDetails& details
); | | virtual bool handleMatch( ResultDetails* resultDetails ); | |
| virtual int bufferedMatches() const { return _bufferedMatches; } | | virtual int bufferedMatches() const { return _bufferedMatches; } | |
| private: | | private: | |
| int _skip; | | int _skip; | |
| int _bufferedMatches; | | int _bufferedMatches; | |
| }; | | }; | |
| | | | |
| class ScanAndOrder; | | class ScanAndOrder; | |
| | | | |
| /** Build strategy for a cursor returning out of order results. */ | | /** Build strategy for a cursor returning out of order results. */ | |
| class ReorderBuildStrategy : public ResponseBuildStrategy { | | class ReorderBuildStrategy : public ResponseBuildStrategy { | |
| public: | | public: | |
| static ReorderBuildStrategy* make( const ParsedQuery& parsedQuery, | | static ReorderBuildStrategy* make( const ParsedQuery& parsedQuery, | |
| const shared_ptr<Cursor>& cursor
, | | const shared_ptr<Cursor>& cursor
, | |
| BufBuilder& buf, | | BufBuilder& buf, | |
| const QueryPlanSummary& queryPla
n ); | | const QueryPlanSummary& queryPla
n ); | |
|
| virtual bool handleMatch( bool &orderedMatch, MatchDetails& details
); | | virtual bool handleMatch( ResultDetails* resultDetails ); | |
| /** Handle a match without performing deduping. */ | | /** Handle a match without performing deduping. */ | |
|
| void _handleMatchNoDedup(); | | void _handleMatchNoDedup( ResultDetails* resultDetails ); | |
| virtual int rewriteMatches(); | | virtual int rewriteMatches(); | |
| virtual int bufferedMatches() const { return _bufferedMatches; } | | virtual int bufferedMatches() const { return _bufferedMatches; } | |
| private: | | private: | |
| ReorderBuildStrategy( const ParsedQuery& parsedQuery, | | ReorderBuildStrategy( const ParsedQuery& parsedQuery, | |
| const shared_ptr<Cursor>& cursor, | | const shared_ptr<Cursor>& cursor, | |
| BufBuilder& buf ); | | BufBuilder& buf ); | |
| void init( const QueryPlanSummary& queryPlan ); | | void init( const QueryPlanSummary& queryPlan ); | |
| ScanAndOrder *newScanAndOrder( const QueryPlanSummary &queryPlan )
const; | | ScanAndOrder *newScanAndOrder( const QueryPlanSummary &queryPlan )
const; | |
| shared_ptr<ScanAndOrder> _scanAndOrder; | | shared_ptr<ScanAndOrder> _scanAndOrder; | |
| int _bufferedMatches; | | int _bufferedMatches; | |
| | | | |
| skipping to change at line 231 | | skipping to change at line 237 | |
| class HybridBuildStrategy : public ResponseBuildStrategy { | | class HybridBuildStrategy : public ResponseBuildStrategy { | |
| public: | | public: | |
| static HybridBuildStrategy* make( const ParsedQuery& parsedQuery, | | static HybridBuildStrategy* make( const ParsedQuery& parsedQuery, | |
| const shared_ptr<QueryOptimizerCu
rsor>& cursor, | | const shared_ptr<QueryOptimizerCu
rsor>& cursor, | |
| BufBuilder& buf ); | | BufBuilder& buf ); | |
| private: | | private: | |
| HybridBuildStrategy( const ParsedQuery &parsedQuery, | | HybridBuildStrategy( const ParsedQuery &parsedQuery, | |
| const shared_ptr<QueryOptimizerCursor> &cursor, | | const shared_ptr<QueryOptimizerCursor> &cursor, | |
| BufBuilder &buf ); | | BufBuilder &buf ); | |
| void init(); | | void init(); | |
|
| virtual bool handleMatch( bool &orderedMatch, MatchDetails &details
); | | virtual bool handleMatch( ResultDetails* resultDetails ); | |
| virtual int rewriteMatches(); | | virtual int rewriteMatches(); | |
| virtual int bufferedMatches() const; | | virtual int bufferedMatches() const; | |
| virtual void finishedFirstBatch(); | | virtual void finishedFirstBatch(); | |
|
| bool handleReorderMatch(); | | bool handleReorderMatch( ResultDetails* resultDetails ); | |
| DiskLocDupSet _scanAndOrderDups; | | DiskLocDupSet _scanAndOrderDups; | |
| OrderedBuildStrategy _orderedBuild; | | OrderedBuildStrategy _orderedBuild; | |
| scoped_ptr<ReorderBuildStrategy> _reorderBuild; | | scoped_ptr<ReorderBuildStrategy> _reorderBuild; | |
| bool _reorderedMatches; | | bool _reorderedMatches; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Builds a query response with the help of an ExplainRecordingStrategy
and a | | * Builds a query response with the help of an ExplainRecordingStrategy
and a | |
| * ResponseBuildStrategy. | | * ResponseBuildStrategy. | |
| */ | | */ | |
| | | | |
| skipping to change at line 286 | | skipping to change at line 292 | |
| | | | |
| private: | | private: | |
| QueryResponseBuilder( const ParsedQuery &parsedQuery, const shared_
ptr<Cursor> &cursor ); | | QueryResponseBuilder( const ParsedQuery &parsedQuery, const shared_
ptr<Cursor> &cursor ); | |
| void init( const QueryPlanSummary &queryPlan, const BSONObj &oldPla
n ); | | void init( const QueryPlanSummary &queryPlan, const BSONObj &oldPla
n ); | |
| | | | |
| ShardChunkManagerPtr newChunkManager() const; | | ShardChunkManagerPtr newChunkManager() const; | |
| shared_ptr<ExplainRecordingStrategy> newExplainRecordingStrategy | | shared_ptr<ExplainRecordingStrategy> newExplainRecordingStrategy | |
| ( const QueryPlanSummary &queryPlan, const BSONObj &oldPlan ) const
; | | ( const QueryPlanSummary &queryPlan, const BSONObj &oldPlan ) const
; | |
| shared_ptr<ResponseBuildStrategy> newResponseBuildStrategy | | shared_ptr<ResponseBuildStrategy> newResponseBuildStrategy | |
| ( const QueryPlanSummary &queryPlan ); | | ( const QueryPlanSummary &queryPlan ); | |
|
| bool currentMatches( MatchDetails& details ); | | /** | |
| bool chunkMatches(); | | * @return true if the cursor's document matches the query. | |
| | | * @param resultDetails describes how the document was matched and | |
| | | loaded. | |
| | | */ | |
| | | bool currentMatches( ResultDetails* resultDetails ); | |
| | | /** | |
| | | * @return true if the cursor's document is in a valid chunk range. | |
| | | * @param resultDetails describes how the document was matched and | |
| | | loaded. | |
| | | */ | |
| | | bool chunkMatches( ResultDetails* resultDetails ); | |
| const ParsedQuery &_parsedQuery; | | const ParsedQuery &_parsedQuery; | |
| shared_ptr<Cursor> _cursor; | | shared_ptr<Cursor> _cursor; | |
| shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor; | | shared_ptr<QueryOptimizerCursor> _queryOptimizerCursor; | |
| BufBuilder _buf; | | BufBuilder _buf; | |
| ShardChunkManagerPtr _chunkManager; | | ShardChunkManagerPtr _chunkManager; | |
| shared_ptr<ExplainRecordingStrategy> _explain; | | shared_ptr<ExplainRecordingStrategy> _explain; | |
| shared_ptr<ResponseBuildStrategy> _builder; | | shared_ptr<ResponseBuildStrategy> _builder; | |
| }; | | }; | |
| | | | |
| } // namespace mongo | | } // namespace mongo | |
| | | | |
End of changes. 16 change blocks. |
| 26 lines changed or deleted | | 44 lines changed or added | |
|
| queryoptimizer.h | | queryoptimizer.h | |
| | | | |
| skipping to change at line 54 | | skipping to change at line 54 | |
| static QueryPlan *make( NamespaceDetails *d, | | static QueryPlan *make( NamespaceDetails *d, | |
| int idxNo, // -1 = no index | | int idxNo, // -1 = no index | |
| const FieldRangeSetPair &frsp, | | const FieldRangeSetPair &frsp, | |
| const FieldRangeSetPair *originalFrsp, | | const FieldRangeSetPair *originalFrsp, | |
| const BSONObj &originalQuery, | | const BSONObj &originalQuery, | |
| const BSONObj &order, | | const BSONObj &order, | |
| const shared_ptr<const ParsedQuery> &parsedQ
uery = | | const shared_ptr<const ParsedQuery> &parsedQ
uery = | |
| shared_ptr<const ParsedQuery>(), | | shared_ptr<const ParsedQuery>(), | |
| const BSONObj &startKey = BSONObj(), | | const BSONObj &startKey = BSONObj(), | |
| const BSONObj &endKey = BSONObj(), | | const BSONObj &endKey = BSONObj(), | |
|
| string special="" ); | | const std::string& special="" ); | |
| | | | |
| /** Categorical classification of a QueryPlan's utility. */ | | /** Categorical classification of a QueryPlan's utility. */ | |
| enum Utility { | | enum Utility { | |
| Impossible, // Cannot produce any matches, so the query must ha
ve an empty result set. | | Impossible, // Cannot produce any matches, so the query must ha
ve an empty result set. | |
| // No other plans need to be considered. | | // No other plans need to be considered. | |
| Optimal, // Should run as the only candidate plan in the abs
ence of an Impossible | | Optimal, // Should run as the only candidate plan in the abs
ence of an Impossible | |
| // plan. | | // plan. | |
| Helpful, // Should be considered. | | Helpful, // Should be considered. | |
| Unhelpful, // Should not be considered. | | Unhelpful, // Should not be considered. | |
| Disallowed // Must not be considered unless explicitly hinted.
May produce a | | Disallowed // Must not be considered unless explicitly hinted.
May produce a | |
| | | | |
| skipping to change at line 102 | | skipping to change at line 102 | |
| const IndexDetails *index() const { return _index; } | | const IndexDetails *index() const { return _index; } | |
| int idxNo() const { return _idxNo; } | | int idxNo() const { return _idxNo; } | |
| const char *ns() const { return _frs.ns(); } | | const char *ns() const { return _frs.ns(); } | |
| NamespaceDetails *nsd() const { return _d; } | | NamespaceDetails *nsd() const { return _d; } | |
| BSONObj originalQuery() const { return _originalQuery; } | | BSONObj originalQuery() const { return _originalQuery; } | |
| shared_ptr<FieldRangeVector> originalFrv() const { return _original
Frv; } | | shared_ptr<FieldRangeVector> originalFrv() const { return _original
Frv; } | |
| | | | |
| const FieldRangeSet &multikeyFrs() const { return _frsMulti; } | | const FieldRangeSet &multikeyFrs() const { return _frsMulti; } | |
| | | | |
| shared_ptr<Projection::KeyOnly> keyFieldsOnly() const { return _key
FieldsOnly; } | | shared_ptr<Projection::KeyOnly> keyFieldsOnly() const { return _key
FieldsOnly; } | |
|
| | | const ParsedQuery* parsedQuery() const { return _parsedQuery.get();
} | |
| | | | |
| /** @return a shared, lazily initialized matcher for the query plan
. */ | | /** @return a shared, lazily initialized matcher for the query plan
. */ | |
| shared_ptr<CoveredIndexMatcher> matcher() const; | | shared_ptr<CoveredIndexMatcher> matcher() const; | |
| | | | |
| QueryPlanSummary summary() const; | | QueryPlanSummary summary() const; | |
| | | | |
| /** The following member functions are for testing, or public for t
esting. */ | | /** The following member functions are for testing, or public for t
esting. */ | |
| | | | |
| shared_ptr<FieldRangeVector> frv() const { return _frv; } | | shared_ptr<FieldRangeVector> frv() const { return _frv; } | |
| bool isMultiKey() const; | | bool isMultiKey() const; | |
| | | | |
| skipping to change at line 123 | | skipping to change at line 124 | |
| bool queryBoundsExactOrderSuffix() const; | | bool queryBoundsExactOrderSuffix() const; | |
| | | | |
| private: | | private: | |
| | | | |
| QueryPlan(NamespaceDetails *d, | | QueryPlan(NamespaceDetails *d, | |
| int idxNo, | | int idxNo, | |
| const FieldRangeSetPair &frsp, | | const FieldRangeSetPair &frsp, | |
| const BSONObj &originalQuery, | | const BSONObj &originalQuery, | |
| const BSONObj &order, | | const BSONObj &order, | |
| const shared_ptr<const ParsedQuery> &parsedQuery, | | const shared_ptr<const ParsedQuery> &parsedQuery, | |
|
| string special ); | | const std::string& special ); | |
| void init( const FieldRangeSetPair *originalFrsp, | | void init( const FieldRangeSetPair *originalFrsp, | |
| const BSONObj &startKey, | | const BSONObj &startKey, | |
| const BSONObj &endKey ); | | const BSONObj &endKey ); | |
| | | | |
| void checkTableScanAllowed() const; | | void checkTableScanAllowed() const; | |
| int independentRangesSingleIntervalLimit() const; | | int independentRangesSingleIntervalLimit() const; | |
| /** @return true when the plan's query may contains an $exists:fals
e predicate. */ | | /** @return true when the plan's query may contains an $exists:fals
e predicate. */ | |
| bool hasPossibleExistsFalsePredicate() const; | | bool hasPossibleExistsFalsePredicate() const; | |
| | | | |
| NamespaceDetails * _d; | | NamespaceDetails * _d; | |
| | | | |
| skipping to change at line 678 | | skipping to change at line 679 | |
| virtual bool supportYields() { return true; } | | virtual bool supportYields() { return true; } | |
| virtual BSONObj indexKeyPattern() { return _c->indexKeyPattern(); } | | virtual BSONObj indexKeyPattern() { return _c->indexKeyPattern(); } | |
| | | | |
| /** Deduping documents from a prior cursor is handled by the matche
r. */ | | /** Deduping documents from a prior cursor is handled by the matche
r. */ | |
| virtual bool getsetdup(DiskLoc loc) { return _c->getsetdup( loc );
} | | virtual bool getsetdup(DiskLoc loc) { return _c->getsetdup( loc );
} | |
| | | | |
| virtual bool modifiedKeys() const { return true; } | | virtual bool modifiedKeys() const { return true; } | |
| | | | |
| virtual bool isMultiKey() const { return _mps->hasMultiKey(); } | | virtual bool isMultiKey() const { return _mps->hasMultiKey(); } | |
| | | | |
|
| virtual shared_ptr< CoveredIndexMatcher > matcherPtr() const { retu
rn _matcher; } | | | |
| virtual CoveredIndexMatcher* matcher() const { return _matcher.get(
); } | | virtual CoveredIndexMatcher* matcher() const { return _matcher.get(
); } | |
| | | | |
| virtual bool capped() const { return _c->capped(); } | | virtual bool capped() const { return _c->capped(); } | |
| | | | |
| virtual long long nscanned() { return _nscanned + _c->nscanned(); } | | virtual long long nscanned() { return _nscanned + _c->nscanned(); } | |
| | | | |
| void noteIterate( bool match, bool loadedRecord ); | | void noteIterate( bool match, bool loadedRecord ); | |
| | | | |
| const QueryPlan &queryPlan() const { | | const QueryPlan &queryPlan() const { | |
| verify( _c->ok() && _queryPlan ); | | verify( _c->ok() && _queryPlan ); | |
| | | | |
End of changes. 4 change blocks. |
| 3 lines changed or deleted | | 3 lines changed or added | |
|
| queryutil.h | | queryutil.h | |
| | | | |
| skipping to change at line 28 | | skipping to change at line 28 | |
| #pragma once | | #pragma once | |
| | | | |
| #include "jsobj.h" | | #include "jsobj.h" | |
| #include "indexkey.h" | | #include "indexkey.h" | |
| #include "projection.h" | | #include "projection.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| extern const int MaxBytesToReturnToClientAtOnce; | | extern const int MaxBytesToReturnToClientAtOnce; | |
| | | | |
|
| | | //maximum number of intervals produced by $in queries. | |
| | | static const unsigned MAX_IN_COMBINATIONS = 4000000; | |
| | | | |
| /* This is for languages whose "objects" are not well ordered (JSON is
well ordered). | | /* This is for languages whose "objects" are not well ordered (JSON is
well ordered). | |
| [ { a : ... } , { b : ... } ] -> { a : ..., b : ... } | | [ { a : ... } , { b : ... } ] -> { a : ..., b : ... } | |
| */ | | */ | |
| inline BSONObj transformOrderFromArrayFormat(BSONObj order) { | | inline BSONObj transformOrderFromArrayFormat(BSONObj order) { | |
| /* note: this is slow, but that is ok as order will have very few p
ieces */ | | /* note: this is slow, but that is ok as order will have very few p
ieces */ | |
| BSONObjBuilder b; | | BSONObjBuilder b; | |
| char p[2] = "0"; | | char p[2] = "0"; | |
| | | | |
| while ( 1 ) { | | while ( 1 ) { | |
| BSONObj j = order.getObjectField(p); | | BSONObj j = order.getObjectField(p); | |
| | | | |
| skipping to change at line 299 | | skipping to change at line 302 | |
| * Creates a FieldRange representing a superset of the BSONElement
values matching a query | | * Creates a FieldRange representing a superset of the BSONElement
values matching a query | |
| * expression element. | | * expression element. | |
| * @param e - The query expression element. | | * @param e - The query expression element. | |
| * @param isNot - Indicates that 'e' appears within a query $not cl
ause and its matching | | * @param isNot - Indicates that 'e' appears within a query $not cl
ause and its matching | |
| * semantics are inverted. | | * semantics are inverted. | |
| * @param optimize - If true, the range may be bracketed by 'e''s d
ata type. | | * @param optimize - If true, the range may be bracketed by 'e''s d
ata type. | |
| * TODO It is unclear why 'optimize' is optional, see SERVER-51
65. | | * TODO It is unclear why 'optimize' is optional, see SERVER-51
65. | |
| */ | | */ | |
| FieldRange( const BSONElement &e , bool isNot, bool optimize ); | | FieldRange( const BSONElement &e , bool isNot, bool optimize ); | |
| | | | |
|
| | | void setElemMatchContext( const BSONElement& elemMatchContext ) { | |
| | | _elemMatchContext = elemMatchContext; | |
| | | } | |
| | | | |
| /** | | /** | |
| * @return Range intersection with 'other'. | | * @return Range intersection with 'other'. | |
| * @param singleKey - Indicate whether intersection will be perform
ed in a single value or | | * @param singleKey - Indicate whether intersection will be perform
ed in a single value or | |
| * multi value context. | | * multi value context. | |
| */ | | */ | |
| const FieldRange &intersect( const FieldRange &other, bool singleKe
y ); | | const FieldRange &intersect( const FieldRange &other, bool singleKe
y ); | |
| /** @return Range union with 'other'. */ | | /** @return Range union with 'other'. */ | |
| const FieldRange &operator|=( const FieldRange &other ); | | const FieldRange &operator|=( const FieldRange &other ); | |
| /** @return Range of elements elements included in 'this' but not '
other'. */ | | /** @return Range of elements elements included in 'this' but not '
other'. */ | |
| const FieldRange &operator-=( const FieldRange &other ); | | const FieldRange &operator-=( const FieldRange &other ); | |
| | | | |
| skipping to change at line 347 | | skipping to change at line 354 | |
| */ | | */ | |
| bool mustBeExactMatchRepresentation() const { return _exactMatchRep
resentation; } | | bool mustBeExactMatchRepresentation() const { return _exactMatchRep
resentation; } | |
| /* Checks whether this FieldRange is a non-empty union of point-int
ervals. | | /* Checks whether this FieldRange is a non-empty union of point-int
ervals. | |
| * Examples: | | * Examples: | |
| * FieldRange( { a:3 } ), isPointIntervalSet() -> true | | * FieldRange( { a:3 } ), isPointIntervalSet() -> true | |
| * FieldRange( { a:{ $in:[ 1, 2 ] } } ), isPointIntervalSet() -> t
rue | | * FieldRange( { a:{ $in:[ 1, 2 ] } } ), isPointIntervalSet() -> t
rue | |
| * FieldRange( { a:{ $gt:5 } } ), isPointIntervalSet() -> false | | * FieldRange( { a:{ $gt:5 } } ), isPointIntervalSet() -> false | |
| * FieldRange( {} ), isPointIntervalSet() -> false | | * FieldRange( {} ), isPointIntervalSet() -> false | |
| */ | | */ | |
| bool isPointIntervalSet() const; | | bool isPointIntervalSet() const; | |
|
| | | const BSONElement& elemMatchContext() const { return _elemMatchCont
ext; } | |
| | | | |
| /** Empty the range so it includes no BSONElements. */ | | /** Empty the range so it includes no BSONElements. */ | |
| void makeEmpty() { _intervals.clear(); } | | void makeEmpty() { _intervals.clear(); } | |
| const vector<FieldInterval> &intervals() const { return _intervals;
} | | const vector<FieldInterval> &intervals() const { return _intervals;
} | |
| string getSpecial() const { return _special; } | | string getSpecial() const { return _special; } | |
| /** Make component intervals noninclusive. */ | | /** Make component intervals noninclusive. */ | |
| void setExclusiveBounds(); | | void setExclusiveBounds(); | |
| /** | | /** | |
| * Constructs a range where all FieldIntervals and FieldBounds are
in | | * Constructs a range where all FieldIntervals and FieldBounds are
in | |
| * the opposite order of the current range. | | * the opposite order of the current range. | |
| * NOTE the resulting intervals might not be strictValid(). | | * NOTE the resulting intervals might not be strictValid(). | |
| */ | | */ | |
| void reverse( FieldRange &ret ) const; | | void reverse( FieldRange &ret ) const; | |
| | | | |
|
| bool hasSpecialThatNeedsIndex() const { verify( _special.size() ); | | | |
| return _specialNeedsIndex; } | | | |
| | | | |
| string toString() const; | | string toString() const; | |
| private: | | private: | |
| BSONObj addObj( const BSONObj &o ); | | BSONObj addObj( const BSONObj &o ); | |
| void finishOperation( const vector<FieldInterval> &newIntervals, co
nst FieldRange &other, | | void finishOperation( const vector<FieldInterval> &newIntervals, co
nst FieldRange &other, | |
| bool exactMatchRepresentation ); | | bool exactMatchRepresentation ); | |
| vector<FieldInterval> _intervals; | | vector<FieldInterval> _intervals; | |
| // Owns memory for our BSONElements. | | // Owns memory for our BSONElements. | |
| vector<BSONObj> _objData; | | vector<BSONObj> _objData; | |
|
| string _special; | | string _special; // Index type name of a non standard (eg '2d') ind | |
| bool _specialNeedsIndex; | | ex required by a parsed | |
| | | // query operator (eg '$near'). | |
| bool _exactMatchRepresentation; | | bool _exactMatchRepresentation; | |
|
| | | BSONElement _elemMatchContext; // Parent $elemMatch object of the f | |
| | | ield constraint that | |
| | | // generated this FieldRange. For e | |
| | | xample if the query is | |
| | | // { a:{ $elemMatch:{ b:1, c:1 } } } | |
| | | , then the | |
| | | // _elemMatchContext for the FieldRa | |
| | | nge on 'a.b' is the query | |
| | | // element having field name '$elemM | |
| | | atch'. | |
| }; | | }; | |
| | | | |
|
| /** | | | |
| * A BoundList contains intervals specified by inclusive start | | | |
| * and end bounds. The intervals should be nonoverlapping and occur in | | | |
| * the specified direction of traversal. For example, given a simple i | | | |
| ndex {i:1} | | | |
| * and direction +1, one valid BoundList is: (1, 2); (4, 6). The same | | | |
| BoundList | | | |
| * would be valid for index {i:-1} with direction -1. | | | |
| */ | | | |
| typedef vector<pair<BSONObj,BSONObj> > BoundList; | | | |
| | | | |
| class QueryPattern; | | class QueryPattern; | |
| | | | |
| /** | | /** | |
| * A set of FieldRanges determined from constraints on the fields of a
query, | | * A set of FieldRanges determined from constraints on the fields of a
query, | |
| * that may be used to determine index bounds. | | * that may be used to determine index bounds. | |
| */ | | */ | |
| class FieldRangeSet { | | class FieldRangeSet { | |
| public: | | public: | |
| friend class OrRangeGenerator; | | friend class OrRangeGenerator; | |
| friend class FieldRangeVector; | | friend class FieldRangeVector; | |
| | | | |
| skipping to change at line 462 | | skipping to change at line 464 | |
| /** | | /** | |
| * @return a simplified query from the extreme values of the non un
iversal | | * @return a simplified query from the extreme values of the non un
iversal | |
| * fields. | | * fields. | |
| * @param fields If specified, the fields of the returned object ar
e | | * @param fields If specified, the fields of the returned object ar
e | |
| * ordered to match those of 'fields'. | | * ordered to match those of 'fields'. | |
| */ | | */ | |
| BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const; | | BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const; | |
| | | | |
| QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; | | QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; | |
| string getSpecial() const; | | string getSpecial() const; | |
|
| bool hasSpecialThatNeedsIndex() const; | | | |
| | | | |
| /** | | /** | |
| * @return a FieldRangeSet approximation of the documents in 'this'
but | | * @return a FieldRangeSet approximation of the documents in 'this'
but | |
| * not in 'other'. The approximation will be a superset of the doc
uments | | * not in 'other'. The approximation will be a superset of the doc
uments | |
| * in 'this' but not 'other'. | | * in 'this' but not 'other'. | |
| */ | | */ | |
| const FieldRangeSet &operator-=( const FieldRangeSet &other ); | | const FieldRangeSet &operator-=( const FieldRangeSet &other ); | |
| /** @return intersection of 'this' with 'other'. */ | | /** @return intersection of 'this' with 'other'. */ | |
| const FieldRangeSet &operator&=( const FieldRangeSet &other ); | | const FieldRangeSet &operator&=( const FieldRangeSet &other ); | |
| | | | |
| /** | | /** | |
|
| * @return an ordered list of bounds generated using an index key p | | | |
| attern | | | |
| * and traversal direction. | | | |
| * | | | |
| * The value of matchPossible() should be true, otherwise this func | | | |
| tion | | | |
| * may @throw. | | | |
| * | | | |
| * NOTE This function is deprecated in the query optimizer and only | | | |
| * currently used by sharding code. | | | |
| */ | | | |
| BoundList indexBounds( const BSONObj &keyPattern, int direction ) c | | | |
| onst; | | | |
| | | | |
| /** | | | |
| * @return - A new FieldRangeSet based on this FieldRangeSet, but w
ith only | | * @return - A new FieldRangeSet based on this FieldRangeSet, but w
ith only | |
| * a subset of the fields. | | * a subset of the fields. | |
| * @param fields - Only fields which are represented as field names
in this object | | * @param fields - Only fields which are represented as field names
in this object | |
| * will be included in the returned FieldRangeSet. | | * will be included in the returned FieldRangeSet. | |
| */ | | */ | |
| FieldRangeSet *subset( const BSONObj &fields ) const; | | FieldRangeSet *subset( const BSONObj &fields ) const; | |
| | | | |
| /** | | /** | |
| * @return A new FieldRangeSet based on this FieldRangeSet, but wit
h all field names | | * @return A new FieldRangeSet based on this FieldRangeSet, but wit
h all field names | |
| * prefixed by the specified @param prefix field name. | | * prefixed by the specified @param prefix field name. | |
| | | | |
| skipping to change at line 584 | | skipping to change at line 573 | |
| bool matchPossible() const { return _multiKey.matchPossible(); } | | bool matchPossible() const { return _multiKey.matchPossible(); } | |
| /** | | /** | |
| * @return false if a match is impossible on the specified index. | | * @return false if a match is impossible on the specified index. | |
| * @param idxNo -1 for non index scan. | | * @param idxNo -1 for non index scan. | |
| */ | | */ | |
| bool matchPossibleForIndex( NamespaceDetails *d, int idxNo, const B
SONObj &keyPattern ) const; | | bool matchPossibleForIndex( NamespaceDetails *d, int idxNo, const B
SONObj &keyPattern ) const; | |
| | | | |
| const char *ns() const { return _singleKey.ns(); } | | const char *ns() const { return _singleKey.ns(); } | |
| | | | |
| string getSpecial() const { return _singleKey.getSpecial(); } | | string getSpecial() const { return _singleKey.getSpecial(); } | |
|
| bool hasSpecialThatNeedsIndex() const { return _singleKey.hasSpecia
lThatNeedsIndex(); } | | | |
| | | | |
| /** Intersect with another FieldRangeSetPair. */ | | /** Intersect with another FieldRangeSetPair. */ | |
| FieldRangeSetPair &operator&=( const FieldRangeSetPair &other ); | | FieldRangeSetPair &operator&=( const FieldRangeSetPair &other ); | |
| /** | | /** | |
| * Subtract a FieldRangeSet, generally one expressing a range that
has | | * Subtract a FieldRangeSet, generally one expressing a range that
has | |
| * already been scanned. | | * already been scanned. | |
| */ | | */ | |
| FieldRangeSetPair &operator-=( const FieldRangeSet &scanned ); | | FieldRangeSetPair &operator-=( const FieldRangeSet &scanned ); | |
| | | | |
|
| BoundList shardKeyIndexBounds( const BSONObj &keyPattern ) const { | | bool matchPossibleForSingleKeyFRS( const BSONObj &keyPattern ) cons | |
| return _singleKey.indexBounds( keyPattern, 1 ); | | t { | |
| } | | | |
| | | | |
| bool matchPossibleForShardKey( const BSONObj &keyPattern ) const { | | | |
| return _singleKey.matchPossibleForIndex( keyPattern ); | | return _singleKey.matchPossibleForIndex( keyPattern ); | |
| } | | } | |
| | | | |
| BSONObj originalQuery() const { return _singleKey.originalQuery();
} | | BSONObj originalQuery() const { return _singleKey.originalQuery();
} | |
| | | | |
|
| | | const FieldRangeSet getSingleKeyFRS() const { return _singleKey; } | |
| | | const FieldRangeSet getMultiKeyFRS() const { return _singleKey; } | |
| | | | |
| string toString() const; | | string toString() const; | |
| private: | | private: | |
| FieldRangeSetPair( const FieldRangeSet &singleKey, const FieldRange
Set &multiKey ) | | FieldRangeSetPair( const FieldRangeSet &singleKey, const FieldRange
Set &multiKey ) | |
| :_singleKey( singleKey ), _multiKey( multiKey ) {} | | :_singleKey( singleKey ), _multiKey( multiKey ) {} | |
| void assertValidIndex( const NamespaceDetails *d, int idxNo ) const
; | | void assertValidIndex( const NamespaceDetails *d, int idxNo ) const
; | |
| void assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxN
o ) const; | | void assertValidIndexOrNoIndex( const NamespaceDetails *d, int idxN
o ) const; | |
| /** matchPossibleForIndex() must be true. */ | | /** matchPossibleForIndex() must be true. */ | |
| BSONObj simplifiedQueryForIndex( NamespaceDetails *d, int idxNo, co
nst BSONObj &keyPattern ) const; | | BSONObj simplifiedQueryForIndex( NamespaceDetails *d, int idxNo, co
nst BSONObj &keyPattern ) const; | |
| FieldRangeSet _singleKey; | | FieldRangeSet _singleKey; | |
| FieldRangeSet _multiKey; | | FieldRangeSet _multiKey; | |
| | | | |
End of changes. 12 change blocks. |
| 38 lines changed or deleted | | 26 lines changed or added | |
|
| rs.h | | rs.h | |
| | | | |
| skipping to change at line 298 | | skipping to change at line 298 | |
| rwlock lk(m, true); | | rwlock lk(m, true); | |
| verify(!sp.state.primary()); | | verify(!sp.state.primary()); | |
| sp.primary = remote; | | sp.primary = remote; | |
| } | | } | |
| StateBox() : m("StateBox") { } | | StateBox() : m("StateBox") { } | |
| private: | | private: | |
| RWLock m; | | RWLock m; | |
| SP sp; | | SP sp; | |
| }; | | }; | |
| | | | |
|
| void parseReplsetCmdLine(string cfgString, string& setname, vector<Host | | void parseReplsetCmdLine(const std::string& cfgString, | |
| AndPort>& seeds, set<HostAndPort>& seedSet ); | | string& setname, | |
| | | vector<HostAndPort>& seeds, | |
| | | set<HostAndPort>& seedSet); | |
| | | | |
| /** Parameter given to the --replSet command line option (parsed). | | /** Parameter given to the --replSet command line option (parsed). | |
| Syntax is "<setname>/<seedhost1>,<seedhost2>" | | Syntax is "<setname>/<seedhost1>,<seedhost2>" | |
| where setname is a name and seedhost is "<host>[:<port>]" */ | | where setname is a name and seedhost is "<host>[:<port>]" */ | |
| class ReplSetCmdline { | | class ReplSetCmdline { | |
| public: | | public: | |
|
| ReplSetCmdline(string cfgString) { parseReplsetCmdLine(cfgString, s
etname, seeds, seedSet); } | | ReplSetCmdline(const std::string& cfgString) { parseReplsetCmdLine(
cfgString, setname, seeds, seedSet); } | |
| string setname; | | string setname; | |
| vector<HostAndPort> seeds; | | vector<HostAndPort> seeds; | |
| set<HostAndPort> seedSet; | | set<HostAndPort> seedSet; | |
| }; | | }; | |
| | | | |
| /* information about the entire repl set, such as the various servers i
n the set, and their state */ | | /* information about the entire repl set, such as the various servers i
n the set, and their state */ | |
| /* note: We currently do not free mem when the set goes away - it is as
sumed the replset is a | | /* note: We currently do not free mem when the set goes away - it is as
sumed the replset is a | |
| singleton and long lived. | | singleton and long lived. | |
| */ | | */ | |
| class ReplSetImpl : protected RSBase { | | class ReplSetImpl : protected RSBase { | |
| | | | |
| skipping to change at line 371 | | skipping to change at line 374 | |
| void blockSync(bool block); | | void blockSync(bool block); | |
| | | | |
| // set of electable members' _ids | | // set of electable members' _ids | |
| set<unsigned> _electableSet; | | set<unsigned> _electableSet; | |
| protected: | | protected: | |
| // "heartbeat message" | | // "heartbeat message" | |
| // sent in requestHeartbeat respond in field "hbm" | | // sent in requestHeartbeat respond in field "hbm" | |
| char _hbmsg[256]; // we change this unlocked, thus not an stl::stri
ng | | char _hbmsg[256]; // we change this unlocked, thus not an stl::stri
ng | |
| time_t _hbmsgTime; // when it was logged | | time_t _hbmsgTime; // when it was logged | |
| public: | | public: | |
|
| void sethbmsg(string s, int logLevel = 0); | | void sethbmsg(const std::string& s, int logLevel = 0); | |
| | | | |
| /** | | /** | |
| * Election with Priorities | | * Election with Priorities | |
| * | | * | |
| * Each node (n) keeps a set of nodes that could be elected primary
. | | * Each node (n) keeps a set of nodes that could be elected primary
. | |
| * Each node in this set: | | * Each node in this set: | |
| * | | * | |
| * 1. can connect to a majority of the set | | * 1. can connect to a majority of the set | |
| * 2. has a priority greater than 0 | | * 2. has a priority greater than 0 | |
| * 3. has an optime within 10 seconds of the most up-to-date node | | * 3. has an optime within 10 seconds of the most up-to-date node | |
| | | | |
| skipping to change at line 430 | | skipping to change at line 433 | |
| void _fillIsMaster(BSONObjBuilder&); | | void _fillIsMaster(BSONObjBuilder&); | |
| void _fillIsMasterHost(const Member*, vector<string>&, vector<strin
g>&, vector<string>&); | | void _fillIsMasterHost(const Member*, vector<string>&, vector<strin
g>&, vector<string>&); | |
| const ReplSetConfig& config() { return *_cfg; } | | const ReplSetConfig& config() { return *_cfg; } | |
| string name() const { return _name; } /* @return replica set's logi
cal name */ | | string name() const { return _name; } /* @return replica set's logi
cal name */ | |
| MemberState state() const { return box.getState(); } | | MemberState state() const { return box.getState(); } | |
| void _fatal(); | | void _fatal(); | |
| void _getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) con
st; | | void _getOplogDiagsAsHtml(unsigned server_id, stringstream& ss) con
st; | |
| void _summarizeAsHtml(stringstream&) const; | | void _summarizeAsHtml(stringstream&) const; | |
| void _summarizeStatus(BSONObjBuilder&) const; // for replSetGetStat
us command | | void _summarizeStatus(BSONObjBuilder&) const; // for replSetGetStat
us command | |
| | | | |
|
| /* throws exception if a problem initializing. */ | | | |
| ReplSetImpl(ReplSetCmdline&); | | | |
| // used for testing | | | |
| ReplSetImpl(); | | | |
| | | | |
| /* call afer constructing to start - returns fairly quickly after l
aunching its threads */ | | /* call afer constructing to start - returns fairly quickly after l
aunching its threads */ | |
| void _go(); | | void _go(); | |
| | | | |
| private: | | private: | |
| string _name; | | string _name; | |
| const vector<HostAndPort> *_seeds; | | const vector<HostAndPort> *_seeds; | |
| ReplSetConfig *_cfg; | | ReplSetConfig *_cfg; | |
| | | | |
| /** | | /** | |
| * Finds the configuration with the highest version number and atte
mpts | | * Finds the configuration with the highest version number and atte
mpts | |
| * load it. | | * load it. | |
| */ | | */ | |
|
| bool _loadConfigFinish(vector<ReplSetConfig>& v); | | bool _loadConfigFinish(vector<ReplSetConfig*>& v); | |
| /** | | /** | |
| * Gather all possible configs (from command line seeds, our own co
nfig | | * Gather all possible configs (from command line seeds, our own co
nfig | |
| * doc, and any hosts listed therein) and try to initiate from the
most | | * doc, and any hosts listed therein) and try to initiate from the
most | |
| * recent config we find. | | * recent config we find. | |
| */ | | */ | |
| void loadConfig(); | | void loadConfig(); | |
| | | | |
| list<HostAndPort> memberHostnames() const; | | list<HostAndPort> memberHostnames() const; | |
| bool iAmArbiterOnly() const { return myConfig().arbiterOnly; } | | bool iAmArbiterOnly() const { return myConfig().arbiterOnly; } | |
| bool iAmPotentiallyHot() const { | | bool iAmPotentiallyHot() const { | |
| return myConfig().potentiallyHot() && // not an arbiter | | return myConfig().potentiallyHot() && // not an arbiter | |
| elect.steppedDown <= time(0) && // not stepped down/frozen | | elect.steppedDown <= time(0) && // not stepped down/frozen | |
| state() == MemberState::RS_SECONDARY; // not stale | | state() == MemberState::RS_SECONDARY; // not stale | |
| } | | } | |
| protected: | | protected: | |
| Member *_self; | | Member *_self; | |
| bool _buildIndexes; // = _self->config().buildIndexes | | bool _buildIndexes; // = _self->config().buildIndexes | |
|
| | | | |
| | | ReplSetImpl(); | |
| | | /* throws exception if a problem initializing. */ | |
| | | void init(ReplSetCmdline&); | |
| | | | |
| void setSelfTo(Member *); // use this as it sets buildIndexes var | | void setSelfTo(Member *); // use this as it sets buildIndexes var | |
| private: | | private: | |
| List1<Member> _members; // all members of the set EXCEPT _self. | | List1<Member> _members; // all members of the set EXCEPT _self. | |
| ReplSetConfig::MemberCfg _config; // config of _self | | ReplSetConfig::MemberCfg _config; // config of _self | |
| unsigned _id; // _id of _self | | unsigned _id; // _id of _self | |
| | | | |
| int _maintenanceMode; // if we should stay in recovering state | | int _maintenanceMode; // if we should stay in recovering state | |
| public: | | public: | |
| // this is called from within a writelock in logOpRS | | // this is called from within a writelock in logOpRS | |
| unsigned selfId() const { return _id; } | | unsigned selfId() const { return _id; } | |
| Manager *mgr; | | Manager *mgr; | |
| GhostSync *ghost; | | GhostSync *ghost; | |
| /** | | /** | |
| * This forces a secondary to go into recovering state and stay the
re | | * This forces a secondary to go into recovering state and stay the
re | |
| * until this is called again, passing in "false". Multiple thread
s can | | * until this is called again, passing in "false". Multiple thread
s can | |
| * call this and it will leave maintenance mode once all of the cal
lers | | * call this and it will leave maintenance mode once all of the cal
lers | |
| * have called it again, passing in false. | | * have called it again, passing in false. | |
| */ | | */ | |
|
| bool setMaintenanceMode(const bool inc); | | void setMaintenanceMode(const bool inc); | |
| private: | | private: | |
| Member* head() const { return _members.head(); } | | Member* head() const { return _members.head(); } | |
| public: | | public: | |
| const Member* findById(unsigned id) const; | | const Member* findById(unsigned id) const; | |
|
| | | Member* findByName(const std::string& hostname) const; | |
| private: | | private: | |
| void _getTargets(list<Target>&, int &configVersion); | | void _getTargets(list<Target>&, int &configVersion); | |
| void getTargets(list<Target>&, int &configVersion); | | void getTargets(list<Target>&, int &configVersion); | |
| void startThreads(); | | void startThreads(); | |
| friend class FeedbackThread; | | friend class FeedbackThread; | |
| friend class CmdReplSetElect; | | friend class CmdReplSetElect; | |
| friend class Member; | | friend class Member; | |
| friend class Manager; | | friend class Manager; | |
| friend class GhostSync; | | friend class GhostSync; | |
| friend class Consensus; | | friend class Consensus; | |
| | | | |
| skipping to change at line 550 | | skipping to change at line 554 | |
| const OpTime lastOtherOpTime() const; | | const OpTime lastOtherOpTime() const; | |
| static void setMinValid(BSONObj obj); | | static void setMinValid(BSONObj obj); | |
| | | | |
| int oplogVersion; | | int oplogVersion; | |
| private: | | private: | |
| IndexPrefetchConfig _indexPrefetchConfig; | | IndexPrefetchConfig _indexPrefetchConfig; | |
| }; | | }; | |
| | | | |
| class ReplSet : public ReplSetImpl { | | class ReplSet : public ReplSetImpl { | |
| public: | | public: | |
|
| ReplSet(); | | static ReplSet* make(ReplSetCmdline& replSetCmdline); | |
| ReplSet(ReplSetCmdline& replSetCmdline); | | | |
| virtual ~ReplSet() {} | | virtual ~ReplSet() {} | |
| | | | |
| // for the replSetStepDown command | | // for the replSetStepDown command | |
| bool stepDown(int secs) { return _stepDown(secs); } | | bool stepDown(int secs) { return _stepDown(secs); } | |
| | | | |
| // for the replSetFreeze command | | // for the replSetFreeze command | |
| bool freeze(int secs) { return _freeze(secs); } | | bool freeze(int secs) { return _freeze(secs); } | |
| | | | |
| string selfFullName() { | | string selfFullName() { | |
| verify( _self ); | | verify( _self ); | |
| | | | |
| skipping to change at line 607 | | skipping to change at line 610 | |
| */ | | */ | |
| const ReplSetConfig& getConfig() { return config(); } | | const ReplSetConfig& getConfig() { return config(); } | |
| | | | |
| bool lockedByMe() { return RSBase::lockedByMe(); } | | bool lockedByMe() { return RSBase::lockedByMe(); } | |
| | | | |
| // heartbeat msg to send to others; descriptive diagnostic info | | // heartbeat msg to send to others; descriptive diagnostic info | |
| string hbmsg() const { | | string hbmsg() const { | |
| if( time(0)-_hbmsgTime > 120 ) return ""; | | if( time(0)-_hbmsgTime > 120 ) return ""; | |
| return _hbmsg; | | return _hbmsg; | |
| } | | } | |
|
| | | | |
| | | protected: | |
| | | ReplSet(); | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Base class for repl set commands. Checks basic things such if we're
in | | * Base class for repl set commands. Checks basic things such if we're
in | |
| * rs mode before the command does its real work. | | * rs mode before the command does its real work. | |
| */ | | */ | |
| class ReplSetCommand : public Command { | | class ReplSetCommand : public Command { | |
| protected: | | protected: | |
| ReplSetCommand(const char * s, bool show=false) : Command(s, show)
{ } | | ReplSetCommand(const char * s, bool show=false) : Command(s, show)
{ } | |
| virtual bool slaveOk() const { return true; } | | virtual bool slaveOk() const { return true; } | |
| | | | |
End of changes. 10 change blocks. |
| 13 lines changed or deleted | | 18 lines changed or added | |
|
| rs_config.h | | rs_config.h | |
| | | | |
| skipping to change at line 39 | | skipping to change at line 39 | |
| class Member; | | class Member; | |
| const string rsConfigNs = "local.system.replset"; | | const string rsConfigNs = "local.system.replset"; | |
| | | | |
| class ReplSetConfig { | | class ReplSetConfig { | |
| enum { EMPTYCONFIG = -2 }; | | enum { EMPTYCONFIG = -2 }; | |
| struct TagSubgroup; | | struct TagSubgroup; | |
| | | | |
| // Protects _groups. | | // Protects _groups. | |
| static mongo::mutex groupMx; | | static mongo::mutex groupMx; | |
| public: | | public: | |
|
| ReplSetConfig(); | | | |
| /** | | /** | |
| * This contacts the given host and tries to get a config from them
. | | * This contacts the given host and tries to get a config from them
. | |
| * | | * | |
| * This sends a test heartbeat to the host and, if all goes well an
d the | | * This sends a test heartbeat to the host and, if all goes well an
d the | |
| * host has a more recent config, fetches the config and loads it (
see | | * host has a more recent config, fetches the config and loads it (
see | |
| * from(). | | * from(). | |
| * | | * | |
| * If it's contacting itself, it skips the heartbeat (for obvious | | * If it's contacting itself, it skips the heartbeat (for obvious | |
| * reasons.) If something is misconfigured, throws an exception. If
the | | * reasons.) If something is misconfigured, throws an exception. If
the | |
| * host couldn't be queried or is just blank, ok() will be false. | | * host couldn't be queried or is just blank, ok() will be false. | |
| */ | | */ | |
|
| ReplSetConfig(const HostAndPort& h); | | static ReplSetConfig* make(const HostAndPort& h); | |
| | | | |
| | | static ReplSetConfig* make(BSONObj cfg, bool force=false); | |
| | | | |
|
| ReplSetConfig(BSONObj cfg, bool force=false); | | /** | |
| | | * This uses DBDirectClient to check itself for a config. This way | |
| | | we don't need to connect | |
| | | * to ourselves over the network to fetch our own config. | |
| | | */ | |
| | | static ReplSetConfig* makeDirect(); | |
| | | | |
| bool ok() const { return _ok; } | | bool ok() const { return _ok; } | |
| | | | |
| struct TagRule; | | struct TagRule; | |
| | | | |
| struct MemberCfg { | | struct MemberCfg { | |
| MemberCfg() : _id(-1), votes(1), priority(1.0), arbiterOnly(fal
se), slaveDelay(0), hidden(false), buildIndexes(true) { } | | MemberCfg() : _id(-1), votes(1), priority(1.0), arbiterOnly(fal
se), slaveDelay(0), hidden(false), buildIndexes(true) { } | |
| int _id; /* ordinal */ | | int _id; /* ordinal */ | |
| unsigned votes; /* how many votes this node gets. default
1. */ | | unsigned votes; /* how many votes this node gets. default
1. */ | |
| HostAndPort h; | | HostAndPort h; | |
| | | | |
| skipping to change at line 159 | | skipping to change at line 164 | |
| * servers is safe if 4 of the servers are arbiters). | | * servers is safe if 4 of the servers are arbiters). | |
| */ | | */ | |
| private: | | private: | |
| void setMajority(); | | void setMajority(); | |
| public: | | public: | |
| int getMajority() const; | | int getMajority() const; | |
| | | | |
| bool _constructed; | | bool _constructed; | |
| | | | |
| /** | | /** | |
|
| * Returns if replication chaining is allowed. | | * Get the timeout to use for heartbeats. | |
| */ | | */ | |
|
| bool chainingAllowed() const; | | int getHeartbeatTimeout() const; | |
| | | | |
| private: | | | |
| bool _ok; | | | |
| | | | |
| /** | | /** | |
|
| * If replication can be chained. If chaining is disallowed, it can | | * Default timeout: 10 seconds | |
| still be explicitly | | | |
| * enabled via the replSetSyncFrom command, but it will not happen | | | |
| automatically. | | | |
| */ | | */ | |
|
| bool _chainingAllowed; | | static const int DEFAULT_HB_TIMEOUT; | |
| | | | |
| | | private: | |
| | | ReplSetConfig(); | |
| | | void init(const HostAndPort& h); | |
| | | void init(BSONObj cfg, bool force); | |
| | | | |
| | | bool _ok; | |
| int _majority; | | int _majority; | |
| | | | |
| void from(BSONObj); | | void from(BSONObj); | |
| void clear(); | | void clear(); | |
| | | | |
| struct TagClause; | | struct TagClause; | |
| | | | |
| /** | | /** | |
|
| | | * The timeout to use for heartbeats | |
| | | */ | |
| | | int _heartbeatTimeout; | |
| | | | |
| | | /** | |
| * This is a logical grouping of servers. It is pointed to by a se
t of | | * This is a logical grouping of servers. It is pointed to by a se
t of | |
| * servers with a certain tag. | | * servers with a certain tag. | |
| * | | * | |
| * For example, suppose servers A, B, and C have the tag "dc" : "ny
c". If we | | * For example, suppose servers A, B, and C have the tag "dc" : "ny
c". If we | |
| * have a rule {"dc" : 2}, then we want A _or_ B _or_ C to have the | | * have a rule {"dc" : 2}, then we want A _or_ B _or_ C to have the | |
| * write for one of the "dc" critiria to be fulfilled, so all three
will | | * write for one of the "dc" critiria to be fulfilled, so all three
will | |
| * point to this subgroup. When one of their oplog-tailing cursors
is | | * point to this subgroup. When one of their oplog-tailing cursors
is | |
| * updated, this subgroup is updated. | | * updated, this subgroup is updated. | |
| */ | | */ | |
| struct TagSubgroup : boost::noncopyable { | | struct TagSubgroup : boost::noncopyable { | |
| ~TagSubgroup(); // never called; not defined | | ~TagSubgroup(); // never called; not defined | |
|
| TagSubgroup(string nm) : name(nm) { } | | TagSubgroup(const std::string& nm) : name(nm) { } | |
| const string name; | | const string name; | |
| OpTime last; | | OpTime last; | |
| vector<TagClause*> clauses; | | vector<TagClause*> clauses; | |
| | | | |
| // this probably won't actually point to valid members after th
e | | // this probably won't actually point to valid members after th
e | |
| // subgroup is created, as initFromConfig() makes a copy of the | | // subgroup is created, as initFromConfig() makes a copy of the | |
| // config | | // config | |
| set<MemberCfg*> m; | | set<MemberCfg*> m; | |
| | | | |
| void updateLast(const OpTime& op); | | void updateLast(const OpTime& op); | |
| | | | |
End of changes. 9 change blocks. |
| 14 lines changed or deleted | | 26 lines changed or added | |
|
| shard.h | | shard.h | |
| | | | |
| skipping to change at line 102 | | skipping to change at line 102 | |
| | | | |
| string toString() const { | | string toString() const { | |
| return _name + ":" + _addr; | | return _name + ":" + _addr; | |
| } | | } | |
| | | | |
| friend ostream& operator << (ostream& out, const Shard& s) { | | friend ostream& operator << (ostream& out, const Shard& s) { | |
| return (out << s.toString()); | | return (out << s.toString()); | |
| } | | } | |
| | | | |
| bool operator==( const Shard& s ) const { | | bool operator==( const Shard& s ) const { | |
|
| if ( _name != s._name ) | | bool n = _name == s._name; | |
| return false; | | bool a = _addr == s._addr; | |
| return _cs.sameLogicalEndpoint( s._cs ); | | | |
| | | verify( n == a ); // names and address are 1 to 1 | |
| | | return n; | |
| } | | } | |
| | | | |
| bool operator!=( const Shard& s ) const { | | bool operator!=( const Shard& s ) const { | |
|
| return ! ( *this == s ); | | bool n = _name == s._name; | |
| | | bool a = _addr == s._addr; | |
| | | return ! ( n && a ); | |
| } | | } | |
| | | | |
| bool operator==( const string& s ) const { | | bool operator==( const string& s ) const { | |
| return _name == s || _addr == s; | | return _name == s || _addr == s; | |
| } | | } | |
| | | | |
| bool operator!=( const string& s ) const { | | bool operator!=( const string& s ) const { | |
| return _name != s && _addr != s; | | return _name != s && _addr != s; | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 270 | | skipping to change at line 274 | |
| | | | |
| ChunkManagerPtr getManager() const { | | ChunkManagerPtr getManager() const { | |
| return _manager; | | return _manager; | |
| } | | } | |
| | | | |
| bool setVersion() { | | bool setVersion() { | |
| _finishInit(); | | _finishInit(); | |
| return _setVersion; | | return _setVersion; | |
| } | | } | |
| | | | |
|
| static void sync( const string& db ); | | static void sync(); | |
| | | | |
| void donotCheckVersion() { | | void donotCheckVersion() { | |
| _setVersion = false; | | _setVersion = false; | |
| _finishedInit = true; | | _finishedInit = true; | |
| } | | } | |
| | | | |
| bool ok() const { return _conn > 0; } | | bool ok() const { return _conn > 0; } | |
| | | | |
| /** | | /** | |
| this just passes through excpet it checks for stale configs | | this just passes through excpet it checks for stale configs | |
| */ | | */ | |
| bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r
es ); | | bool runCommand( const string& db , const BSONObj& cmd , BSONObj& r
es ); | |
| | | | |
| /** checks all of my thread local connections for the version of th
is ns */ | | /** checks all of my thread local connections for the version of th
is ns */ | |
| static void checkMyConnectionVersions( const string & ns ); | | static void checkMyConnectionVersions( const string & ns ); | |
| | | | |
|
| /** | | | |
| * Whether or not we should release all connections after an operat | | | |
| ion with | | | |
| * a response. | | | |
| */ | | | |
| static bool releaseConnectionsAfterResponse; | | | |
| | | | |
| /** | | | |
| * Returns all the current sharded connections to the pool. | | | |
| * Note: This is *dangerous* if we have GLE state. | | | |
| */ | | | |
| static void releaseMyConnections(); | | | |
| | | | |
| private: | | private: | |
| void _init(); | | void _init(); | |
| void _finishInit(); | | void _finishInit(); | |
| | | | |
| bool _finishedInit; | | bool _finishedInit; | |
| | | | |
| string _addr; | | string _addr; | |
| string _ns; | | string _ns; | |
| ChunkManagerPtr _manager; | | ChunkManagerPtr _manager; | |
| | | | |
| | | | |
| skipping to change at line 323 | | skipping to change at line 315 | |
| extern DBConnectionPool shardConnectionPool; | | extern DBConnectionPool shardConnectionPool; | |
| | | | |
| class ShardingConnectionHook : public DBConnectionHook { | | class ShardingConnectionHook : public DBConnectionHook { | |
| public: | | public: | |
| | | | |
| ShardingConnectionHook( bool shardedConnections ) | | ShardingConnectionHook( bool shardedConnections ) | |
| : _shardedConnections( shardedConnections ) { | | : _shardedConnections( shardedConnections ) { | |
| } | | } | |
| | | | |
| virtual void onCreate( DBClientBase * conn ); | | virtual void onCreate( DBClientBase * conn ); | |
|
| | | virtual void onHandedOut( DBClientBase * conn ); | |
| virtual void onDestroy( DBClientBase * conn ); | | virtual void onDestroy( DBClientBase * conn ); | |
| | | | |
| bool _shardedConnections; | | bool _shardedConnections; | |
| }; | | }; | |
| } | | } | |
| | | | |
End of changes. 5 change blocks. |
| 18 lines changed or deleted | | 10 lines changed or added | |
|
| shardkey.h | | shardkey.h | |
| | | | |
| skipping to change at line 21 | | skipping to change at line 21 | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU Affero General Public License for more details. | | * GNU Affero General Public License for more details. | |
| * | | * | |
| * You should have received a copy of the GNU Affero General Public Licen
se | | * You should have received a copy of the GNU Affero General Public Licen
se | |
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
|
| | | #include "mongo/db/keypattern.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class Chunk; | | class Chunk; | |
|
| | | class FieldRangeSet; | |
| | | | |
| /* A ShardKeyPattern is a pattern indicating what data to extract from
the object to make the shard key from. | | /* A ShardKeyPattern is a pattern indicating what data to extract from
the object to make the shard key from. | |
| Analogous to an index key pattern. | | Analogous to an index key pattern. | |
| */ | | */ | |
| class ShardKeyPattern { | | class ShardKeyPattern { | |
| public: | | public: | |
| ShardKeyPattern( BSONObj p = BSONObj() ); | | ShardKeyPattern( BSONObj p = BSONObj() ); | |
| | | | |
| /** | | /** | |
| global min is the lowest possible value for this key | | global min is the lowest possible value for this key | |
| | | | |
| skipping to change at line 55 | | skipping to change at line 58 | |
| } | | } | |
| | | | |
| bool isGlobalMax( const BSONObj& k ) const { | | bool isGlobalMax( const BSONObj& k ) const { | |
| return k.woCompare( globalMax() ) == 0; | | return k.woCompare( globalMax() ) == 0; | |
| } | | } | |
| | | | |
| bool isGlobal( const BSONObj& k ) const { | | bool isGlobal( const BSONObj& k ) const { | |
| return isGlobalMin( k ) || isGlobalMax( k ); | | return isGlobalMin( k ) || isGlobalMax( k ); | |
| } | | } | |
| | | | |
|
| /** compare shard keys from the objects specified | | | |
| l < r negative | | | |
| l == r 0 | | | |
| l > r positive | | | |
| */ | | | |
| int compare( const BSONObj& l , const BSONObj& r ) const; | | | |
| | | | |
| /** | | /** | |
| @return whether or not obj has all fields in this shard key patt
ern | | @return whether or not obj has all fields in this shard key patt
ern | |
| e.g. | | e.g. | |
| ShardKey({num:1}).hasShardKey({ name:"joe", num:3 }) is true | | ShardKey({num:1}).hasShardKey({ name:"joe", num:3 }) is true | |
| ShardKey({"a.b":1}).hasShardKey({ "a.b":"joe"}) is true | | ShardKey({"a.b":1}).hasShardKey({ "a.b":"joe"}) is true | |
| ShardKey({"a.b":1}).hasShardKey({ "a": {"b":"joe"}}) is true | | ShardKey({"a.b":1}).hasShardKey({ "a": {"b":"joe"}}) is true | |
| | | | |
| ShardKey({num:1}).hasShardKey({ name:"joe"}) is false | | ShardKey({num:1}).hasShardKey({ name:"joe"}) is false | |
| ShardKey({num:1}).hasShardKey({ name:"joe", num:{$gt:3} }) is
false | | ShardKey({num:1}).hasShardKey({ name:"joe", num:{$gt:3} }) is
false | |
| | | | |
| see unit test for more examples | | see unit test for more examples | |
| */ | | */ | |
| bool hasShardKey( const BSONObj& obj ) const; | | bool hasShardKey( const BSONObj& obj ) const; | |
| | | | |
|
| BSONObj key() const { return pattern; } | | BSONObj key() const { return pattern.toBSON(); } | |
| | | | |
| string toString() const; | | string toString() const; | |
| | | | |
| BSONObj extractKey(const BSONObj& from) const; | | BSONObj extractKey(const BSONObj& from) const; | |
| | | | |
| bool partOfShardKey(const char* key ) const { | | bool partOfShardKey(const char* key ) const { | |
| return pattern.hasField(key); | | return pattern.hasField(key); | |
| } | | } | |
| bool partOfShardKey(const string& key ) const { | | bool partOfShardKey(const string& key ) const { | |
| return pattern.hasField(key.c_str()); | | return pattern.hasField(key.c_str()); | |
| } | | } | |
| | | | |
| /** | | /** | |
| * @return | | * @return | |
| * true if 'this' is a prefix (not necessarily contained) of 'other
Pattern'. | | * true if 'this' is a prefix (not necessarily contained) of 'other
Pattern'. | |
| */ | | */ | |
|
| bool isPrefixOf( const BSONObj& otherPattern ) const; | | bool isPrefixOf( const KeyPattern& otherPattern ) const; | |
| | | | |
| | | /** | |
| | | * @return | |
| | | * true if this shard key is compatible with a unique index on 'uni | |
| | | queIndexPattern'. | |
| | | * Primarily this just checks whether 'this' is a prefix of 'u | |
| | | niqueIndexPattern', | |
| | | * However it does not need to be an exact syntactic prefix du | |
| | | e to "hashed" | |
| | | * indexes or mismatches in ascending/descending order. Also, | |
| | | uniqueness of the | |
| | | * _id field is guaranteed by the generation process (or by th | |
| | | e user) so every | |
| | | * index that begins with _id is unique index compatible with | |
| | | any shard key. | |
| | | * Examples: | |
| | | * shard key {a : 1} is compatible with a unique index on {_ | |
| | | id : 1} | |
| | | * shard key {a : 1} is compatible with a unique index on {a | |
| | | : 1 , b : 1} | |
| | | * shard key {a : 1} is compatible with a unique index on {a | |
| | | : -1 , b : 1 } | |
| | | * shard key {a : "hashed"} is compatible with a unique inde | |
| | | x on {a : 1} | |
| | | * shard key {a : 1} is not compatible with a unique index o | |
| | | n {b : 1} | |
| | | * shard key {a : "hashed" , b : 1 } is not compatible with | |
| | | unique index on { b : 1 } | |
| | | * Note: | |
| | | * this method assumes that 'uniqueIndexPattern' is a valid | |
| | | index pattern, | |
| | | * and is capable of being a unique index. A pattern like { | |
| | | k : "hashed" } | |
| | | * is never capable of being a unique index, and thus is an | |
| | | invalid setting | |
| | | * for the 'uniqueIndexPattern' argument. | |
| | | */ | |
| | | bool isUniqueIndexCompatible( const KeyPattern& uniqueIndexPattern | |
| | | ) const; | |
| | | | |
| | | /** | |
| | | * @return | |
| | | * true if keyPattern contains any computed values, (e.g. {a : "has | |
| | | hed"}) | |
| | | * false if keyPattern consists of only ascending/descending fields | |
| | | (e.g. {a : 1, b : -1}) | |
| | | * With our current index expression language, "special" shar | |
| | | d keys are any keys | |
| | | * that are not a simple list of field names and 1/-1 values. | |
| | | */ | |
| | | bool isSpecial() const { return pattern.isSpecial(); } | |
| | | | |
| /** | | /** | |
| * @return BSONObj with _id and shardkey at front. May return origi
nal object. | | * @return BSONObj with _id and shardkey at front. May return origi
nal object. | |
| */ | | */ | |
| BSONObj moveToFront(const BSONObj& obj) const; | | BSONObj moveToFront(const BSONObj& obj) const; | |
| | | | |
|
| | | /**@param queryConstraints a FieldRangeSet formed from parsing a qu | |
| | | ery | |
| | | * @return an ordered list of bounds generated using this KeyPatter | |
| | | n | |
| | | * and the constraints from the FieldRangeSet | |
| | | * | |
| | | * The value of frsp->matchPossibleForSingleKeyFRS(fromQuery) shoul | |
| | | d be true, | |
| | | * otherwise this function could throw. | |
| | | * | |
| | | */ | |
| | | BoundList keyBounds( const FieldRangeSet& queryConstraints ) const{ | |
| | | return pattern.keyBounds( queryConstraints ); | |
| | | } | |
| | | | |
| private: | | private: | |
|
| BSONObj pattern; | | KeyPattern pattern; | |
| BSONObj gMin; | | BSONObj gMin; | |
| BSONObj gMax; | | BSONObj gMax; | |
| | | | |
| /* question: better to have patternfields precomputed or not? depe
nds on if we use copy constructor often. */ | | /* question: better to have patternfields precomputed or not? depe
nds on if we use copy constructor often. */ | |
| set<string> patternfields; | | set<string> patternfields; | |
| }; | | }; | |
| | | | |
| inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const { | | inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const { | |
|
| BSONObj k = from; | | BSONObj k = pattern.extractSingleKey( from ); | |
| bool needExtraction = false; | | | |
| | | | |
| BSONObjIterator a(from); | | | |
| BSONObjIterator b(pattern); | | | |
| while (a.more() && b.more()){ | | | |
| if (strcmp(a.next().fieldName(), b.next().fieldName()) != 0){ | | | |
| needExtraction = true; | | | |
| break; | | | |
| } | | | |
| } | | | |
| | | | |
| if (needExtraction || a.more() != b.more()) | | | |
| k = from.extractFields(pattern); | | | |
| | | | |
| uassert(13334, "Shard Key must be less than 512 bytes", k.objsize()
< 512); | | uassert(13334, "Shard Key must be less than 512 bytes", k.objsize()
< 512); | |
| return k; | | return k; | |
| } | | } | |
| | | | |
| } | | } | |
| | | | |
End of changes. 8 change blocks. |
| 25 lines changed or deleted | | 73 lines changed or added | |
|
| sock.h | | sock.h | |
| | | | |
| skipping to change at line 128 | | skipping to change at line 128 | |
| | | | |
| extern SockAddr unknownAddress; // ( "0.0.0.0", 0 ) | | extern SockAddr unknownAddress; // ( "0.0.0.0", 0 ) | |
| | | | |
| /** this is not cache and does a syscall */ | | /** this is not cache and does a syscall */ | |
| string getHostName(); | | string getHostName(); | |
| | | | |
| /** this is cached, so if changes during the process lifetime | | /** this is cached, so if changes during the process lifetime | |
| * will be stale */ | | * will be stale */ | |
| string getHostNameCached(); | | string getHostNameCached(); | |
| | | | |
|
| | | string prettyHostName(); | |
| | | | |
| /** | | /** | |
| * thrown by Socket and SockAddr | | * thrown by Socket and SockAddr | |
| */ | | */ | |
| class SocketException : public DBException { | | class SocketException : public DBException { | |
| public: | | public: | |
| const enum Type { CLOSED , RECV_ERROR , SEND_ERROR, RECV_TIMEOUT, S
END_TIMEOUT, FAILED_STATE, CONNECT_ERROR } _type; | | const enum Type { CLOSED , RECV_ERROR , SEND_ERROR, RECV_TIMEOUT, S
END_TIMEOUT, FAILED_STATE, CONNECT_ERROR } _type; | |
| | | | |
|
| SocketException( Type t , string server , int code = 9001 , string
extra="" ) | | SocketException( Type t , const std::string& server , int code = 90
01 , const std::string& extra="" ) | |
| : DBException( (string)"socket exception [" + _getStringType(
t ) + "] for " + server, code ), | | : DBException( (string)"socket exception [" + _getStringType(
t ) + "] for " + server, code ), | |
| _type(t), | | _type(t), | |
| _server(server), | | _server(server), | |
| _extra(extra) | | _extra(extra) | |
| {} | | {} | |
| | | | |
| virtual ~SocketException() throw() {} | | virtual ~SocketException() throw() {} | |
| | | | |
| bool shouldPrint() const { return _type != CLOSED; } | | bool shouldPrint() const { return _type != CLOSED; } | |
| virtual string toString() const; | | virtual string toString() const; | |
|
| | | virtual const std::string* server() const { return &_server; } | |
| private: | | private: | |
| | | | |
| // TODO: Allow exceptions better control over their messages | | // TODO: Allow exceptions better control over their messages | |
| static string _getStringType( Type t ){ | | static string _getStringType( Type t ){ | |
| switch (t) { | | switch (t) { | |
| case CLOSED: return "CLOSED"; | | case CLOSED: return "CLOSED"; | |
| case RECV_ERROR: return "RECV_ERROR"; | | case RECV_ERROR: return "RECV_ERROR"; | |
| case SEND_ERROR: return "SEND_ERROR"; | | case SEND_ERROR: return "SEND_ERROR"; | |
| case RECV_TIMEOUT: return "RECV_TIMEOUT"; | | case RECV_TIMEOUT: return "RECV_TIMEOUT"; | |
| case SEND_TIMEOUT: return "SEND_TIMEOUT"; | | case SEND_TIMEOUT: return "SEND_TIMEOUT"; | |
| | | | |
| skipping to change at line 207 | | skipping to change at line 209 | |
| Socket(int sock, const SockAddr& farEnd); | | Socket(int sock, const SockAddr& farEnd); | |
| | | | |
| /** In some cases the timeout will actually be 2x this value - eg w
e do a partial send, | | /** In some cases the timeout will actually be 2x this value - eg w
e do a partial send, | |
| then the timeout fires, then we try to send again, then the tim
eout fires again with | | then the timeout fires, then we try to send again, then the tim
eout fires again with | |
| no data sent, then we detect that the other side is down. | | no data sent, then we detect that the other side is down. | |
| | | | |
| Generally you don't want a timeout, you should be very prepared
for errors if you set one. | | Generally you don't want a timeout, you should be very prepared
for errors if you set one. | |
| */ | | */ | |
| Socket(double so_timeout = 0, int logLevel = 0 ); | | Socket(double so_timeout = 0, int logLevel = 0 ); | |
| | | | |
|
| ~Socket(); | | ~Socket() { | |
| | | close(); | |
| | | } | |
| | | | |
| bool connect(SockAddr& farEnd); | | bool connect(SockAddr& farEnd); | |
| void close(); | | void close(); | |
| | | | |
| void send( const char * data , int len, const char *context ); | | void send( const char * data , int len, const char *context ); | |
| void send( const vector< pair< char *, int > > &data, const char *c
ontext ); | | void send( const vector< pair< char *, int > > &data, const char *c
ontext ); | |
| | | | |
| // recv len or throw SocketException | | // recv len or throw SocketException | |
| void recv( char * data , int len ); | | void recv( char * data , int len ); | |
| int unsafe_recv( char *buf, int max ); | | int unsafe_recv( char *buf, int max ); | |
| | | | |
End of changes. 4 change blocks. |
| 3 lines changed or deleted | | 7 lines changed or added | |
|
| str.h | | str.h | |
| | | | |
| skipping to change at line 40 | | skipping to change at line 40 | |
| #include <string> | | #include <string> | |
| #include <sstream> | | #include <sstream> | |
| | | | |
| // this violates the README rules for mongoutils: | | // this violates the README rules for mongoutils: | |
| #include "../../bson/util/builder.h" | | #include "../../bson/util/builder.h" | |
| | | | |
| namespace mongoutils { | | namespace mongoutils { | |
| | | | |
| namespace str { | | namespace str { | |
| | | | |
|
| typedef std::string string; | | | |
| | | | |
| /** the idea here is to make one liners easy. e.g.: | | /** the idea here is to make one liners easy. e.g.: | |
| | | | |
| return str::stream() << 1 << ' ' << 2; | | return str::stream() << 1 << ' ' << 2; | |
| | | | |
| since the following doesn't work: | | since the following doesn't work: | |
| | | | |
| (stringstream() << 1).str(); | | (stringstream() << 1).str(); | |
| */ | | */ | |
| class stream { | | class stream { | |
| public: | | public: | |
| | | | |
| skipping to change at line 70 | | skipping to change at line 68 | |
| | | | |
| inline bool startsWith(const char *str, const char *prefix) { | | inline bool startsWith(const char *str, const char *prefix) { | |
| const char *s = str; | | const char *s = str; | |
| const char *p = prefix; | | const char *p = prefix; | |
| while( *p ) { | | while( *p ) { | |
| if( *p != *s ) return false; | | if( *p != *s ) return false; | |
| p++; s++; | | p++; s++; | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
|
| inline bool startsWith(string s, string p) { return startsWith(s.c_ | | inline bool startsWith(const std::string& s, const std::string& p) | |
| str(), p.c_str()); } | | { | |
| | | return startsWith(s.c_str(), p.c_str()); | |
| | | } | |
| | | | |
| // while these are trivial today use in case we do different wide c
har things later | | // while these are trivial today use in case we do different wide c
har things later | |
| inline bool startsWith(const char *p, char ch) { return *p == ch; } | | inline bool startsWith(const char *p, char ch) { return *p == ch; } | |
|
| inline bool startsWith(string s, char ch) { return startsWith(s.c_s
tr(), ch); } | | inline bool startsWith(const std::string& s, char ch) { return star
tsWith(s.c_str(), ch); } | |
| | | | |
|
| inline bool endsWith(string s, string p) { | | inline bool endsWith(const std::string& s, const std::string& p) { | |
| int l = p.size(); | | int l = p.size(); | |
| int x = s.size(); | | int x = s.size(); | |
| if( x < l ) return false; | | if( x < l ) return false; | |
| return strncmp(s.c_str()+x-l, p.c_str(), l) == 0; | | return strncmp(s.c_str()+x-l, p.c_str(), l) == 0; | |
| } | | } | |
| inline bool endsWith(const char *s, char p) { | | inline bool endsWith(const char *s, char p) { | |
| size_t len = strlen(s); | | size_t len = strlen(s); | |
| return len && s[len-1] == p; | | return len && s[len-1] == p; | |
| } | | } | |
| | | | |
| inline bool equals( const char * a , const char * b ) { return strc
mp( a , b ) == 0; } | | inline bool equals( const char * a , const char * b ) { return strc
mp( a , b ) == 0; } | |
| | | | |
| /** find char x, and return rest of string thereafter, or "" if not
found */ | | /** find char x, and return rest of string thereafter, or "" if not
found */ | |
| inline const char * after(const char *s, char x) { | | inline const char * after(const char *s, char x) { | |
| const char *p = strchr(s, x); | | const char *p = strchr(s, x); | |
| return (p != 0) ? p+1 : ""; | | return (p != 0) ? p+1 : ""; | |
| } | | } | |
|
| inline string after(const string& s, char x) { | | inline std::string after(const std::string& s, char x) { | |
| const char *p = strchr(s.c_str(), x); | | const char *p = strchr(s.c_str(), x); | |
|
| return (p != 0) ? string(p+1) : ""; | | return (p != 0) ? std::string(p+1) : ""; | |
| } | | } | |
| | | | |
| /** find string x, and return rest of string thereafter, or "" if n
ot found */ | | /** find string x, and return rest of string thereafter, or "" if n
ot found */ | |
| inline const char * after(const char *s, const char *x) { | | inline const char * after(const char *s, const char *x) { | |
| const char *p = strstr(s, x); | | const char *p = strstr(s, x); | |
| return (p != 0) ? p+strlen(x) : ""; | | return (p != 0) ? p+strlen(x) : ""; | |
| } | | } | |
|
| inline string after(string s, string x) { | | inline std::string after(const std::string& s, const std::string& x
) { | |
| const char *p = strstr(s.c_str(), x.c_str()); | | const char *p = strstr(s.c_str(), x.c_str()); | |
|
| return (p != 0) ? string(p+x.size()) : ""; | | return (p != 0) ? std::string(p+x.size()) : ""; | |
| } | | } | |
| | | | |
| /** @return true if s contains x | | /** @return true if s contains x | |
| * These should not be used with strings containing NUL bytes | | * These should not be used with strings containing NUL bytes | |
| */ | | */ | |
|
| inline bool contains(string s, string x) { | | inline bool contains(const std::string& s, const std::string& x) { | |
| return strstr(s.c_str(), x.c_str()) != 0; | | return strstr(s.c_str(), x.c_str()) != 0; | |
| } | | } | |
|
| inline bool contains(string s, char x) { | | inline bool contains(const std::string& s, char x) { | |
| verify(x != '\0'); // this expects c-strings so don't use when
looking for NUL bytes | | verify(x != '\0'); // this expects c-strings so don't use when
looking for NUL bytes | |
| return strchr(s.c_str(), x) != 0; | | return strchr(s.c_str(), x) != 0; | |
| } | | } | |
| | | | |
| /** @return everything before the character x, else entire string *
/ | | /** @return everything before the character x, else entire string *
/ | |
|
| inline string before(const string& s, char x) { | | inline std::string before(const std::string& s, char x) { | |
| const char *p = strchr(s.c_str(), x); | | const char *p = strchr(s.c_str(), x); | |
| return (p != 0) ? s.substr(0, p-s.c_str()) : s; | | return (p != 0) ? s.substr(0, p-s.c_str()) : s; | |
| } | | } | |
| | | | |
| /** @return everything before the string x, else entire string */ | | /** @return everything before the string x, else entire string */ | |
|
| inline string before(const string& s, const string& x) { | | inline std::string before(const std::string& s, const std::string&
x) { | |
| const char *p = strstr(s.c_str(), x.c_str()); | | const char *p = strstr(s.c_str(), x.c_str()); | |
| return (p != 0) ? s.substr(0, p-s.c_str()) : s; | | return (p != 0) ? s.substr(0, p-s.c_str()) : s; | |
| } | | } | |
| | | | |
| /** check if if strings share a common starting prefix | | /** check if if strings share a common starting prefix | |
| @return offset of divergence (or length if equal). 0=nothing i
n common. */ | | @return offset of divergence (or length if equal). 0=nothing i
n common. */ | |
| inline int shareCommonPrefix(const char *p, const char *q) { | | inline int shareCommonPrefix(const char *p, const char *q) { | |
| int ofs = 0; | | int ofs = 0; | |
| while( 1 ) { | | while( 1 ) { | |
| if( *p == 0 || *q == 0 ) | | if( *p == 0 || *q == 0 ) | |
| break; | | break; | |
| if( *p != *q ) | | if( *p != *q ) | |
| break; | | break; | |
| p++; q++; ofs++; | | p++; q++; ofs++; | |
| } | | } | |
| return ofs; | | return ofs; | |
| } | | } | |
|
| inline int shareCommonPrefix(const string &a, const string &b) | | inline int shareCommonPrefix(const std::string &a, const std::strin
g &b) | |
| { return shareCommonPrefix(a.c_str(), b.c_str()); } | | { return shareCommonPrefix(a.c_str(), b.c_str()); } | |
| | | | |
| /** string to unsigned. zero if not a number. can end with non-num
chars */ | | /** string to unsigned. zero if not a number. can end with non-num
chars */ | |
|
| inline unsigned toUnsigned(const string& a) { | | inline unsigned toUnsigned(const std::string& a) { | |
| unsigned x = 0; | | unsigned x = 0; | |
| const char *p = a.c_str(); | | const char *p = a.c_str(); | |
| while( 1 ) { | | while( 1 ) { | |
| if( !isdigit(*p) ) | | if( !isdigit(*p) ) | |
| break; | | break; | |
| x = x * 10 + (*p - '0'); | | x = x * 10 + (*p - '0'); | |
| p++; | | p++; | |
| } | | } | |
| return x; | | return x; | |
| } | | } | |
| | | | |
| /** split a string on a specific char. We don't split N times, jus
t once | | /** split a string on a specific char. We don't split N times, jus
t once | |
| on the first occurrence. If char not present entire string is
in L | | on the first occurrence. If char not present entire string is
in L | |
| and R is empty. | | and R is empty. | |
| @return true if char found | | @return true if char found | |
| */ | | */ | |
|
| inline bool splitOn(const string &s, char c, string& L, string& R)
{ | | inline bool splitOn(const std::string &s, char c, std::string& L, s
td::string& R) { | |
| const char *start = s.c_str(); | | const char *start = s.c_str(); | |
| const char *p = strchr(start, c); | | const char *p = strchr(start, c); | |
| if( p == 0 ) { | | if( p == 0 ) { | |
| L = s; R.clear(); | | L = s; R.clear(); | |
| return false; | | return false; | |
| } | | } | |
|
| L = string(start, p-start); | | L = std::string(start, p-start); | |
| R = string(p+1); | | R = std::string(p+1); | |
| return true; | | return true; | |
| } | | } | |
| /** split scanning reverse direction. Splits ONCE ONLY. */ | | /** split scanning reverse direction. Splits ONCE ONLY. */ | |
|
| inline bool rSplitOn(const string &s, char c, string& L, string& R)
{ | | inline bool rSplitOn(const std::string &s, char c, std::string& L,
std::string& R) { | |
| const char *start = s.c_str(); | | const char *start = s.c_str(); | |
| const char *p = strrchr(start, c); | | const char *p = strrchr(start, c); | |
| if( p == 0 ) { | | if( p == 0 ) { | |
| L = s; R.clear(); | | L = s; R.clear(); | |
| return false; | | return false; | |
| } | | } | |
|
| L = string(start, p-start); | | L = std::string(start, p-start); | |
| R = string(p+1); | | R = std::string(p+1); | |
| return true; | | return true; | |
| } | | } | |
| | | | |
| /** @return number of occurrences of c in s */ | | /** @return number of occurrences of c in s */ | |
|
| inline unsigned count( const string& s , char c ) { | | inline unsigned count( const std::string& s , char c ) { | |
| unsigned n=0; | | unsigned n=0; | |
| for ( unsigned i=0; i<s.size(); i++ ) | | for ( unsigned i=0; i<s.size(); i++ ) | |
| if ( s[i] == c ) | | if ( s[i] == c ) | |
| n++; | | n++; | |
| return n; | | return n; | |
| } | | } | |
| | | | |
| /** trim leading spaces. spaces only, not tabs etc. */ | | /** trim leading spaces. spaces only, not tabs etc. */ | |
|
| inline string ltrim(const string& s) { | | inline std::string ltrim(const std::string& s) { | |
| const char *p = s.c_str(); | | const char *p = s.c_str(); | |
| while( *p == ' ' ) p++; | | while( *p == ' ' ) p++; | |
| return p; | | return p; | |
| } | | } | |
| | | | |
| /** remove trailing chars in place */ | | /** remove trailing chars in place */ | |
|
| inline void stripTrailing(string& s, const char *chars) { | | inline void stripTrailing(std::string& s, const char *chars) { | |
| string::iterator i = s.end(); | | std::string::iterator i = s.end(); | |
| while( s.begin() != i ) { | | while( s.begin() != i ) { | |
| i--; | | i--; | |
| if( contains(chars, *i) ) { | | if( contains(chars, *i) ) { | |
| s.erase(i); | | s.erase(i); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| } | | } | |
| | | | |
| | | | |
End of changes. 21 change blocks. |
| 26 lines changed or deleted | | 26 lines changed or added | |
|
| syncclusterconnection.h | | syncclusterconnection.h | |
| | | | |
| skipping to change at line 53 | | skipping to change at line 53 | |
| | | | |
| using DBClientBase::query; | | using DBClientBase::query; | |
| using DBClientBase::update; | | using DBClientBase::update; | |
| using DBClientBase::remove; | | using DBClientBase::remove; | |
| | | | |
| /** | | /** | |
| * @param commaSeparated should be 3 hosts comma separated | | * @param commaSeparated should be 3 hosts comma separated | |
| */ | | */ | |
| SyncClusterConnection( const list<HostAndPort> &, double socketTime
out = 0); | | SyncClusterConnection( const list<HostAndPort> &, double socketTime
out = 0); | |
| SyncClusterConnection( string commaSeparated, double socketTimeout
= 0); | | SyncClusterConnection( string commaSeparated, double socketTimeout
= 0); | |
|
| SyncClusterConnection( string a , string b , string c, double socke | | SyncClusterConnection( const std::string& a, | |
| tTimeout = 0 ); | | const std::string& b, | |
| | | const std::string& c, | |
| | | double socketTimeout = 0 ); | |
| ~SyncClusterConnection(); | | ~SyncClusterConnection(); | |
| | | | |
| /** | | /** | |
| * @return true if all servers are up and ready for writes | | * @return true if all servers are up and ready for writes | |
| */ | | */ | |
| bool prepare( string& errmsg ); | | bool prepare( string& errmsg ); | |
| | | | |
| /** | | /** | |
| * runs fsync on all servers | | * runs fsync on all servers | |
| */ | | */ | |
| | | | |
| skipping to change at line 121 | | skipping to change at line 124 | |
| | | | |
| virtual bool lazySupported() const { return false; } | | virtual bool lazySupported() const { return false; } | |
| private: | | private: | |
| SyncClusterConnection( SyncClusterConnection& prev, double socketTi
meout = 0 ); | | SyncClusterConnection( SyncClusterConnection& prev, double socketTi
meout = 0 ); | |
| string _toString() const; | | string _toString() const; | |
| bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO
NObj &info, int options=0); | | bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO
NObj &info, int options=0); | |
| auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que
ry, int nToReturn, int nToSkip, | | auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que
ry, int nToReturn, int nToSkip, | |
| const BSONObj *fieldsToRetu
rn, int queryOptions, int batchSize ); | | const BSONObj *fieldsToRetu
rn, int queryOptions, int batchSize ); | |
| int _lockType( const string& name ); | | int _lockType( const string& name ); | |
| void _checkLast(); | | void _checkLast(); | |
|
| void _connect( string host ); | | void _connect( const std::string& host ); | |
| | | | |
| string _address; | | string _address; | |
| vector<string> _connAddresses; | | vector<string> _connAddresses; | |
| vector<DBClientConnection*> _conns; | | vector<DBClientConnection*> _conns; | |
| map<string,int> _lockTypes; | | map<string,int> _lockTypes; | |
| mongo::mutex _mutex; | | mongo::mutex _mutex; | |
| | | | |
| vector<BSONObj> _lastErrors; | | vector<BSONObj> _lastErrors; | |
| | | | |
| double _socketTimeout; | | double _socketTimeout; | |
| | | | |
End of changes. 2 change blocks. |
| 3 lines changed or deleted | | 5 lines changed or added | |
|
| text.h | | text.h | |
| // text.h | | // text.h | |
|
| | | | |
| /* | | /* | |
| * Copyright 2010 10gen Inc. | | * Copyright 2010 10gen Inc. | |
| * | | * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | | * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | | * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | | * You may obtain a copy of the License at | |
| * | | * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | | * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | | * | |
| * Unless required by applicable law or agreed to in writing, software | | * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | | * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed. | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli
ed. | |
| * See the License for the specific language governing permissions and | | * See the License for the specific language governing permissions and | |
| * limitations under the License. | | * limitations under the License. | |
| */ | | */ | |
| | | | |
|
| /* Copyright 2009 10gen Inc. | | | |
| * | | | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | | | |
| * you may not use this file except in compliance with the License. | | | |
| * You may obtain a copy of the License at | | | |
| * | | | |
| * http://www.apache.org/licenses/LICENSE-2.0 | | | |
| * | | | |
| * Unless required by applicable law or agreed to in writing, software | | | |
| * distributed under the License is distributed on an "AS IS" BASIS, | | | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli | | | |
| ed. | | | |
| * See the License for the specific language governing permissions and | | | |
| * limitations under the License. | | | |
| */ | | | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include <vector> | | #include <vector> | |
| #include <string> | | #include <string> | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class StringSplitter { | | class StringSplitter { | |
| public: | | public: | |
| /** @param big the string to be split | | /** @param big the string to be split | |
| | | | |
| skipping to change at line 61 | | skipping to change at line 47 | |
| | | | |
| /** get next split string fragment */ | | /** get next split string fragment */ | |
| std::string next(); | | std::string next(); | |
| | | | |
| void split( std::vector<std::string>& l ); | | void split( std::vector<std::string>& l ); | |
| | | | |
| std::vector<std::string> split(); | | std::vector<std::string> split(); | |
| | | | |
| static std::vector<std::string> split( const std::string& big , con
st std::string& splitter ); | | static std::vector<std::string> split( const std::string& big , con
st std::string& splitter ); | |
| | | | |
|
| static std::string join( std::vector<std::string>& l , const std::s
tring& split ); | | static std::string join( const std::vector<std::string>& l , const
std::string& split ); | |
| | | | |
| private: | | private: | |
| const char * _big; | | const char * _big; | |
| const char * _splitter; | | const char * _splitter; | |
| }; | | }; | |
| | | | |
| /* This doesn't defend against ALL bad UTF8, but it will guarantee that
the | | /* This doesn't defend against ALL bad UTF8, but it will guarantee that
the | |
| * string can be converted to sequence of codepoints. However, it doesn
't | | * string can be converted to sequence of codepoints. However, it doesn
't | |
| * guarantee that the codepoints are valid. | | * guarantee that the codepoints are valid. | |
| */ | | */ | |
| bool isValidUTF8(const char *s); | | bool isValidUTF8(const char *s); | |
|
| bool isValidUTF8(std::string s); | | bool isValidUTF8(const std::string& s); | |
| | | | |
| // expect that n contains a base ten number and nothing else after it | | // expect that n contains a base ten number and nothing else after it | |
| // NOTE win version hasn't been tested directly | | // NOTE win version hasn't been tested directly | |
| long long parseLL( const char *n ); | | long long parseLL( const char *n ); | |
| | | | |
| #if defined(_WIN32) | | #if defined(_WIN32) | |
| | | | |
| std::string toUtf8String(const std::wstring& wide); | | std::string toUtf8String(const std::wstring& wide); | |
| | | | |
| std::wstring toWideString(const char *s); | | std::wstring toWideString(const char *s); | |
| | | | |
End of changes. 4 change blocks. |
| 18 lines changed or deleted | | 3 lines changed or added | |
|
| update_internal.h | | update_internal.h | |
| | | | |
| skipping to change at line 33 | | skipping to change at line 33 | |
| #include "mongo/db/jsobjmanipulator.h" | | #include "mongo/db/jsobjmanipulator.h" | |
| #include "mongo/db/matcher.h" | | #include "mongo/db/matcher.h" | |
| #include "mongo/util/embedded_builder.h" | | #include "mongo/util/embedded_builder.h" | |
| #include "mongo/util/stringutils.h" | | #include "mongo/util/stringutils.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class ModState; | | class ModState; | |
| class ModSetState; | | class ModSetState; | |
| | | | |
|
| /** | | | |
| * a.$ -> a | | | |
| * @return true if out is set and we made a change | | | |
| */ | | | |
| bool getCanonicalIndexField( const string& fullName, string* out ); | | | |
| | | | |
| /* Used for modifiers such as $inc, $set, $push, ... | | /* Used for modifiers such as $inc, $set, $push, ... | |
| * stores the info about a single operation | | * stores the info about a single operation | |
| * once created should never be modified | | * once created should never be modified | |
| */ | | */ | |
| struct Mod { | | struct Mod { | |
| // See opFromStr below | | // See opFromStr below | |
| // 0 1 2 3 4 5 6 7 8
9 10 11 12 13 | | // 0 1 2 3 4 5 6 7 8
9 10 11 12 13 | |
| enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI
TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO } op; | | enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI
TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO } op; | |
| | | | |
| static const char* modNames[]; | | static const char* modNames[]; | |
| | | | |
| skipping to change at line 90 | | skipping to change at line 84 | |
| void setFieldName( const char* s ) { | | void setFieldName( const char* s ) { | |
| fieldName = s; | | fieldName = s; | |
| shortFieldName = strrchr( fieldName , '.' ); | | shortFieldName = strrchr( fieldName , '.' ); | |
| if ( shortFieldName ) | | if ( shortFieldName ) | |
| shortFieldName++; | | shortFieldName++; | |
| else | | else | |
| shortFieldName = fieldName; | | shortFieldName = fieldName; | |
| } | | } | |
| | | | |
| /** | | /** | |
|
| * @param in incrememnts the actual value inside in | | * @param in increments the actual value inside in | |
| */ | | */ | |
| void incrementMe( BSONElement& in ) const { | | void incrementMe( BSONElement& in ) const { | |
| BSONElementManipulator manip( in ); | | BSONElementManipulator manip( in ); | |
| switch ( in.type() ) { | | switch ( in.type() ) { | |
| case NumberDouble: | | case NumberDouble: | |
| manip.setNumber( elt.numberDouble() + in.numberDouble() ); | | manip.setNumber( elt.numberDouble() + in.numberDouble() ); | |
| break; | | break; | |
| case NumberLong: | | case NumberLong: | |
| manip.setLong( elt.numberLong() + in.numberLong() ); | | manip.setLong( elt.numberLong() + in.numberLong() ); | |
| break; | | break; | |
| | | | |
| skipping to change at line 152 | | skipping to change at line 146 | |
| static bool isIndexed( const string& fullName , const set<string>&
idxKeys ) { | | static bool isIndexed( const string& fullName , const set<string>&
idxKeys ) { | |
| const char * fieldName = fullName.c_str(); | | const char * fieldName = fullName.c_str(); | |
| // check if there is an index key that is a parent of mod | | // check if there is an index key that is a parent of mod | |
| for( const char* dot = strchr( fieldName, '.' ); dot; dot = str
chr( dot + 1, '.' ) ) | | for( const char* dot = strchr( fieldName, '.' ); dot; dot = str
chr( dot + 1, '.' ) ) | |
| if ( idxKeys.count( string( fieldName, dot - fieldName ) )
) | | if ( idxKeys.count( string( fieldName, dot - fieldName ) )
) | |
| return true; | | return true; | |
| | | | |
| // check if there is an index key equal to mod | | // check if there is an index key equal to mod | |
| if ( idxKeys.count(fullName) ) | | if ( idxKeys.count(fullName) ) | |
| return true; | | return true; | |
|
| | | | |
| // check if there is an index key that is a child of mod | | // check if there is an index key that is a child of mod | |
| set< string >::const_iterator j = idxKeys.upper_bound( fullName
); | | set< string >::const_iterator j = idxKeys.upper_bound( fullName
); | |
| if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful
lName.size()] == '.' ) | | if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful
lName.size()] == '.' ) | |
| return true; | | return true; | |
| | | | |
| return false; | | return false; | |
| } | | } | |
| | | | |
|
| /** | | | |
| * checks if mod is in the index by inspecting fieldName, and remov | | | |
| ing | | | |
| * .$ or .### substrings (#=digit) with any number of digits. | | | |
| * | | | |
| * @return true iff the mod is indexed | | | |
| */ | | | |
| bool isIndexed( const set<string>& idxKeys ) const { | | bool isIndexed( const set<string>& idxKeys ) const { | |
|
| string myFieldName = fieldName; | | string fullName = fieldName; | |
| | | | |
|
| // first, check if full name is in idxKeys | | if ( isIndexed( fullName , idxKeys ) ) | |
| if ( isIndexed( myFieldName , idxKeys ) ) | | | |
| return true; | | return true; | |
| | | | |
|
| string x; | | if ( strstr( fieldName , "." ) ) { | |
| if ( getCanonicalIndexField( myFieldName, &x ) ) { | | // check for a.0.1 | |
| if ( isIndexed( x, idxKeys ) ) | | StringBuilder buf; | |
| | | for ( size_t i=0; i<fullName.size(); i++ ) { | |
| | | char c = fullName[i]; | |
| | | | |
| | | if ( c == '$' && | |
| | | i > 0 && fullName[i-1] == '.' && | |
| | | i+1<fullName.size() && | |
| | | fullName[i+1] == '.' ) { | |
| | | i++; | |
| | | continue; | |
| | | } | |
| | | | |
| | | buf << c; | |
| | | | |
| | | if ( c != '.' ) | |
| | | continue; | |
| | | | |
| | | if ( ! isdigit( fullName[i+1] ) ) | |
| | | continue; | |
| | | | |
| | | bool possible = true; | |
| | | size_t j=i+2; | |
| | | for ( ; j<fullName.size(); j++ ) { | |
| | | char d = fullName[j]; | |
| | | if ( d == '.' ) | |
| | | break; | |
| | | if ( isdigit( d ) ) | |
| | | continue; | |
| | | possible = false; | |
| | | break; | |
| | | } | |
| | | | |
| | | if ( possible ) | |
| | | i = j; | |
| | | } | |
| | | string x = buf.str(); | |
| | | if ( isIndexed( x , idxKeys ) ) | |
| return true; | | return true; | |
| } | | } | |
| | | | |
| return false; | | return false; | |
| } | | } | |
| | | | |
| void apply( BSONBuilderBase& b , BSONElement in , ModState& ms ) co
nst; | | void apply( BSONBuilderBase& b , BSONElement in , ModState& ms ) co
nst; | |
| | | | |
| /** | | /** | |
| * @return true iff toMatch should be removed from the array | | * @return true iff toMatch should be removed from the array | |
| | | | |
| skipping to change at line 333 | | skipping to change at line 355 | |
| */ | | */ | |
| void updateIsIndexed( const set<string>& idxKeys, const set<string>
* backgroundKeys ); | | void updateIsIndexed( const set<string>& idxKeys, const set<string>
* backgroundKeys ); | |
| | | | |
| // TODO: this is inefficient - should probably just handle when ite
rating | | // TODO: this is inefficient - should probably just handle when ite
rating | |
| ModSet * fixDynamicArray( const string& elemMatchKey ) const; | | ModSet * fixDynamicArray( const string& elemMatchKey ) const; | |
| | | | |
| bool hasDynamicArray() const { return _hasDynamicArray; } | | bool hasDynamicArray() const { return _hasDynamicArray; } | |
| | | | |
| /** | | /** | |
| * creates a ModSetState suitable for operation on obj | | * creates a ModSetState suitable for operation on obj | |
|
| * doesn't change or modify this ModSet or any underying Mod | | * doesn't change or modify this ModSet or any underlying Mod | |
| */ | | */ | |
| auto_ptr<ModSetState> prepare( const BSONObj& obj ) const; | | auto_ptr<ModSetState> prepare( const BSONObj& obj ) const; | |
| | | | |
| /** | | /** | |
| * given a query pattern, builds an object suitable for an upsert | | * given a query pattern, builds an object suitable for an upsert | |
| * will take the query spec and combine all $ operators | | * will take the query spec and combine all $ operators | |
| */ | | */ | |
| BSONObj createNewFromQuery( const BSONObj& query ); | | BSONObj createNewFromQuery( const BSONObj& query ); | |
| | | | |
| int isIndexed() const { return _isIndexed; } | | int isIndexed() const { return _isIndexed; } | |
| | | | |
| skipping to change at line 437 | | skipping to change at line 459 | |
| return true; | | return true; | |
| case Mod::BIT: | | case Mod::BIT: | |
| case Mod::BITAND: | | case Mod::BITAND: | |
| case Mod::BITOR: | | case Mod::BITOR: | |
| return true; | | return true; | |
| default: | | default: | |
| return false; | | return false; | |
| } | | } | |
| } | | } | |
| | | | |
|
| const char* getOpLogName() const; | | | |
| void appendForOpLog( BSONObjBuilder& b ) const; | | void appendForOpLog( BSONObjBuilder& b ) const; | |
| | | | |
| void apply( BSONBuilderBase& b , BSONElement in ) { | | void apply( BSONBuilderBase& b , BSONElement in ) { | |
| m->apply( b , in , *this ); | | m->apply( b , in , *this ); | |
| } | | } | |
| | | | |
| void appendIncValue( BSONBuilderBase& b , bool useFullName ) const
{ | | void appendIncValue( BSONBuilderBase& b , bool useFullName ) const
{ | |
| const char* n = useFullName ? m->fieldName : m->shortFieldName; | | const char* n = useFullName ? m->fieldName : m->shortFieldName; | |
| | | | |
| switch ( incType ) { | | switch ( incType ) { | |
| | | | |
| skipping to change at line 618 | | skipping to change at line 639 | |
| | | | |
| // re-writing for oplog | | // re-writing for oplog | |
| | | | |
| bool DEPRECATED_needOpLogRewrite() const { | | bool DEPRECATED_needOpLogRewrite() const { | |
| for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ ) | | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ ) | |
| if ( i->second->DEPRECATED_needOpLogRewrite() ) | | if ( i->second->DEPRECATED_needOpLogRewrite() ) | |
| return true; | | return true; | |
| return false; | | return false; | |
| } | | } | |
| | | | |
|
| BSONObj getOpLogRewrite() const; | | BSONObj getOpLogRewrite() const { | |
| | | BSONObjBuilder b; | |
| | | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m | |
| | | ods.end(); i++ ) | |
| | | i->second->appendForOpLog( b ); | |
| | | return b.obj(); | |
| | | } | |
| | | | |
| bool DEPRECATED_haveArrayDepMod() const { | | bool DEPRECATED_haveArrayDepMod() const { | |
| for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ ) | | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ ) | |
| if ( i->second->m->arrayDep() ) | | if ( i->second->m->arrayDep() ) | |
| return true; | | return true; | |
| return false; | | return false; | |
| } | | } | |
| | | | |
| void DEPRECATED_appendSizeSpecForArrayDepMods( BSONObjBuilder& b )
const { | | void DEPRECATED_appendSizeSpecForArrayDepMods( BSONObjBuilder& b )
const { | |
| for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ ) { | | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m
ods.end(); i++ ) { | |
| | | | |
End of changes. 10 change blocks. |
| 24 lines changed or deleted | | 50 lines changed or added | |
|