allocator.h   allocator.h 
skipping to change at line 34 skipping to change at line 34
if ( x == 0 ) dbexit( EXIT_OOM_MALLOC , "malloc fails"); if ( x == 0 ) dbexit( EXIT_OOM_MALLOC , "malloc fails");
return x; return x;
} }
inline void * ourrealloc(void *ptr, size_t size) { inline void * ourrealloc(void *ptr, size_t size) {
void *x = realloc(ptr, size); void *x = realloc(ptr, size);
if ( x == 0 ) dbexit( EXIT_OOM_REALLOC , "realloc fails"); if ( x == 0 ) dbexit( EXIT_OOM_REALLOC , "realloc fails");
return x; return x;
} }
#define malloc mongo::ourmalloc #define MONGO_malloc mongo::ourmalloc
#define realloc mongo::ourrealloc #define malloc MONGO_malloc
#define MONGO_realloc mongo::ourrealloc
#define realloc MONGO_realloc
} // namespace mongo } // namespace mongo
 End of changes. 1 change blocks. 
2 lines changed or deleted 4 lines changed or added


 assert_util.h   assert_util.h 
skipping to change at line 139 skipping to change at line 139
return "userassert:" + msg; return "userassert:" + msg;
} }
}; };
class MsgAssertionException : public AssertionException { class MsgAssertionException : public AssertionException {
public: public:
MsgAssertionException(int c, const char *m) { MsgAssertionException(int c, const char *m) {
code = c; code = c;
msg = m; msg = m;
} }
MsgAssertionException(int c, const string& m) {
code = c;
msg = m;
}
virtual bool severe() { virtual bool severe() {
return false; return false;
} }
virtual string toString() const { virtual string toString() const {
return "massert:" + msg; return "massert:" + msg;
} }
}; };
void asserted(const char *msg, const char *file, unsigned line); void asserted(const char *msg, const char *file, unsigned line);
void wasserted(const char *msg, const char *file, unsigned line); void wasserted(const char *msg, const char *file, unsigned line);
void uasserted(int msgid, const char *msg); void uasserted(int msgid, const char *msg);
inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_ str()); } inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_ str()); }
void uassert_nothrow(const char *msg); // reported via lasterror, but d on't throw exception void uassert_nothrow(const char *msg); // reported via lasterror, but d on't throw exception
void msgassertedNoTrace(int msgid, const char *msg);
void msgasserted(int msgid, const char *msg); void msgasserted(int msgid, const char *msg);
inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg .c_str()); } inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg .c_str()); }
#ifdef assert #ifdef assert
#undef assert #undef assert
#endif #endif
#define assert(_Expression) (void)( (!!(_Expression)) || (mongo::asserted(# #define MONGO_assert(_Expression) (void)( (!!(_Expression)) || (mongo::asse
_Expression, __FILE__, __LINE__), 0) ) rted(#_Expression, __FILE__, __LINE__), 0) )
#define assert MONGO_assert
/* "user assert". if asserts, user did something wrong, not our code * / /* "user assert". if asserts, user did something wrong, not our code * /
//#define uassert( 10269 , _Expression) (void)( (!!(_Expression)) || (uasse inline void uassert(unsigned msgid, string msg, bool expr) {
rted(#_Expression, __FILE__, __LINE__), 0) ) if( !expr ) uasserted(msgid, msg.c_str());
#define uassert(msgid, msg,_Expression) (void)( (!!(_Expression)) || (mongo }
::uasserted(msgid, msg), 0) )
#define xassert(_Expression) (void)( (!!(_Expression)) || (mongo::asserted( template<class T>
#_Expression, __FILE__, __LINE__), 0) ) inline void uassert(unsigned msgid, string msg, const T&t , bool expr)
{
if( !expr ){
stringstream ss;
ss << msg << " " << t.toString();
uasserted(msgid, ss.str());
}
}
#define yassert 1 inline void uassert(unsigned msgid, const char * msg, bool expr) {
if( !expr ) uasserted(msgid, msg);
}
/* warning only - keeps going */ /* warning only - keeps going */
#define wassert(_Expression) (void)( (!!(_Expression)) || (mongo::wasserted #define MONGO_wassert(_Expression) (void)( (!!(_Expression)) || (mongo::was
(#_Expression, __FILE__, __LINE__), 0) ) serted(#_Expression, __FILE__, __LINE__), 0) )
#define wassert MONGO_wassert
/* display a message, no context, and throw assertionexception /* display a message, no context, and throw assertionexception
easy way to throw an exception and log something without our stack t race easy way to throw an exception and log something without our stack t race
display happening. display happening.
*/ */
#define massert(msgid, msg,_Expression) (void)( (!!(_Expression)) || (mongo inline void massert(unsigned msgid, string msg, bool expr) {
::msgasserted(msgid, msg), 0) ) if( !expr) msgasserted(msgid, msg.c_str());
}
inline void massert(unsigned msgid, const char * msg, bool expr) {
if( !expr) msgasserted(msgid, msg);
}
/* dassert is 'debug assert' -- might want to turn off for production a s these /* dassert is 'debug assert' -- might want to turn off for production a s these
could be slow. could be slow.
*/ */
#if defined(_DEBUG) #if defined(_DEBUG)
#define dassert assert # define MONGO_dassert assert
#else #else
#define dassert(x) # define MONGO_dassert(x)
#endif #endif
#define dassert MONGO_dassert
// some special ids that we want to duplicate // some special ids that we want to duplicate
// > 10000 asserts // > 10000 asserts
// < 10000 UserException // < 10000 UserException
#define ASSERT_ID_DUPKEY 11000 enum { ASSERT_ID_DUPKEY = 11000 };
/* throws a uassertion with an appropriate msg */
void streamNotGood( int code , string msg , std::ios& myios ); void streamNotGood( int code , string msg , std::ios& myios );
#define ASSERT_STREAM_GOOD(msgid,msg,stream) (void)( (!!((stream).good())) inline void assertStreamGood(unsigned msgid, string msg, std::ios& myio
|| (mongo::streamNotGood(msgid, msg, stream), 0) ) s) {
if( !myios.good() ) streamNotGood(msgid, msg, myios);
}
string demangleName( const type_info& typeinfo );
} // namespace mongo } // namespace mongo
#define BOOST_CHECK_EXCEPTION( expression ) \ #define BOOST_CHECK_EXCEPTION MONGO_BOOST_CHECK_EXCEPTION
#define MONGO_BOOST_CHECK_EXCEPTION( expression ) \
try { \ try { \
expression; \ expression; \
} catch ( const std::exception &e ) { \ } catch ( const std::exception &e ) { \
problem() << "caught boost exception: " << e.what() << endl; \ problem() << "caught boost exception: " << e.what() << endl; \
assert( false ); \ assert( false ); \
} catch ( ... ) { \ } catch ( ... ) { \
massert( 10437 , "unknown boost failed" , false ); \ massert( 10437 , "unknown boost failed" , false ); \
} }
#define DESTRUCTOR_GUARD( expression ) \ #define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD
#define MONGO_DESTRUCTOR_GUARD( expression ) \
try { \ try { \
expression; \ expression; \
} catch ( const std::exception &e ) { \ } catch ( const std::exception &e ) { \
problem() << "caught exception (" << e.what() << ") in destructor ( " << __FUNCTION__ << ")" << endl; \ problem() << "caught exception (" << e.what() << ") in destructor ( " << __FUNCTION__ << ")" << endl; \
} catch ( ... ) { \ } catch ( ... ) { \
problem() << "caught unknown exception in destructor (" << __FUNCTI ON__ << ")" << endl; \ problem() << "caught unknown exception in destructor (" << __FUNCTI ON__ << ")" << endl; \
} }
 End of changes. 16 change blocks. 
20 lines changed or deleted 47 lines changed or added


 atomic_int.h   atomic_int.h 
skipping to change at line 25 skipping to change at line 25
* 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
#if defined(_WIN32) #if defined(_WIN32)
# include <windows.h> # include <windows.h>
#endif #endif
namespace mongo{ namespace mongo {
struct AtomicUInt{ struct AtomicUInt{
AtomicUInt() : x(0) {} AtomicUInt() : x(0) {}
AtomicUInt(unsigned z) : x(z) { } AtomicUInt(unsigned z) : x(z) { }
volatile unsigned x; volatile unsigned x;
operator unsigned() const { operator unsigned() const {
return x; return x;
} }
inline AtomicUInt operator++(); // ++prefix inline AtomicUInt operator++(); // ++prefix
inline AtomicUInt operator++(int);// postfix++ inline AtomicUInt operator++(int);// postfix++
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 btree.h   btree.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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
#include "diskloc.h" #include "diskloc.h"
#include "pdfile.h" #include "pdfile.h"
namespace mongo { namespace mongo {
#pragma pack(1) #pragma pack(1)
struct _KeyNode { struct _KeyNode {
DiskLoc prevChildBucket; // the lchild DiskLoc prevChildBucket; // the lchild
skipping to change at line 86 skipping to change at line 86
#pragma pack(1) #pragma pack(1)
/* this class is all about the storage management */ /* this class is all about the storage management */
class BucketBasics { class BucketBasics {
friend class BtreeBuilder; friend class BtreeBuilder;
friend class KeyNode; friend class KeyNode;
public: public:
void dumpTree(DiskLoc thisLoc, const BSONObj &order); void dumpTree(DiskLoc thisLoc, const BSONObj &order);
bool isHead() { return parent.isNull(); } bool isHead() { return parent.isNull(); }
void assertValid(const BSONObj &order, bool force = false); void assertValid(const Ordering &order, bool force = false);
void assertValid(const BSONObj &orderObj, bool force = false) {
return assertValid(Ordering::make(orderObj),force);
}
int fullValidate(const DiskLoc& thisLoc, const BSONObj &order); /* traverses everything */ int fullValidate(const DiskLoc& thisLoc, const BSONObj &order); /* traverses everything */
KeyNode keyNode(int i) const { KeyNode keyNode(int i) const {
if ( i >= n ){ if ( i >= n ){
massert( 13000 , (string)"invalid keyNode: " + BSON( "i" < < i << "n" << n ).jsonString() , i < n ); massert( 13000 , (string)"invalid keyNode: " + BSON( "i" < < i << "n" << n ).jsonString() , i < n );
} }
return KeyNode(*this, k(i)); return KeyNode(*this, k(i));
} }
protected: protected:
skipping to change at line 109 skipping to change at line 112
char * dataAt(short ofs) { char * dataAt(short ofs) {
return data + ofs; return data + ofs;
} }
void init(); // initialize a new node void init(); // initialize a new node
/* returns false if node is full and must be split /* returns false if node is full and must be split
keypos is where to insert -- inserted after that key #. so keyp os=0 is the leftmost one. keypos is where to insert -- inserted after that key #. so keyp os=0 is the leftmost one.
*/ */
bool basicInsert(const DiskLoc& thisLoc, int keypos, const DiskLoc& recordLoc, const BSONObj& key, const BSONObj &order); bool basicInsert(const DiskLoc& thisLoc, int keypos, const DiskLoc& recordLoc, const BSONObj& key, const Ordering &order);
/** /**
* @return true if works, false if not enough space * @return true if works, false if not enough space
*/ */
bool _pushBack(const DiskLoc& recordLoc, BSONObj& key, const BSONOb bool _pushBack(const DiskLoc& recordLoc, BSONObj& key, const Orderi
j &order, DiskLoc prevChild); ng &order, DiskLoc prevChild);
void pushBack(const DiskLoc& recordLoc, BSONObj& key, const BSONObj void pushBack(const DiskLoc& recordLoc, BSONObj& key, const Orderin
&order, DiskLoc prevChild){ g &order, DiskLoc prevChild){
bool ok = _pushBack( recordLoc , key , order , prevChild ); bool ok = _pushBack( recordLoc , key , order , prevChild );
assert(ok); assert(ok);
} }
void popBack(DiskLoc& recLoc, BSONObj& key); void popBack(DiskLoc& recLoc, BSONObj& key);
void _delKeyAtPos(int keypos); // low level version that doesn't de al with child ptrs. void _delKeyAtPos(int keypos); // low level version that doesn't de al with child ptrs.
/* !Packed means there is deleted fragment space within the bucket. /* !Packed means there is deleted fragment space within the bucket.
We "repack" when we run out of space before considering the node We "repack" when we run out of space before considering the node
to be full. to be full.
*/ */
enum Flags { Packed=1 }; enum Flags { Packed=1 };
DiskLoc& childForPos(int p) { DiskLoc& childForPos(int p) {
return p == n ? nextChild : k(p).prevChildBucket; return p == n ? nextChild : k(p).prevChildBucket;
} }
int totalDataSize() const; int totalDataSize() const;
void pack( const BSONObj &order ); void pack( const Ordering &order );
void setNotPacked(); void setNotPacked();
void setPacked(); void setPacked();
int _alloc(int bytes); int _alloc(int bytes);
void _unalloc(int bytes); void _unalloc(int bytes);
void truncateTo(int N, const BSONObj &order); void truncateTo(int N, const Ordering &order);
void markUnused(int keypos); void markUnused(int keypos);
/* BtreeBuilder uses the parent var as a temp place to maintain a l inked list chain. /* BtreeBuilder uses the parent var as a temp place to maintain a l inked list chain.
we use tempNext() when we do that to be less confusing. (one mig ht have written a union in C) we use tempNext() when we do that to be less confusing. (one mig ht have written a union in C)
*/ */
DiskLoc& tempNext() { return parent; } DiskLoc& tempNext() { return parent; }
public: public:
DiskLoc parent; DiskLoc parent;
string bucketSummary() const { string bucketSummary() const {
stringstream ss; stringstream ss;
ss << " Bucket info:" << endl; ss << " Bucket info:" << endl;
ss << " n: " << n << endl; ss << " n: " << n << endl;
ss << " parent: " << parent.toString() << endl; ss << " parent: " << parent.toString() << endl;
ss << " nextChild: " << parent.toString() << endl; ss << " nextChild: " << parent.toString() << endl;
ss << " Size: " << _Size << " flags:" << flags << endl; ss << " flags:" << flags << endl;
ss << " emptySize: " << emptySize << " topSize: " << topSize << endl; ss << " emptySize: " << emptySize << " topSize: " << topSize << endl;
return ss.str(); return ss.str();
} }
bool isUsed( int i ) const { bool isUsed( int i ) const {
return k(i).isUsed(); return k(i).isUsed();
} }
protected: protected:
void _shape(int level, stringstream&); void _shape(int level, stringstream&);
DiskLoc nextChild; // child bucket off and to the right of the high est key. DiskLoc nextChild; // child bucket off and to the right of the high est key.
int _Size; // total size of this btree node in bytes. constant.
private:
unsigned short _wasSize; // can be reused, value is 8192 in current
pdfile version Apr2010
unsigned short _reserved1; // zero
protected:
int Size() const; int Size() const;
int flags; int flags;
int emptySize; // size of the empty region int emptySize; // size of the empty region
int topSize; // size of the data at the top of the bucket (keys are at the beginning or 'bottom') int topSize; // size of the data at the top of the bucket (keys are at the beginning or 'bottom')
int n; // # of keys so far. int n; // # of keys so far.
int reserved; int reserved;
const _KeyNode& k(int i) const { const _KeyNode& k(int i) const {
return ((_KeyNode*)data)[i]; return ((_KeyNode*)data)[i];
} }
_KeyNode& k(int i) { _KeyNode& k(int i) {
skipping to change at line 194 skipping to change at line 202
friend class BtreeCursor; friend class BtreeCursor;
public: public:
void dump(); void dump();
/* @return true if key exists in index /* @return true if key exists in index
order - indicates order of keys in the index. this is basically the index's key pattern, e.g.: order - indicates order of keys in the index. this is basically the index's key pattern, e.g.:
BSONObj order = ((IndexDetails&)idx).keyPattern(); BSONObj order = ((IndexDetails&)idx).keyPattern();
likewise below in bt_insert() etc. likewise below in bt_insert() etc.
*/ */
bool exists(const IndexDetails& idx, DiskLoc thisLoc, const BSONObj & key, BSONObj order); bool exists(const IndexDetails& idx, DiskLoc thisLoc, const BSONObj & key, const Ordering& order);
bool wouldCreateDup( bool wouldCreateDup(
const IndexDetails& idx, DiskLoc thisLoc, const IndexDetails& idx, DiskLoc thisLoc,
const BSONObj& key, BSONObj order, const BSONObj& key, const Ordering& order,
DiskLoc self); DiskLoc self);
static DiskLoc addBucket(IndexDetails&); /* start a new index off, empty */ static DiskLoc addBucket(IndexDetails&); /* start a new index off, empty */
void deallocBucket(const DiskLoc &thisLoc); // clear bucket memory, placeholder for deallocation void deallocBucket(const DiskLoc &thisLoc); // clear bucket memory, placeholder for deallocation
static void renameIndexNamespace(const char *oldNs, const char *new Ns); static void renameIndexNamespace(const char *oldNs, const char *new Ns);
int bt_insert(DiskLoc thisLoc, DiskLoc recordLoc, int bt_insert(DiskLoc thisLoc, DiskLoc recordLoc,
const BSONObj& key, const BSONObj &order, bool dupsAllow ed, const BSONObj& key, const Ordering &order, bool dupsAllo wed,
IndexDetails& idx, bool toplevel = true); IndexDetails& idx, bool toplevel = true);
bool unindex(const DiskLoc& thisLoc, IndexDetails& id, BSONObj& key , const DiskLoc& recordLoc); bool unindex(const DiskLoc& thisLoc, IndexDetails& id, BSONObj& key , const DiskLoc& recordLoc);
/* locate may return an "unused" key that is just a marker. so be careful. /* locate may return an "unused" key that is just a marker. so be careful.
looks for a key:recordloc pair. looks for a key:recordloc pair.
found - returns true if exact match found. note you can get bac k a position found - returns true if exact match found. note you can get bac k a position
result even if found is false. result even if found is false.
*/ */
DiskLoc locate(const IndexDetails& , const DiskLoc& thisLoc, const BSONObj& key, const BSONObj &order, DiskLoc locate(const IndexDetails& , const DiskLoc& thisLoc, const BSONObj& key, const Ordering &order,
int& pos, bool& found, DiskLoc recordLoc, int direct ion=1); int& pos, bool& found, DiskLoc recordLoc, int direct ion=1);
/** /**
* find the first instance of the key * find the first instance of the key
* does not handle dups * does not handle dups
* returned DiskLock isNull if can't find anything with that * returned DiskLock isNull if can't find anything with that
*/ */
DiskLoc findSingle( const IndexDetails& , const DiskLoc& thisLoc, c onst BSONObj& key ); DiskLoc findSingle( const IndexDetails& , const DiskLoc& thisLoc, c onst BSONObj& key );
/* advance one key position in the index: */ /* advance one key position in the index: */
skipping to change at line 246 skipping to change at line 254
private: private:
void fixParentPtrs(const DiskLoc& thisLoc); void fixParentPtrs(const DiskLoc& thisLoc);
void delBucket(const DiskLoc& thisLoc, IndexDetails&); void delBucket(const DiskLoc& thisLoc, IndexDetails&);
void delKeyAtPos(const DiskLoc& thisLoc, IndexDetails& id, int p); void delKeyAtPos(const DiskLoc& thisLoc, IndexDetails& id, int p);
BSONObj keyAt(int keyOfs) { BSONObj keyAt(int keyOfs) {
return keyOfs >= n ? BSONObj() : keyNode(keyOfs).key; return keyOfs >= n ? BSONObj() : keyNode(keyOfs).key;
} }
static BtreeBucket* allocTemp(); /* caller must release with free() */ static BtreeBucket* allocTemp(); /* caller must release with free() */
void insertHere(DiskLoc thisLoc, int keypos, void insertHere(DiskLoc thisLoc, int keypos,
DiskLoc recordLoc, const BSONObj& key, const BSONOb j &order, DiskLoc recordLoc, const BSONObj& key, const Orderi ng &order,
DiskLoc lchild, DiskLoc rchild, IndexDetails&); DiskLoc lchild, DiskLoc rchild, IndexDetails&);
int _insert(DiskLoc thisLoc, DiskLoc recordLoc, int _insert(DiskLoc thisLoc, DiskLoc recordLoc,
const BSONObj& key, const BSONObj &order, bool dupsAllo wed, const BSONObj& key, const Ordering &order, bool dupsAll owed,
DiskLoc lChild, DiskLoc rChild, IndexDetails&); DiskLoc lChild, DiskLoc rChild, IndexDetails&);
bool find(const IndexDetails& idx, const BSONObj& key, DiskLoc reco rdLoc, const BSONObj &order, int& pos, bool assertIfDup); bool find(const IndexDetails& idx, const BSONObj& key, DiskLoc reco rdLoc, const Ordering &order, int& pos, bool assertIfDup);
static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largest Loc, int& largestKey); static void findLargestKey(const DiskLoc& thisLoc, DiskLoc& largest Loc, int& largestKey);
public: public:
// simply builds and returns a dup key error message string // simply builds and returns a dup key error message string
static string dupKeyError( const IndexDetails& idx , const BSONObj& key ); static string dupKeyError( const IndexDetails& idx , const BSONObj& key );
}; };
class BtreeCursor : public Cursor { class BtreeCursor : public Cursor {
public: public:
BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails&, const BSONObj &startKey, const BSONObj &endKey, bool endKeyInclusive, int direction ); BtreeCursor( NamespaceDetails *_d, int _idxNo, const IndexDetails&, const BSONObj &startKey, const BSONObj &endKey, bool endKeyInclusive, int direction );
skipping to change at line 392 skipping to change at line 400
BSONObj keyAtKeyOfs; // so we can tell if things moved around on us between the query and the getMore call BSONObj keyAtKeyOfs; // so we can tell if things moved around on us between the query and the getMore call
DiskLoc locAtKeyOfs; DiskLoc locAtKeyOfs;
BoundList bounds_; BoundList bounds_;
unsigned boundIndex_; unsigned boundIndex_;
const IndexSpec& _spec; const IndexSpec& _spec;
}; };
#pragma pack() #pragma pack()
inline bool IndexDetails::hasKey(const BSONObj& key) { inline bool IndexDetails::hasKey(const BSONObj& key) {
return head.btree()->exists(*this, head, key, keyPattern()); return head.btree()->exists(*this, head, key, Ordering::make(keyPat tern()));
} }
inline bool IndexDetails::wouldCreateDup(const BSONObj& key, DiskLoc se lf) { inline bool IndexDetails::wouldCreateDup(const BSONObj& key, DiskLoc se lf) {
return head.btree()->wouldCreateDup(*this, head, key, keyPattern(), self); return head.btree()->wouldCreateDup(*this, head, key, Ordering::mak e(keyPattern()), self);
} }
/* build btree from the bottom up */ /* build btree from the bottom up */
/* _ TODO dropDups */ /* _ TODO dropDups */
class BtreeBuilder { class BtreeBuilder {
bool dupsAllowed; bool dupsAllowed;
IndexDetails& idx; IndexDetails& idx;
unsigned long long n; unsigned long long n;
BSONObj keyLast; BSONObj keyLast;
BSONObj order; BSONObj order;
Ordering ordering;
bool committed; bool committed;
DiskLoc cur, first; DiskLoc cur, first;
BtreeBucket *b; BtreeBucket *b;
void newBucket(); void newBucket();
void buildNextLevel(DiskLoc); void buildNextLevel(DiskLoc);
public: public:
~BtreeBuilder(); ~BtreeBuilder();
 End of changes. 18 change blocks. 
20 lines changed or deleted 30 lines changed or added


 builder.h   builder.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 "../stdafx.h" #include <string>
#include <string.h> #include <string.h>
#include <stdio.h>
#include <boost/shared_ptr.hpp>
namespace mongo { namespace mongo {
class StringBuilder; class StringBuilder;
class BufBuilder { class BufBuilder {
public: public:
BufBuilder(int initsize = 512) : size(initsize) { BufBuilder(int initsize = 512) : size(initsize) {
if ( size > 0 ) { if ( size > 0 ) {
data = (char *) malloc(size); data = (char *) malloc(size);
assert(data); assert(data != 0);
} else { } else {
data = 0; data = 0;
} }
l = 0; l = 0;
} }
~BufBuilder() { ~BufBuilder() {
kill(); kill();
} }
void kill() { void kill() {
skipping to change at line 94 skipping to change at line 96
append<unsigned>(j); append<unsigned>(j);
} }
void append(bool j) { void append(bool j) {
append<bool>(j); append<bool>(j);
} }
void append(double j) { void append(double j) {
append<double>(j); append<double>(j);
} }
void append(const void *src, size_t len) { void append(const void *src, size_t len) {
memcpy(grow(len), src, len); memcpy(grow((int) len), src, len);
} }
void append(const char *str) { void append(const char *str) {
append((void*) str, strlen(str)+1); append((void*) str, strlen(str)+1);
} }
void append(const string &str) { void append(const std::string &str) {
append( (void *)str.c_str(), str.length() + 1 ); append( (void *)str.c_str(), str.length() + 1 );
} }
void append( int val , int padding ){
}
int len() const { int len() const {
return l; return l;
} }
void setlen( int newLen ){ void setlen( int newLen ){
l = newLen; l = newLen;
} }
private: private:
/* returns the pre-grow write position */ /* returns the pre-grow write position */
skipping to change at line 142 skipping to change at line 140
return data + oldlen; return data + oldlen;
} }
char *data; char *data;
int l; int l;
int size; int size;
friend class StringBuilder; friend class StringBuilder;
}; };
#if defined(_WIN32)
#pragma warning( disable : 4996 )
#endif
class StringBuilder { class StringBuilder {
public: public:
StringBuilder( int initsize=256 ) StringBuilder( int initsize=256 )
: _buf( initsize ){ : _buf( initsize ){
} }
#define SBNUM(val,maxSize,macro) \ #define SBNUM(val,maxSize,macro) \
int prev = _buf.l; \ int prev = _buf.l; \
int z = sprintf( _buf.grow(maxSize) , macro , (val) ); \ int z = sprintf( _buf.grow(maxSize) , macro , (val) ); \
_buf.l = prev + z; \ _buf.l = prev + z; \
skipping to change at line 182 skipping to change at line 184
StringBuilder& operator<<( unsigned long long x ){ StringBuilder& operator<<( unsigned long long x ){
SBNUM( x , 22 , "%llu" ); SBNUM( x , 22 , "%llu" );
} }
StringBuilder& operator<<( short x ){ StringBuilder& operator<<( short x ){
SBNUM( x , 8 , "%hd" ); SBNUM( x , 8 , "%hd" );
} }
StringBuilder& operator<<( char c ){ StringBuilder& operator<<( char c ){
_buf.grow( 1 )[0] = c; _buf.grow( 1 )[0] = c;
return *this; return *this;
} }
#undef SBNUM
void append( const char * str ){ void append( const char * str ){
int x = strlen( str ); int x = (int) strlen( str );
memcpy( _buf.grow( x ) , str , x ); memcpy( _buf.grow( x ) , str , x );
} }
StringBuilder& operator<<( const char * str ){ StringBuilder& operator<<( const char * str ){
append( str ); append( str );
return *this; return *this;
} }
StringBuilder& operator<<( const string& s ){ StringBuilder& operator<<( const std::string& s ){
append( s.c_str() ); append( s.c_str() );
return *this; return *this;
} }
// access // access
void reset( int maxSize = 0 ){ void reset( int maxSize = 0 ){
_buf.reset( maxSize ); _buf.reset( maxSize );
} }
string str(){ std::string str(){
return string(_buf.data, _buf.l); return std::string(_buf.data, _buf.l);
} }
private: private:
BufBuilder _buf; BufBuilder _buf;
}; };
} // namespace mongo } // namespace mongo
 End of changes. 11 change blocks. 
12 lines changed or deleted 15 lines changed or added


 chunk.h   chunk.h 
skipping to change at line 26 skipping to change at line 26
* 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 "../stdafx.h" #include "../pch.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "../client/model.h" #include "../client/model.h"
#include "../bson/util/atomic_int.h"
#include "shardkey.h" #include "shardkey.h"
#include <boost/utility.hpp> #include "shard.h"
#undef assert
#define assert xassert
namespace mongo { namespace mongo {
class DBConfig; class DBConfig;
class ChunkManager; class ChunkManager;
class ChunkObjUnitTest; class ChunkObjUnitTest;
typedef unsigned long long ShardChunkVersion; typedef unsigned long long ShardChunkVersion;
/** /**
skipping to change at line 64 skipping to change at line 63
const BSONObj& getMin() const { return _min; } const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; } const BSONObj& getMax() const { return _max; }
void setMin(const BSONObj& o){ void setMin(const BSONObj& o){
_min = o; _min = o;
} }
void setMax(const BSONObj& o){ void setMax(const BSONObj& o){
_max = o; _max = o;
} }
string getShard() const{ Shard getShard() const{
return _shard; return _shard;
} }
void setShard( string shard ); void setShard( const Shard& shard );
bool contains( const BSONObj& obj ) const; bool contains( const BSONObj& obj ) const;
string toString() const; string toString() const;
operator string() const { return toString(); } operator string() const { return toString(); }
friend ostream& operator << (ostream& out, const Chunk& c){ return (out << c.toString()); }
bool operator==(const Chunk& s) const; bool operator==(const Chunk& s) const;
bool operator!=(const Chunk& s) const{ bool operator!=(const Chunk& s) const{
return ! ( *this == s ); return ! ( *this == s );
} }
void getFilter( BSONObjBuilder& b ) const; void getFilter( BSONObjBuilder& b ) const;
BSONObj getFilter() const{ BSONObjBuilder b; getFilter( b ); return b.obj(); } BSONObj getFilter() const{ BSONObjBuilder b; getFilter( b ); return b.obj(); }
skipping to change at line 107 skipping to change at line 107
* 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
*/ */
bool splitIfShould( long dataWritten ); bool splitIfShould( long dataWritten );
/* /*
* moves either this shard or newShard if it makes sense too * moves either this shard or newShard if it makes sense too
* @return whether or not a shard was moved * @return whether or not a shard was moved
*/ */
bool moveIfShould( Chunk * newShard = 0 ); bool moveIfShould( Chunk * newShard = 0 );
bool moveAndCommit( const string& to , string& errmsg ); bool moveAndCommit( const Shard& to , string& errmsg );
virtual const char * getNS(){ return "config.chunks"; } virtual const char * getNS(){ return "config.chunks"; }
virtual void serialize(BSONObjBuilder& to); virtual void serialize(BSONObjBuilder& to);
virtual void unserialize(const BSONObj& from); virtual void unserialize(const BSONObj& from);
virtual string modelServer(); virtual string modelServer();
void appendShortVersion( const char * name , BSONObjBuilder& b );
virtual void save( bool check=false ); virtual void save( bool check=false );
void ensureIndex(); void ensureIndex();
void _markModified(); void _markModified();
static int MaxChunkSize; static int MaxChunkSize;
static string genID( const string& ns , const BSONObj& min );
private: private:
// main shard info // main shard info
ChunkManager * _manager; ChunkManager * _manager;
ShardKeyPattern skey() const; ShardKeyPattern skey() const;
string _ns; string _ns;
BSONObj _min; BSONObj _min;
BSONObj _max; BSONObj _max;
string _shard; Shard _shard;
ShardChunkVersion _lastmod; ShardChunkVersion _lastmod;
bool _modified; bool _modified;
// transient stuff // transient stuff
long _dataWritten; long _dataWritten;
// methods, etc.. // methods, etc..
skipping to change at line 165 skipping to change at line 169
class ChunkManager { class ChunkManager {
public: public:
ChunkManager( DBConfig * config , string ns , ShardKeyPattern patte rn , bool unique ); ChunkManager( DBConfig * config , string ns , ShardKeyPattern patte rn , bool unique );
virtual ~ChunkManager(); virtual ~ChunkManager();
string getns(){ string getns(){
return _ns; return _ns;
} }
int numChunks(){ return _chunks.size(); } int numChunks(){ rwlock lk( _lock , false ); return _chunks.size();
Chunk* getChunk( int i ){ return _chunks[i]; } }
Chunk* getChunk( int i ){ rwlock lk( _lock , false ); return _chunk
s[i]; }
bool hasShardKey( const BSONObj& obj ); bool hasShardKey( const BSONObj& obj );
Chunk& findChunk( const BSONObj& obj ); Chunk& findChunk( const BSONObj& obj , bool retry = false );
Chunk* findChunkOnServer( const string& server ) const; Chunk* findChunkOnServer( const Shard& shard ) const;
ShardKeyPattern& getShardKey(){ return _key; } ShardKeyPattern& getShardKey(){ return _key; }
bool isUnique(){ return _unique; } bool isUnique(){ return _unique; }
/** /**
* makes sure the shard index is on all servers * makes sure the shard index is on all servers
*/ */
void ensureIndex(); void ensureIndex();
/** /**
* @return number of Chunk added to the vector * @return number of Chunk added to the vector
*/ */
int getChunksForQuery( vector<Chunk*>& chunks , const BSONObj& quer y ); int getChunksForQuery( vector<Chunk*>& chunks , const BSONObj& quer y );
void getAllServers( set<string>& allServers ); /**
* @return number of Shards added to the set
*/
int getShardsForQuery( set<Shard>& shards , const BSONObj& query );
void getAllShards( set<Shard>& all );
void save(); void save();
string toString() const; string toString() const;
operator string() const { return toString(); } operator string() const { return toString(); }
ShardChunkVersion getVersion( const string& server ) const; ShardChunkVersion getVersion( const Shard& shard ) const;
ShardChunkVersion getVersion() const; ShardChunkVersion getVersion() const;
/** /**
* this is just an increasing number of how many ChunkManagers we h ave so we know if something has been updated * this is just an increasing number of how many ChunkManagers we h ave so we know if something has been updated
*/ */
unsigned long long getSequenceNumber(){ unsigned long long getSequenceNumber(){
return _sequenceNumber; return _sequenceNumber;
} }
void drop(); void drop();
private: private:
void _reload();
void _load();
DBConfig * _config; DBConfig * _config;
string _ns; string _ns;
ShardKeyPattern _key; ShardKeyPattern _key;
bool _unique; bool _unique;
vector<Chunk*> _chunks; vector<Chunk*> _chunks;
map<string,unsigned long long> _maxMarkers; map<string,unsigned long long> _maxMarkers;
typedef map<BSONObj,Chunk*,BSONObjCmp> ChunkMap; typedef map<BSONObj,Chunk*,BSONObjCmp> ChunkMap;
ChunkMap _chunkMap; ChunkMap _chunkMap; // max -> Chunk
unsigned long long _sequenceNumber; unsigned long long _sequenceNumber;
RWLock _lock;
friend class Chunk; friend class Chunk;
static unsigned long long NextSequenceNumber; static AtomicUInt NextSequenceNumber;
/**
* @return number of Chunk matching the query or -1 for all chunks.
*/
int _getChunksForQuery( vector<Chunk*>& chunks , const BSONObj& que
ry );
}; };
// like BSONObjCmp. for use as an STL comparison functor // like BSONObjCmp. for use as an STL comparison functor
// key-order in "order" argument must match key-order in shardkey // key-order in "order" argument must match key-order in shardkey
class ChunkCmp { class ChunkCmp {
public: public:
ChunkCmp( const BSONObj &order = BSONObj() ) : _cmp( order ) {} ChunkCmp( const BSONObj &order = BSONObj() ) : _cmp( order ) {}
bool operator()( const Chunk &l, const Chunk &r ) const { bool operator()( const Chunk &l, const Chunk &r ) const {
return _cmp(l.getMin(), r.getMin()); return _cmp(l.getMin(), r.getMin());
} }
 End of changes. 18 change blocks. 
16 lines changed or deleted 39 lines changed or added


 client.h   client.h 
skipping to change at line 27 skipping to change at line 27
*/ */
/* Client represents a connection to the database (the server-side) and cor responds /* Client represents a connection to the database (the server-side) and cor responds
to an open socket (or logical connection if pooling on sockets) from a c lient. to an open socket (or logical connection if pooling on sockets) from a c lient.
todo: switch to asio...this will fit nicely with that. todo: switch to asio...this will fit nicely with that.
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
#include "security.h" #include "security.h"
#include "namespace.h" #include "namespace.h"
#include "lasterror.h" #include "lasterror.h"
#include "stats/top.h" #include "stats/top.h"
namespace mongo { namespace mongo {
class AuthenticationInfo; class AuthenticationInfo;
class Database; class Database;
class CurOp; class CurOp;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 clientcursor.h   clientcursor.h 
skipping to change at line 27 skipping to change at line 27
*/ */
/* Cursor -- and its derived classes -- are our internal cursors. /* Cursor -- and its derived classes -- are our internal cursors.
ClientCursor is a wrapper that represents a cursorid from our database ClientCursor is a wrapper that represents a cursorid from our database
application's perspective. application's perspective.
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
#include "cursor.h" #include "cursor.h"
#include "jsobj.h" #include "jsobj.h"
#include "../util/message.h" #include "../util/message.h"
#include "../util/background.h"
#include "diskloc.h" #include "diskloc.h"
#include "dbhelpers.h" #include "dbhelpers.h"
#include "matcher.h" #include "matcher.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
namespace mongo { namespace mongo {
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 */
class Cursor; /* internal server cursor base class */ class Cursor; /* internal server cursor base class */
class ClientCursor; class ClientCursor;
skipping to change at line 289 skipping to change at line 290
void setDoingDeletes( bool doingDeletes ){ void setDoingDeletes( bool doingDeletes ){
_doingDeletes = doingDeletes; _doingDeletes = doingDeletes;
} }
static unsigned byLocSize(); // just for diagnostics static unsigned byLocSize(); // just for diagnostics
static void informAboutToDeleteBucket(const DiskLoc& b); static void informAboutToDeleteBucket(const DiskLoc& b);
static void aboutToDelete(const DiskLoc& dl); static void aboutToDelete(const DiskLoc& dl);
}; };
class ClientCursorMonitor : public BackgroundJob {
public:
void run();
};
extern ClientCursorMonitor clientCursorMonitor;
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
1 lines changed or deleted 9 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 "../stdafx.h" #include "../pch.h"
namespace mongo { namespace mongo {
/* command line options /* command line options
*/ */
/* concurrency: OK/READ */ /* concurrency: OK/READ */
struct CmdLine { struct CmdLine {
int port; // --port int port; // --port
bool rest; // --rest bool rest; // --rest
string replSet; // --replSet <seedlist>
string source; // --source string source; // --source
string only; // --only string only; // --only
bool quiet; // --quiet bool quiet; // --quiet
bool notablescan; // --notablescan bool notablescan; // --notablescan
bool prealloc; // --noprealloc bool prealloc; // --noprealloc
bool smallfiles; // --smallfiles bool smallfiles; // --smallfiles
bool quota; // --quota bool quota; // --quota
int quotaFiles; // --quotaFiles int quotaFiles; // --quotaFiles
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 commands.h   commands.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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
namespace mongo { namespace mongo {
class BSONObj; class BSONObj;
class BSONObjBuilder; class BSONObjBuilder;
class BufBuilder; class BufBuilder;
class Client; class Client;
// db "commands" (sent via db.$cmd.findOne(...)) /** mongodb "commands" (sent via db.$cmd.findOne(...))
// subclass to make a command. subclass to make a command. define a singleton object for it.
*/
class Command { class Command {
public: public:
enum LockType { READ = -1 , NONE = 0 , WRITE = 1 }; enum LockType { READ = -1 , NONE = 0 , WRITE = 1 };
string name; const string name;
/* run the given command /* run the given command
implement this... implement this...
fromRepl - command is being invoked as part of replication synci ng. In this situation you fromRepl - command is being invoked as part of replication synci ng. In this situation you
normally do not want to log the command to the local oplog. normally do not want to log the command to the local oplog.
return value is true if succeeded. if false, set errmsg text. return value is true if succeeded. if false, set errmsg text.
*/ */
virtual bool run(const char *ns, BSONObj& cmdObj, string& errmsg, B SONObjBuilder& result, bool fromRepl) = 0; virtual bool run(const char *ns, BSONObj& cmdObj, string& errmsg, B SONObjBuilder& result, bool fromRepl) = 0;
/* /*
note: logTheTop() MUST be false if READ note: logTheTop() MUST be false if READ
if NONE, can't use Client::Context setup if NONE, can't use Client::Context setup
use with caution use with caution
*/ */
virtual LockType locktype() = 0; virtual LockType locktype() const = 0;
/* Return true if only the admin ns has privileges to run this comm and. */ /* Return true if only the admin ns has privileges to run this comm and. */
virtual bool adminOnly() { virtual bool adminOnly() const {
return false; return false;
} }
void htmlHelp(stringstream&) const;
/* Like adminOnly, but even stricter: we must either be authenticat ed for admin db, /* Like adminOnly, but even stricter: we must either be authenticat ed for admin db,
or, if running without auth, on the local interface. or, if running without auth, on the local interface.
When localHostOnlyIfNoAuth() is true, adminOnly() must also be t rue. When localHostOnlyIfNoAuth() is true, adminOnly() must also be t rue.
*/ */
virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return false; } virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return false; }
/* Return true if slaves of a replication pair are allowed to execu te the command /* Return true if slaves of a replication pair are allowed to execu te the command
(the command directly from a client -- if fromRepl, always allow ed). (the command directly from a client -- if fromRepl, always allow ed).
*/ */
virtual bool slaveOk() = 0; virtual bool slaveOk() const = 0;
/* Return true if the client force a command to be run on a slave b y /* Return true if the client force a command to be run on a slave b y
turning on the 'slaveok' option in the command query. turning on the 'slaveok' option in the command query.
*/ */
virtual bool slaveOverrideOk() { virtual bool slaveOverrideOk() {
return false; return false;
} }
/* Override and return true to if true,log the operation (logOp()) to the replication log. /* Override and return true to if true,log the operation (logOp()) to the replication log.
(not done if fromRepl of course) (not done if fromRepl of course)
skipping to change at line 96 skipping to change at line 99
return false; return false;
} }
virtual void help( stringstream& help ) const; virtual void help( stringstream& help ) const;
/* Return true if authentication and security applies to the comman ds. Some commands /* Return true if authentication and security applies to the comman ds. Some commands
(e.g., getnonce, authenticate) can be done by anyone even unauth orized. (e.g., getnonce, authenticate) can be done by anyone even unauth orized.
*/ */
virtual bool requiresAuth() { return true; } virtual bool requiresAuth() { return true; }
Command(const char *_name); /** @param webUI expose the command in the web ui as localhost:2801
7/<name>
@param oldName an optional old, deprecated name for the command
*/
Command(const char *_name, bool webUI = false, const char *oldName
= 0);
virtual ~Command() {} virtual ~Command() {}
protected: protected:
BSONObj getQuery( const BSONObj& cmdObj ){ BSONObj getQuery( const BSONObj& cmdObj ){
if ( cmdObj["query"].type() == Object ) if ( cmdObj["query"].type() == Object )
return cmdObj["query"].embeddedObject(); return cmdObj["query"].embeddedObject();
if ( cmdObj["q"].type() == Object ) if ( cmdObj["q"].type() == Object )
return cmdObj["q"].embeddedObject(); return cmdObj["q"].embeddedObject();
return BSONObj(); return BSONObj();
} }
static map<string,Command*> * _commands; static map<string,Command*> * _commands;
static map<string,Command*> * _commandsByBestName;
static map<string,Command*> * _webCommands;
public: public:
static const map<string,Command*>* commandsByBestName() { return _c
ommandsByBestName; }
static const map<string,Command*>* webCommands() { return _webComma
nds; }
static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS ONObjBuilder& anObjBuilder); static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BS ONObjBuilder& anObjBuilder);
static LockType locktype( const string& name ); static LockType locktype( const string& name );
static Command * findCommand( const string& name ); static Command * findCommand( const string& name );
}; };
bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions); bool _runCommands(const char *ns, BSONObj& jsobj, BufBuilder &b, BSONOb jBuilder& anObjBuilder, bool fromRepl, int queryOptions);
} // namespace mongo } // namespace mongo
 End of changes. 10 change blocks. 
8 lines changed or deleted 23 lines changed or added


 connpool.h   connpool.h 
skipping to change at line 22 skipping to change at line 22
* 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 <stack> #include <stack>
#include "dbclient.h" #include "dbclient.h"
#include "redef_macros.h"
namespace mongo { namespace mongo {
struct PoolForHost { struct PoolForHost {
PoolForHost()
: created(0){}
std::stack<DBClientBase*> pool; std::stack<DBClientBase*> pool;
long long created;
}; };
class DBConnectionHook { class DBConnectionHook {
public: public:
virtual ~DBConnectionHook(){} virtual ~DBConnectionHook(){}
virtual void onCreate( DBClientBase * conn ){} virtual void onCreate( DBClientBase * conn ){}
virtual void onHandedOut( DBClientBase * conn ){} virtual void onHandedOut( DBClientBase * conn ){}
}; };
skipping to change at line 54 skipping to change at line 58
request... request...
Usage: Usage:
{ {
ScopedDbConnection c("myserver"); ScopedDbConnection c("myserver");
c.conn()... c.conn()...
} }
*/ */
class DBConnectionPool { class DBConnectionPool {
mongo::mutex poolMutex; mongo::mutex _mutex;
map<string,PoolForHost*> pools; // servername -> pool map<string,PoolForHost*> _pools; // servername -> pool
list<DBConnectionHook*> _hooks; list<DBConnectionHook*> _hooks;
void onCreate( DBClientBase * conn ); void onCreate( DBClientBase * conn );
void onHandedOut( DBClientBase * conn ); void onHandedOut( DBClientBase * conn );
public: public:
void flush(); void flush();
DBClientBase *get(const string& host); DBClientBase *get(const string& host);
void release(const string& host, DBClientBase *c) { void release(const string& host, DBClientBase *c) {
if ( c->isFailed() ) if ( c->isFailed() ){
delete c;
return; return;
scoped_lock L(poolMutex); }
pools[host]->pool.push(c); scoped_lock L(_mutex);
_pools[host]->pool.push(c);
} }
void addHook( DBConnectionHook * hook ); void addHook( DBConnectionHook * hook );
void appendInfo( BSONObjBuilder& b );
}; };
extern DBConnectionPool pool; extern DBConnectionPool pool;
/** Use to get a connection from the pool. On exceptions things /** Use to get a connection from the pool. On exceptions things
clean up nicely. clean up nicely.
*/ */
class ScopedDbConnection { class ScopedDbConnection : boost::noncopyable {
const string host; const string _host;
DBClientBase *_conn; DBClientBase *_conn;
public: public:
/** get the associated connection object */ /** get the associated connection object */
DBClientBase* operator->(){ DBClientBase* operator->(){
uassert( 11004 , "did you call done already" , _conn ); uassert( 11004 , "did you call done already" , _conn );
return _conn; return _conn;
} }
/** get the associated connection object */ /** get the associated connection object */
DBClientBase& conn() { DBClientBase& conn() {
uassert( 11005 , "did you call done already" , _conn ); uassert( 11005 , "did you call done already" , _conn );
return *_conn; return *_conn;
} }
/** get the associated connection object */
DBClientBase* get() {
uassert( 13102 , "did you call done already" , _conn );
return _conn;
}
ScopedDbConnection()
: _host( "" ) , _conn(0) {
}
/** throws UserException if can't connect */ /** throws UserException if can't connect */
ScopedDbConnection(const string& _host) : ScopedDbConnection(const string& host)
host(_host), _conn( pool.get(_host) ) { : _host(host), _conn( pool.get(host) ) {
//cout << " for: " << _host << " got conn: " << _conn << endl;
} }
ScopedDbConnection(const string& host, DBClientBase* conn )
: _host( host ) , _conn( conn ){
}
string getHost() const { return _host; }
/** Force closure of the connection. You should call this if you l eave it in /** Force closure of the connection. You should call this if you l eave it in
a bad state. Destructor will do this too, but it is verbose. a bad state. Destructor will do this too, but it is verbose.
*/ */
void kill() { void kill() {
delete _conn; delete _conn;
_conn = 0; _conn = 0;
} }
/** Call this when you are done with the connection. /** Call this when you are done with the connection.
skipping to change at line 122 skipping to change at line 144
*/ */
void done() { void done() {
if ( ! _conn ) if ( ! _conn )
return; return;
/* we could do this, but instead of assume one is using autorec onnect mode on the connection /* we could do this, but instead of assume one is using autorec onnect mode on the connection
if ( _conn->isFailed() ) if ( _conn->isFailed() )
kill(); kill();
else else
*/ */
pool.release(host, _conn); pool.release(_host, _conn);
_conn = 0; _conn = 0;
} }
ScopedDbConnection * steal();
~ScopedDbConnection(); ~ScopedDbConnection();
}; };
} // namespace mongo } // namespace mongo
#include "undef_macros.h"
 End of changes. 14 change blocks. 
11 lines changed or deleted 35 lines changed or added


 counters.h   counters.h 
skipping to change at line 18 skipping to change at line 18
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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/>.
*/ */
#include "../../stdafx.h" #pragma once
#include "../../pch.h"
#include "../jsobj.h" #include "../jsobj.h"
#include "../../util/message.h" #include "../../util/message.h"
#include "../../util/processinfo.h" #include "../../util/processinfo.h"
namespace mongo { namespace mongo {
/** /**
* for storing operation counters * for storing operation counters
* note: not thread safe. ok with that for speed * note: not thread safe. ok with that for speed
*/ */
skipping to change at line 120 skipping to change at line 122
void append( BSONObjBuilder& b ); void append( BSONObjBuilder& b );
private: private:
long long _total_time; long long _total_time;
long long _flushes; long long _flushes;
int _last_time; int _last_time;
Date_t _last; Date_t _last;
}; };
extern FlushCounters globalFlushCounters; extern FlushCounters globalFlushCounters;
class GenericCounter {
public:
void hit( const string& name , int count=0 );
BSONObj getObj();
private:
map<string,long long> _counts; // TODO: replace with thread safe ma
p
mongo::mutex _mutex;
};
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 13 lines changed or added


 curop.h   curop.h 
skipping to change at line 22 skipping to change at line 22
* 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.h" #include "namespace.h"
#include "client.h" #include "client.h"
#include "../util/atomic_int.h" #include "../bson/util/atomic_int.h"
#include "db.h" #include "db.h"
namespace mongo { namespace mongo {
class OpDebug { class OpDebug {
public: public:
StringBuilder str; StringBuilder str;
void reset(){ void reset(){
str.reset(); str.reset();
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 cursor.h   cursor.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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
#include "diskloc.h" #include "diskloc.h"
namespace mongo { namespace mongo {
class Record; class Record;
/* Query cursors, base class. This is for our internal cursors. "Clie ntCursor" is a separate /* Query cursors, base class. This is for our internal cursors. "Clie ntCursor" is a separate
concept and is for the user's cursor. concept and is for the user's cursor.
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 cursors.h   cursors.h 
skipping to change at line 20 skipping to change at line 20
* 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 "../stdafx.h" #include "../pch.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
#include "../db/dbmessage.h" #include "../db/dbmessage.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "../client/parallel.h" #include "../client/parallel.h"
#include "request.h" #include "request.h"
namespace mongo { namespace mongo {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 d_logic.h   d_logic.h 
skipping to change at line 20 skipping to change at line 20
* 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 "../stdafx.h" #include "../pch.h"
namespace mongo { namespace mongo {
/** /**
* @return true if we have any shard info for the ns * @return true if we have any shard info for the ns
*/ */
bool haveLocalShardingInfo( const string& ns ); bool haveLocalShardingInfo( const string& ns );
/** /**
* @return true if the current threads shard version is ok, or not in s harded version * @return true if the current threads shard version is ok, or not in s harded version
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 db.h   db.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 "../stdafx.h" #include "../pch.h"
#include "../util/message.h" #include "../util/message.h"
#include "boost/version.hpp" #include "boost/version.hpp"
#include "concurrency.h" #include "concurrency.h"
#include "pdfile.h" #include "pdfile.h"
#include "client.h" #include "client.h"
namespace mongo { namespace mongo {
// void jniCallback(Message& m, Message& out); // void jniCallback(Message& m, Message& out);
skipping to change at line 211 skipping to change at line 211
real = new dbtemprelease(); real = new dbtemprelease();
} }
~dbtempreleasecond(){ ~dbtempreleasecond(){
if ( real ){ if ( real ){
delete real; delete real;
real = 0; real = 0;
} }
} }
bool unlocked(){
return real > 0;
}
}; };
extern TicketHolder connTicketHolder;
} // namespace mongo } // namespace mongo
//#include "dbinfo.h" //#include "dbinfo.h"
#include "concurrency.h" #include "concurrency.h"
 End of changes. 3 change blocks. 
3 lines changed or deleted 4 lines changed or added


 dbclient.h   dbclient.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 "../stdafx.h" #include "../pch.h"
#include "../util/message.h" #include "../util/message.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
#include "../db/json.h" #include "../db/json.h"
#include <stack> #include <stack>
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
skipping to change at line 75 skipping to change at line 75
enum UpdateOptions { enum UpdateOptions {
/** Upsert - that is, insert the item if no matching item is found. */ /** Upsert - that is, insert the item if no matching item is found. */
UpdateOption_Upsert = 1 << 0, UpdateOption_Upsert = 1 << 0,
/** Update multiple documents (if multiple documents match query ex pression). /** Update multiple documents (if multiple documents match query ex pression).
(Default is update a single document and stop.) */ (Default is update a single document and stop.) */
UpdateOption_Multi = 1 << 1 UpdateOption_Multi = 1 << 1
}; };
/**
* controls how much a clients cares about writes
* default is NORMAL
*/
enum WriteConcern {
W_NONE = 0 , // TODO: not every connection type fully supports this
W_NORMAL = 1
// TODO SAFE = 2
};
class BSONObj; class BSONObj;
class ScopedDbConnection;
class DBClientCursor;
/** Represents a Mongo query expression. Typically one uses the QUERY( ...) macro to construct a Query object. /** Represents a Mongo query expression. Typically one uses the QUERY( ...) macro to construct a Query object.
Examples: Examples:
QUERY( "age" << 33 << "school" << "UCLA" ).sort("name") QUERY( "age" << 33 << "school" << "UCLA" ).sort("name")
QUERY( "age" << GT << 30 << LT << 50 ) QUERY( "age" << GT << 30 << LT << 50 )
*/ */
class Query { class Query {
public: public:
BSONObj obj; BSONObj obj;
Query() : obj(BSONObj()) { } Query() : obj(BSONObj()) { }
skipping to change at line 163 skipping to change at line 175
Examples: Examples:
conn.findOne("test.coll", Query("{a:3}").where("this.b == 2 | | this.c == 3")); conn.findOne("test.coll", Query("{a:3}").where("this.b == 2 | | this.c == 3"));
Query badBalance = Query().where("this.debits - this.credits < 0"); Query badBalance = Query().where("this.debits - this.credits < 0");
*/ */
Query& where(const string &jscode, BSONObj scope); Query& where(const string &jscode, BSONObj scope);
Query& where(const string &jscode) { return where(jscode, BSONObj() ); } Query& where(const string &jscode) { return where(jscode, BSONObj() ); }
/** /**
* if this query has an orderby, hint, or some other field * if this query has an orderby, hint, or some other field
*/ */
bool isComplex() const; bool isComplex( bool * hasDollar = 0 ) const;
BSONObj getFilter() const; BSONObj getFilter() const;
BSONObj getSort() const; BSONObj getSort() const;
BSONObj getHint() const; BSONObj getHint() const;
bool isExplain() const; bool isExplain() const;
string toString() const; string toString() const;
operator string() const { return toString(); } operator string() const { return toString(); }
private: private:
void makeComplex(); void makeComplex();
skipping to change at line 201 skipping to change at line 213
*/ */
class DBConnector { class DBConnector {
public: public:
virtual ~DBConnector() {} virtual ~DBConnector() {}
virtual bool call( Message &toSend, Message &response, bool assertO k=true ) = 0; virtual bool call( Message &toSend, Message &response, bool assertO k=true ) = 0;
virtual void say( Message &toSend ) = 0; virtual void say( Message &toSend ) = 0;
virtual void sayPiggyBack( Message &toSend ) = 0; virtual void sayPiggyBack( Message &toSend ) = 0;
virtual void checkResponse( const string &data, int nReturned ) {} virtual void checkResponse( const string &data, int nReturned ) {}
}; };
/** Queries return a cursor object */
class DBClientCursor : boost::noncopyable {
friend class DBClientBase;
bool init();
public:
/** If true, safe to call next(). Requests more from server
if necessary. */
bool more();
/** If true, there is more in our local buffers to be fetched via n
ext(). Returns
false when a getMore request back to server would be required.
You can use this
if you want to exhaust whatever data has been fetched to the cl
ient already but
then perhaps stop.
*/
bool moreInCurrentBatch() { return !_putBack.empty() || pos < nRetu
rned; }
/** next
@return next object in the result cursor.
on an error at the remote server, you will get back:
{ $err: <string> }
if you do not want to handle that yourself, call nextSafe().
*/
BSONObj next();
/**
restore an object previously returned by next() to the cursor
*/
void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); }
/** throws AssertionException if get back { $err : ... } */
BSONObj nextSafe() {
BSONObj o = next();
BSONElement e = o.firstElement();
assert( strcmp(e.fieldName(), "$err") != 0 );
return o;
}
/**
iterate the rest of the cursor and return the number if items
*/
int itcount(){
int c = 0;
while ( more() ){
next();
c++;
}
return c;
}
/** cursor no longer valid -- use with tailable cursors.
note you should only rely on this once more() returns false;
'dead' may be preset yet some data still queued and locally
available from the dbclientcursor.
*/
bool isDead() const {
return cursorId == 0;
}
bool tailable() const {
return (opts & QueryOption_CursorTailable) != 0;
}
/** see QueryResult::ResultFlagType (db/dbmessage.h) for flag value
s
mostly these flags are for internal purposes -
ResultFlag_ErrSet is the possible exception to that
*/
bool hasResultFlag( int flag ){
return (resultFlags & flag) != 0;
}
DBClientCursor( DBConnector *_connector, const string &_ns, BSONObj
_query, int _nToReturn,
int _nToSkip, const BSONObj *_fieldsToReturn, int q
ueryOptions , int bs ) :
connector(_connector),
ns(_ns),
query(_query),
nToReturn(_nToReturn),
haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_C
ursorTailable)),
nToSkip(_nToSkip),
fieldsToReturn(_fieldsToReturn),
opts(queryOptions),
batchSize(bs),
m(new Message()),
cursorId(),
nReturned(),
pos(),
data(),
_ownCursor( true ) {
}
DBClientCursor( DBConnector *_connector, const string &_ns, long lo
ng _cursorId, int _nToReturn, int options ) :
connector(_connector),
ns(_ns),
nToReturn( _nToReturn ),
haveLimit( _nToReturn > 0 && !(options & QueryOption_Cursor
Tailable)),
opts( options ),
m(new Message()),
cursorId( _cursorId ),
nReturned(),
pos(),
data(),
_ownCursor( true ) {
}
virtual ~DBClientCursor();
long long getCursorId() const { return cursorId; }
/** by default we "own" the cursor and will send the server a KillC
ursor
message when ~DBClientCursor() is called. This function overrid
es that.
*/
void decouple() { _ownCursor = false; }
private:
int nextBatchSize();
DBConnector *connector;
string ns;
BSONObj query;
int nToReturn;
bool haveLimit;
int nToSkip;
const BSONObj *fieldsToReturn;
int opts;
int batchSize;
auto_ptr<Message> m;
stack< BSONObj > _putBack;
int resultFlags;
long long cursorId;
int nReturned;
int pos;
const char *data;
void dataReceived();
void requestMore();
bool _ownCursor; // see decouple()
};
/** /**
The interface that any db connection should implement The interface that any db connection should implement
*/ */
class DBClientInterface : boost::noncopyable { class DBClientInterface : boost::noncopyable {
public: public:
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) = 0; const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) = 0;
virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn = 0, int options = 0 ) = 0; virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn = 0, int options = 0 ) = 0;
skipping to change at line 373 skipping to change at line 248
}; };
/** /**
DB "commands" DB "commands"
Basically just invocations of connection.$cmd.findOne({...}); Basically just invocations of connection.$cmd.findOne({...});
*/ */
class DBClientWithCommands : public DBClientInterface { class DBClientWithCommands : public DBClientInterface {
set<string> _seenIndexes; set<string> _seenIndexes;
public: public:
/** controls how chatty the client is about network errors & such.
See log.h */
int _logLevel;
DBClientWithCommands() : _logLevel(0) { }
/** helper function. run a simple command where the command expression is simply /** helper function. run a simple command where the command expression is simply
{ command : 1 } { command : 1 }
@param info -- where to put result object. may be null if call er doesn't need that info @param info -- where to put result object. may be null if call er doesn't need that info
@param command -- command name @param command -- command name
@return true if the command returned "ok". @return true if the command returned "ok".
*/ */
bool simpleCommand(const string &dbname, BSONObj *info, const strin g &command); bool simpleCommand(const string &dbname, BSONObj *info, const strin g &command);
/** Run a database command. Database commands are represented as B SON objects. Common database /** Run a database command. Database commands are represented as B SON objects. Common database
commands have prebuilt helper functions -- see below. If a hel per is not available you can commands have prebuilt helper functions -- see below. If a hel per is not available you can
directly call runCommand. directly call runCommand.
@param dbname database name. Use "admin" for global administra tive commands. @param dbname database name. Use "admin" for global administra tive commands.
@param cmd the command object to execute. For exam ple, { ismaster : 1 } @param cmd the command object to execute. For exam ple, { ismaster : 1 }
@param info the result object the database returns. Typically has { ok : ..., errmsg : ... } fields @param info the result object the database returns. Typically has { ok : ..., errmsg : ... } fields
set. set.
@param options see enum QueryOptions - normally not needed to r un a command
@return true if the command returned "ok". @return true if the command returned "ok".
*/ */
virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info, int options=0); virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info, int options=0);
/** Authorize access to a particular database. /** Authorize access to a particular database.
Authentication is separate for each database on the server -- you may authenticate for any Authentication is separate for each database on the server -- you may authenticate for any
number of databases on a single connection. number of databases on a single connection.
The "admin" database is special and once authenticat ed provides access to all databases on the The "admin" database is special and once authenticat ed provides access to all databases on the
server. server.
@param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested @param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested
skipping to change at line 674 skipping to change at line 554
protected: protected:
bool isOk(const BSONObj&); bool isOk(const BSONObj&);
}; };
/** /**
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:
WriteConcern _writeConcern;
public: public:
DBClientBase(){
_writeConcern = W_NORMAL;
}
WriteConcern getWriteConcern() const { return _writeConcern; }
void setWriteConcern( WriteConcern w ){ _writeConcern = w; }
/** send a query to the database. /** send a query to the database.
ns: namespace to query, format is <dbname>.<collectname @param ns namespace to query, format is <dbname>.<collectname>[.<c
>[.<collectname>]* ollectname>]*
query: query to perform on the collection. this is a BSON @param query query to perform on the collection. this is a BSONOb
Obj (binary JSON) 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.
nToReturn: n to return. 0 = unlimited @param nToReturn n to return. 0 = unlimited
nToSkip: start with the nth item @param nToSkip start with the nth item
fieldsToReturn: @param fieldsToReturn optional template of which fields to select.
optional template of which fields to select. if unspecified, retur if unspecified, returns all fields
ns all fields @param queryOptions see options enum at top of this file
queryOptions: see options enum at top of this file
@return cursor. 0 if error (connection failure) @return cursor. 0 if error (connection failure)
@throws AssertionException @throws AssertionException
*/ */
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ); const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 );
/** @param cursorId id of cursor to retrieve /** @param cursorId id of cursor to retrieve
@return an handle to a previously allocated cursor @return an handle to a previously allocated cursor
@throws AssertionException @throws AssertionException
skipping to change at line 718 skipping to change at line 608
/** /**
remove matching objects from the database remove matching objects from the database
@param justOne if this true, then once a single match is found w ill stop @param justOne if this true, then once a single match is found w ill stop
*/ */
virtual void remove( const string &ns , Query q , bool justOne = 0 ); virtual void remove( const string &ns , Query q , bool justOne = 0 );
/** /**
updates objects matching query updates objects matching query
*/ */
virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = 0 , bool multi = 0 ); virtual void update( const string &ns , Query query , BSONObj obj , bool upsert = false , bool multi = false );
virtual string getServerAddress() const = 0; virtual string getServerAddress() const = 0;
virtual bool isFailed() const = 0; virtual bool isFailed() const = 0;
static int countCommas( const string& s ){ static int countCommas( const string& s ){
int n = 0; int n = 0;
for ( unsigned i=0; i<s.size(); i++ ) for ( unsigned i=0; i<s.size(); i++ )
if ( s[i] == ',' ) if ( s[i] == ',' )
n++; n++;
return n; return n;
} }
}; }; // end DBClientBase
class DBClientPaired; class DBClientPaired;
class ConnectException : public UserException { class ConnectException : public UserException {
public: public:
ConnectException(string msg) : UserException(9000,msg) { } ConnectException(string msg) : UserException(9000,msg) { }
}; };
/** /**
A basic connection to the database. A basic connection to the database.
skipping to change at line 761 skipping to change at line 651
string serverAddress; // remember for reconnects string serverAddress; // remember for reconnects
void _checkConnection(); void _checkConnection();
void checkConnection() { if( failed ) _checkConnection(); } void checkConnection() { if( failed ) _checkConnection(); }
map< string, pair<string,string> > authCache; map< string, pair<string,string> > authCache;
int _timeout; int _timeout;
public: public:
/** /**
@param _autoReconnect if true, automatically reconnect on a conn ection failure @param _autoReconnect if true, automatically reconnect on a conn ection failure
@param cp used by DBClientPaired. You do not need to specify th is parameter @param cp used by DBClientPaired. You do not need to specify th is parameter
@param timeout tcp timeout in seconds - this is for read/write, @param timeout tcp timeout in seconds - this is for read/write,
not connect not connect.
Connect timeout is fixed, but short, at 5 seconds.
*/ */
DBClientConnection(bool _autoReconnect=false,DBClientPaired* cp=0,i nt timeout=0) : DBClientConnection(bool _autoReconnect=false, DBClientPaired* cp=0, int timeout=0) :
clientPaired(cp), failed(false), autoReconnect(_autoReconne ct), lastReconnectTry(0), _timeout(timeout) { } clientPaired(cp), failed(false), autoReconnect(_autoReconne ct), lastReconnectTry(0), _timeout(timeout) { }
/** Connect to a Mongo database server. /** Connect to a Mongo database server.
If autoReconnect is true, you can try to use the DBClientConnect ion even when If autoReconnect is true, you can try to use the DBClientConnect ion even when
false was returned -- it will try to connect again. false was returned -- it will try to connect again.
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 )
If you use IPv6 you must add a port number ( ::1:27017 ) If you use IPv6 you must add a port number ( ::1:27017 )
@param errmsg any relevant error message will appended to the st ring @param errmsg any relevant error message will appended to the st ring
skipping to change at line 794 skipping to change at line 685
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 )
*/ */
void connect(string serverHostname) { void connect(string serverHostname) {
string errmsg; string errmsg;
if( !connect(serverHostname.c_str(), errmsg) ) if( !connect(serverHostname.c_str(), errmsg) )
throw ConnectException(string("can't connect ") + errmsg); throw ConnectException(string("can't connect ") + errmsg);
} }
virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true); virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true);
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn = 0, int nToSkip = 0, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0,
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) { const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) {
checkConnection(); checkConnection();
return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize ); return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize );
} }
/** /**
@return true if this connection is currently in a failed state. When autoreconnect is on, @return true if this connection is currently in a failed state. When autoreconnect is on,
a connection will transition back to an ok state after r econnecting. a connection will transition back to an ok state after r econnecting.
*/ */
bool isFailed() const { bool isFailed() const {
skipping to change at line 923 skipping to change at line 814
DBClientConnection& slaveConn(); DBClientConnection& slaveConn();
/* TODO - not yet implemented. mongos may need these. */ /* TODO - not yet implemented. mongos may need these. */
virtual bool call( Message &toSend, Message &response, bool assertO k=true ) { assert(false); return false; } virtual bool call( Message &toSend, Message &response, bool assertO k=true ) { assert(false); return false; }
virtual void say( Message &toSend ) { assert(false); } virtual void say( Message &toSend ) { assert(false); }
virtual void sayPiggyBack( Message &toSend ) { assert(false); } virtual void sayPiggyBack( Message &toSend ) { assert(false); }
virtual void checkResponse( const char *data, int nReturned ) { ass ert(false); } virtual void checkResponse( const char *data, int nReturned ) { ass ert(false); }
bool isFailed() const { bool isFailed() const {
// TODO: this really should check isFailed on current master as well // TODO: this really should check isFailed on current master as well
return master > NotSetR; return master < Left;
} }
}; };
/** pings server to check if it's up /** pings server to check if it's up
*/ */
bool serverAlive( const string &uri ); bool serverAlive( const string &uri );
DBClientBase * createDirectClient(); DBClientBase * createDirectClient();
} // namespace mongo } // namespace mongo
#include "dbclientcursor.h"
#include "undef_macros.h"
 End of changes. 18 change blocks. 
169 lines changed or deleted 48 lines changed or added


 dbhelpers.h   dbhelpers.h 
skipping to change at line 25 skipping to change at line 25
* 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/>.
*/ */
/* db helpers are helper functions and classes that let us easily manipulat e the local /* db helpers are helper functions and classes that let us easily manipulat e the local
database instance. database instance.
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
#include "client.h" #include "client.h"
#include "db.h" #include "db.h"
namespace mongo { namespace mongo {
class Cursor; class Cursor;
class CoveredIndexMatcher; class CoveredIndexMatcher;
class CursorIterator { class CursorIterator {
public: public:
skipping to change at line 94 skipping to change at line 94
/* Get/put the first object from a collection. Generally only usef ul if the collection /* Get/put the first object from a collection. Generally only usef ul if the collection
only ever has a single object -- which is a "singleton collectio n". only ever has a single object -- which is a "singleton collectio n".
You do not need to set the database before calling. You do not need to set the database before calling.
Returns: true if object exists. Returns: true if object exists.
*/ */
static bool getSingleton(const char *ns, BSONObj& result); static bool getSingleton(const char *ns, BSONObj& result);
static void putSingleton(const char *ns, BSONObj obj); static void putSingleton(const char *ns, BSONObj obj);
static void putSingletonGod(const char *ns, BSONObj obj, bool logTh eOp);
/* Remove all objects from a collection. /* Remove all objects from a collection.
You do not need to set the database before calling. You do not need to set the database before calling.
*/ */
static void emptyCollection(const char *ns); static void emptyCollection(const char *ns);
}; };
class Database; class Database;
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 dbmessage.h   dbmessage.h 
skipping to change at line 91 skipping to change at line 91
public: public:
DbMessage(const Message& _m) : m(_m) { DbMessage(const Message& _m) : m(_m) {
theEnd = _m.data->_data + _m.data->dataLen(); theEnd = _m.data->_data + _m.data->dataLen();
int *r = (int *) _m.data->_data; int *r = (int *) _m.data->_data;
reserved = *r; reserved = *r;
r++; r++;
data = (const char *) r; data = (const char *) r;
nextjsobj = data; nextjsobj = data;
} }
const char * getns() { const char * getns() const {
return data; return data;
} }
void getns(Namespace& ns) { void getns(Namespace& ns) const {
ns = data; ns = data;
} }
const char * afterNS() const {
return data + strlen( data ) + 1;
}
int getInt( int num ) const {
const int * foo = (const int*)afterNS();
return foo[num];
}
int getQueryNToReturn() const {
return getInt( 1 );
}
void resetPull(){ void resetPull(){
nextjsobj = data; nextjsobj = data;
} }
int pullInt() { int pullInt() {
if ( nextjsobj == data ) if ( nextjsobj == data )
nextjsobj += strlen(data) + 1; // skip namespace nextjsobj += strlen(data) + 1; // skip namespace
int i = *((int *)nextjsobj); int i = *((int *)nextjsobj);
nextjsobj += 4; nextjsobj += 4;
return i; return i;
} }
skipping to change at line 119 skipping to change at line 132
return pullInt64(); return pullInt64();
} }
long long &pullInt64() { long long &pullInt64() {
if ( nextjsobj == data ) if ( nextjsobj == data )
nextjsobj += strlen(data) + 1; // skip namespace nextjsobj += strlen(data) + 1; // skip namespace
long long &i = *((long long *)nextjsobj); long long &i = *((long long *)nextjsobj);
nextjsobj += 8; nextjsobj += 8;
return i; return i;
} }
OID* getOID() { OID* getOID() const {
return (OID *) (data + strlen(data) + 1); // skip namespace return (OID *) (data + strlen(data) + 1); // skip namespace
} }
void getQueryStuff(const char *&query, int& ntoreturn) { void getQueryStuff(const char *&query, int& ntoreturn) {
int *i = (int *) (data + strlen(data) + 1); int *i = (int *) (data + strlen(data) + 1);
ntoreturn = *i; ntoreturn = *i;
i++; i++;
query = (const char *) i; query = (const char *) i;
} }
/* for insert and update msgs */ /* for insert and update msgs */
bool moreJSObjs() { bool moreJSObjs() const {
return nextjsobj != 0; return nextjsobj != 0;
} }
BSONObj nextJsObj() { BSONObj nextJsObj() {
if ( nextjsobj == data ) { if ( nextjsobj == data ) {
nextjsobj += strlen(data) + 1; // skip namespace nextjsobj += strlen(data) + 1; // skip namespace
massert( 13066 , "Message contains no documents", theEnd > nextjsobj ); massert( 13066 , "Message contains no documents", theEnd > nextjsobj );
} }
massert( 10304 , "Remaining data too small for BSON object", t heEnd - nextjsobj > 3 ); massert( 10304 , "Remaining data too small for BSON object", t heEnd - nextjsobj > 3 );
BSONObj js(nextjsobj); BSONObj js(nextjsobj);
massert( 10305 , "Invalid object size", js.objsize() > 3 ); massert( 10305 , "Invalid object size", js.objsize() > 3 );
skipping to change at line 153 skipping to change at line 166
js.objsize() < ( theEnd - data ) ); js.objsize() < ( theEnd - data ) );
if ( objcheck && !js.valid() ) { if ( objcheck && !js.valid() ) {
massert( 10307 , "bad object in message", false); massert( 10307 , "bad object in message", false);
} }
nextjsobj += js.objsize(); nextjsobj += js.objsize();
if ( nextjsobj >= theEnd ) if ( nextjsobj >= theEnd )
nextjsobj = 0; nextjsobj = 0;
return js; return js;
} }
const Message& msg() { const Message& msg() const {
return m; return m;
} }
void markSet(){ void markSet(){
mark = nextjsobj; mark = nextjsobj;
} }
void markReset(){ void markReset(){
nextjsobj = mark; nextjsobj = mark;
} }
 End of changes. 6 change blocks. 
5 lines changed or deleted 18 lines changed or added


 debug_util.h   debug_util.h 
skipping to change at line 22 skipping to change at line 22
* 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
#ifndef _WIN32 #ifndef _WIN32
#include <signal.h> #include <signal.h>
#endif // ndef _WIN32 #endif
namespace mongo { namespace mongo {
// for debugging // for debugging
typedef struct _Ints { typedef struct _Ints {
int i[100]; int i[100];
} *Ints; } *Ints;
typedef struct _Chars { typedef struct _Chars {
char c[200]; char c[200];
} *Chars; } *Chars;
typedef char CHARS[400]; typedef char CHARS[400];
typedef struct _OWS { typedef struct _OWS {
int size; int size;
char type; char type;
char string[400]; char string[400];
} *OWS; } *OWS;
// for now, running on win32 means development not production --
// use this to log things just there.
#if defined(_WIN32)
#define WIN if( 1 )
#else
#define WIN if( 0 )
#endif
#if defined(_DEBUG) #if defined(_DEBUG)
#define DEV if( 1 ) # define MONGO_DEV if( 1 )
#else #else
#define DEV if( 0 ) # define MONGO_DEV if( 0 )
#endif #endif
#define DEV MONGO_DEV
#define DEBUGGING if( 0 ) #define MONGO_DEBUGGING if( 0 )
#define DEBUGGING MONGO_DEBUGGING
// The following declare one unique counter per enclosing function. // The following declare one unique counter per enclosing function.
// NOTE The implementation double-increments on a match, but we don't reall y care. // NOTE The implementation double-increments on a match, but we don't reall y care.
#define SOMETIMES( occasion, howOften ) for( static unsigned occasion = 0; #define MONGO_SOMETIMES( occasion, howOften ) for( static unsigned occasion
++occasion % howOften == 0; ) = 0; ++occasion % howOften == 0; )
#define OCCASIONALLY SOMETIMES( occasionally, 16 ) #define SOMETIMES MONGO_SOMETIMES
#define RARELY SOMETIMES( rarely, 128 )
#define ONCE for( static bool undone = true; undone; undone = false ) #define MONGO_OCCASIONALLY SOMETIMES( occasionally, 16 )
#define OCCASIONALLY MONGO_OCCASIONALLY
#define MONGO_RARELY SOMETIMES( rarely, 128 )
#define RARELY MONGO_RARELY
#define MONGO_ONCE for( static bool undone = true; undone; undone = false )
#define ONCE MONGO_ONCE
#if defined(_WIN32) #if defined(_WIN32)
#define strcasecmp _stricmp inline int strcasecmp(const char* s1, const char* s2) {return _stricmp( s1, s2);}
#endif #endif
// Sets SIGTRAP handler to launch GDB // Sets SIGTRAP handler to launch GDB
// Noop unless on *NIX and compiled with _DEBUG // Noop unless on *NIX and compiled with _DEBUG
void setupSIGTRAPforGDB(); void setupSIGTRAPforGDB();
#if defined(_WIN32) #if defined(_WIN32)
inline void breakpoint() {} //noop inline void breakpoint() {} //noop
#else // defined(_WIN32) #else // defined(_WIN32)
// code to raise a breakpoint in GDB // code to raise a breakpoint in GDB
 End of changes. 8 change blocks. 
18 lines changed or deleted 19 lines changed or added


 engine.h   engine.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 "../stdafx.h" #include "../pch.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
extern const char * jsconcatcode; // TODO: change name to mongoJSCode extern const char * jsconcatcode; // TODO: change name to mongoJSCode
namespace mongo { namespace mongo {
typedef unsigned long long ScriptingFunction; typedef unsigned long long ScriptingFunction;
typedef BSONObj (*NativeFunction) ( const BSONObj &args ); typedef BSONObj (*NativeFunction) ( const BSONObj &args );
class Scope : boost::noncopyable { class Scope : boost::noncopyable {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 engine_java.h   engine_java.h 
skipping to change at line 22 skipping to change at line 22
* 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.
*/ */
/* this file contains code to call into java (into the 10gen sandbox) from inside the database */ /* this file contains code to call into java (into the 10gen sandbox) from inside the database */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
#include <jni.h> #include <jni.h>
#include <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
#include <errno.h> #include <errno.h>
#include <sys/types.h> #include <sys/types.h>
#if !defined(_WIN32) #if !defined(_WIN32)
#include <dirent.h> #include <dirent.h>
#endif #endif
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 engine_spidermonkey.h   engine_spidermonkey.h 
skipping to change at line 45 skipping to change at line 45
#ifdef WIN32 #ifdef WIN32
#include "jstypes.h" #include "jstypes.h"
#undef JS_PUBLIC_API #undef JS_PUBLIC_API
#undef JS_PUBLIC_DATA #undef JS_PUBLIC_DATA
#define JS_PUBLIC_API(t) t #define JS_PUBLIC_API(t) t
#define JS_PUBLIC_DATA(t) t #define JS_PUBLIC_DATA(t) t
#endif #endif
#include "jsapi.h" #include "jsapi.h"
#include "jsobj.h"
#include "jsdate.h" #include "jsdate.h"
#include "jsregexp.h" #include "jsregexp.h"
#else #else
#include "js/jsapi.h" #include "js/jsapi.h"
#include "js/jsobj.h" #include "js/jsobj.h"
#include "js/jsdate.h" #include "js/jsdate.h"
#include "js/jsregexp.h" #include "js/jsregexp.h"
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 extsort.h   extsort.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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
#include "namespace.h" #include "namespace.h"
#include "curop.h" #include "curop.h"
#include "../util/array.h" #include "../util/array.h"
namespace mongo { namespace mongo {
/** /**
for sorting by BSONObj and attaching a value for sorting by BSONObj and attaching a value
*/ */
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 file.h   file.h 
skipping to change at line 121 skipping to change at line 121
}; };
#else #else
class File : public FileInterface { class File : public FileInterface {
int fd; int fd;
bool _bad; bool _bad;
void err(bool ok) { void err(bool ok) {
if( !ok && !_bad ) { if( !ok && !_bad ) {
_bad = true; _bad = true;
log() << "File I/O " << OUTPUT_ERRNO << '\n'; log() << "File I/O " << errnoWithDescription() << '\n';
} }
} }
public: public:
File() { File() {
fd = -1; fd = -1;
_bad = true; _bad = true;
} }
~File() { ~File() {
if( is_open() ) ::close(fd); if( is_open() ) ::close(fd);
fd = -1; fd = -1;
} }
#ifndef O_NOATIME #ifndef O_NOATIME
#define O_NOATIME 0 #define O_NOATIME 0
#define lseek64 lseek #define lseek64 lseek
#endif #endif
void open(const char *filename, bool readOnly=false ) { void open(const char *filename, bool readOnly=false ) {
fd = ::open(filename, O_CREAT | ( readOnly ? 0 : O_RDWR ) | O_NOATI ME, S_IRUSR | S_IWUSR); fd = ::open(filename, O_CREAT | ( readOnly ? 0 : O_RDWR ) | O_NOATI ME, S_IRUSR | S_IWUSR);
if ( fd <= 0 ) { if ( fd <= 0 ) {
out() << "couldn't open " << filename << ' ' << OUTPUT_ERRNO << endl; out() << "couldn't open " << filename << ' ' << errnoWithDescri ption() << endl;
return; return;
} }
_bad = false; _bad = false;
} }
void write(fileofs o, const char *data, unsigned len) { void write(fileofs o, const char *data, unsigned len) {
lseek64(fd, o, SEEK_SET); lseek64(fd, o, SEEK_SET);
err( ::write(fd, data, len) == (int) len ); err( ::write(fd, data, len) == (int) len );
} }
void read(fileofs o, char *data, unsigned len) { void read(fileofs o, char *data, unsigned len) {
lseek(fd, o, SEEK_SET); lseek(fd, o, SEEK_SET);
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 file_allocator.h   file_allocator.h 
skipping to change at line 18 skipping to change at line 18
* *
* 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.
*/ */
#include "../stdafx.h" #include "../pch.h"
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
#if defined(__freebsd__) #if defined(__freebsd__)
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#ifndef O_NOATIME #ifndef O_NOATIME
#define O_NOATIME 0 #define O_NOATIME 0
#endif #endif
skipping to change at line 109 skipping to change at line 109
void waitUntilFinished() const { void waitUntilFinished() const {
#if !defined(_WIN32) #if !defined(_WIN32)
if ( failed_ ) if ( failed_ )
return; return;
scoped_lock lk( pendingMutex_ ); scoped_lock lk( pendingMutex_ );
while( pending_.size() != 0 ) while( pending_.size() != 0 )
pendingUpdated_.wait( lk.boost() ); pendingUpdated_.wait( lk.boost() );
#endif #endif
} }
static void ensureLength( int fd , long size ){
#if defined(_WIN32)
// we don't zero on windows
// TODO : we should to avoid fragmentation
#else
#if defined(__linux__)
int ret = posix_fallocate(fd,0,size);
if ( ret == 0 )
return;
log() << "posix_fallocate failed: " << errnoWithDescription( re
t ) << " falling back" << endl;
#endif
off_t filelen = lseek(fd, 0, SEEK_END);
if ( filelen < size ) {
massert( 10440 , "failure creating new datafile", filelen
== 0 );
// Check for end of disk.
massert( 10441 , "Unable to allocate file of desired size"
,
size - 1 == lseek(fd, size - 1, SEEK_SET) );
massert( 10442 , "Unable to allocate file of desired size"
,
1 == write(fd, "", 1) );
lseek(fd, 0, SEEK_SET);
long z = 256 * 1024;
char buf[z];
memset(buf, 0, z);
long left = size;
while ( left > 0 ) {
long towrite = left;
if ( towrite > z )
towrite = z;
int written = write( fd , buf , towrite );
massert( 10443 , errnoWithPrefix("write failed" ), writ
ten > 0 );
left -= written;
}
}
#endif
}
private: private:
#if !defined(_WIN32) #if !defined(_WIN32)
void checkFailure() { void checkFailure() {
massert( 12520, "file allocation failure", !failed_ ); massert( 12520, "file allocation failure", !failed_ );
} }
// caller must hold pendingMutex_ lock. Returns size if allocated or // caller must hold pendingMutex_ lock. Returns size if allocated or
// allocation requested, -1 otherwise. // allocation requested, -1 otherwise.
long prevSize( const string &name ) const { long prevSize( const string &name ) const {
if ( pendingSize_.count( name ) > 0 ) if ( pendingSize_.count( name ) > 0 )
skipping to change at line 164 skipping to change at line 206
if ( a_.pending_.size() == 0 ) if ( a_.pending_.size() == 0 )
break; break;
name = a_.pending_.front(); name = a_.pending_.front();
size = a_.pendingSize_[ name ]; size = a_.pendingSize_[ name ];
} }
try { try {
log() << "allocating new datafile " << name << ", filling with zeroes..." << endl; log() << "allocating new datafile " << name << ", filling with zeroes..." << endl;
long fd = open(name.c_str(), O_CREAT | O_RDWR | O_NOATIME, S_IRUSR | S_IWUSR); long fd = open(name.c_str(), O_CREAT | O_RDWR | O_NOATIME, S_IRUSR | S_IWUSR);
if ( fd <= 0 ) { if ( fd <= 0 ) {
stringstream ss; stringstream ss;
ss << "couldn't open " << name << ' ' << OU TPUT_ERRNO; ss << "couldn't open " << name << ' ' << er rnoWithDescription();
massert( 10439 , ss.str(), fd <= 0 ); massert( 10439 , ss.str(), fd <= 0 );
} }
#if defined(POSIX_FADV_DONTNEED) #if defined(POSIX_FADV_DONTNEED)
if( posix_fadvise(fd, 0, size, POSIX_FADV_DONTN EED) ) { if( posix_fadvise(fd, 0, size, POSIX_FADV_DONTN EED) ) {
log() << "warning: posix_fadvise fails " << name << ' ' << OUTPUT_ERRNO << endl; log() << "warning: posix_fadvise fails " << name << ' ' << errnoWithDescription() << endl;
} }
#endif #endif
Timer t;
/* make sure the file is the full desired lengt h */ /* make sure the file is the full desired lengt h */
off_t filelen = lseek(fd, 0, SEEK_END); ensureLength( fd , size );
if ( filelen < size ) {
massert( 10440 , "failure creating new dat log() << "done allocating datafile " << name <<
afile", filelen == 0 ); ", "
// Check for end of disk. << "size: " << size/1024/1024 << "MB, "
massert( 10441 , "Unable to allocate file << " took " << ((double)t.millis())/1000.
of desired size", 0 << " secs"
size - 1 == lseek(fd, size - 1, SEE << endl;
K_SET) );
massert( 10442 , "Unable to allocate file
of desired size",
1 == write(fd, "", 1) );
lseek(fd, 0, SEEK_SET);
Timer t;
long z = 256 * 1024;
char buf[z];
memset(buf, 0, z);
long left = size;
while ( left > 0 ) {
long towrite = left;
if ( towrite > z )
towrite = z;
int written = write( fd , buf , towrite
);
massert( 10443 , errnostring("write fai
led" ), written > 0 );
left -= written;
}
log() << "done allocating datafile " << nam
e << ", size: " << size/1024/1024 << "MB, took " << ((double)t.millis())/10
00.0 << " secs" << endl;
}
close( fd ); close( fd );
} catch ( ... ) { } catch ( ... ) {
problem() << "Failed to allocate new file: " << name problem() << "Failed to allocate new file: " << name
<< ", size: " << size << ", aborting. " << endl; << ", size: " << size << ", aborting. " << endl;
try { try {
BOOST_CHECK_EXCEPTION( boost::filesystem::r emove( name ) ); BOOST_CHECK_EXCEPTION( boost::filesystem::r emove( name ) );
} catch ( ... ) { } catch ( ... ) {
} }
scoped_lock lk( a_.pendingMutex_ ); scoped_lock lk( a_.pendingMutex_ );
 End of changes. 7 change blocks. 
35 lines changed or deleted 60 lines changed or added


 framework.h   framework.h 
skipping to change at line 24 skipping to change at line 24
* *
* 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/>.
*/ */
/* /*
simple portable regression system simple portable regression system
*/ */
#include "../stdafx.h" #include "../pch.h"
#define ASSERT_EXCEPTION(a,b) \ #define ASSERT_EXCEPTION(a,b) \
try { \ try { \
a; \ a; \
mongo::regression::assert_fail( #a , __FILE__ , __LINE__ ); \ mongo::regression::assert_fail( #a , __FILE__ , __LINE__ ); \
} catch ( b& ){ \ } catch ( b& ){ \
mongo::regression::assert_pass(); \ mongo::regression::assert_pass(); \
} }
#define ASSERT_EQUALS(a,b) (mongo::regression::MyAsserts( #a , #b , __FILE_ _ , __LINE__ ) ).ae( (a) , (b) ) #define ASSERT_EQUALS(a,b) (mongo::regression::MyAsserts( #a , #b , __FILE_ _ , __LINE__ ) ).ae( (a) , (b) )
skipping to change at line 46 skipping to change at line 46
#define FAIL(x) mongo::regression::fail( #x , __FILE__ , __LINE__ ) #define FAIL(x) mongo::regression::fail( #x , __FILE__ , __LINE__ )
#include "../db/instance.h" #include "../db/instance.h"
namespace mongo { namespace mongo {
namespace regression { namespace regression {
class Result; class Result;
string demangleName( const type_info& typeinfo );
class TestCase { class TestCase {
public: public:
virtual ~TestCase(){} virtual ~TestCase(){}
virtual void run() = 0; virtual void run() = 0;
virtual string getName() = 0; virtual string getName() = 0;
}; };
template< class T > template< class T >
class TestHolderBase : public TestCase { class TestHolderBase : public TestCase {
public: public:
 End of changes. 2 change blocks. 
3 lines changed or deleted 1 lines changed or added


 goodies.h   goodies.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 "../bson/util/misc.h"
namespace mongo { namespace mongo {
#if !defined(_WIN32) && !defined(NOEXECINFO) && !defined(__freebsd__) && !d efined(__sun__) #if !defined(_WIN32) && !defined(NOEXECINFO) && !defined(__freebsd__) && !d efined(__sun__)
} // namespace mongo } // namespace mongo
#include <pthread.h> #include <pthread.h>
#include <execinfo.h> #include <execinfo.h>
namespace mongo { namespace mongo {
skipping to change at line 104 skipping to change at line 106
for ( int i = 0; i < 16; i++ ) for ( int i = 0; i < 16; i++ )
cout << (unsigned) ((unsigned char)*p++) << ' '; cout << (unsigned) ((unsigned char)*p++) << ' ';
cout << endl; cout << endl;
len -= 16; len -= 16;
} }
} catch (...) { } catch (...) {
} }
} }
// PRINT(2+2); prints "2+2: 4" // PRINT(2+2); prints "2+2: 4"
#define PRINT(x) cout << #x ": " << (x) << endl #define MONGO_PRINT(x) cout << #x ": " << (x) << endl
#define PRINT MONGO_PRINT
// PRINTFL; prints file:line // PRINTFL; prints file:line
#define PRINTFL cout << __FILE__ ":" << __LINE__ << endl #define MONGO_PRINTFL cout << __FILE__ ":" << __LINE__ << endl
#define PRINTFL MONGO_PRINTFL
#undef yassert
#undef assert #undef assert
#define assert xassert #define assert MONGO_assert
#define yassert 1
struct WrappingInt { struct WrappingInt {
WrappingInt() { WrappingInt() {
x = 0; x = 0;
} }
WrappingInt(unsigned z) : x(z) { } WrappingInt(unsigned z) : x(z) { }
unsigned x; unsigned x;
operator unsigned() const { operator unsigned() const {
return x; return x;
} }
skipping to change at line 143 skipping to change at line 144
return !(r<=*this); return !(r<=*this);
} }
}; };
} // namespace mongo } // namespace mongo
#include <ctime> #include <ctime>
namespace mongo { namespace mongo {
inline void time_t_to_String(time_t t, char *buf) {
#if defined(_WIN32)
ctime_s(buf, 64, &t);
#else
ctime_r(&t, buf);
#endif
buf[24] = 0; // don't want the \n
}
inline void time_t_to_Struct(time_t t, struct tm * buf , bool local = f alse ) { inline void time_t_to_Struct(time_t t, struct tm * buf , bool local = f alse ) {
#if defined(_WIN32) #if defined(_WIN32)
if ( local ) if ( local )
localtime_s( buf , &t ); localtime_s( buf , &t );
else else
gmtime_s(buf, &t); gmtime_s(buf, &t);
#else #else
if ( local ) if ( local )
localtime_r(&t, buf); localtime_r(&t, buf);
else else
gmtime_r(&t, buf); gmtime_r(&t, buf);
#endif #endif
} }
#define asctime _asctime_not_threadsafe_ inline string terseCurrentTime(){
#define gmtime _gmtime_not_threadsafe_ struct tm t;
#define localtime _localtime_not_threadsafe_ time_t_to_Struct( time(0) , &t );
#define ctime _ctime_is_not_threadsafe_ stringstream ss;
ss << ( 1900 + t.tm_year ) << "-"
<< t.tm_mon << "-"
<< t.tm_mday << "-"
<< t.tm_hour << "-"
<< t.tm_min;
return ss.str();
}
#define MONGO_asctime _asctime_not_threadsafe_
#define asctime MONGO_asctime
#define MONGO_gmtime _gmtime_not_threadsafe_
#define gmtime MONGO_gmtime
#define MONGO_localtime _localtime_not_threadsafe_
#define localtime MONGO_localtime
#define MONGO_ctime _ctime_is_not_threadsafe_
#define ctime MONGO_ctime
#if defined(_WIN32) || defined(__sunos__) #if defined(_WIN32) || defined(__sunos__)
inline void sleepsecs(int s) { inline void sleepsecs(int s) {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
xt.sec += s; xt.sec += s;
boost::thread::sleep(xt); boost::thread::sleep(xt);
} }
inline void sleepmillis(int s) { inline void sleepmillis(int s) {
boost::xtime xt; boost::xtime xt;
skipping to change at line 227 skipping to change at line 235
struct timespec out; struct timespec out;
if ( nanosleep( &t , &out ) ){ if ( nanosleep( &t , &out ) ){
cout << "nanosleep failed" << endl; cout << "nanosleep failed" << endl;
} }
} }
inline void sleepmillis(int s) { inline void sleepmillis(int s) {
sleepmicros( s * 1000 ); sleepmicros( s * 1000 );
} }
#endif #endif
// note this wraps // note this wraps
inline int tdiff(unsigned told, unsigned tnew) { inline int tdiff(unsigned told, unsigned tnew) {
return WrappingInt::diff(tnew, told); return WrappingInt::diff(tnew, told);
} }
inline unsigned curTimeMillis() { inline unsigned curTimeMillis() {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
unsigned t = xt.nsec / 1000000; unsigned t = xt.nsec / 1000000;
return (xt.sec & 0xfffff) * 1000 + t; return (xt.sec & 0xfffff) * 1000 + t;
} }
struct Date_t {
// TODO: make signed (and look for related TODO's)
unsigned long long millis;
Date_t(): millis(0) {}
Date_t(unsigned long long m): millis(m) {}
operator unsigned long long&() { return millis; }
operator const unsigned long long&() const { return millis; }
};
inline Date_t jsTime() { inline Date_t jsTime() {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
unsigned long long t = xt.nsec / 1000000; unsigned long long t = xt.nsec / 1000000;
return ((unsigned long long) xt.sec * 1000) + t; return ((unsigned long long) xt.sec * 1000) + t;
} }
inline unsigned long long curTimeMicros64() { inline unsigned long long curTimeMicros64() {
boost::xtime xt; boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); boost::xtime_get(&xt, boost::TIME_UTC);
skipping to change at line 360 skipping to change at line 359
*/ */
//typedef scoped_lock lock; //typedef scoped_lock lock;
inline bool startsWith(const char *str, const char *prefix) { inline bool startsWith(const char *str, const char *prefix) {
size_t l = strlen(prefix); size_t l = strlen(prefix);
if ( strlen(str) < l ) return false; if ( strlen(str) < l ) return false;
return strncmp(str, prefix, l) == 0; return strncmp(str, prefix, l) == 0;
} }
inline bool startsWith(string s, string p) { return startsWith(s.c_str( ), p.c_str()); }
inline bool endsWith(const char *p, const char *suffix) { inline bool endsWith(const char *p, const char *suffix) {
size_t a = strlen(p); size_t a = strlen(p);
size_t b = strlen(suffix); size_t b = strlen(suffix);
if ( b > a ) return false; if ( b > a ) return false;
return strcmp(p + a - b, suffix) == 0; return strcmp(p + a - b, suffix) == 0;
} }
} // namespace mongo } // namespace mongo
skipping to change at line 647 skipping to change at line 647
size_t _size; size_t _size;
char * _buf; char * _buf;
}; };
ostream& operator<<( ostream &s, const ThreadSafeString &o ); ostream& operator<<( ostream &s, const ThreadSafeString &o );
inline bool isNumber( char c ) { inline bool isNumber( char c ) {
return c >= '0' && c <= '9'; return c >= '0' && c <= '9';
} }
inline unsigned stringToNum(const char *str) {
unsigned x = 0;
const char *p = str;
while( 1 ) {
if( !isNumber(*p) ) {
if( *p == 0 && p != str )
break;
throw 0;
}
x = x * 10 + *p++ - '0';
}
return x;
}
// for convenience, '{' is greater than anything and stops number parsi ng // for convenience, '{' is greater than anything and stops number parsi ng
inline int lexNumCmp( const char *s1, const char *s2 ) { inline int lexNumCmp( const char *s1, const char *s2 ) {
while( *s1 && *s2 ) { while( *s1 && *s2 ) {
bool p1 = ( *s1 == '{' ); bool p1 = ( *s1 == '{' );
bool p2 = ( *s2 == '{' ); bool p2 = ( *s2 == '{' );
if ( p1 && !p2 ) if ( p1 && !p2 )
return 1; return 1;
if ( p2 && !p1 ) if ( p2 && !p1 )
return -1; return -1;
 End of changes. 10 change blocks. 
29 lines changed or deleted 43 lines changed or added


 gridfs.h   gridfs.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 "dbclient.h" #include "dbclient.h"
#include "redef_macros.h"
namespace mongo { namespace mongo {
typedef unsigned long long gridfs_offset; typedef unsigned long long gridfs_offset;
class GridFS; class GridFS;
class GridFile; class GridFile;
class Chunk { class Chunk {
public: public:
skipping to change at line 201 skipping to change at line 202
GridFile( GridFS * grid , BSONObj obj ); GridFile( GridFS * grid , BSONObj obj );
void _exists(); void _exists();
GridFS * _grid; GridFS * _grid;
BSONObj _obj; BSONObj _obj;
friend class GridFS; friend class GridFS;
}; };
} }
#include "undef_macros.h"
 End of changes. 2 change blocks. 
0 lines changed or deleted 1 lines changed or added


 hashtab.h   hashtab.h 
skipping to change at line 25 skipping to change at line 25
* *
* 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 "../stdafx.h" #include "../pch.h"
#include <map> #include <map>
namespace mongo { namespace mongo {
#pragma pack(1) #pragma pack(1)
/* you should define: /* you should define:
int Key::hash() return > 0 always. int Key::hash() return > 0 always.
*/ */
skipping to change at line 160 skipping to change at line 160
n.hash = k.hash(); n.hash = k.hash();
} }
else { else {
assert( n.hash == k.hash() ); assert( n.hash == k.hash() );
} }
n.value = value; n.value = value;
return true; return true;
} }
typedef void (*IteratorCallback)( const Key& k , Type& v ); typedef void (*IteratorCallback)( const Key& k , Type& v );
void iterAll( IteratorCallback callback ){ void iterAll( IteratorCallback callback ){
for ( int i=0; i<n; i++ ){ for ( int i=0; i<n; i++ ){
if ( ! nodes(i).inUse() ) if ( ! nodes(i).inUse() )
continue; continue;
callback( nodes(i).k , nodes(i).value ); callback( nodes(i).k , nodes(i).value );
} }
} }
// TODO: should probably use boost::bind for this, but didn't want
to look at it
typedef void (*IteratorCallback2)( const Key& k , Type& v , void *
extra );
void iterAll( IteratorCallback2 callback , void * extra ){
for ( int i=0; i<n; i++ ){
if ( ! nodes(i).inUse() )
continue;
callback( nodes(i).k , nodes(i).value , extra );
}
}
}; };
#pragma pack() #pragma pack()
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
2 lines changed or deleted 13 lines changed or added


 httpclient.h   httpclient.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 "../stdafx.h" #include "../pch.h"
namespace mongo { namespace mongo {
class HttpClient { class HttpClient {
public: public:
class Result { class Result {
public: public:
Result(){} Result(){}
const string& getEntireResponse() const { const string& getEntireResponse() const {
return _entireResponse; return _entireResponse;
} }
const map<string,string> getHeaders() const {
return _headers;
}
const string& getBody() const {
return _body;
}
private: private:
void _init( int code , string entire );
int _code; int _code;
string _entireResponse; string _entireResponse;
map<string,string> _headers;
string _body;
friend class HttpClient; friend class HttpClient;
}; };
/** /**
* @return response code * @return response code
*/ */
int get( string url , Result * result = 0 ); int get( string url , Result * result = 0 );
/** /**
* @return response code * @return response code
 End of changes. 4 change blocks. 
1 lines changed or deleted 17 lines changed or added


 index.h   index.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 "../stdafx.h" #include "../pch.h"
#include "diskloc.h" #include "diskloc.h"
#include "jsobj.h" #include "jsobj.h"
#include <map> #include "indexkey.h"
namespace mongo { namespace mongo {
class IndexSpec;
class IndexType; // TODO: this name sucks
class IndexPlugin;
class IndexDetails;
enum IndexSuitability { USELESS = 0 , HELPFUL = 1 , OPTIMAL = 2 };
/**
* this represents an instance of a index plugin
* done this way so parsing, etc... can be cached
* so if there is a FTS IndexPlugin, for each index using FTS
* there will be 1 of these, and it can have things pre-parsed, etc...
*/
class IndexType : boost::noncopyable {
public:
IndexType( const IndexPlugin * plugin , const IndexSpec * spec );
virtual ~IndexType();
virtual void getKeys( const BSONObj &obj, BSONObjSetDefaultOrder &k
eys ) const = 0;
virtual auto_ptr<Cursor> newCursor( const BSONObj& query , const BS
ONObj& order , int numWanted ) const = 0;
/** optional op : changes query to match what's in the index */
virtual BSONObj fixKey( const BSONObj& in ) { return in; }
/** optional op : compare 2 objects with regards to this index */
virtual int compare( const BSONObj& l , const BSONObj& r ) const;
/** @return plugin */
const IndexPlugin * getPlugin() const { return _plugin; }
const BSONObj& keyPattern() const;
virtual IndexSuitability suitability( const BSONObj& query , const
BSONObj& order ) const ;
virtual bool scanAndOrderRequired( const BSONObj& query , const BSO
NObj& order ) const ;
protected:
const IndexPlugin * _plugin;
const IndexSpec * _spec;
};
/**
* this represents a plugin
* a plugin could be something like full text search, sparse index, etc
...
* 1 of these exists per type of index per server
* 1 IndexType is created per index using this plugin
*/
class IndexPlugin : boost::noncopyable {
public:
IndexPlugin( const string& name );
virtual ~IndexPlugin(){}
virtual IndexType* generate( const IndexSpec * spec ) const = 0;
static IndexPlugin* get( const string& name ){
if ( ! _plugins )
return 0;
map<string,IndexPlugin*>::iterator i = _plugins->find( name );
if ( i == _plugins->end() )
return 0;
return i->second;
}
string getName() const { return _name; }
private:
string _name;
static map<string,IndexPlugin*> * _plugins;
};
/* precomputed details about an index, used for inserting keys on updat
es
stored/cached in NamespaceDetailsTransient, or can be used standalon
e
*/
class IndexSpec {
public:
BSONObj keyPattern; // e.g., { name : 1 }
BSONObj info; // this is the same as IndexDetails::info.obj()
IndexSpec()
: _details(0) , _finishedInit(false){
}
IndexSpec( const BSONObj& k , const BSONObj& m = BSONObj() )
: keyPattern(k) , info(m) , _details(0) , _finishedInit(false){
_init();
}
/**
this is a DiscLoc of an IndexDetails info
should have a key field
*/
IndexSpec( const DiskLoc& loc ){
reset( loc );
}
void reset( const DiskLoc& loc );
void reset( const IndexDetails * details );
void getKeys( const BSONObj &obj, BSONObjSetDefaultOrder &keys ) co
nst;
BSONElement missingField() const { return _nullElt; }
string getTypeName() const {
if ( _indexType.get() )
return _indexType->getPlugin()->getName();
return "";
}
IndexType* getType() const {
return _indexType.get();
}
const IndexDetails * getDetails() const {
return _details;
}
IndexSuitability suitability( const BSONObj& query , const BSONObj&
order ) const ;
protected:
IndexSuitability _suitability( const BSONObj& query , const BSONObj
& order ) const ;
void _getKeys( vector<const char*> fieldNames , vector<BSONElement>
fixed , const BSONObj &obj, BSONObjSetDefaultOrder &keys ) const;
BSONSizeTracker _sizeTracker;
vector<const char*> _fieldNames;
vector<BSONElement> _fixed;
BSONObj _nullKey;
BSONObj _nullObj;
BSONElement _nullElt;
shared_ptr<IndexType> _indexType;
const IndexDetails * _details;
void _init();
public:
bool _finishedInit;
friend class IndexType;
};
/* Details about a particular index. There is one of these effective ly for each object in /* Details about a particular index. There is one of these effective ly for each object in
system.namespaces (although this also includes the head pointer, which is not in that system.namespaces (although this also includes the head pointer, which is not in that
collection). collection).
** MemoryMapped Record ** (i.e., this is on disk data) ** MemoryMapped Record ** (i.e., this is on disk data)
*/ */
class IndexDetails { class IndexDetails {
public: public:
DiskLoc head; /* btree head disk location */ DiskLoc head; /* btree head disk location */
skipping to change at line 303 skipping to change at line 159
if( added.empty() || !idx.unique() ) if( added.empty() || !idx.unique() )
return; return;
for( vector<BSONObj*>::iterator i = added.begin(); i != added.e nd(); i++ ) { for( vector<BSONObj*>::iterator i = added.begin(); i != added.e nd(); i++ ) {
bool dup = idx.wouldCreateDup(**i, curObjLoc); bool dup = idx.wouldCreateDup(**i, curObjLoc);
uassert( 11001 , "E11001 duplicate key on update", !dup); uassert( 11001 , "E11001 duplicate key on update", !dup);
} }
} }
}; };
class NamespaceDetails; class NamespaceDetails;
void getIndexChanges(vector<IndexChanges>& v, NamespaceDetails& d, BSON // changedId should be initialized to false
Obj newObj, BSONObj oldObj); void getIndexChanges(vector<IndexChanges>& v, NamespaceDetails& d, BSON
Obj newObj, BSONObj oldObj, bool &cangedId);
void dupCheck(vector<IndexChanges>& v, NamespaceDetails& d, DiskLoc cur ObjLoc); void dupCheck(vector<IndexChanges>& v, NamespaceDetails& d, DiskLoc cur ObjLoc);
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
159 lines changed or deleted 5 lines changed or added


 instance.h   instance.h 
skipping to change at line 32 skipping to change at line 32
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "curop.h" #include "curop.h"
#include "security.h" #include "security.h"
#include "cmdline.h" #include "cmdline.h"
#include "client.h" #include "client.h"
namespace mongo { namespace mongo {
extern string dbExecCommand; extern string dbExecCommand;
#define OPWRITE if( _diaglog.level & 1 ) _diaglog.write((char *) m.data, m.
data->len);
#define OPREAD if( _diaglog.level & 2 ) _diaglog.readop((char *) m.data, m.
data->len);
struct DiagLog { struct DiagLog {
ofstream *f; ofstream *f;
/* 0 = off; 1 = writes, 2 = reads, 3 = both /* 0 = off; 1 = writes, 2 = reads, 3 = both
7 = log a few reads, and all writes. 7 = log a few reads, and all writes.
*/ */
int level; int level;
mongo::mutex mutex; mongo::mutex mutex;
DiagLog() : f(0) , level(0) { } DiagLog() : f(0) , level(0) { }
void init() { void init() {
 End of changes. 1 change blocks. 
5 lines changed or deleted 0 lines changed or added


 introspect.h   introspect.h 
skipping to change at line 22 skipping to change at line 22
* 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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
#include "pdfile.h" #include "pdfile.h"
namespace mongo { namespace mongo {
/* --- profiling -------------------------------------------- /* --- profiling --------------------------------------------
do when database->profile is set do when database->profile is set
*/ */
void profile(const char *str, void profile(const char *str,
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 jsobj.h   jsobj.h 
skipping to change at line 26 skipping to change at line 26
* 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.
*/ */
/** /**
BSONObj and its helpers BSONObj and its helpers
"BSON" stands for "binary JSON" -- ie a binary way to represent objects that would be "BSON" stands for "binary JSON" -- ie a binary way to represent objects that would be
represented in JSON (plus a few extensions useful for databases & other languages). represented in JSON (plus a few extensions useful for databases & other languages).
http://www.mongodb.org/display/DOCS/BSON http://www.bsonspec.org/
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
#include "../util/builder.h" #include "../bson/util/builder.h"
#include "../util/optime.h" #include "../util/optime.h"
#include "boost/utility.hpp" #include "boost/utility.hpp"
#include <set> #include <set>
#include "../bson/bsontypes.h"
#include "../bson/oid.h"
#include "../bson/bsonelement.h"
#include "../bson/bsonobj.h"
#include "../bson/bsonmisc.h"
#include "../bson/bsonobjbuilder.h"
#include "../bson/bsonobjiterator.h"
#include "../bson/bsoninlines.h"
#include "../bson/ordering.h"
namespace mongo { #include "../bson/bson_db.h"
class BSONObj;
struct BSONArray; // empty subclass of BSONObj useful for overloading
class BSONElement;
class Record;
class BSONObjBuilder;
class BSONArrayBuilder;
class BSONObjBuilderValueStream;
#pragma pack(1)
/**
the complete list of valid BSON types
*/
enum BSONType {
/** smaller than all other types */
MinKey=-1,
/** end of object */
EOO=0,
/** double precision floating point value */
NumberDouble=1,
/** character string, stored in utf8 */
String=2,
/** an embedded object */
Object=3,
/** an embedded array */
Array=4,
/** binary data */
BinData=5,
/** Undefined type */
Undefined=6,
/** ObjectId */
jstOID=7,
/** boolean type */
Bool=8,
/** date type */
Date=9,
/** null type */
jstNULL=10,
/** regular expression, a pattern with options */
RegEx=11,
/** deprecated / will be redesigned */
DBRef=12,
/** deprecated / use CodeWScope */
Code=13,
/** a programming language (e.g., Python) symbol */
Symbol=14,
/** javascript code that can execute on the database server, with S
avedContext */
CodeWScope=15,
/** 32 bit signed integer */
NumberInt = 16,
/** Updated to a Date with value next OpTime on insert */
Timestamp = 17,
/** 64 bit integer */
NumberLong = 18,
/** max type that is not MaxKey */
JSTypeMax=18,
/** larger than all other types */
MaxKey=127
};
/* subtypes of BinData.
bdtCustom and above are ones that the JS compiler understands, but a
re
opaque to the database.
*/
enum BinDataType { Function=1, ByteArray=2, bdtUUID = 3, MD5Type=5, bdt
Custom=128 };
/** Object ID type.
BSON objects typically have an _id field for the object id. This f
ield should be the first
member of the object when present. class OID is a special type tha
t is a 12 byte id which
is likely to be unique to the system. You may also use other types
for _id's.
When _id field is missing from a BSON object, on an insert the data
base may insert one
automatically in certain circumstances.
Warning: You must call OID::newState() after a fork().
*/
class OID {
union {
struct{
long long a;
unsigned b;
};
unsigned char data[12];
};
static unsigned _machine;
public:
/** call this after a fork */
static void newState();
/** initialize to 'null' */
void clear() { a = 0; b = 0; }
const unsigned char *getData() const { return data; }
bool operator==(const OID& r) {
return a==r.a&&b==r.b;
}
bool operator!=(const OID& r) {
return a!=r.a||b!=r.b;
}
/** The object ID output as 24 hex digits. */
string str() const {
stringstream s;
s << hex;
// s.fill( '0' );
// s.width( 2 );
// fill wasn't working so doing manually...
for( int i = 0; i < 8; i++ ) {
unsigned u = data[i];
if( u < 16 ) s << '0';
s << u;
}
const unsigned char * raw = (const unsigned char*)&b;
for( int i = 0; i < 4; i++ ) {
unsigned u = raw[i];
if( u < 16 ) s << '0';
s << u;
}
/*
s.width( 16 );
s << a;
s.width( 8 );
s << b;
s << dec;
*/
return s.str();
}
/**
sets the contents to a new oid / randomized value
*/
void init();
/** Set to the hex string value specified. */
void init( string s );
};
ostream& operator<<( ostream &s, const OID &o );
/** Formatting mode for generating JSON from BSON.
See <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JS
ON>
for details.
*/
enum JsonStringFormat {
/** strict RFC format */
Strict,
/** 10gen format, which is close to JS format. This form is unders
tandable by
javascript running inside the Mongo server via eval() */
TenGen,
/** Javascript JSON compatible */
JS
};
/* l and r MUST have same type when called: check that first. */
int compareElementValues(const BSONElement& l, const BSONElement& r);
#pragma pack()
/* internals
<type><fieldName ><value>
-------- size() ------------
-fieldNameSize-
value()
type()
*/
/** BSONElement represents an "element" in a BSONObj. So for the objec
t { a : 3, b : "abc" },
'a : 3' is the first element (key+value).
The BSONElement object points into the BSONObj's data. Thus the BSO
NObj must stay in scope
for the life of the BSONElement.
*/
class BSONElement {
friend class BSONObjIterator;
friend class BSONObj;
public:
string toString( bool includeFieldName = true ) const;
operator string() const { return toString(); }
string jsonString( JsonStringFormat format, bool includeFieldNames
= true ) const;
/** Returns the type of the element */
BSONType type() const {
return (BSONType) *data;
}
/** returns the tyoe of the element fixed for the main type
the main purpose is numbers. any numeric type will return Numb
erDouble
Note: if the order changes, indexes have to be re-built or than
can be corruption
*/
int canonicalType() const {
BSONType t = type();
switch ( t ){
case MinKey:
case MaxKey:
return t;
case EOO:
case Undefined:
return 0;
case jstNULL:
return 5;
case NumberDouble:
case NumberInt:
case NumberLong:
return 10;
case String:
case Symbol:
return 15;
case Object:
return 20;
case Array:
return 25;
case BinData:
return 30;
case jstOID:
return 35;
case Bool:
return 40;
case Date:
case Timestamp:
return 45;
case RegEx:
return 50;
case DBRef:
return 55;
case Code:
return 60;
case CodeWScope:
return 65;
default:
assert(0);
return -1;
}
}
/** Indicates if it is the end-of-object element, which is present
at the end of
every BSON object.
*/
bool eoo() const {
return type() == EOO;
}
/** Size of the element.
@param maxLen If maxLen is specified, don't scan more than maxL
en bytes to calculate size.
*/
int size( int maxLen = -1 ) const;
/** Wrap this element up as a singleton object. */
BSONObj wrap() const;
/** Wrap this element up as a singleton object with a new name. */
BSONObj wrap( const char* newName) const;
/** field name of the element. e.g., for
name : "Joe"
"name" is the fieldname
*/
const char * fieldName() const {
if ( eoo() ) return ""; // no fieldname for it.
return data + 1;
}
/** raw data of the element's value (so be careful). */
const char * value() const {
return (data + fieldNameSize() + 1);
}
/** size in bytes of the element's value (when applicable). */
int valuesize() const {
return size() - fieldNameSize() - 1;
}
bool isBoolean() const {
return type() == Bool;
}
/** @return value of a boolean element.
You must assure element is a boolean before
calling. */
bool boolean() const {
return *value() ? true : false;
}
/** Retrieve a java style date value from the element.
Ensure element is of type Date before calling.
*/
Date_t date() const {
return *reinterpret_cast< const Date_t* >( value() );
}
/** Convert the value to boolean, regardless of its type, in a java
script-like fashion
(i.e., treat zero and null as false).
*/
bool trueValue() const {
switch( type() ) {
case NumberLong:
return *reinterpret_cast< const long long* >( value() )
!= 0;
case NumberDouble:
return *reinterpret_cast< const double* >( value() ) !=
0;
case NumberInt:
return *reinterpret_cast< const int* >( value() ) != 0;
case Bool:
return boolean();
case EOO:
case jstNULL:
case Undefined:
return false;
default:
;
}
return true;
}
/** True if element is of a numeric type. */
bool isNumber() const {
switch( type() ) {
case NumberLong:
case NumberDouble:
case NumberInt:
return true;
default:
return false;
}
}
bool isSimpleType() const {
switch( type() ){
case NumberLong:
case NumberDouble:
case NumberInt:
case String:
case Bool:
case Date:
case jstOID:
return true;
default:
return false;
}
}
/** Return double value for this field. MUST be NumberDouble type.
*/
double _numberDouble() const {return *reinterpret_cast< const doubl
e* >( value() ); }
/** Return double value for this field. MUST be NumberInt type. */
int _numberInt() const {return *reinterpret_cast< const int* >( val
ue() ); }
/** Return double value for this field. MUST be NumberLong type. */
long long _numberLong() const {return *reinterpret_cast< const long
long* >( value() ); }
/** Retrieve int value for the element safely. Zero returned if no
t a number. */
int numberInt() const {
switch( type() ) {
case NumberDouble:
return (int) _numberDouble();
case NumberInt:
return _numberInt();
case NumberLong:
return (int) _numberLong();
default:
return 0;
}
}
/** Retrieve long value for the element safely. Zero returned if n
ot a number. */
long long numberLong() const {
switch( type() ) {
case NumberDouble:
return (long long) _numberDouble();
case NumberInt:
return _numberInt();
case NumberLong:
return _numberLong();
default:
return 0;
}
}
/** Retrieve the numeric value of the element. If not of a numeric
type, returns 0.
NOTE: casts to double, data loss may occur with large (>52 bit)
NumberLong values.
*/
double numberDouble() const {
switch( type() ) {
case NumberDouble:
return _numberDouble();
case NumberInt:
return *reinterpret_cast< const int* >( value() );
case NumberLong:
return (double) *reinterpret_cast< const long long* >(
value() );
default:
return 0;
}
}
/** Retrieve the numeric value of the element. If not of a numeric
type, returns 0.
NOTE: casts to double, data loss may occur with large (>52 bit)
NumberLong values.
*/
double number() const { return numberDouble(); }
/** Retrieve the object ID stored in the object.
You must ensure the element is of type jstOID first. */
const OID &__oid() const {
return *reinterpret_cast< const OID* >( value() );
}
/** True if element is null. */
bool isNull() const {
return type() == jstNULL;
}
/** Size (length) of a string element.
You must assure of type String first. */
int valuestrsize() const {
return *reinterpret_cast< const int* >( value() );
}
// for objects the size *includes* the size of the size field
int objsize() const {
return *reinterpret_cast< const int* >( value() );
}
/** Get a string's value. Also gives you start of the real data fo
r an embedded object.
You must assure data is of an appropriate type first -- see als
o valuestrsafe().
*/
const char * valuestr() const {
return value() + 4;
}
/** Get the string value of the element. If not a string returns "
". */
const char *valuestrsafe() const {
return type() == String ? valuestr() : "";
}
/** Get the string value of the element. If not a string returns "
". */
string str() const { return valuestrsafe(); }
/** Get javascript code of a CodeWScope data element. */
const char * codeWScopeCode() const {
return value() + 8;
}
/** Get the scope SavedContext of a CodeWScope data element. */
const char * codeWScopeScopeData() const {
// TODO fix
return codeWScopeCode() + strlen( codeWScopeCode() ) + 1;
}
/** Get the embedded object this element holds. */
BSONObj embeddedObject() const;
/* uasserts if not an object */
BSONObj embeddedObjectUserCheck() const;
BSONObj codeWScopeObject() const;
string ascode() const {
switch( type() ){
case String:
case Code:
return valuestr();
case CodeWScope:
return codeWScopeCode();
default:
log() << "can't convert type: " << (int)(type()) << " to co
de" << endl;
}
uassert( 10062 , "not code" , 0 );
return "";
}
/** Get binary data. Element must be of type BinData */
const char *binData(int& len) const {
// BinData: <int len> <byte subtype> <byte[len] data>
assert( type() == BinData );
len = valuestrsize();
return value() + 5;
}
BinDataType binDataType() const {
// BinData: <int len> <byte subtype> <byte[len] data>
assert( type() == BinData );
unsigned char c = (value() + 4)[0];
return (BinDataType)c;
}
/** Retrieve the regex string for a Regex element */
const char *regex() const {
assert(type() == RegEx);
return value();
}
/** Retrieve the regex flags (options) for a Regex element */
const char *regexFlags() const {
const char *p = regex();
return p + strlen(p) + 1;
}
/** like operator== but doesn't check the fieldname,
just the value.
*/
bool valuesEqual(const BSONElement& r) const {
return woCompare( r , false ) == 0;
}
/** Returns true if elements are equal. */
bool operator==(const BSONElement& r) const {
return woCompare( r , true ) == 0;
}
/** Well ordered comparison.
@return <0: l<r. 0:l==r. >0:l>r
order by type, field name, and field value.
If considerFieldName is true, pay attention to the field name.
*/
int woCompare( const BSONElement &e, bool considerFieldName = true
) const;
const char * rawdata() const {
return data;
}
/** 0 == Equality, just not defined yet */
int getGtLtOp( int def = 0 ) const;
/** Constructs an empty element */
BSONElement();
/** Check that data is internally consistent. */
void validate() const;
/** True if this element may contain subobjects. */
bool mayEncapsulate() const {
switch ( type() ){
case Object:
case Array:
case CodeWScope:
return true;
default:
return false;
}
}
/** True if this element can be a BSONObj */
bool isABSONObj() const {
switch( type() ){
case Object:
case Array:
return true;
default:
return false;
}
}
OpTime optime() const {
return OpTime( *reinterpret_cast< const unsigned long long* >(
value() ) );
}
Date_t timestampTime() const{
unsigned long long t = ((unsigned int*)(value() + 4 ))[0];
return t * 1000;
}
unsigned int timestampInc() const{
return ((unsigned int*)(value() ))[0];
}
const char * dbrefNS() const {
uassert( 10063 , "not a dbref" , type() == DBRef );
return value() + 4;
}
const OID& dbrefOID() const {
uassert( 10064 , "not a dbref" , type() == DBRef );
const char * start = value();
start += 4 + *reinterpret_cast< const int* >( start );
return *reinterpret_cast< const OID* >( start );
}
bool operator<( const BSONElement& other ) const {
int x = (int)canonicalType() - (int)other.canonicalType();
if ( x < 0 ) return true;
else if ( x > 0 ) return false;
return compareElementValues(*this,other) < 0;
}
// If maxLen is specified, don't scan more than maxLen bytes.
BSONElement(const char *d, int maxLen = -1) : data(d) {
fieldNameSize_ = -1;
if ( eoo() )
fieldNameSize_ = 0;
else {
if ( maxLen != -1 ) {
int size = strnlen( fieldName(), maxLen - 1 );
massert( 10333 , "Invalid field name", size != -1 );
fieldNameSize_ = size + 1;
}
}
totalSize = -1;
}
private:
const char *data;
mutable int fieldNameSize_; // cached value
int fieldNameSize() const {
if ( fieldNameSize_ == -1 )
fieldNameSize_ = (int)strlen( fieldName() ) + 1;
return fieldNameSize_;
}
mutable int totalSize; /* caches the computed size */
};
int getGtLtOp(const BSONElement& e);
struct BSONElementCmpWithoutField {
bool operator()( const BSONElement &l, const BSONElement &r ) const
{
return l.woCompare( r, false ) < 0;
}
};
typedef set< BSONElement, BSONElementCmpWithoutField > BSONElementSet;
/**
C++ representation of a "BSON" object -- that is, an extended JSO
N-style
object in a binary representation.
Note that BSONObj's have a smart pointer capability built in -- so y
ou can
pass them around by value. The reference counts used to implement t
his
do not use locking, so copying and destroying BSONObj's are not thre
ad-safe
operations.
BSON object format:
\code
<unsigned totalSize> {<byte BSONType><cstring FieldName><Data>}* EOO
totalSize includes itself.
Data:
Bool: <byte>
EOO: nothing follows
Undefined: nothing follows
OID: an OID object
NumberDouble: <double>
NumberInt: <int32>
String: <unsigned32 strsizewithnull><cstring>
Date: <8bytes>
Regex: <cstring regex><cstring options>
Object: a nested object, leading with its entire size, which termin
ates with EOO.
Array: same as object
DBRef: <strlen> <cstring ns> <oid>
DBRef: a database reference: basically a collection name plus an O
bject ID
BinData: <int len> <byte subtype> <byte[len] data>
Code: a function (not a closure): same format as String.
Symbol: a language symbol (say a python symbol). same format as St
ring.
Code With Scope: <total size><String><Object>
\endcode
*/
class BSONObj {
friend class BSONObjIterator;
class Holder {
public:
Holder( const char *objdata ) :
_objdata( objdata ) {
}
~Holder() {
free((void *)_objdata);
_objdata = 0;
}
private:
const char *_objdata;
};
const char *_objdata;
boost::shared_ptr< Holder > _holder;
void init(const char *data, bool ifree) {
if ( ifree )
_holder.reset( new Holder( data ) );
_objdata = data;
if ( ! isValid() ){
stringstream ss;
ss << "Invalid BSONObj spec size: " << objsize();
try {
BSONElement e = firstElement();
ss << " first element:" << e.toString() << " ";
}
catch ( ... ){}
string s = ss.str();
massert( 10334 , s , 0 );
}
}
#pragma pack(1)
static struct EmptyObject {
EmptyObject() {
len = 5;
jstype = EOO;
}
int len;
char jstype;
} emptyObject;
#pragma pack()
public:
/** Construct a BSONObj from data in the proper format.
@param ifree true if the BSONObj should free() the msgdata when
it destructs.
*/
explicit BSONObj(const char *msgdata, bool ifree = false) {
init(msgdata, ifree);
}
BSONObj(const Record *r);
/** Construct an empty BSONObj -- that is, {}. */
BSONObj() : _objdata( reinterpret_cast< const char * >( &emptyObjec
t ) ) { }
// defensive
~BSONObj() { _objdata = 0; }
void appendSelfToBufBuilder(BufBuilder& b) const {
assert( objsize() );
b.append(reinterpret_cast<const void *>( objdata() ), objsize()
);
}
/** Readable representation of a BSON object in an extended JSON-st
yle notation.
This is an abbreviated representation which might be used for l
ogging.
*/
string toString( bool isArray = false ) const;
operator string() const { return toString(); }
/** Properly formatted JSON string. */
string jsonString( JsonStringFormat format = Strict ) const;
/** note: addFields always adds _id even if not specified */
int addFields(BSONObj& from, set<string>& fields); /* returns n add
ed */
/** returns # of top level fields in the object
note: iterates to count the fields
*/
int nFields() const;
/** adds the field names to the fields set. does NOT clear it (app
ends). */
int getFieldNames(set<string>& fields) const;
/** return has eoo() true if no match
supports "." notation to reach into embedded objects
*/
BSONElement getFieldDotted(const char *name) const;
/** Like getFieldDotted(), but expands multikey arrays and returns
all matching objects
*/
void getFieldsDotted(const char *name, BSONElementSet &ret ) const;
/** Like getFieldDotted(), but returns first array encountered whil
e traversing the
dotted fields of name. The name variable is updated to represe
nt field
names with respect to the returned element. */
BSONElement getFieldDottedOrArray(const char *&name) const;
/** Get the field of the specified name. eoo() is true on the retur
ned
element if not found.
*/
BSONElement getField(const char *name) const;
/** Get the field of the specified name. eoo() is true on the retur
ned
element if not found.
*/
BSONElement getField(const string name) const {
return getField( name.c_str() );
};
/** Get the field of the specified name. eoo() is true on the retur
ned
element if not found.
*/
BSONElement operator[] (const char *field) const {
return getField(field);
}
BSONElement operator[] (const string& field) const {
return getField(field);
}
BSONElement operator[] (int field) const {
stringstream ss;
ss << field;
string s = ss.str();
return getField(s.c_str());
}
/** @return true if field exists */
bool hasField( const char * name )const {
return ! getField( name ).eoo();
}
/** @return "" if DNE or wrong type */
const char * getStringField(const char *name) const;
/** @return subobject of the given name */
BSONObj getObjectField(const char *name) const;
/** @return INT_MIN if not present - does some type conversions */
int getIntField(const char *name) const;
/** @return false if not present */
bool getBoolField(const char *name) const;
/** makes a new BSONObj with the fields specified in pattern.
fields returned in the order they appear in pattern.
if any field is missing or undefined in the object, that field i
n the
output will be null.
sets output field names to match pattern field names.
If an array is encountered while scanning the dotted names in pa
ttern,
that field is treated as missing.
*/
BSONObj extractFieldsDotted(BSONObj pattern) const;
/**
sets element field names to empty string
If a field in pattern is missing, it is omitted from the returne
d
object.
*/
BSONObj extractFieldsUnDotted(BSONObj pattern) const;
/** extract items from object which match a pattern object.
e.g., if pattern is { x : 1, y : 1 }, builds an obje
ct with
x and y elements of this object, if they are present
.
returns elements with original field names
*/
BSONObj extractFields(const BSONObj &pattern , bool fillWithNull=fa
lse) const;
BSONObj filterFieldsUndotted(const BSONObj &filter, bool inFilter)
const;
BSONElement getFieldUsingIndexNames(const char *fieldName, const BS
ONObj &indexKey) const;
/** @return the raw data of the object */
const char *objdata() const {
return _objdata;
}
/** @return total size of the BSON object in bytes */
int objsize() const {
return *(reinterpret_cast<const int*>(objdata()));
}
bool isValid();
/** @return if the user is a valid user doc
criter: isValid() no . or $ field names
*/
bool okForStorage() const;
/** @return true if object is empty -- i.e., {} */
bool isEmpty() const {
return objsize() <= 5;
}
void dump() const {
out() << hex;
const char *p = objdata();
for ( int i = 0; i < objsize(); i++ ) {
out() << i << '\t' << ( 0xff & ( (unsigned) *p ) );
if ( *p >= 'A' && *p <= 'z' )
out() << '\t' << *p;
out() << endl;
p++;
}
}
// Alternative output format
string hexDump() const;
/**wo='well ordered'. fields must be in same order in each object.
Ordering is with respect to the signs of the elements in idxKey.
@return <0 if l<r. 0 if l==r. >0 if l>r
*/
int woCompare(const BSONObj& r, const BSONObj &idxKey = BSONObj(),
bool considerFieldName=true) const;
int woSortOrder( const BSONObj& r , const BSONObj& sortKey ) const;
/** This is "shallow equality" -- ints and doubles won't match. fo
r a
deep equality test use woCompare (which is slower).
*/
bool woEqual(const BSONObj& r) const {
int os = objsize();
if ( os == r.objsize() ) {
return (os == 0 || memcmp(objdata(),r.objdata(),os)==0);
}
return false;
}
/** @return first field of the object */
BSONElement firstElement() const {
return BSONElement(objdata() + 4);
}
/** use getField() instead. */
//BSONElement getField(const char *name) const;
//BSONElement getField(string name) const {
/** @return true if field exists in the object */
bool hasElement(const char *name) const;
/** Get the _id field from the object. For good performance
drivers should
assure that _id is the first element of the object; however, co
rrect operation
is assured regardless.
@return true if found
*/
bool getObjectID(BSONElement& e) const;
/** makes a copy of the object.
*/
BSONObj copy() const;
/* make sure the data buffer is under the control of BSONObj's and
not a remote buffer */
BSONObj getOwned() const{
if ( !isOwned() )
return copy();
return *this;
}
bool isOwned() const { return _holder.get() != 0; }
/** @return A hash code for the object */
int hash() const {
unsigned x = 0;
const char *p = objdata();
for ( int i = 0; i < objsize(); i++ )
x = x * 131 + p[i];
return (x & 0x7fffffff) | 0x8000000; // must be > 0
}
// Return a version of this object where top level elements of type
s
// that are not part of the bson wire protocol are replaced with
// string identifier equivalents.
// TODO Support conversion of element types other than min and max.
BSONObj clientReadable() const;
/** Return new object with the field names replaced by those in the
passed object. */
BSONObj replaceFieldNames( const BSONObj &obj ) const;
/** true unless corrupt */
bool valid() const;
string md5() const;
bool operator==( const BSONObj& other ){
return woCompare( other ) == 0;
}
enum MatchType {
Equality = 0,
LT = 0x1,
LTE = 0x3,
GTE = 0x6,
GT = 0x4,
opIN = 0x8, // { x : { $in : [1,2,3] } }
NE = 0x9,
opSIZE = 0x0A,
opALL = 0x0B,
NIN = 0x0C,
opEXISTS = 0x0D,
opMOD = 0x0E,
opTYPE = 0x0F,
opREGEX = 0x10,
opOPTIONS = 0x11,
opELEM_MATCH = 0x12,
opNEAR = 0x13,
opWITHIN = 0x14,
opMAX_DISTANCE=0x15
};
};
ostream& operator<<( ostream &s, const BSONObj &o );
ostream& operator<<( ostream &s, const BSONElement &e );
struct BSONArray: BSONObj {
// Don't add anything other than forwarding constructors!!!
BSONArray(): BSONObj() {}
explicit BSONArray(const BSONObj& obj): BSONObj(obj) {}
};
class BSONObjCmp {
public:
BSONObjCmp( const BSONObj &_order = BSONObj() ) : order( _order ) {
}
bool operator()( const BSONObj &l, const BSONObj &r ) const {
return l.woCompare( r, order ) < 0;
}
private:
BSONObj order;
};
class BSONObjCmpDefaultOrder : public BSONObjCmp {
public:
BSONObjCmpDefaultOrder() : BSONObjCmp( BSONObj() ) {}
};
typedef set< BSONObj, BSONObjCmpDefaultOrder > BSONObjSetDefaultOrder;
enum FieldCompareResult {
LEFT_SUBFIELD = -2,
LEFT_BEFORE = -1,
SAME = 0,
RIGHT_BEFORE = 1 ,
RIGHT_SUBFIELD = 2
};
FieldCompareResult compareDottedFieldNames( const string& l , const str
ing& r );
/** Use BSON macro to build a BSONObj from a stream
e.g.,
BSON( "name" << "joe" << "age" << 33 )
with auto-generated object id:
BSON( GENOID << "name" << "joe" << "age" << 33 )
The labels GT, GTE, LT, LTE, NE can be helpful for stream-oriented cons
truction
of a BSONObj, particularly when assembling a Query. For example,
BSON( "a" << GT << 23.4 << NE << 30 << "b" << 2 ) produces the object
{ a: { \$gt: 23.4, \$ne: 30 }, b: 2 }.
*/
#define BSON(x) (( mongo::BSONObjBuilder(64) << x ).obj())
/** Use BSON_ARRAY macro like BSON macro, but without keys
BSONArray arr = BSON_ARRAY( "hello" << 1 << BSON( "foo" << BSON_ARRAY(
"bar" << "baz" << "qux" ) ) );
*/
#define BSON_ARRAY(x) (( mongo::BSONArrayBuilder() << x ).arr())
/* Utility class to auto assign object IDs.
Example:
cout << BSON( GENOID << "z" << 3 ); // { _id : ..., z : 3 }
*/
extern struct IDLabeler { } GENOID;
/* Utility class to add a Date element with the current time
Example:
cout << BSON( "created" << DATENOW ); // { created : "2009-10-09 1
1:41:42" }
*/
extern struct DateNowLabeler { } DATENOW;
// Utility class to implement GT, GTE, etc as described above.
class Labeler {
public:
struct Label {
Label( const char *l ) : l_( l ) {}
const char *l_;
};
Labeler( const Label &l, BSONObjBuilderValueStream *s ) : l_( l ),
s_( s ) {}
template<class T>
BSONObjBuilder& operator<<( T value );
/* the value of the element e is appended i.e. for
"age" << GT << someElement
one gets
{ age : { $gt : someElement's value } }
*/
BSONObjBuilder& operator<<( const BSONElement& e );
private:
const Label &l_;
BSONObjBuilderValueStream *s_;
};
extern Labeler::Label GT;
extern Labeler::Label GTE;
extern Labeler::Label LT;
extern Labeler::Label LTE;
extern Labeler::Label NE;
extern Labeler::Label SIZE;
// Utility class to implement BSON( key << val ) as described above.
class BSONObjBuilderValueStream : public boost::noncopyable {
public:
friend class Labeler;
BSONObjBuilderValueStream( BSONObjBuilder * builder );
BSONObjBuilder& operator<<( const BSONElement& e );
template<class T>
BSONObjBuilder& operator<<( T value );
BSONObjBuilder& operator<<(DateNowLabeler& id);
Labeler operator<<( const Labeler::Label &l );
void endField( const char *nextFieldName = 0 );
bool subobjStarted() const { return _fieldName != 0; }
private:
const char * _fieldName;
BSONObjBuilder * _builder;
bool haveSubobj() const { return _subobj.get() != 0; }
BSONObjBuilder *subobj();
auto_ptr< BSONObjBuilder > _subobj;
};
/**
used in conjuction with BSONObjBuilder, allows for proper buffer siz
e to prevent crazy memory usage
*/
class BSONSizeTracker {
public:
#define BSONSizeTrackerSize 10
BSONSizeTracker(){
_pos = 0;
for ( int i=0; i<BSONSizeTrackerSize; i++ )
_sizes[i] = 512; // this is the default, so just be consist
ent
}
~BSONSizeTracker(){
}
void got( int size ){
_sizes[_pos++] = size;
if ( _pos >= BSONSizeTrackerSize )
_pos = 0;
}
/**
* right now choosing largest size
*/
int getSize() const {
int x = 16; // sane min
for ( int i=0; i<BSONSizeTrackerSize; i++ ){
if ( _sizes[i] > x )
x = _sizes[i];
}
return x;
}
private:
int _pos;
int _sizes[BSONSizeTrackerSize];
};
/**
utility for creating a BSONObj
*/
class BSONObjBuilder : boost::noncopyable {
public:
/** @param initsize this is just a hint as to the final size of the
object */
BSONObjBuilder(int initsize=512) : b(buf_), buf_(initsize), offset_
( 0 ), s_( this ) , _tracker(0) {
b.skip(4); /*leave room for size field*/
}
/** @param baseBuilder construct a BSONObjBuilder using an existing
BufBuilder */
BSONObjBuilder( BufBuilder &baseBuilder ) : b( baseBuilder ), buf_(
0 ), offset_( baseBuilder.len() ), s_( this ) , _tracker(0) {
b.skip( 4 );
}
BSONObjBuilder( const BSONSizeTracker & tracker ) : b(buf_) , buf_(
tracker.getSize() ), offset_(0), s_( this ) , _tracker( (BSONSizeTracker*)(
&tracker) ){
b.skip( 4 );
}
/** add all the fields from the object specified to this object */
BSONObjBuilder& appendElements(BSONObj x);
/** append element to the object we are building */
void append( const BSONElement& e) {
assert( !e.eoo() ); // do not append eoo, that would corrupt us
. the builder auto appends when done() is called.
b.append((void*) e.rawdata(), e.size());
}
/** append an element but with a new name */
void appendAs(const BSONElement& e, const char *as) {
assert( !e.eoo() ); // do not append eoo, that would corrupt us
. the builder auto appends when done() is called.
b.append((char) e.type());
b.append(as);
b.append((void *) e.value(), e.valuesize());
}
void appendAs(const BSONElement& e, const string& as) {
appendAs( e , as.c_str() );
}
/** add a subobject as a member */
void append(const char *fieldName, BSONObj subObj) {
b.append((char) Object);
b.append(fieldName);
b.append((void *) subObj.objdata(), subObj.objsize());
}
void append(const string& fieldName , BSONObj subObj) {
append( fieldName.c_str() , subObj );
}
/** add header for a new subobject and return bufbuilder for writin
g to
the subobject's body */
BufBuilder &subobjStart(const char *fieldName) {
b.append((char) Object);
b.append(fieldName);
return b;
}
/** add a subobject as a member with type Array. Thus arr object s
hould have "0", "1", ...
style fields in it.
*/
void appendArray(const char *fieldName, BSONObj subObj) {
b.append((char) Array);
b.append(fieldName);
b.append((void *) subObj.objdata(), subObj.objsize());
}
void append(const char *fieldName, BSONArray arr) { appendArray(fie
ldName, arr); }
/** add header for a new subarray and return bufbuilder for writing
to
the subarray's body */
BufBuilder &subarrayStart(const char *fieldName) {
b.append((char) Array);
b.append(fieldName);
return b;
}
/** Append a boolean element */
void appendBool(const char *fieldName, int val) {
b.append((char) Bool);
b.append(fieldName);
b.append((char) (val?1:0));
}
/** Append a boolean element */
void append(const char *fieldName, bool val) {
b.append((char) Bool);
b.append(fieldName);
b.append((char) (val?1:0));
}
/** Append a 32 bit integer element */
void append(const char *fieldName, int n) {
b.append((char) NumberInt);
b.append(fieldName);
b.append(n);
}
/** Append a 32 bit integer element */
void append(const string &fieldName, int n) {
append( fieldName.c_str(), n );
}
/** Append a 32 bit unsigned element - cast to a signed int. */
void append(const char *fieldName, unsigned n) { append(fieldName,
(int) n); }
/** Append a NumberLong */
void append(const char *fieldName, long long n) {
b.append((char) NumberLong);
b.append(fieldName);
b.append(n);
}
/** Append a NumberLong */
void append(const string& fieldName, long long n) {
append( fieldName.c_str() , n );
}
/** appends a number. if n < max(int)/2 then uses int, otherwise l
ong long */
void appendIntOrLL( const string& fieldName , long long n ){
long long x = n;
if ( x < 0 )
x = x * -1;
if ( x < ( numeric_limits<int>::max() / 2 ) )
append( fieldName.c_str() , (int)n );
else
append( fieldName.c_str() , n );
}
/**
* appendNumber is a series of method for appending the smallest se
nsible type
* mostly for JS
*/
void appendNumber( const string& fieldName , int n ){
append( fieldName.c_str() , n );
}
void appendNumber( const string& fieldName , double d ){
append( fieldName.c_str() , d );
}
void appendNumber( const string& fieldName , long long l ){
static long long maxInt = (int)pow( 2.0 , 30.0 );
static long long maxDouble = (long long)pow( 2.0 , 40.0 );
if ( l < maxInt )
append( fieldName.c_str() , (int)l );
else if ( l < maxDouble )
append( fieldName.c_str() , (double)l );
else
append( fieldName.c_str() , l );
}
/** Append a double element */
BSONObjBuilder& append(const char *fieldName, double n) {
b.append((char) NumberDouble);
b.append(fieldName);
b.append(n);
return *this;
}
/** tries to append the data as a number
* @return true if the data was able to be converted to a number
*/
bool appendAsNumber( const string& fieldName , const string& data )
;
/** Append a BSON Object ID (OID type). */
void appendOID(const char *fieldName, OID *oid = 0 , bool generateI
fBlank = false ) {
b.append((char) jstOID);
b.append(fieldName);
if ( oid )
b.append( (void *) oid, 12 );
else {
OID tmp;
if ( generateIfBlank )
tmp.init();
else
tmp.clear();
b.append( (void *) &tmp, 12 );
}
}
void append( const char *fieldName, OID oid ) {
appendOID( fieldName, &oid );
}
/** Append a time_t date.
@param dt a C-style 32 bit date value, that is
the number of seconds since January 1, 1970, 00:00:00
GMT
*/
void appendTimeT(const char *fieldName, time_t dt) {
b.append((char) Date);
b.append(fieldName);
b.append(static_cast<unsigned long long>(dt) * 1000);
}
/** Append a date.
@param dt a Java-style 64 bit date value, that is
the number of milliseconds since January 1, 1970, 00:
00:00 GMT
*/
void appendDate(const char *fieldName, Date_t dt) {
b.append((char) Date);
b.append(fieldName);
b.append(dt);
}
void append(const char *fieldName, Date_t dt) {
appendDate(fieldName, dt);
}
/** Append a regular expression value
@param regex the regular expression pattern
@param regex options such as "i" or "g"
*/
void appendRegex(const char *fieldName, const char *regex, const ch
ar *options = "") {
b.append((char) RegEx);
b.append(fieldName);
b.append(regex);
b.append(options);
}
/** Append a regular expression value
@param regex the regular expression pattern
@param regex options such as "i" or "g"
*/
void appendRegex(string fieldName, string regex, string options = "
") {
appendRegex(fieldName.c_str(), regex.c_str(), options.c_str());
}
void appendCode(const char *fieldName, const char *code) {
b.append((char) Code);
b.append(fieldName);
b.append((int) strlen(code)+1);
b.append(code);
}
/** Append a string element */
BSONObjBuilder& append(const char *fieldName, const char *str) {
b.append((char) String);
b.append(fieldName);
b.append((int) strlen(str)+1);
b.append(str);
return *this;
}
/** Append a string element */
void append(const char *fieldName, string str) {
append(fieldName, str.c_str());
}
void appendSymbol(const char *fieldName, const char *symbol) {
b.append((char) Symbol);
b.append(fieldName);
b.append((int) strlen(symbol)+1);
b.append(symbol);
}
/** Append a Null element to the object */
void appendNull( const char *fieldName ) {
b.append( (char) jstNULL );
b.append( fieldName );
}
// Append an element that is less than all other keys.
void appendMinKey( const char *fieldName ) {
b.append( (char) MinKey );
b.append( fieldName );
}
// Append an element that is greater than all other keys.
void appendMaxKey( const char *fieldName ) {
b.append( (char) MaxKey );
b.append( fieldName );
}
// Append a Timestamp field -- will be updated to next OpTime on db
insert.
void appendTimestamp( const char *fieldName ) {
b.append( (char) Timestamp );
b.append( fieldName );
b.append( (unsigned long long) 0 );
}
void appendTimestamp( const char *fieldName , unsigned long long va
l ) {
b.append( (char) Timestamp );
b.append( fieldName );
b.append( val );
}
/**
* @param time - in millis (but stored in seconds)
*/
void appendTimestamp( const char *fieldName , unsigned long long ti
me , unsigned int inc ){
OpTime t( (unsigned) (time / 1000) , inc );
appendTimestamp( fieldName , t.asDate() );
}
/* Deprecated (but supported) */
void appendDBRef( const char *fieldName, const char *ns, const OID
&oid ) {
b.append( (char) DBRef );
b.append( fieldName );
b.append( (int) strlen( ns ) + 1 );
b.append( ns );
b.append( (void *) &oid, 12 );
}
/** Append a binary data element
@param fieldName name of the field
@param len length of the binary data in bytes
@param type type information for the data. @see BinDataType. U
se ByteArray if you
don't care about the type.
@param data the byte array
*/
void appendBinData( const char *fieldName, int len, BinDataType typ
e, const char *data ) {
b.append( (char) BinData );
b.append( fieldName );
b.append( len );
b.append( (char) type );
b.append( (void *) data, len );
}
void appendBinData( const char *fieldName, int len, BinDataType typ
e, const unsigned char *data ) {
appendBinData(fieldName, len, type, (const char *) data);
}
/**
@param len the length of data
*/
void appendBinDataArray( const char * fieldName , const char * data
, int len ){
b.append( (char) BinData );
b.append( fieldName );
b.append( len + 4 );
b.append( (char)0x2 );
b.append( len );
b.append( (void *) data, len );
}
/** Append to the BSON object a field of type CodeWScope. This is
a javascript code
fragment accompanied by some scope that goes with it.
*/
void appendCodeWScope( const char *fieldName, const char *code, con
st BSONObj &scope ) {
b.append( (char) CodeWScope );
b.append( fieldName );
b.append( ( int )( 4 + 4 + strlen( code ) + 1 + scope.objsize()
) );
b.append( ( int ) strlen( code ) + 1 );
b.append( code );
b.append( ( void * )scope.objdata(), scope.objsize() );
}
void appendUndefined( const char *fieldName ) {
b.append( (char) Undefined );
b.append( fieldName );
}
/* helper function -- see Query::where() for primary way to do this
. */
void appendWhere( const char *code, const BSONObj &scope ){
appendCodeWScope( "$where" , code , scope );
}
void appendWhere( const string &code, const BSONObj &scope ){
appendWhere( code.c_str(), scope );
}
/**
these are the min/max when comparing, not strict min/max element
s for a given type
*/
void appendMinForType( const string& field , int type );
void appendMaxForType( const string& field , int type );
/** Append an array of values. */
template < class T >
void append( const char *fieldName, const vector< T >& vals ) {
BSONObjBuilder arrBuilder;
for ( unsigned int i = 0; i < vals.size(); ++i )
arrBuilder.append( numStr( i ).c_str(), vals[ i ] );
marshalArray( fieldName, arrBuilder.done() );
}
/* Append an array of ints
void appendArray( const char *fieldName, const vector< int >& vals
) {
BSONObjBuilder arrBuilder;
for ( unsigned i = 0; i < vals.size(); ++i )
arrBuilder.append( numStr( i ).c_str(), vals[ i ] );
marshalArray( fieldName, arrBuilder.done() );
}*/
/** The returned BSONObj will free the buffer when it is finished.
*/
BSONObj obj() {
massert( 10335 , "builder does not own memory", owned() );
int l;
return BSONObj(decouple(l), true);
}
/** Fetch the object we have built.
BSONObjBuilder still frees the object when the build
er goes out of
scope -- very important to keep in mind. Use obj()
if you
would like the BSONObj to last longer than the build
er.
*/
BSONObj done() {
return BSONObj(_done());
}
/** Peek at what is in the builder, but leave the builder ready for
more appends.
The returned object is only valid until the next modification o
r destruction of the builder.
Intended use case: append a field if not already there.
*/
BSONObj asTempObj() {
BSONObj temp(_done());
b.setlen(b.len()-1); //next append should overwrite the EOO
return temp;
}
/* assume ownership of the buffer - you must then free it (with fre
e()) */
char* decouple(int& l) {
char *x = _done();
assert( x );
l = b.len();
b.decouple();
return x;
}
void decouple() {
b.decouple(); // post done() call version. be sure jsobj fr
ees...
}
void appendKeys( const BSONObj& keyPattern , const BSONObj& values
);
private:
static const string numStrs[100]; // cache of 0 to 99 inclusive
public:
static string numStr( int i ) {
if (i>=0 && i<100)
return numStrs[i];
stringstream o;
o << i;
return o.str();
}
/** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<(const char * name ) {
s_.endField( name );
return s_;
}
/** Stream oriented way to add field names and values. */
BSONObjBuilder& operator<<( IDLabeler ) {
OID oid;
oid.init();
appendOID("_id", &oid);
return *this;
}
// prevent implicit string conversions which would allow bad things
like BSON( BSON( "foo" << 1 ) << 2 )
struct ForceExplicitString {
ForceExplicitString( const string &str ) : str_( str ) {}
string str_;
};
/** Stream oriented way to add field names and values. */
BSONObjBuilderValueStream &operator<<( const ForceExplicitString& n
ame ) {
return operator<<( name.str_.c_str() );
}
Labeler operator<<( const Labeler::Label &l ) {
massert( 10336 , "No subobject started", s_.subobjStarted() );
return s_ << l;
}
bool owned() const {
return &b == &buf_;
}
private:
// Append the provided arr object as an array.
void marshalArray( const char *fieldName, const BSONObj &arr ) {
b.append( (char) Array );
b.append( fieldName );
b.append( (void *) arr.objdata(), arr.objsize() );
}
char* _done() {
s_.endField();
b.append((char) EOO);
char *data = b.buf() + offset_;
int size = b.len() - offset_;
*((int*)data) = size;
if ( _tracker )
_tracker->got( size );
return data;
}
BufBuilder &b;
BufBuilder buf_;
int offset_;
BSONObjBuilderValueStream s_;
BSONSizeTracker * _tracker;
};
class BSONArrayBuilder : boost::noncopyable{
public:
BSONArrayBuilder() : _i(0), _b() {}
BSONArrayBuilder( BufBuilder &b ) : _i(0), _b(b) {}
template <typename T>
BSONArrayBuilder& append(const T& x){
_b.append(num().c_str(), x);
return *this;
}
BSONArrayBuilder& append(const BSONElement& e){
_b.appendAs(e, num());
return *this;
}
template <typename T>
BSONArrayBuilder& operator<<(const T& x){
return append(x);
}
void appendNull() {
_b.appendNull(num().c_str());
}
BSONArray arr(){ return BSONArray(_b.obj()); }
BSONObj done() { return _b.done(); }
template <typename T>
BSONArrayBuilder& append(const char *name, const T& x){
fill( name );
append( x );
return *this;
}
BufBuilder &subobjStart( const char *name ) {
fill( name );
return _b.subobjStart( num().c_str() );
}
BufBuilder &subarrayStart( const char *name ) {
fill( name );
return _b.subarrayStart( num().c_str() );
}
void appendArray( const char *name, BSONObj subObj ) {
fill( name );
_b.appendArray( num().c_str(), subObj );
}
void appendAs( const BSONElement &e, const char *name ) {
fill( name );
append( e );
}
private:
void fill( const char *name ) {
char *r;
int n = strtol( name, &r, 10 );
uassert( 13048, "can't append to array using string field name"
, !*r );
while( _i < n )
append( nullElt() );
}
static BSONElement nullElt() {
static BSONObj n = nullObj();
return n.firstElement();
}
static BSONObj nullObj() {
BSONObjBuilder b;
b.appendNull( "" );
return b.obj();
}
string num(){ return _b.numStr(_i++); }
int _i;
BSONObjBuilder _b;
};
/** iterator for a BSONObj
Note each BSONObj ends with an EOO element: so you will get more() o
n an empty
object, although next().eoo() will be true.
todo: we may want to make a more stl-like iterator interface for thi
s
with things like begin() and end()
*/
class BSONObjIterator {
public:
/** Create an iterator for a BSON object.
*/
BSONObjIterator(const BSONObj& jso) {
int sz = jso.objsize();
if ( sz == 0 ) {
pos = theend = 0;
return;
}
pos = jso.objdata() + 4;
theend = jso.objdata() + sz;
}
/** @return true if more elements exist to be enumerated. */
bool moreWithEOO() {
return pos < theend;
}
bool more(){
return pos < theend && pos[0];
}
/** @return the next element in the object. For the final element,
element.eoo() will be true. */
BSONElement next( bool checkEnd = false ) {
assert( pos < theend );
BSONElement e( pos, checkEnd ? (int)(theend - pos) : -1 );
pos += e.size( checkEnd ? (int)(theend - pos) : -1 );
return e;
}
private:
const char *pos;
const char *theend;
};
/* iterator a BSONObj which is an array, in array order.
class JSArrayIter {
public:
BSONObjIterator(const BSONObj& jso) {
...
}
bool more() { return ... }
BSONElement next() {
...
}
};
*/
extern BSONObj maxKey;
extern BSONObj minKey;
// 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;
/*- just for testing -- */
#pragma pack(1)
struct JSObj1 {
JSObj1() {
totsize=sizeof(JSObj1);
n = NumberDouble;
strcpy_s(nname, 5, "abcd");
N = 3.1;
s = String;
strcpy_s(sname, 7, "abcdef");
slen = 10;
strcpy_s(sval, 10, "123456789");
eoo = EOO;
}
unsigned totsize;
char n;
char nname[5];
double N;
char s;
char sname[7];
unsigned slen;
char sval[10];
char eoo;
};
#pragma pack()
extern JSObj1 js1;
#ifdef _DEBUG
#define CHECK_OBJECT( o , msg ) massert( 10337 , (string)"object not valid
" + (msg) , (o).isValid() )
#else
#define CHECK_OBJECT( o , msg )
#endif
inline BSONObj BSONElement::embeddedObjectUserCheck() const {
uassert( 10065 , "invalid parameter: expected an object", isABSONO
bj() );
return BSONObj(value());
}
inline BSONObj BSONElement::embeddedObject() const {
assert( isABSONObj() );
return BSONObj(value());
}
inline BSONObj BSONElement::codeWScopeObject() const {
assert( type() == CodeWScope );
int strSizeWNull = *(int *)( value() + 4 );
return BSONObj( value() + 4 + 4 + strSizeWNull );
}
inline BSONObj BSONObj::copy() const {
char *p = (char*) malloc(objsize());
memcpy(p, objdata(), objsize());
return BSONObj(p, true);
}
// wrap this element up as a singleton object.
inline BSONObj BSONElement::wrap() const {
BSONObjBuilder b(size()+6);
b.append(*this);
return b.obj();
}
inline BSONObj BSONElement::wrap( const char * newName ) const {
BSONObjBuilder b(size()+6+strlen(newName));
b.appendAs(*this,newName);
return b.obj();
}
inline bool BSONObj::hasElement(const char *name) const {
if ( !isEmpty() ) {
BSONObjIterator it(*this);
while ( it.moreWithEOO() ) {
BSONElement e = it.next();
if ( strcmp(name, e.fieldName()) == 0 )
return true;
}
}
return false;
}
inline BSONElement BSONObj::getField(const char *name) const {
BSONObjIterator i(*this);
while ( i.more() ) {
BSONElement e = i.next();
if ( strcmp(e.fieldName(), name) == 0 )
return e;
}
return BSONElement();
}
/* add all the fields from the object specified to this object */
inline BSONObjBuilder& BSONObjBuilder::appendElements(BSONObj x) {
BSONObjIterator it(x);
while ( it.moreWithEOO() ) {
BSONElement e = it.next();
if ( e.eoo() ) break;
append(e);
}
return *this;
}
inline bool BSONObj::isValid(){
int x = objsize();
return x > 0 && x <= 1024 * 1024 * 8;
}
inline bool BSONObj::getObjectID(BSONElement& e) const {
BSONElement f = getField("_id");
if( !f.eoo() ) {
e = f;
return true;
}
return false;
}
inline BSONObjBuilderValueStream::BSONObjBuilderValueStream( BSONObjBui
lder * builder ) {
_fieldName = 0;
_builder = builder;
}
template<class T>
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( T value )
{
_builder->append(_fieldName, value);
_fieldName = 0;
return *_builder;
}
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<( const BSO
NElement& e ) {
_builder->appendAs( e , _fieldName );
_fieldName = 0;
return *_builder;
}
inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<(DateNowLab
eler& id){
_builder->appendDate(_fieldName, jsTime());
_fieldName = 0;
return *_builder;
}
inline Labeler BSONObjBuilderValueStream::operator<<( const Labeler::La
bel &l ) {
return Labeler( l, this );
}
inline void BSONObjBuilderValueStream::endField( const char *nextFieldN
ame ) {
if ( _fieldName && haveSubobj() ) {
_builder->append( _fieldName, subobj()->done() );
}
_subobj.reset();
_fieldName = nextFieldName;
}
inline BSONObjBuilder *BSONObjBuilderValueStream::subobj() {
if ( !haveSubobj() )
_subobj.reset( new BSONObjBuilder() );
return _subobj.get();
}
template<class T> inline
BSONObjBuilder& Labeler::operator<<( T value ) {
s_->subobj()->append( l_.l_, value );
return *s_->_builder;
}
inline
BSONObjBuilder& Labeler::operator<<( const BSONElement& e ) {
s_->subobj()->appendAs( e, l_.l_ );
return *s_->_builder;
}
// {a: {b:1}} -> {a.b:1}
void nested2dotted(BSONObjBuilder& b, const BSONObj& obj, const string&
base="");
inline BSONObj nested2dotted(const BSONObj& obj){
BSONObjBuilder b;
nested2dotted(b, obj);
return b.obj();
}
// {a.b:1} -> {a: {b:1}}
void dotted2nested(BSONObjBuilder& b, const BSONObj& obj);
inline BSONObj dotted2nested(const BSONObj& obj){
BSONObjBuilder b;
dotted2nested(b, obj);
return b.obj();
}
/* WARNING: nested/dotted conversions are not 100% reversible
* nested2dotted(dotted2nested({a.b: {c:1}})) -> {a.b.c: 1}
* also, dotted2nested ignores order
*/
typedef map<string, BSONElement> BSONMap;
inline BSONMap bson2map(const BSONObj& obj){
BSONMap m;
BSONObjIterator it(obj);
while (it.more()){
BSONElement e = it.next();
m[e.fieldName()] = e;
}
return m;
}
struct BSONElementFieldNameCmp {
bool operator()( const BSONElement &l, const BSONElement &r ) const
{
return strcmp( l.fieldName() , r.fieldName() ) <= 0;
}
};
typedef set<BSONElement, BSONElementFieldNameCmp> BSONSortedElements;
inline BSONSortedElements bson2set( const BSONObj& obj ){
BSONSortedElements s;
BSONObjIterator it(obj);
while ( it.more() )
s.insert( it.next() );
return s;
}
class BSONObjIteratorSorted {
public:
BSONObjIteratorSorted( const BSONObj& o );
~BSONObjIteratorSorted(){
assert( _fields );
delete[] _fields;
_fields = 0;
}
bool more(){
return _cur < _nfields;
}
BSONElement next(){
assert( _fields );
if ( _cur < _nfields )
return BSONElement( _fields[_cur++] );
return BSONElement();
}
private:
const char ** _fields;
int _nfields;
int _cur;
};
} // namespace mongo
 End of changes. 5 change blocks. 
4 lines changed or deleted 12 lines changed or added


 jsobjmanipulator.h   jsobjmanipulator.h 
skipping to change at line 43 skipping to change at line 43
} }
/** Replace a Timestamp type with a Date type initialized to /** Replace a Timestamp type with a Date type initialized to
OpTime::now().asDate() OpTime::now().asDate()
*/ */
void initTimestamp(); void initTimestamp();
/** Change the value, in place, of the number. */ /** Change the value, in place, of the number. */
void setNumber(double d) { void setNumber(double d) {
if ( _element.type() == NumberDouble ) *reinterpret_cast< doubl e * >( value() ) = d; if ( _element.type() == NumberDouble ) *reinterpret_cast< doubl e * >( value() ) = d;
else if ( _element.type() == NumberInt ) *reinterpret_cast< int * >( value() ) = (int) d; else if ( _element.type() == NumberInt ) *reinterpret_cast< int * >( value() ) = (int) d;
else assert(0);
} }
void setLong(long long n) { void setLong(long long n) {
if( _element.type() == NumberLong ) *reinterpret_cast< long lon assert( _element.type() == NumberLong );
g * >( value() ) = n; *reinterpret_cast< long long * >( value() ) = n;
} }
void setInt(int n) { void setInt(int n) {
assert( _element.type() == NumberInt ); assert( _element.type() == NumberInt );
*reinterpret_cast< int * >( value() ) = n; *reinterpret_cast< int * >( value() ) = n;
} }
/** Replace the type and value of the element with the type and val ue of e, /** Replace the type and value of the element with the type and val ue of e,
preserving the original fieldName */ preserving the original fieldName */
void replaceTypeAndValue( const BSONElement &e ) { void replaceTypeAndValue( const BSONElement &e ) {
*data() = e.type(); *data() = e.type();
 End of changes. 2 change blocks. 
2 lines changed or deleted 3 lines changed or added


 json.h   json.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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
namespace mongo { namespace mongo {
/** Create a BSONObj from a JSON <http://www.json.org> string. In addi tion /** Create a BSONObj from a JSON <http://www.json.org> string. In addi tion
to the JSON extensions extensions described here to the JSON extensions extensions described here
<http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JSON>, <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JSON>,
this function accepts certain unquoted field names and allows single q uotes this function accepts certain unquoted field names and allows single q uotes
to optionally be used when specifying field names and string values in stead to optionally be used when specifying field names and string values in stead
of double quotes. JSON unicode escape sequences (of the form \uXXXX) are of double quotes. JSON unicode escape sequences (of the form \uXXXX) are
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 lasterror.h   lasterror.h 
skipping to change at line 22 skipping to change at line 22
* 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 <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
#undef assert #undef assert
#define assert xassert #define assert MONGO_assert
namespace mongo { namespace mongo {
class BSONObjBuilder; class BSONObjBuilder;
class Message; class Message;
struct LastError { struct LastError {
int code; int code;
string msg; string msg;
enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ;
/* todo: nObjects should be 64 bit */ /* todo: nObjects should be 64 bit */
skipping to change at line 90 skipping to change at line 90
* id of 0 means should use thread local management * id of 0 means should use thread local management
*/ */
void setID( int id ); void setID( int id );
int getID(); int getID();
void remove( int id ); void remove( int id );
void release(); void release();
/** when db receives a message/request, call this */ /** when db receives a message/request, call this */
void startRequest( Message& m , LastError * connectionOwned ); void startRequest( Message& m , LastError * connectionOwned );
void startRequest( Message& m ); LastError * startRequest( Message& m , int clientId = 0 );
// used to disable lastError reporting while processing a killCurso rs message // used to disable lastError reporting while processing a killCurso rs message
// disable causes get() to return 0. // disable causes get() to return 0.
LastError *disableForCommand(); // only call once per command invoc ation! LastError *disableForCommand(); // only call once per command invoc ation!
private: private:
ThreadLocalValue<int> _id; ThreadLocalValue<int> _id;
boost::thread_specific_ptr<LastError> _tl; boost::thread_specific_ptr<LastError> _tl;
struct Status { struct Status {
time_t time; time_t time;
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 locks.h   locks.h 
skipping to change at line 19 skipping to change at line 19
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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/>.
*/ */
//#include "../stdafx.h" //#include "../pch.h"
#pragma once #pragma once
#if defined(_WIN32) #if defined(_WIN32)
#if BOOST_VERSION >= 103500 #if BOOST_VERSION >= 103500
#include <boost/thread/shared_mutex.hpp> #include <boost/thread/shared_mutex.hpp>
#undef assert #undef assert
#define assert xassert #define assert MONGO_assert
#else #else
#error need boost >= 1.35 for windows #error need boost >= 1.35 for windows
#endif #endif
#define BOOST_RWLOCK #define BOOST_RWLOCK
#else #else
#include <pthread.h> #include <pthread.h>
skipping to change at line 68 skipping to change at line 68
void unlock_shared(){ void unlock_shared(){
_m.unlock_shared(); _m.unlock_shared();
} }
bool lock_shared_try( int millis ){ bool lock_shared_try( int millis ){
boost::system_time until = get_system_time(); boost::system_time until = get_system_time();
until += boost::posix_time::milliseconds(millis); until += boost::posix_time::milliseconds(millis);
return _m.timed_lock_shared( until ); return _m.timed_lock_shared( until );
} }
bool lock_try( int millis ){
boost::system_time until = get_system_time();
until += boost::posix_time::milliseconds(millis);
return _m.timed_lock( until );
}
}; };
#else #else
class RWLock { class RWLock {
pthread_rwlock_t _lock; pthread_rwlock_t _lock;
inline void check( int x ){ inline void check( int x ){
if( x == 0 ) if( x == 0 )
return; return;
log() << "pthread rwlock failed: " << x << endl; log() << "pthread rwlock failed: " << x << endl;
assert( x == 0 ); assert( x == 0 );
} }
public: public:
RWLock(){ RWLock(){
check( pthread_rwlock_init( &_lock , 0 ) ); check( pthread_rwlock_init( &_lock , 0 ) );
} }
~RWLock(){ ~RWLock(){
check( pthread_rwlock_destroy( &_lock ) ); if ( ! __destroyingStatics ){
check( pthread_rwlock_destroy( &_lock ) );
}
} }
void lock(){ void lock(){
check( pthread_rwlock_wrlock( &_lock ) ); check( pthread_rwlock_wrlock( &_lock ) );
} }
void unlock(){ void unlock(){
check( pthread_rwlock_unlock( &_lock ) ); check( pthread_rwlock_unlock( &_lock ) );
} }
void lock_shared(){ void lock_shared(){
check( pthread_rwlock_rdlock( &_lock ) ); check( pthread_rwlock_rdlock( &_lock ) );
} }
void unlock_shared(){ void unlock_shared(){
check( pthread_rwlock_unlock( &_lock ) ); check( pthread_rwlock_unlock( &_lock ) );
} }
bool lock_shared_try( int millis ){ bool lock_shared_try( int millis ){
while ( millis-- ){ return _try( millis , false );
int x = pthread_rwlock_tryrdlock( &_lock ); }
if ( x == 0 )
bool lock_try( int millis ){
return _try( millis , true );
}
bool _try( int millis , bool write ){
while ( true ) {
int x = write ?
pthread_rwlock_trywrlock( &_lock ) :
pthread_rwlock_tryrdlock( &_lock );
if ( x <= 0 )
return true; return true;
if ( millis-- <= 0 )
return false;
if ( x == EBUSY ){ if ( x == EBUSY ){
sleepmillis(1); sleepmillis(1);
continue; continue;
} }
check(x); check(x);
} }
return false; return false;
} }
}; };
#endif #endif
struct rwlock {
rwlock( const RWLock& lock , bool write , bool alreadyHaveLock = fa
lse )
: _lock( (RWLock&)lock ) , _write( write ){
if ( ! alreadyHaveLock ){
if ( _write )
_lock.lock();
else
_lock.lock_shared();
}
}
~rwlock(){
if ( _write )
_lock.unlock();
else
_lock.unlock_shared();
}
RWLock& _lock;
bool _write;
};
} }
 End of changes. 9 change blocks. 
6 lines changed or deleted 55 lines changed or added


 log.h   log.h 
skipping to change at line 118 skipping to change at line 118
virtual Nullstream& operator<< (ostream& ( *endl )(ostream&)) { virtual Nullstream& operator<< (ostream& ( *endl )(ostream&)) {
return *this; return *this;
} }
virtual Nullstream& operator<< (ios_base& (*hex)(ios_base&)) { virtual Nullstream& operator<< (ios_base& (*hex)(ios_base&)) {
return *this; return *this;
} }
virtual void flush(){} virtual void flush(){}
}; };
extern Nullstream nullstream; extern Nullstream nullstream;
#define LOGIT { ss << x; return *this; }
class Logstream : public Nullstream { class Logstream : public Nullstream {
static mongo::mutex mutex; static mongo::mutex mutex;
static int doneSetup; static int doneSetup;
stringstream ss; stringstream ss;
public: public:
static int magicNumber(){ static int magicNumber(){
return 1717; return 1717;
} }
void flush() { void flush() {
// this ensures things are sane // this ensures things are sane
if ( doneSetup == 1717 ){ if ( doneSetup == 1717 ){
scoped_lock lk(mutex); scoped_lock lk(mutex);
cout << ss.str(); cout << ss.str();
cout.flush(); cout.flush();
} }
ss.str(""); ss.str("");
} }
Logstream& operator<<(const char *x) LOGIT
Logstream& operator<<(char *x) LOGIT /** note these are virtual */
Logstream& operator<<(char x) LOGIT Logstream& operator<<(const char *x) { ss << x; return *this; }
Logstream& operator<<(int x) LOGIT Logstream& operator<<(char *x) { ss << x; return *this; }
Logstream& operator<<(ExitCode x) LOGIT Logstream& operator<<(char x) { ss << x; return *this; }
Logstream& operator<<(long x) LOGIT Logstream& operator<<(int x) { ss << x; return *this; }
Logstream& operator<<(unsigned long x) LOGIT Logstream& operator<<(ExitCode x) { ss << x; return *this; }
Logstream& operator<<(unsigned x) LOGIT Logstream& operator<<(long x) { ss << x; return *this; }
Logstream& operator<<(double x) LOGIT Logstream& operator<<(unsigned long x) { ss << x; return *this; }
Logstream& operator<<(void *x) LOGIT Logstream& operator<<(unsigned x) { ss << x; return *this; }
Logstream& operator<<(const void *x) LOGIT Logstream& operator<<(double x) { ss << x; return *this; }
Logstream& operator<<(long long x) LOGIT Logstream& operator<<(void *x) { ss << x; return *this; }
Logstream& operator<<(unsigned long long x) LOGIT Logstream& operator<<(const void *x) { ss << x; return *this; }
Logstream& operator<<(bool x) LOGIT Logstream& operator<<(long long x) { ss << x; return *this; }
Logstream& operator<<(unsigned long long x) { ss << x; return *this
; }
Logstream& operator<<(bool x) { ss << x; return *this
; }
Logstream& operator<<(const LazyString& x) { Logstream& operator<<(const LazyString& x) {
ss << x.val(); ss << x.val();
return *this; return *this;
} }
Logstream& operator<< (ostream& ( *_endl )(ostream&)) { Logstream& operator<< (ostream& ( *_endl )(ostream&)) {
ss << '\n'; ss << '\n';
flush(); flush();
return *this; return *this;
} }
Logstream& operator<< (ios_base& (*_hex)(ios_base&)) { Logstream& operator<< (ios_base& (*_hex)(ios_base&)) {
skipping to change at line 245 skipping to change at line 246
return l; return l;
} }
/** /**
log to a file rather than stdout log to a file rather than stdout
defined in assert_util.cpp defined in assert_util.cpp
*/ */
void initLogging( const string& logpath , bool append ); void initLogging( const string& logpath , bool append );
void rotateLogs( int signal = 0 ); void rotateLogs( int signal = 0 );
#define OUTPUT_ERRNOX(x) "errno:" << x << " " << strerror(x) inline string errnoWithDescription(int x = errno) {
#define OUTPUT_ERRNO OUTPUT_ERRNOX(errno) stringstream s;
s << "errno:" << x << ' ' << strerror(x);
return s.str();
}
string errnostring( const char * prefix = 0 ); /** output the error # and error message with prefix.
handy for use as parm in uassert/massert.
*/
string errnoWithPrefix( const char * prefix = 0 );
} // namespace mongo } // namespace mongo
 End of changes. 4 change blocks. 
19 lines changed or deleted 28 lines changed or added


 lruishmap.h   lruishmap.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 "../stdafx.h" #include "../pch.h"
#include "../util/goodies.h" #include "../util/goodies.h"
namespace mongo { namespace mongo {
/* Your K object must define: /* Your K object must define:
int hash() - must always return > 0. int hash() - must always return > 0.
operator== operator==
*/ */
template <class K, class V, int MaxChain> template <class K, class V, int MaxChain>
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 matcher.h   matcher.h 
skipping to change at line 138 skipping to change at line 138
const BSONElement &toMatch, const BSONObj &obj, const BSONElement &toMatch, const BSONObj &obj,
const ElementMatcher&bm, MatchDetails * details ); const ElementMatcher&bm, MatchDetails * details );
public: public:
static int opDirection(int op) { static int opDirection(int op) {
return op <= BSONObj::LTE ? -1 : 1; return op <= BSONObj::LTE ? -1 : 1;
} }
// Only specify constrainIndexKey if matches() will be called with // Only specify constrainIndexKey if matches() will be called with
// index keys having empty string field names. // index keys having empty string field names.
Matcher(const BSONObj &pattern, const BSONObj &constrainIndexKey = BSONObj()); Matcher(const BSONObj &pattern, const BSONObj &constrainIndexKey = BSONObj(), bool subMatcher = false);
~Matcher(); ~Matcher();
bool matches(const BSONObj& j, MatchDetails * details = 0 ); bool matches(const BSONObj& j, MatchDetails * details = 0 );
bool keyMatch() const { return !all && !haveSize && !hasArray && !h // until SERVER-109 $or is opaque to indexes
aveNeg; } bool keyMatch() const { return !all && !haveSize && !hasArray && !h
aveNeg && _orMatchers.size() == 0; }
bool atomic() const { return _atomic; } bool atomic() const { return _atomic; }
bool hasType( BSONObj::MatchType type ) const; bool hasType( BSONObj::MatchType type ) const;
string toString() const {
return jsobj.toString();
}
private: private:
void addBasic(const BSONElement &e, int c, bool isNot) { void addBasic(const BSONElement &e, int c, bool isNot) {
// TODO May want to selectively ignore these element types base d on op type. // TODO May want to selectively ignore these element types base d on op type.
if ( e.type() == MinKey || e.type() == MaxKey ) if ( e.type() == MinKey || e.type() == MaxKey )
return; return;
basics.push_back( ElementMatcher( e , c, isNot ) ); basics.push_back( ElementMatcher( e , c, isNot ) );
} }
void addRegex(const char *fieldName, const char *regex, const char *flags, bool isNot = false); void addRegex(const char *fieldName, const char *regex, const char *flags, bool isNot = false);
bool addOp( const BSONElement &e, const BSONElement &fe, bool isNot , const char *& regex, const char *&flags ); bool addOp( const BSONElement &e, const BSONElement &fe, bool isNot , const char *& regex, const char *&flags );
int valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm); int valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm);
bool parseOrNor( const BSONElement &e, bool subMatcher );
void parseOr( const BSONElement &e, bool subMatcher, vector< shared
_ptr< Matcher > > &matchers );
Where *where; // set if query uses $where Where *where; // set if query uses $where
BSONObj jsobj; // the query pattern. e.g., { name : "joe" } BSONObj jsobj; // the query pattern. e.g., { name : "joe" }
BSONObj constrainIndexKey_; BSONObj constrainIndexKey_;
vector<ElementMatcher> basics; vector<ElementMatcher> basics;
bool haveSize; bool haveSize;
bool all; bool all;
bool hasArray; bool hasArray;
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)
skipping to change at line 183 skipping to change at line 192
i.e. we stay locked the whole time. i.e. we stay locked the whole time.
http://www.mongodb.org/display/DOCS/Removing[ http://www.mongodb.org/display/DOCS/Removing[
*/ */
bool _atomic; bool _atomic;
RegexMatcher regexs[4]; RegexMatcher regexs[4];
int nRegex; int nRegex;
// 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;
vector< shared_ptr< Matcher > > _orMatchers;
vector< shared_ptr< Matcher > > _norMatchers;
friend class CoveredIndexMatcher; friend class CoveredIndexMatcher;
}; };
// If match succeeds on index key, then attempt to match full document. // If match succeeds on index key, then attempt to match full document.
class CoveredIndexMatcher : boost::noncopyable { class CoveredIndexMatcher : boost::noncopyable {
public: public:
CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey Pattern); CoveredIndexMatcher(const BSONObj &pattern, const BSONObj &indexKey Pattern);
bool matches(const BSONObj &o){ return _docMatcher.matches( o ); } bool matches(const BSONObj &o){ return _docMatcher.matches( o ); }
bool matches(const BSONObj &key, const DiskLoc &recLoc , MatchDetai ls * details = 0 ); bool matches(const BSONObj &key, const DiskLoc &recLoc , MatchDetai ls * details = 0 );
 End of changes. 5 change blocks. 
3 lines changed or deleted 15 lines changed or added


 message.h   message.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 "../util/sock.h" #include "../util/sock.h"
#include "../util/atomic_int.h" #include "../bson/util/atomic_int.h"
#include "hostandport.h"
namespace mongo { namespace mongo {
extern bool noUnixSocket; extern bool noUnixSocket;
class Message; class Message;
class MessagingPort; class MessagingPort;
class PiggyBackData; class PiggyBackData;
typedef AtomicUInt MSGID; typedef AtomicUInt MSGID;
class Listener { class Listener {
public: public:
Listener(const string &ip, int p, bool logConnect=true ) : _ip(ip), _port(p), _logConnect(logConnect) { } Listener(const string &ip, int p, bool logConnect=true ) : _port(p) , _ip(ip), _logConnect(logConnect) { }
virtual ~Listener() {} virtual ~Listener() {}
void initAndListen(); // never returns unless error (start a thread ) void initAndListen(); // never returns unless error (start a thread )
/* spawn a thread, etc., then return */ /* spawn a thread, etc., then return */
virtual void accepted(int sock, const SockAddr& from); virtual void accepted(int sock, const SockAddr& from);
virtual void accepted(MessagingPort *mp){ virtual void accepted(MessagingPort *mp){
assert(!"You must overwrite one of the accepted methods"); assert(!"You must overwrite one of the accepted methods");
} }
const int _port;
private: private:
string _ip; string _ip;
int _port;
bool _logConnect; bool _logConnect;
}; };
class AbstractMessagingPort { class AbstractMessagingPort {
public: public:
virtual ~AbstractMessagingPort() { } virtual ~AbstractMessagingPort() { }
virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available virtual void reply(Message& received, Message& response, MSGID resp onseTo) = 0; // like the reply below, but doesn't rely on received.data sti ll being available
virtual void reply(Message& received, Message& response) = 0; virtual void reply(Message& received, Message& response) = 0;
virtual unsigned remotePort() = 0 ; virtual HostAndPort remote() const = 0;
virtual unsigned remotePort() const = 0;
}; };
class MessagingPort : public AbstractMessagingPort { class MessagingPort : public AbstractMessagingPort {
public: public:
MessagingPort(int sock, const SockAddr& farEnd); MessagingPort(int sock, const SockAddr& farEnd);
// in some cases the timeout will actually be 2x this value - eg we do a partial send, // in some cases the timeout will actually be 2x this value - eg we do a partial send,
// then the timeout fires, then we try to send again, then the time out fires again with // then the timeout fires, then we try to send again, then the time out 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
MessagingPort(int timeout = 0); MessagingPort(int timeout = 0, int logLevel = 0 );
virtual ~MessagingPort(); virtual ~MessagingPort();
void shutdown(); void shutdown();
bool connect(SockAddr& farEnd); bool connect(SockAddr& farEnd);
/* it's assumed if you reuse a message object, that it doesn't cros s MessagingPort's. /* it's assumed if you reuse a message object, that it doesn't cros s MessagingPort's.
also, the Message data will go out of scope on the subsequent re cv call. also, the Message data will go out of scope on the subsequent re cv call.
*/ */
bool recv(Message& m); bool recv(Message& m);
void reply(Message& received, Message& response, MSGID responseTo); void reply(Message& received, Message& response, MSGID responseTo);
void reply(Message& received, Message& response); void reply(Message& received, Message& response);
bool call(Message& toSend, Message& response); bool call(Message& toSend, Message& response);
void say(Message& toSend, int responseTo = -1); void say(Message& toSend, int responseTo = -1);
void piggyBack( Message& toSend , int responseTo = -1 ); void piggyBack( Message& toSend , int responseTo = -1 );
virtual unsigned remotePort(); virtual unsigned remotePort() const;
virtual HostAndPort remote() const;
// send len or throw SocketException // send len or throw SocketException
void send( const char * data , int len, const char *context ); void send( const char * data , int len, const char *context );
// 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 );
private: private:
int sock; int sock;
PiggyBackData * piggyBackData; PiggyBackData * piggyBackData;
public: public:
SockAddr farEnd; SockAddr farEnd;
int _timeout; int _timeout;
int _logLevel; // passed to log() when logging errors
friend class PiggyBackData; friend class PiggyBackData;
}; };
//#pragma pack() //#pragma pack()
#pragma pack(1) #pragma pack(1)
enum Operations { enum Operations {
opReply = 1, /* reply. responseTo is set. */ opReply = 1, /* reply. responseTo is set. */
dbMsg = 1000, /* generic msg command followed by a string */ dbMsg = 1000, /* generic msg command followed by a string */
skipping to change at line 247 skipping to change at line 252
class SocketException : public DBException { class SocketException : public DBException {
public: public:
virtual const char* what() const throw() { return "socket exception "; } virtual const char* what() const throw() { return "socket exception "; }
virtual int getCode(){ return 9001; } virtual int getCode(){ return 9001; }
}; };
MSGID nextMessageId(); MSGID nextMessageId();
void setClientId( int id ); void setClientId( int id );
int getClientId(); int getClientId();
extern TicketHolder connTicketHolder;
} // namespace mongo } // namespace mongo
 End of changes. 9 change blocks. 
6 lines changed or deleted 14 lines changed or added


 message_server.h   message_server.h 
skipping to change at line 25 skipping to change at line 25
* limitations under the License. * limitations under the License.
*/ */
/* /*
abstract database server abstract database server
async io core, worker thread system async io core, worker thread system
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
namespace mongo { namespace mongo {
class MessageHandler { class MessageHandler {
public: public:
virtual ~MessageHandler(){} virtual ~MessageHandler(){}
virtual void process( Message& m , AbstractMessagingPort* p ) = 0; virtual void process( Message& m , AbstractMessagingPort* p ) = 0;
}; };
class MessageServer { class MessageServer {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 miniwebserver.h   miniwebserver.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 "../stdafx.h" #include "../pch.h"
#include "message.h" #include "message.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
namespace mongo { namespace mongo {
class MiniWebServer : public Listener { class MiniWebServer : public Listener {
public: public:
MiniWebServer(const string &ip, int _port); MiniWebServer(const string &ip, int _port);
virtual ~MiniWebServer() {} virtual ~MiniWebServer() {}
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 mockdbclient.h   mockdbclient.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 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 "../client/dbclient.h" #include "../client/dbclient.h"
#include "../db/commands.h" #include "../db/commands.h"
#include "../db/replpair.h"
class MockDBClientConnection : public DBClientConnection { class MockDBClientConnection : public DBClientConnection {
public: public:
MockDBClientConnection() : connect_() {} MockDBClientConnection() : connect_() {}
virtual virtual
BSONObj findOne(const string &ns, Query query, const BSONObj *fieldsToR eturn = 0, int queryOptions = 0) { BSONObj findOne(const string &ns, Query query, const BSONObj *fieldsToR eturn = 0, int queryOptions = 0) {
return one_; return one_;
} }
virtual virtual
bool connect(const string &serverHostname, string& errmsg) { bool connect(const string &serverHostname, string& errmsg) {
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 model.h   model.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 "dbclient.h" #include "dbclient.h"
#include "redef_macros.h"
namespace mongo { namespace mongo {
/** Model is a base class for defining objects which are serializable t o the Mongo /** Model is a base class for defining objects which are serializable t o the Mongo
database via the database driver. database via the database driver.
Definition Definition
Your serializable class should inherit from Model and implement the abstract methods Your serializable class should inherit from Model and implement the abstract methods
below. below.
skipping to change at line 43 skipping to change at line 44
more than once. more than once.
*/ */
class Model { class Model {
public: public:
Model() { } Model() { }
virtual ~Model() { } virtual ~Model() { }
virtual const char * getNS() = 0; virtual const char * getNS() = 0;
virtual void serialize(BSONObjBuilder& to) = 0; virtual void serialize(BSONObjBuilder& to) = 0;
virtual void unserialize(const BSONObj& from) = 0; virtual void unserialize(const BSONObj& from) = 0;
virtual BSONObj toObject();
virtual void append( const char * name , BSONObjBuilder& b );
virtual string modelServer() = 0; virtual string modelServer() = 0;
/** Load a single object. /** Load a single object.
@return true if successful. @return true if successful.
*/ */
virtual bool load(BSONObj& query); virtual bool load(BSONObj& query);
virtual void save( bool safe=false ); virtual void save( bool safe=false );
virtual void remove( bool safe=false ); virtual void remove( bool safe=false );
protected: protected:
BSONObj _id; BSONObj _id;
}; };
} // namespace mongo } // namespace mongo
#include "undef_macros.h"
 End of changes. 3 change blocks. 
0 lines changed or deleted 3 lines changed or added


 module.h   module.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 "../stdafx.h" #include "../pch.h"
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <list> #include <list>
namespace mongo { namespace mongo {
/** /**
* Module is the base class for adding modules to MongoDB * Module is the base class for adding modules to MongoDB
* modules allow adding hooks and features to mongo * modules allow adding hooks and features to mongo
* the idea is to add hooks into the main code for module support where needed * the idea is to add hooks into the main code for module support where needed
* some ideas are: monitoring, indexes, full text search * some ideas are: monitoring, indexes, full text search
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 namespace.h   namespace.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 "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
#include "queryutil.h" #include "queryutil.h"
#include "diskloc.h" #include "diskloc.h"
#include "../util/hashtab.h" #include "../util/hashtab.h"
#include "../util/mmap.h" #include "../util/mmap.h"
namespace mongo { namespace mongo {
class Cursor; class Cursor;
skipping to change at line 111 skipping to change at line 111
/* for more than 10 indexes -- see NamespaceDetails::Extra */ /* for more than 10 indexes -- see NamespaceDetails::Extra */
string extraName() { string extraName() {
string s = string(buf) + "$extra"; string s = string(buf) + "$extra";
massert( 10348 , "ns name too long", s.size() < MaxNsLen); massert( 10348 , "ns name too long", s.size() < MaxNsLen);
return s; return s;
} }
bool isExtra() const { bool isExtra() const {
const char *p = strstr(buf, "$extra"); const char *p = strstr(buf, "$extra");
return p && p[6] == 0; //==0 important in case an index uses na me "$extra_1" for example return p && p[6] == 0; //==0 important in case an index uses na me "$extra_1" for example
} }
bool hasDollarSign() const {
return strstr( buf , "$" ) > 0;
}
void kill() { void kill() {
buf[0] = 0x7f; buf[0] = 0x7f;
} }
bool operator==(const char *r) { bool operator==(const char *r) {
return strcmp(buf, r) == 0; return strcmp(buf, r) == 0;
} }
bool operator==(const Namespace& r) { bool operator==(const Namespace& r) {
return strcmp(buf, r.buf) == 0; return strcmp(buf, r.buf) == 0;
skipping to change at line 664 skipping to change at line 667
loc = l->firstExtent; loc = l->firstExtent;
return true; return true;
} }
return false; return false;
} }
bool allocated() const { bool allocated() const {
return ht != 0; return ht != 0;
} }
void getNamespaces( list<string>& tofill , bool onlyCollections = t
rue ) const;
private: private:
boost::filesystem::path path() const; boost::filesystem::path path() const;
void maybeMkdir() const; void maybeMkdir() const;
MMF f; MMF f;
HashTable<Namespace,NamespaceDetails,MMF::Pointer> *ht; HashTable<Namespace,NamespaceDetails,MMF::Pointer> *ht;
string dir_; string dir_;
string database_; string database_;
}; };
 End of changes. 3 change blocks. 
1 lines changed or deleted 7 lines changed or added


 parallel.h   parallel.h 
skipping to change at line 22 skipping to change at line 22
* 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.
*/ */
/** /**
tools for wokring in parallel/sharded/clustered environment tools for wokring in parallel/sharded/clustered environment
*/ */
#include "../stdafx.h" #include "../pch.h"
#include "dbclient.h" #include "dbclient.h"
#include "redef_macros.h"
#include "../db/dbmessage.h" #include "../db/dbmessage.h"
#include "../db/matcher.h"
namespace mongo { namespace mongo {
/** /**
* this is a cursor that works over a set of servers * this is a cursor that works over a set of servers
* can be used in serial/paralellel as controlled by sub classes * can be used in serial/paralellel as controlled by sub classes
*/ */
class ClusteredCursor { class ClusteredCursor {
public: public:
ClusteredCursor( QueryMessage& q ); ClusteredCursor( QueryMessage& q );
skipping to change at line 93 skipping to change at line 96
operator string() const { operator string() const {
return toString(); return toString();
} }
string _server; string _server;
BSONObj _extra; BSONObj _extra;
BSONObj _orderObject; BSONObj _orderObject;
}; };
class FilteringClientCursor {
public:
FilteringClientCursor( const BSONObj filter = BSONObj() );
FilteringClientCursor( auto_ptr<DBClientCursor> cursor , const BSON
Obj filter = BSONObj() );
~FilteringClientCursor();
void reset( auto_ptr<DBClientCursor> cursor );
bool more();
BSONObj next();
BSONObj peek();
private:
void _advance();
Matcher _matcher;
auto_ptr<DBClientCursor> _cursor;
BSONObj _next;
bool _done;
};
class Servers {
public:
Servers(){
}
void add( const ServerAndQuery& s ){
add( s._server , s._extra );
}
void add( const string& server , const BSONObj& filter ){
vector<BSONObj>& mine = _filters[server];
mine.push_back( filter.getOwned() );
}
// TOOO: pick a less horrible name
class View {
View( const Servers* s ){
for ( map<string, vector<BSONObj> >::const_iterator i=s->_f
ilters.begin(); i!=s->_filters.end(); ++i ){
_servers.push_back( i->first );
_filters.push_back( i->second );
}
}
public:
int size() const {
return _servers.size();
}
string getServer( int n ) const {
return _servers[n];
}
vector<BSONObj> getFilter( int n ) const {
return _filters[ n ];
}
private:
vector<string> _servers;
vector< vector<BSONObj> > _filters;
friend class Servers;
};
View view() const {
return View( this );
}
private:
map<string, vector<BSONObj> > _filters;
friend class View;
};
/** /**
* runs a query in serial across any number of servers * runs a query in serial across any number of servers
* returns all results from 1 server, then the next, etc... * returns all results from 1 server, then the next, etc...
*/ */
class SerialServerClusteredCursor : public ClusteredCursor { class SerialServerClusteredCursor : public ClusteredCursor {
public: public:
SerialServerClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , int sortOrder=0); SerialServerClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , int sortOrder=0);
virtual bool more(); virtual bool more();
virtual BSONObj next(); virtual BSONObj next();
virtual string type() const { return "SerialServer"; } virtual string type() const { return "SerialServer"; }
private: private:
vector<ServerAndQuery> _servers; vector<ServerAndQuery> _servers;
unsigned _serverIndex; unsigned _serverIndex;
auto_ptr<DBClientCursor> _current; FilteringClientCursor _current;
int _needToSkip;
}; };
/** /**
* runs a query in parellel across N servers * runs a query in parellel across N servers
* sots * sots
*/ */
class ParallelSortClusteredCursor : public ClusteredCursor { class ParallelSortClusteredCursor : public ClusteredCursor {
public: public:
ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , const BSONObj& sortKey ); ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , Q ueryMessage& q , const BSONObj& sortKey );
ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , c onst string& ns , ParallelSortClusteredCursor( const set<ServerAndQuery>& servers , c onst string& ns ,
const Query& q , int options=0, const BSONObj& fields=BSONObj() ); const Query& q , int options=0, const BSONObj& fields=BSONObj() );
virtual ~ParallelSortClusteredCursor(); virtual ~ParallelSortClusteredCursor();
virtual bool more(); virtual bool more();
virtual BSONObj next(); virtual BSONObj next();
virtual string type() const { return "ParallelSort"; } virtual string type() const { return "ParallelSort"; }
private: private:
void _init(); void _init();
void advance();
int _numServers; int _numServers;
set<ServerAndQuery> _servers; set<ServerAndQuery> _servers;
BSONObj _sortKey; BSONObj _sortKey;
auto_ptr<DBClientCursor> * _cursors; FilteringClientCursor * _cursors;
BSONObj * _nexts; int _needToSkip;
}; };
/** /**
* tools for doing asynchronous operations * tools for doing asynchronous operations
* right now uses underlying sync network ops and uses another thread * right now uses underlying sync network ops and uses another thread
* should be changed to use non-blocking io * should be changed to use non-blocking io
*/ */
class Future { class Future {
public: public:
class CommandResult { class CommandResult {
skipping to change at line 192 skipping to change at line 269
static void commandThread(); static void commandThread();
static shared_ptr<CommandResult> spawnCommand( const string& server , const string& db , const BSONObj& cmd ); static shared_ptr<CommandResult> spawnCommand( const string& server , const string& db , const BSONObj& cmd );
private: private:
static shared_ptr<CommandResult> * _grab; static shared_ptr<CommandResult> * _grab;
}; };
} }
#include "undef_macros.h"
 End of changes. 8 change blocks. 
6 lines changed or deleted 85 lines changed or added


 pdfile.h   pdfile.h 
skipping to change at line 28 skipping to change at line 28
Files: Files:
database.ns - namespace index database.ns - namespace index
database.1 - data files database.1 - data files
database.2 database.2
... ...
*/ */
#pragma once #pragma once
#include "../stdafx.h" #include "../pch.h"
#include "../util/mmap.h" #include "../util/mmap.h"
#include "diskloc.h" #include "diskloc.h"
#include "jsobjmanipulator.h" #include "jsobjmanipulator.h"
#include "namespace.h" #include "namespace.h"
#include "client.h" #include "client.h"
namespace mongo { namespace mongo {
class DataFileHeader; class DataFileHeader;
class Extent; class Extent;
skipping to change at line 103 skipping to change at line 103
class DataFileMgr { class DataFileMgr {
friend class BasicCursor; friend class BasicCursor;
public: public:
void init(const string& path ); void init(const string& path );
/* see if we can find an extent of the right size in the freelist. */ /* see if we can find an extent of the right size in the freelist. */
static Extent* allocFromFreeList(const char *ns, int approxSize, bo ol capped = false); static Extent* allocFromFreeList(const char *ns, int approxSize, bo ol capped = false);
/** @return DiskLoc where item ends up */ /** @return DiskLoc where item ends up */
// changedId should be initialized to false
const DiskLoc updateRecord( const DiskLoc updateRecord(
const char *ns, const char *ns,
NamespaceDetails *d, NamespaceDetails *d,
NamespaceDetailsTransient *nsdt, NamespaceDetailsTransient *nsdt,
Record *toupdate, const DiskLoc& dl, Record *toupdate, const DiskLoc& dl,
const char *buf, int len, OpDebug& debug); const char *buf, int len, OpDebug& debug, bool &changedId);
// The object o may be updated if modified on insert. // The object o may be updated if modified on insert.
void insertAndLog( const char *ns, const BSONObj &o, bool god = fal se ); void insertAndLog( const char *ns, const BSONObj &o, bool god = fal se );
DiskLoc insert(const char *ns, BSONObj &o, bool god = false);
/** @param obj both and in and out param -- insert can sometimes mo
dify an object (such as add _id). */
DiskLoc insertWithObjMod(const char *ns, BSONObj &o, bool god = fal
se);
/** @param obj in value only for this version. */
void insertNoReturnVal(const char *ns, BSONObj o, bool god = false)
;
DiskLoc insert(const char *ns, const void *buf, int len, bool god = false, const BSONElement &writeId = BSONElement(), bool mayAddIndex = true ); DiskLoc insert(const char *ns, const void *buf, int len, bool god = false, const BSONElement &writeId = BSONElement(), bool mayAddIndex = true );
void deleteRecord(const char *ns, Record *todelete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false); void deleteRecord(const char *ns, Record *todelete, const DiskLoc& dl, bool cappedOK = false, bool noWarn = false);
static auto_ptr<Cursor> findAll(const char *ns, const DiskLoc &star tLoc = DiskLoc()); static auto_ptr<Cursor> findAll(const char *ns, const DiskLoc &star tLoc = DiskLoc());
/* special version of insert for transaction logging -- streamlined a bit. /* special version of insert for transaction logging -- streamlined a bit.
assumes ns is capped and no indexes assumes ns is capped and no indexes
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);
 End of changes. 4 change blocks. 
3 lines changed or deleted 13 lines changed or added


 query.h   query.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 "../stdafx.h" #include "../pch.h"
#include "../util/message.h" #include "../util/message.h"
#include "dbmessage.h" #include "dbmessage.h"
#include "jsobj.h" #include "jsobj.h"
#include "diskloc.h" #include "diskloc.h"
/* db request message format /* db request message format
unsigned opid; // arbitary; will be echoed back unsigned opid; // arbitary; will be echoed back
byte operation; byte operation;
int options; int options;
skipping to change at line 107 skipping to change at line 107
} }
if ( mod ) if ( mod )
return 3; return 3;
return 4; return 4;
} }
}; };
/* returns true if an existing object was updated, false if no existing object was found. /* returns true if an existing object was updated, false if no existing object was found.
multi - update multiple objects - mostly useful with things like $se t multi - update multiple objects - mostly useful with things like $se t
god - allow access to system namespaces and don't yield god - allow access to system namespaces
*/ */
UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BS ONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug ); UpdateResult updateObjects(const char *ns, const BSONObj& updateobj, BS ONObj pattern, bool upsert, bool multi , bool logop , OpDebug& debug );
UpdateResult _updateObjects(bool god, const char *ns, const BSONObj& up dateobj, BSONObj pattern, bool upsert, bool multi , bool logop , OpDebug& d ebug );
// If justOne is true, deletedId is set to the id of the deleted object . // If justOne is true, deletedId is set to the id of the deleted object .
long long deleteObjects(const char *ns, BSONObj pattern, bool justOne, bool logop = false, bool god=false); long long deleteObjects(const char *ns, BSONObj pattern, bool justOne, bool logop = false, bool god=false);
long long runCount(const char *ns, const BSONObj& cmd, string& err); long long runCount(const char *ns, const BSONObj& cmd, string& err);
auto_ptr< QueryResult > runQuery(Message& m, QueryMessage& q, CurOp& cu rop ); auto_ptr< QueryResult > runQuery(Message& m, QueryMessage& q, CurOp& cu rop );
/* 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 : ... }
skipping to change at line 162 skipping to change at line 163
} }
ParsedQuery( const char* ns , int ntoskip , int ntoreturn , int que ryoptions , const BSONObj& query , const BSONObj& fields ) ParsedQuery( const char* ns , int ntoskip , int ntoreturn , int que ryoptions , const BSONObj& query , const BSONObj& fields )
: _ns( ns ) , _ntoskip( ntoskip ) , _ntoreturn( ntoreturn ) , _ options( queryoptions ){ : _ns( ns ) , _ntoskip( ntoskip ) , _ntoreturn( ntoreturn ) , _ options( queryoptions ){
init( query ); init( query );
initFields( fields ); initFields( fields );
} }
~ParsedQuery(){} ~ParsedQuery(){}
const char * ns() const { return _ns; } const char * ns() const { return _ns; }
bool isLocalDB() const { return strncmp(_ns, "local.", 6) == 0; }
const BSONObj& getFilter() const { return _filter; } const BSONObj& getFilter() const { return _filter; }
FieldMatcher* getFields() const { return _fields.get(); } FieldMatcher* getFields() const { return _fields.get(); }
shared_ptr<FieldMatcher> getFieldPtr() const { return _fields; } shared_ptr<FieldMatcher> getFieldPtr() const { return _fields; }
int getSkip() const { return _ntoskip; } int getSkip() const { return _ntoskip; }
int getNumToReturn() const { return _ntoreturn; } int getNumToReturn() const { return _ntoreturn; }
bool wantMore() const { return _wantMore; } bool wantMore() const { return _wantMore; }
int getOptions() const { return _options; } int getOptions() const { return _options; }
bool hasOption( int x ) const { return x & _options; } bool hasOption( int x ) const { return x & _options; }
bool isExplain() const { return _explain; } bool isExplain() const { return _explain; }
bool isSnapshot() const { return _snapshot; } bool isSnapshot() const { return _snapshot; }
bool returnKey() const { return _returnKey; } bool returnKey() const { return _returnKey; }
const BSONObj& getMin() const { return _min; } const BSONObj& getMin() const { return _min; }
const BSONObj& getMax() const { return _max; } const BSONObj& getMax() const { return _max; }
const BSONObj& getOrder() const { return _order; } const BSONObj& getOrder() const { return _order; }
const BSONElement& getHint() const { return _hint; } const BSONElement& getHint() const { return _hint; }
int getMaxScan() const { return _maxScan; }
bool couldBeCommand() const { bool couldBeCommand() const {
/* we assume you are using findOne() for running a cmd... */ /* we assume you are using findOne() for running a cmd... */
return _ntoreturn == 1 && strstr( _ns , ".$cmd" ); return _ntoreturn == 1 && strstr( _ns , ".$cmd" );
} }
bool hasIndexSpecifier() const { bool hasIndexSpecifier() const {
return ! _hint.eoo() || ! _min.isEmpty() || ! _max.isEmpty(); return ! _hint.eoo() || ! _min.isEmpty() || ! _max.isEmpty();
} }
skipping to change at line 242 skipping to change at line 245
else { else {
_filter = q; _filter = q;
} }
} }
void _reset(){ void _reset(){
_wantMore = true; _wantMore = true;
_explain = false; _explain = false;
_snapshot = false; _snapshot = false;
_returnKey = false; _returnKey = false;
_maxScan = 0;
} }
void _initTop( const BSONObj& top ){ void _initTop( const BSONObj& top ){
BSONObjIterator i( top ); BSONObjIterator i( top );
while ( i.more() ){ while ( i.more() ){
BSONElement e = i.next(); BSONElement e = i.next();
const char * name = e.fieldName(); const char * name = e.fieldName();
if ( strcmp( "$orderby" , name ) == 0 || if ( strcmp( "$orderby" , name ) == 0 ||
strcmp( "orderby" , name ) == 0 ){ strcmp( "orderby" , name ) == 0 ){
skipping to change at line 271 skipping to change at line 275
else if ( strcmp( "$snapshot" , name ) == 0 ) else if ( strcmp( "$snapshot" , name ) == 0 )
_snapshot = e.trueValue(); _snapshot = e.trueValue();
else if ( strcmp( "$min" , name ) == 0 ) else if ( strcmp( "$min" , name ) == 0 )
_min = e.embeddedObject(); _min = e.embeddedObject();
else if ( strcmp( "$max" , name ) == 0 ) else if ( strcmp( "$max" , name ) == 0 )
_max = e.embeddedObject(); _max = e.embeddedObject();
else if ( strcmp( "$hint" , name ) == 0 ) else if ( strcmp( "$hint" , name ) == 0 )
_hint = e; _hint = e;
else if ( strcmp( "$returnKey" , name ) == 0 ) else if ( strcmp( "$returnKey" , name ) == 0 )
_returnKey = e.trueValue(); _returnKey = e.trueValue();
else if ( strcmp( "$maxScan" , name ) == 0 )
_maxScan = e.numberInt();
} }
if ( _snapshot ){ if ( _snapshot ){
uassert( 12001 , "E12001 can't sort with $snapshot", _order .isEmpty() ); uassert( 12001 , "E12001 can't sort with $snapshot", _order .isEmpty() );
uassert( 12002 , "E12002 can't use hint with $snapshot", _h int.eoo() ); uassert( 12002 , "E12002 can't use hint with $snapshot", _h int.eoo() );
} }
} }
skipping to change at line 309 skipping to change at line 315
bool _wantMore; bool _wantMore;
bool _explain; bool _explain;
bool _snapshot; bool _snapshot;
bool _returnKey; bool _returnKey;
BSONObj _min; BSONObj _min;
BSONObj _max; BSONObj _max;
BSONElement _hint; BSONElement _hint;
BSONObj _order; BSONObj _order;
int _maxScan;
}; };
} // namespace mongo } // namespace mongo
#include "clientcursor.h" #include "clientcursor.h"
 End of changes. 8 change blocks. 
2 lines changed or deleted 9 lines changed or added


 queryutil.h   queryutil.h 
skipping to change at line 147 skipping to change at line 147
if ( e.eoo() ) if ( e.eoo() )
break; break;
b.append( e.fieldName(), direction * ( ( e.number() >= 0 ) ? -1 : 1 ) ); b.append( e.fieldName(), direction * ( ( e.number() >= 0 ) ? -1 : 1 ) );
} }
return b.obj(); return b.obj();
} }
map< string, Type > fieldTypes_; map< string, Type > fieldTypes_;
BSONObj sort_; BSONObj sort_;
}; };
// 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;
// ranges of fields' value that may be determined from query -- used to // ranges of fields' value that may be determined from query -- used to
// determine index limits // determine index limits
class FieldRangeSet { class FieldRangeSet {
public: public:
FieldRangeSet( const char *ns, const BSONObj &query , bool optimize =true ); FieldRangeSet( const char *ns, const BSONObj &query , bool optimize =true );
const FieldRange &range( const char *fieldName ) const { const FieldRange &range( const char *fieldName ) const {
map< string, FieldRange >::const_iterator f = ranges_.find( fie ldName ); map< string, FieldRange >::const_iterator f = ranges_.find( fie ldName );
if ( f == ranges_.end() ) if ( f == ranges_.end() )
return trivialRange(); return trivialRange();
return f->second; return f->second;
skipping to change at line 192 skipping to change at line 199
mutable map< string, FieldRange > ranges_; mutable map< string, FieldRange > ranges_;
const char *ns_; const char *ns_;
BSONObj query_; BSONObj query_;
}; };
/** /**
used for doing field limiting used for doing field limiting
*/ */
class FieldMatcher { class FieldMatcher {
public: public:
FieldMatcher()
FieldMatcher(bool include=false) : _include(include){} : _include(true)
, _special(false)
, _includeID(true)
, _skip(0)
, _limit(-1)
{}
void add( const BSONObj& o ); void add( const BSONObj& o );
void append( BSONObjBuilder& b , const BSONElement& e ) const; void append( BSONObjBuilder& b , const BSONElement& e ) const;
BSONObj getSpec() const; BSONObj getSpec() const;
bool includeID() { return _includeID; }
private: private:
void add( const string& field, bool include ); void add( const string& field, bool include );
void add( const string& field, int skip, int limit );
void appendArray( BSONObjBuilder& b , const BSONObj& a ) const; void appendArray( BSONObjBuilder& b , const BSONObj& a ) const;
bool _include; // true if default at this level is to include bool _include; // true if default at this level is to include
bool _special; // true if this level can't be skipped or included w ithout recursing
//TODO: benchmark vector<pair> vs map //TODO: benchmark vector<pair> vs map
typedef map<string, boost::shared_ptr<FieldMatcher> > FieldMap; typedef map<string, boost::shared_ptr<FieldMatcher> > FieldMap;
FieldMap _fields; FieldMap _fields;
BSONObj _source; BSONObj _source;
bool _includeID;
// used for $slice operator
int _skip;
int _limit;
}; };
/** returns a string that when used as a matcher, would match a super s et of regex() /** returns a string that when used as a matcher, would match a super s et of regex()
returns "" for complex regular expressions returns "" for complex regular expressions
used to optimize queries in some simple regex cases that start with '^' used to optimize queries in some simple regex cases that start with '^'
if purePrefix != NULL, sets it to whether the regex can be converte d to a range query if purePrefix != NULL, sets it to whether the regex can be converte d to a range query
*/ */
string simpleRegex(const char* regex, const char* flags, bool* purePref ix=NULL); string simpleRegex(const char* regex, const char* flags, bool* purePref ix=NULL);
 End of changes. 6 change blocks. 
2 lines changed or deleted 24 lines changed or added


 queue.h   queue.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 "../stdafx.h" #include "../pch.h"
#include "../util/goodies.h" #include "../util/goodies.h"
#include <queue> #include <queue>
namespace mongo { namespace mongo {
/** /**
* simple blocking queue * simple blocking queue
*/ */
template<typename T> class BlockingQueue : boost::noncopyable { template<typename T> class BlockingQueue : boost::noncopyable {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 rec.h   rec.h 
skipping to change at line 43 skipping to change at line 43
/* ------------------------------------------------------------------------ -- /* ------------------------------------------------------------------------ --
A RecStoreInterface for the normal mongo mem mapped file (MongoDataFile) A RecStoreInterface for the normal mongo mem mapped file (MongoDataFile)
storage storage
*/ */
NamespaceDetails* nsdetails_notinline(const char *ns); NamespaceDetails* nsdetails_notinline(const char *ns);
class MongoMemMapped_RecStore : public RecStoreInterface { class MongoMemMapped_RecStore : public RecStoreInterface {
public: public:
virtual char* get(DiskLoc d, unsigned len) { return d.rec()->data; } VIRT char* get(DiskLoc d, unsigned len) { return d.rec()->data; }
virtual DiskLoc insert(const char *ns, const void *obuf, int len, bool god) { VIRT DiskLoc insert(const char *ns, const void *obuf, int len, bool god ) {
return theDataFileMgr.insert(ns, obuf, len, god); return theDataFileMgr.insert(ns, obuf, len, god);
} }
virtual void deleteRecord(const char *ns, DiskLoc d) { VIRT void deleteRecord(const char *ns, DiskLoc d) {
theDataFileMgr._deleteRecord(nsdetails_notinline(ns), ns, d.rec(), d); theDataFileMgr._deleteRecord(nsdetails_notinline(ns), ns, d.rec(), d);
} }
virtual void modified(DiskLoc d) { } VIRT void modified(DiskLoc d) { }
virtual void drop(const char *ns) { VIRT void drop(const char *ns) {
dropNS(ns); dropNS(ns);
} }
virtual void rename(const char *fromNs, const char *toNs) { VIRT void rename(const char *fromNs, const char *toNs) {
renameNamespace( fromNs, toNs ); renameNamespace( fromNs, toNs );
} }
/* close datafiles associated with the db specified. */ /* close datafiles associated with the db specified. */
virtual void closeFiles(string dbname, string path) { VIRT void closeFiles(string dbname, string path) {
/* as this is only used for indexes so far, and we are in the same /* as this is only used for indexes so far, and we are in the same
PDFiles as the nonindex data, we just rely on them having been c losed PDFiles as the nonindex data, we just rely on them having been c losed
at the same time. one day this may need to change. at the same time. one day this may need to change.
*/ */
} }
}; };
/* An in memory RecStoreInterface implementation -------------------------- -- /* An in memory RecStoreInterface implementation -------------------------- --
*/ */
skipping to change at line 118 skipping to change at line 118
} }
virtual void rename(const char *fromNs, const char *toNs) { virtual void rename(const char *fromNs, const char *toNs) {
massert( 10373 , "rename not yet implemented for InMem_RecStore", fa lse ); massert( 10373 , "rename not yet implemented for InMem_RecStore", fa lse );
} }
}; };
#endif #endif
/* Glue btree to RecStoreInterface: ---------------------------- */ /* Glue btree to RecStoreInterface: ---------------------------- */
extern RecStoreInterface *btreeStore; typedef MongoMemMapped_RecStore StoreToUse;
extern StoreToUse *btreeStore;
const int BucketSize = 8192; const int BucketSize = 8192;
inline BtreeBucket* DiskLoc::btree() const { inline BtreeBucket* DiskLoc::btree() const {
assert( fileNo != -1 ); assert( fileNo != -1 );
return (BtreeBucket*) btreeStore->get(*this, BucketSize); return (BtreeBucket*) btreeStore->get(*this, BucketSize);
} }
inline BtreeBucket* DiskLoc::btreemod() const { inline BtreeBucket* DiskLoc::btreemod() const {
assert( fileNo != -1 ); assert( fileNo != -1 );
 End of changes. 8 change blocks. 
8 lines changed or deleted 10 lines changed or added


 reccache.h   reccache.h 
skipping to change at line 214 skipping to change at line 214
void closeFiles(string dbname, string path); void closeFiles(string dbname, string path);
// at termination: write dirty pages and close all files // at termination: write dirty pages and close all files
void closing(); void closing();
}; };
extern RecCache theRecCache; extern RecCache theRecCache;
class CachedBasicRecStore : public RecStoreInterface { class CachedBasicRecStore : public RecStoreInterface {
public: public:
virtual char* get(DiskLoc d, unsigned len) { VIRT char* get(DiskLoc d, unsigned len) {
return theRecCache.get(d, len); return theRecCache.get(d, len);
} }
virtual DiskLoc insert(const char *ns, const void *obuf, int len, bool god) { VIRT DiskLoc insert(const char *ns, const void *obuf, int len, bool god ) {
return theRecCache.insert(ns, obuf, len, god); return theRecCache.insert(ns, obuf, len, god);
} }
virtual void modified(DiskLoc d) { VIRT void modified(DiskLoc d) {
theRecCache.dirty(d); theRecCache.dirty(d);
} }
/* drop collection */ /* drop collection */
virtual void drop(const char *ns) { VIRT void drop(const char *ns) {
theRecCache.drop(ns); theRecCache.drop(ns);
} }
virtual void rename(const char *fromNs, const char *toNs) { VIRT void rename(const char *fromNs, const char *toNs) {
massert( 10378 , "rename not yet implemented for CachedBasicRecStore ", false ); massert( 10378 , "rename not yet implemented for CachedBasicRecStore ", false );
} }
/* close datafiles associated with the db specified. */ /* close datafiles associated with the db specified. */
virtual void closeFiles(string dbname, string path) { VIRT void closeFiles(string dbname, string path) {
theRecCache.closeFiles(dbname, dbpath); theRecCache.closeFiles(dbname, dbpath);
} }
}; };
/* see concurrency.h - note on a lock reset from read->write we don't /* see concurrency.h - note on a lock reset from read->write we don't
call dbunlocking_read, we just wait for the final dbunlocking_write call dbunlocking_read, we just wait for the final dbunlocking_write
call call
*/ */
inline void dbunlocking_read() { inline void dbunlocking_read() {
 End of changes. 6 change blocks. 
6 lines changed or deleted 6 lines changed or added


 reci.h   reci.h 
skipping to change at line 24 skipping to change at line 24
* 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 "diskloc.h" #include "diskloc.h"
namespace mongo { namespace mongo {
// #define VIRT virtual
#define VIRT
/* Subclass this and implement your real storage interface. /* Subclass this and implement your real storage interface.
*/ */
class RecStoreInterface { class RecStoreInterface {
public: public:
virtual ~RecStoreInterface() {} //VIRT ~RecStoreInterface() {}
/* Get a pointer to the data at diskloc d. Pointer guaranteed to stay in /* Get a pointer to the data at diskloc d. Pointer guaranteed to stay in
scope through the current database operation's life. scope through the current database operation's life.
*/ */
virtual char* get(DiskLoc d, unsigned len) = 0; //VIRT char* get(DiskLoc d, unsigned len) = 0;
/* indicate that the diskloc specified has been updated. note that as-i s today, the modification may come AFTER this /* indicate that the diskloc specified has been updated. note that as-i s today, the modification may come AFTER this
call -- we handle that currently -- until the dblock finishes. call -- we handle that currently -- until the dblock finishes.
*/ */
virtual void modified(DiskLoc d) = 0; //VIRT void modified(DiskLoc d) = 0;
/* insert specified data as a record */ /* insert specified data as a record */
virtual DiskLoc insert(const char *ns, const void *obuf, int len, bool god) = 0; //VIRT DiskLoc insert(const char *ns, const void *obuf, int len, bool g od) = 0;
virtual void deleteRecord(const char *ns, DiskLoc d) { massert( 10379 , "not implemented RecStoreInterface::deleteRecord", false); } //VIRT void deleteRecord(const char *ns, DiskLoc d) { massert( 10379 , "not implemented RecStoreInterface::deleteRecord", false); }
/* drop the collection */ /* drop the collection */
virtual void drop(const char *ns) = 0; //VIRT void drop(const char *ns) = 0;
/* rename collection */ /* rename collection */
virtual void rename(const char *fromNs, const char *toNs) = 0; //VIRT void rename(const char *fromNs, const char *toNs) = 0;
/* close datafiles associated with the db specified. */ /* close datafiles associated with the db specified. */
virtual void closeFiles(string dbname, string path) = 0; //VIRT void closeFiles(string dbname, string path) = 0;
/* todo add: /* todo add:
closeFiles(dbname) closeFiles(dbname)
eraseFiles(dbname) eraseFiles(dbname)
*/ */
}; };
} }
 End of changes. 9 change blocks. 
8 lines changed or deleted 11 lines changed or added


 repl.h   repl.h 
skipping to change at line 26 skipping to change at line 26
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* replication data overview /* replication data overview
at the slave: at the slave:
local.sources { host: ..., source: ..., only: ..., syncedTo: ..., loca lLogTs: ..., dbsNextPass: { ... }, incompleteCloneDbs: { ... } } local.sources { host: ..., source: ..., only: ..., syncedTo: ..., loca lLogTs: ..., dbsNextPass: { ... }, incompleteCloneDbs: { ... } }
at the master: at the master:
local.oplog.$<source> local.oplog.$<source>
local.oplog.$main is the default
*/ */
#pragma once #pragma once
#include "pdfile.h" #include "pdfile.h"
#include "db.h" #include "db.h"
#include "dbhelpers.h" #include "dbhelpers.h"
#include "query.h" #include "query.h"
#include "queryoptimizer.h" #include "queryoptimizer.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
#include "../util/optime.h" #include "../util/optime.h"
namespace mongo { #include "oplog.h"
class DBClientConnection; namespace mongo {
class DBClientCursor;
/* replication slave? (possibly with slave or repl pair nonmaster) /* replication slave? (possibly with slave or repl pair nonmaster)
--slave cmd line setting -> SimpleSlave --slave cmd line setting -> SimpleSlave
*/ */
typedef enum { NotSlave=0, SimpleSlave, ReplPairSlave } SlaveTypes; typedef enum { NotSlave=0, SimpleSlave, ReplPairSlave } SlaveTypes;
class ReplSettings { class ReplSettings {
public: public:
SlaveTypes slave; SlaveTypes slave;
skipping to change at line 197 skipping to change at line 195
return 0; return 0;
int wait = _sleepAdviceTime - unsigned( time( 0 ) ); int wait = _sleepAdviceTime - unsigned( time( 0 ) );
return wait > 0 ? wait : 0; return wait > 0 ? wait : 0;
} }
static bool throttledForceResyncDead( const char *requester ); static bool throttledForceResyncDead( const char *requester );
static void forceResyncDead( const char *requester ); static void forceResyncDead( const char *requester );
void forceResync( const char *requester ); void forceResync( const char *requester );
}; };
/* Write operation to the log (local.oplog.$main)
"i" insert
"u" update
"d" delete
"c" db cmd
"db" declares presence of a database (ns is set to the db name + '.'
)
*/
void logOp(const char *opstr, const char *ns, const BSONObj& obj, BSONO
bj *patt = 0, bool *b = 0);
// class for managing a set of ids in memory // class for managing a set of ids in memory
class MemIds { class MemIds {
public: public:
MemIds() : size_() {} MemIds() : size_() {}
friend class IdTracker; friend class IdTracker;
void reset() { imp_.clear(); } void reset() {
imp_.clear();
size_ = 0;
}
bool get( const char *ns, const BSONObj &id ) { return imp_[ ns ].c ount( id ); } bool get( const char *ns, const BSONObj &id ) { return imp_[ ns ].c ount( id ); }
void set( const char *ns, const BSONObj &id, bool val ) { void set( const char *ns, const BSONObj &id, bool val ) {
if ( val ) { if ( val ) {
if ( imp_[ ns ].insert( id.getOwned() ).second ) { if ( imp_[ ns ].insert( id.getOwned() ).second ) {
size_ += id.objsize() + sizeof( BSONObj ); size_ += id.objsize() + sizeof( BSONObj );
} }
} else { } else {
if ( imp_[ ns ].erase( id ) == 1 ) { if ( imp_[ ns ].erase( id ) == 1 ) {
size_ -= id.objsize() + sizeof( BSONObj ); size_ -= id.objsize() + sizeof( BSONObj );
} }
skipping to change at line 345 skipping to change at line 337
MemIds memModIds_; MemIds memModIds_;
DbIds dbIds_; DbIds dbIds_;
DbIds dbModIds_; DbIds dbModIds_;
bool inMem_; bool inMem_;
int maxMem_; int maxMem_;
}; };
bool anyReplEnabled(); bool anyReplEnabled();
void appendReplicationInfo( BSONObjBuilder& result , bool authed , int level = 0 ); void appendReplicationInfo( BSONObjBuilder& result , bool authed , int level = 0 );
void replCheckCloseDatabase( Database * db );
extern int __findingStartInitialTimeout; // configurable for testing
class FindingStartCursor {
public:
FindingStartCursor( const QueryPlan & qp ) :
_qp( qp ),
_findingStart( true ),
_findingStartMode(),
_findingStartTimer( 0 ),
_findingStartCursor( 0 )
{ init(); }
bool done() const { return !_findingStart; }
auto_ptr< Cursor > cRelease() { return _c; }
void next() {
if ( !_findingStartCursor || !_findingStartCursor->c->ok() ) {
_findingStart = false;
_c = _qp.newCursor(); // on error, start from beginning
destroyClientCursor();
return;
}
switch( _findingStartMode ) {
case Initial: {
if ( !_matcher->matches( _findingStartCursor->c->currKe
y(), _findingStartCursor->c->currLoc() ) ) {
_findingStart = false; // found first record out of
query range, so scan normally
_c = _qp.newCursor( _findingStartCursor->c->currLoc
() );
destroyClientCursor();
return;
}
_findingStartCursor->c->advance();
RARELY {
if ( _findingStartTimer.seconds() >= __findingStart
InitialTimeout ) {
createClientCursor( startLoc( _findingStartCurs
or->c->currLoc() ) );
_findingStartMode = FindExtent;
return;
}
}
maybeRelease();
return;
}
case FindExtent: {
if ( !_matcher->matches( _findingStartCursor->c->currKe
y(), _findingStartCursor->c->currLoc() ) ) {
_findingStartMode = InExtent;
return;
}
DiskLoc prev = prevLoc( _findingStartCursor->c->currLoc
() );
if ( prev.isNull() ) { // hit beginning, so start scann
ing from here
createClientCursor();
_findingStartMode = InExtent;
return;
}
// There might be a more efficient implementation than
creating new cursor & client cursor each time,
// not worrying about that for now
createClientCursor( prev );
maybeRelease();
return;
}
case InExtent: {
if ( _matcher->matches( _findingStartCursor->c->currKey
(), _findingStartCursor->c->currLoc() ) ) {
_findingStart = false; // found first record in que
ry range, so scan normally
_c = _qp.newCursor( _findingStartCursor->c->currLoc
() );
destroyClientCursor();
return;
}
_findingStartCursor->c->advance();
maybeRelease();
return;
}
default: {
massert( 12600, "invalid _findingStartMode", false );
}
}
}
private:
enum FindingStartMode { Initial, FindExtent, InExtent };
const QueryPlan &_qp;
bool _findingStart;
FindingStartMode _findingStartMode;
auto_ptr< CoveredIndexMatcher > _matcher;
Timer _findingStartTimer;
ClientCursor * _findingStartCursor;
auto_ptr< Cursor > _c;
DiskLoc startLoc( const DiskLoc &rec ) {
Extent *e = rec.rec()->myExtent( rec );
if ( e->myLoc != _qp.nsd()->capExtent )
return e->firstRecord;
// Likely we are on the fresh side of capExtent, so return firs
t fresh record.
// If we are on the stale side of capExtent, then the collectio
n is small and it
// doesn't matter if we start the extent scan with capFirstNewR
ecord.
return _qp.nsd()->capFirstNewRecord;
}
DiskLoc prevLoc( const DiskLoc &rec ) {
Extent *e = rec.rec()->myExtent( rec );
if ( e->xprev.isNull() )
e = _qp.nsd()->lastExtent.ext();
else
e = e->xprev.ext();
if ( e->myLoc != _qp.nsd()->capExtent )
return e->firstRecord;
return DiskLoc(); // reached beginning of collection
}
void createClientCursor( const DiskLoc &startLoc = DiskLoc() ) {
auto_ptr<Cursor> c = _qp.newCursor( startLoc );
_findingStartCursor = new ClientCursor(QueryOption_NoCursorTime
out, c, _qp.ns());
}
void destroyClientCursor() {
if ( _findingStartCursor ) {
ClientCursor::erase( _findingStartCursor->cursorid );
_findingStartCursor = 0;
}
}
void maybeRelease() {
RARELY {
CursorId id = _findingStartCursor->cursorid;
_findingStartCursor->updateLocation();
{
dbtemprelease t;
}
_findingStartCursor = ClientCursor::find( id, false );
}
}
void init() {
// Use a ClientCursor here so we can release db mutex while sca
nning
// oplog (can take quite a while with large oplogs).
auto_ptr<Cursor> c = _qp.newReverseCursor();
_findingStartCursor = new ClientCursor(QueryOption_NoCursorTime
out, c, _qp.ns());
_findingStartTimer.reset();
_findingStartMode = Initial;
BSONElement tsElt = _qp.query()[ "ts" ];
massert( 13044, "no ts field in query", !tsElt.eoo() );
BSONObjBuilder b;
b.append( tsElt );
BSONObj tsQuery = b.obj();
_matcher.reset(new CoveredIndexMatcher(tsQuery, _qp.indexKey())
);
}
};
void updateSlaveLocation( CurOp& curop, const char * ns , OpTime lastOp
);
bool opReplicatedEnough( OpTime op , int w );
} // namespace mongo } // namespace mongo
 End of changes. 6 change blocks. 
178 lines changed or deleted 6 lines changed or added


 replset.h   replset.h 
// /db/repl/replset.h
/** /**
* Copyright (C) 2008 10gen Inc. * Copyright (C) 2008 10gen Inc.
* *
* This program is free software: you can redistribute it and/or modify * 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 , * it under the terms of the GNU Affero General Public License, version 3 ,
* as published by the Free Software Foundation. * as published by the Free Software Foundation.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 "db.h" #include "../../util/concurrency/list.h"
#include "dbhelpers.h" #include "../../util/concurrency/value.h"
#include "json.h" #include "../../util/hostandport.h"
#include "../client/dbclient.h"
#include "repl.h"
#include "cmdline.h"
namespace mongo { namespace mongo {
extern const char *replAllDead; extern bool replSet; // true if using repl sets
extern class ReplSet *theReplSet; // null until initialized
/* ReplPair is a pair of db servers replicating to one another and coop
erating.
Only one member of the pair is active at a time; so this is a smart
master/slave
configuration basically.
You may read from the slave at anytime though (if you don't mind the
slight lag).
todo: Could be extended to be more than a pair, thus the name 'Set' /* information about the entire repl set, such as the various servers i
-- for example, n the set, and their state */
a set of 3... /* note: We currently do not free mem when the set goes away - it is as
sumed the replset is a
singleton and long lived.
*/ */
class ReplSet {
class ReplPair {
public: public:
enum ReplState { bool isMaster(const char *client) {
State_CantArb = -3, //zzz
State_Confused = -2, return false;
State_Negotiating = -1,
State_Slave = 0,
State_Master = 1
};
int state;
ThreadSafeString info; // commentary about our current state
string arbHost; // "-" for no arbiter. "host[:port]"
int remotePort;
string remoteHost;
string remote; // host:port if port specified.
// int date; // -1 not yet set; 0=slave; 1=master
string getInfo() {
stringstream ss;
ss << " state: ";
if ( state == 1 ) ss << "1 State_Master ";
else if ( state == 0 ) ss << "0 State_Slave";
else
ss << "<b>" << state << "</b>";
ss << '\n';
ss << " info: " << info << '\n';
ss << " arbhost: " << arbHost << '\n';
ss << " remote: " << remoteHost << ':' << remotePort << '\n';
// ss << " date: " << date << '\n';
return ss.str();
}
ReplPair(const char *remoteEnd, const char *arbiter);
virtual ~ReplPair() {}
bool dominant(const string& myname) {
if ( myname == remoteHost )
return cmdLine.port > remotePort;
return myname > remoteHost;
}
void setMasterLocked( int n, const char *_comment = "" ) {
dblock p;
setMaster( n, _comment );
} }
void fillIsMaster(BSONObjBuilder&);
void setMaster(int n, const char *_comment = ""); static enum StartupStatus { PRESTART=0, LOADINGCONFIG=1, BADCONFIG=
2, EMPTYCONFIG=3, EMPTYUNREACHABLE=4, FINISHME=5 } startupStatus;
/* negotiate with our peer who is master; returns state of peer */ static string startupStatusMsg;
int negotiate(DBClientConnection *conn, string method); bool fatal;
/* peer unreachable, try our arbitrator */
void arbitrate();
virtual bool ok() const { return !fatal; }
DBClientConnection *newClientConnection() const {
return new DBClientConnection();
}
};
extern ReplPair *replPair; /* @return replica set's logical name */
string getName() const { return _name; }
/* note we always return true for the "local" namespace. /* cfgString format is
replsetname/host1,host2:port,...
where :port is optional.
we should not allow most operations when not the master throws exception if a problem initializing.
also we report not master if we are "dead". */
ReplSet(string cfgString);
See also CmdIsMaster. // for replSetGetStatus command
void summarizeStatus(BSONObjBuilder&) const;
If 'client' is not specified, the current client is used. private:
*/ string _name;
inline bool isMaster( const char *client = 0 ) { const vector<HostAndPort> *_seeds;
if( ! replSettings.slave )
return true;
if ( !client ) { /** load our configuration from admin.replset. try seed machines t
Database *database = cc().database(); oo.
assert( database ); throws exception if a problem.
client = database->name.c_str(); */
} void loadConfig();
if ( replAllDead ) // void addMemberIfMissing(const HostAndPort& p);
return strcmp( client, "local" ) == 0;
if ( replPair ) { struct MemberInfo : public List1<MemberInfo>::Base {
if( replPair->state == ReplPair::State_Master ) MemberInfo(string h, int p) : _port(p), _host(h) {
return true; _dead = false;
} _lastHeartbeat = 0;
else { _upSince = 0;
if( replSettings.master ) { _health = -1.0;
// if running with --master --slave, allow. note that mast
er is also true
// for repl pairs so the check for replPair above is import
ant.
return true;
} }
} string fullName() const {
if( _port < 0 ) return _host;
if ( cc().isGod() ) stringstream ss;
return true; ss << _host << ':' << _port;
return ss.str();
return strcmp( client, "local" ) == 0; }
} double health() const { return _health; }
inline bool isMasterNs( const char *ns ) { time_t upSince() const { return _upSince; }
char cl[ 256 ]; time_t lastHeartbeat() const { return _lastHeartbeat; }
nsToDatabase( ns, cl ); private:
return isMaster( cl ); friend class FeedbackThread; // feedbackthread is the primary w
} riter to these objects
inline ReplPair::ReplPair(const char *remoteEnd, const char *arb) {
state = -1;
remote = remoteEnd;
remotePort = CmdLine::DefaultDBPort;
remoteHost = remoteEnd;
const char *p = strchr(remoteEnd, ':');
if ( p ) {
remoteHost = string(remoteEnd, p-remoteEnd);
remotePort = atoi(p+1);
uassert( 10125 , "bad port #", remotePort > 0 && remotePort < 0
x10000 );
if ( remotePort == CmdLine::DefaultDBPort )
remote = remoteHost; // don't include ":27017" as it is def
ault; in case ran in diff ways over time to normalizke the hostname format
in sources collection
}
uassert( 10126 , "arbiter parm is missing, use '-' for none", arb);
arbHost = arb;
uassert( 10127 , "arbiter parm is empty", !arbHost.empty());
}
/* This is set to true if we have EVER been up to date -- this way a ne
w pair member
which is a replacement won't go online as master until we have initial
ly fully synced.
*/
class PairSync {
int initialsynccomplete;
public:
PairSync() {
initialsynccomplete = -1;
}
/* call before using the class. from dbmutex */
void init() {
BSONObj o;
initialsynccomplete = 0;
if ( Helpers::getSingleton("local.pair.sync", o) )
initialsynccomplete = 1;
}
bool initialSyncCompleted() {
return initialsynccomplete != 0;
}
void setInitialSyncCompleted() { bool _dead;
BSONObj o = fromjson("{\"initialsynccomplete\":1}"); const int _port;
Helpers::putSingleton("local.pair.sync", o); const string _host;
initialsynccomplete = 1; double _health;
log() << "pair: initial sync complete" << endl; time_t _lastHeartbeat;
} time_t _upSince;
public:
DiagStr _lastHeartbeatErrMsg;
};
/* all members of the set EXCEPT SELF. */
List1<MemberInfo> _members;
void setInitialSyncCompletedLocking() { void startHealthThreads();
if ( initialsynccomplete == 1 ) friend class FeedbackThread;
return;
dblock lk;
setInitialSyncCompleted();
}
}; };
} // namespace mongo }
 End of changes. 21 change blocks. 
175 lines changed or deleted 72 lines changed or added


 request.h   request.h 
skipping to change at line 20 skipping to change at line 20
* 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 "../stdafx.h" #include "../pch.h"
#include "../util/message.h" #include "../util/message.h"
#include "../db/dbmessage.h" #include "../db/dbmessage.h"
#include "config.h" #include "config.h"
#include "util.h" #include "util.h"
namespace mongo { namespace mongo {
class ClientInfo; class ClientInfo;
class Request : boost::noncopyable { class Request : boost::noncopyable {
public: public:
Request( Message& m, AbstractMessagingPort* p ); Request( Message& m, AbstractMessagingPort* p );
// ---- message info ----- // ---- message info -----
const char * getns(){ const char * getns() const {
return _d.getns(); return _d.getns();
} }
int op(){ int op() const {
return _m.data->operation(); return _m.data->operation();
} }
bool expectResponse(){ bool expectResponse() const {
return op() == dbQuery || op() == dbGetMore; return op() == dbQuery || op() == dbGetMore;
} }
bool isCommand() const;
MSGID id(){ MSGID id() const {
return _id; return _id;
} }
DBConfig * getConfig(){ DBConfig * getConfig() const {
return _config; return _config;
} }
bool isShardingEnabled(){ bool isShardingEnabled() const {
return _config->isShardingEnabled(); return _config->isShardingEnabled();
} }
ChunkManager * getChunkManager(){ ChunkManager * getChunkManager() const {
return _chunkManager; return _chunkManager;
} }
int getClientId(){ int getClientId() const {
return _clientId; return _clientId;
} }
ClientInfo * getClientInfo(){ ClientInfo * getClientInfo() const {
return _clientInfo; return _clientInfo;
} }
// ---- remote location info ----- // ---- remote location info -----
string singleServerName(); Shard primaryShard() const ;
const char * primaryName(){
return _config->getPrimary().c_str();
}
// ---- low level access ---- // ---- low level access ----
void reply( Message & response ){ void reply( Message & response ){
_p->reply( _m , response , _id ); _p->reply( _m , response , _id );
} }
Message& m(){ return _m; } Message& m() { return _m; }
DbMessage& d(){ return _d; } DbMessage& d() { return _d; }
AbstractMessagingPort* p(){ return _p; } AbstractMessagingPort* p() const { return _p; }
void process( int attempt = 0 ); void process( int attempt = 0 );
private: private:
void reset( bool reload=false ); void reset( bool reload=false );
Message& _m; Message& _m;
DbMessage _d; DbMessage _d;
AbstractMessagingPort* _p; AbstractMessagingPort* _p;
skipping to change at line 111 skipping to change at line 108
ClientInfo * _clientInfo; ClientInfo * _clientInfo;
}; };
typedef map<int,ClientInfo*> ClientCache; typedef map<int,ClientInfo*> ClientCache;
class ClientInfo { class ClientInfo {
public: public:
ClientInfo( int clientId ); ClientInfo( int clientId );
~ClientInfo(); ~ClientInfo();
string getRemote() const { return _remote; }
void addShard( const string& shard ); void addShard( const string& shard );
set<string> * getPrev() const { return _prev; }; set<string> * getPrev() const { return _prev; };
void newRequest(); void newRequest( AbstractMessagingPort* p = 0 );
void disconnect(); void disconnect();
static ClientInfo * get( int clientId = 0 , bool create = true ); static ClientInfo * get( int clientId = 0 , bool create = true );
private: private:
int _id; int _id;
string _remote;
set<string> _a; set<string> _a;
set<string> _b; set<string> _b;
set<string> * _cur; set<string> * _cur;
set<string> * _prev; set<string> * _prev;
int _lastAccess; int _lastAccess;
static mongo::mutex _clientsLock; static mongo::mutex _clientsLock;
static ClientCache _clients; static ClientCache _clients;
static boost::thread_specific_ptr<ClientInfo> _tlInfo; static boost::thread_specific_ptr<ClientInfo> _tlInfo;
}; };
 End of changes. 16 change blocks. 
19 lines changed or deleted 20 lines changed or added


 scanandorder.h   scanandorder.h 
skipping to change at line 57 skipping to change at line 57
/* todo: /* todo:
_ respect limit _ respect limit
_ check for excess mem usage _ check for excess mem usage
_ response size limit from runquery; push it up a bit. _ response size limit from runquery; push it up a bit.
*/ */
inline void fillQueryResultFromObj(BufBuilder& bb, FieldMatcher *filter , BSONObj& js) { inline void fillQueryResultFromObj(BufBuilder& bb, FieldMatcher *filter , BSONObj& js) {
if ( filter ) { if ( filter ) {
BSONObjBuilder b( bb ); BSONObjBuilder b( bb );
BSONObjIterator i( js ); BSONObjIterator i( js );
bool gotId = false;
while ( i.more() ){ while ( i.more() ){
BSONElement e = i.next(); BSONElement e = i.next();
const char * fname = e.fieldName(); const char * fname = e.fieldName();
if ( strcmp( fname , "_id" ) == 0 ){ if ( strcmp( fname , "_id" ) == 0 ){
b.append( e ); if (filter->includeID())
gotId = true; b.append( e );
} else { } else {
filter->append( b , e ); filter->append( b , e );
} }
} }
b.done(); b.done();
} else { } else {
bb.append((void*) js.objdata(), js.objsize()); bb.append((void*) js.objdata(), js.objsize());
} }
} }
 End of changes. 2 change blocks. 
3 lines changed or deleted 2 lines changed or added


 security.h   security.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 <boost/thread/tss.hpp> #include <boost/thread/tss.hpp>
#undef assert #undef assert
#define assert xassert #define assert MONGO_assert
#include "nonce.h" #include "nonce.h"
#include "concurrency.h" #include "concurrency.h"
namespace mongo { namespace mongo {
// --noauth cmd line option // --noauth cmd line option
extern bool noauth; extern bool noauth;
/* for a particular db */ /* for a particular db */
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 shardkey.h   shardkey.h 
skipping to change at line 77 skipping to change at line 77
ShardKey({num:1}).hasShardKey({ name:"joe", num:3 }) is true ShardKey({num:1}).hasShardKey({ name:"joe", num:3 }) is true
*/ */
bool hasShardKey( const BSONObj& obj ); bool hasShardKey( const BSONObj& obj );
/** /**
returns a query that filters results only for the range desired, i.e. returns returns a query that filters results only for the range desired, i.e. returns
{ "field" : { $gte: keyval(min), $lt: keyval(max) } } { "field" : { $gte: keyval(min), $lt: keyval(max) } }
*/ */
void getFilter( BSONObjBuilder& b , const BSONObj& min, const BSONO bj& max ); void getFilter( BSONObjBuilder& b , const BSONObj& min, const BSONO bj& max );
/** @return true if shard s is relevant for query q.
Example:
q: { x : 3 }
*this: { x : 1 }
s: x:2..x:7
-> true
*/
bool relevantForQuery( const BSONObj& q , Chunk * s );
/** /**
Returns if the given sort pattern can be ordered by the shard ke y pattern. Returns if the given sort pattern can be ordered by the shard ke y pattern.
Example Example
sort: { ts: -1 } sort: { ts: -1 }
*this: { ts:1 } *this: { ts:1 }
-> -1 -> -1
@return @return
0 if sort either doesn't have all the fields or has extra fie lds 0 if sort either doesn't have all the fields or has extra fie lds
< 0 if sort is descending < 0 if sort is descending
skipping to change at line 111 skipping to change at line 101
BSONObj key() { return pattern; } BSONObj key() { return pattern; }
string toString() const; string toString() const;
BSONObj extractKey(const BSONObj& from) const; BSONObj extractKey(const BSONObj& from) const;
bool partOfShardKey(const string& key ) const { bool partOfShardKey(const string& key ) const {
return patternfields.count( key ) > 0; return patternfields.count( key ) > 0;
} }
bool uniqueAllowd( const BSONObj& otherPattern ) const;
operator string() const { operator string() const {
return pattern.toString(); return pattern.toString();
} }
private: private:
BSONObj pattern; BSONObj pattern;
BSONObj gMin; BSONObj gMin;
BSONObj gMax; BSONObj gMax;
/* question: better to have patternfields precomputed or not? depe nds on if we use copy contructor often. */ /* question: better to have patternfields precomputed or not? depe nds on if we use copy constructor often. */
set<string> patternfields; set<string> patternfields;
bool relevant(const BSONObj& query, const BSONObj& L, const BSONObj & R);
}; };
inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const { inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const {
return from.extractFields(pattern); return from.extractFields(pattern);
} }
} }
 End of changes. 4 change blocks. 
12 lines changed or deleted 3 lines changed or added


 snapshots.h   snapshots.h 
skipping to change at line 20 skipping to change at line 20
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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 "../../stdafx.h" #include "../../pch.h"
#include "../jsobj.h" #include "../jsobj.h"
#include "top.h" #include "top.h"
#include "../../util/background.h" #include "../../util/background.h"
/** /**
handles snapshotting performance metrics and other such things handles snapshotting performance metrics and other such things
*/ */
namespace mongo { namespace mongo {
class SnapshotThread; class SnapshotThread;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 sock.h   sock.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 "../stdafx.h" #include "../pch.h"
#include <stdio.h> #include <stdio.h>
#include <sstream> #include <sstream>
#include "goodies.h" #include "goodies.h"
#include "../db/jsobj.h" #include "../db/jsobj.h"
#define SOCK_FAMILY_UNKNOWN_ERROR 13078 #define SOCK_FAMILY_UNKNOWN_ERROR 13078
namespace mongo { namespace mongo {
skipping to change at line 233 skipping to change at line 233
}; };
extern SockAddr unknownAddress; // ( "0.0.0.0", 0 ) extern SockAddr unknownAddress; // ( "0.0.0.0", 0 )
const int MaxMTU = 16384; const int MaxMTU = 16384;
inline string getHostName() { inline string getHostName() {
char buf[256]; char buf[256];
int ec = gethostname(buf, 127); int ec = gethostname(buf, 127);
if ( ec || *buf == 0 ) { if ( ec || *buf == 0 ) {
log() << "can't get this server's hostname " << OUTPUT_ERRNO << endl; log() << "can't get this server's hostname " << errnoWithDescri ption() << endl;
return ""; return "";
} }
return buf; return buf;
} }
class ListeningSockets { class ListeningSockets {
public: public:
ListeningSockets() : _sockets( new set<int>() ){ ListeningSockets() : _sockets( new set<int>() ){
} }
skipping to change at line 277 skipping to change at line 277
} }
static ListeningSockets* get(); static ListeningSockets* get();
private: private:
mongo::mutex _mutex; mongo::mutex _mutex;
set<int>* _sockets; set<int>* _sockets;
static ListeningSockets* _instance; static ListeningSockets* _instance;
}; };
#undef SOCK_FAMILY_UNKNOWN_ERROR
} // namespace mongo } // namespace mongo
 End of changes. 3 change blocks. 
2 lines changed or deleted 4 lines changed or added


 strategy.h   strategy.h 
skipping to change at line 20 skipping to change at line 20
* 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 "../stdafx.h" #include "../pch.h"
#include "chunk.h" #include "chunk.h"
#include "request.h" #include "request.h"
namespace mongo { namespace mongo {
class Strategy { class Strategy {
public: public:
Strategy(){} Strategy(){}
virtual ~Strategy() {} virtual ~Strategy() {}
virtual void queryOp( Request& r ) = 0; virtual void queryOp( Request& r ) = 0;
virtual void getMore( Request& r ) = 0; virtual void getMore( Request& r ) = 0;
virtual void writeOp( int op , Request& r ) = 0; virtual void writeOp( int op , Request& r ) = 0;
protected: protected:
void doWrite( int op , Request& r , string server ); void doWrite( int op , Request& r , const Shard& shard );
void doQuery( Request& r , string server ); void doQuery( Request& r , const Shard& shard );
void insert( string server , const char * ns , const BSONObj& obj ) ; void insert( const Shard& shard , const char * ns , const BSONObj& obj );
}; };
extern Strategy * SINGLE; extern Strategy * SINGLE;
extern Strategy * SHARDED; extern Strategy * SHARDED;
bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu nkVersion version , bool authoritative , BSONObj& result ); bool setShardVersion( DBClientBase & conn , const string& ns , ShardChu nkVersion version , bool authoritative , BSONObj& result );
bool lockNamespaceOnServer( const string& server , const string& ns ); bool lockNamespaceOnServer( const Shard& shard , const string& ns );
bool lockNamespaceOnServer( DBClientBase& conn , const string& ns ); bool lockNamespaceOnServer( DBClientBase& conn , const string& ns );
} }
 End of changes. 4 change blocks. 
5 lines changed or deleted 5 lines changed or added


 syncclusterconnection.h   syncclusterconnection.h 
skipping to change at line 18 skipping to change at line 18
* *
* 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.
*/ */
#include "../stdafx.h" #include "../pch.h"
#include "dbclient.h" #include "dbclient.h"
#include "redef_macros.h"
namespace mongo { namespace mongo {
/** /**
* this is a connection to a cluster of servers that operate as one * this is a connection to a cluster of servers that operate as one
* for super high durability * for super high durability
*/ */
class SyncClusterConnection : public DBClientBase { class SyncClusterConnection : public DBClientBase {
public: public:
/** /**
skipping to change at line 48 skipping to change at line 49
*/ */
bool prepare( string& errmsg ); bool prepare( string& errmsg );
/** /**
* runs fsync on all servers * runs fsync on all servers
*/ */
bool fsync( string& errmsg ); bool fsync( string& errmsg );
// --- from DBClientInterface // --- from DBClientInterface
virtual BSONObj findOne(const string &ns, Query query, const BSONOb
j *fieldsToReturn, int queryOptions);
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn, int nToSkip, virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y, int nToReturn, int nToSkip,
const BSONObj *fieldsToRetur n, int queryOptions, int batchSize ); const BSONObj *fieldsToRetur n, int queryOptions, int batchSize );
virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn, int options ); virtual auto_ptr<DBClientCursor> getMore( const string &ns, long lo ng cursorId, int nToReturn, int options );
virtual void insert( const string &ns, BSONObj obj ); virtual void insert( const string &ns, BSONObj obj );
virtual void insert( const string &ns, const vector< BSONObj >& v ) ; virtual void insert( const string &ns, const vector< BSONObj >& v ) ;
virtual void remove( const string &ns , Query query, bool justOne ) ; virtual void remove( const string &ns , Query query, bool justOne ) ;
skipping to change at line 86 skipping to change at line 89
SyncClusterConnection( SyncClusterConnection& prev ); SyncClusterConnection( SyncClusterConnection& prev );
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 );
bool _isReadOnly( const string& name ); int _lockType( const string& name );
void _checkLast(); void _checkLast();
void _connect( string host ); void _connect( string host );
string _address; string _address;
vector<DBClientConnection*> _conns; vector<DBClientConnection*> _conns;
map<string,int> _lockTypes; map<string,int> _lockTypes;
mongo::mutex _mutex;
}; };
}; };
#include "undef_macros.h"
 End of changes. 7 change blocks. 
2 lines changed or deleted 8 lines changed or added


 thread_pool.h   thread_pool.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.
*/ */
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#undef assert #undef assert
#define assert xassert #define assert MONGO_assert
namespace mongo { namespace mongo {
namespace threadpool { namespace threadpool {
class Worker; class Worker;
typedef boost::function<void(void)> Task; //nullary function or functor typedef boost::function<void(void)> Task; //nullary function or functor
// exported to the mongo namespace // exported to the mongo namespace
class ThreadPool : boost::noncopyable{ class ThreadPool : boost::noncopyable{
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 tool.h   tool.h 
skipping to change at line 38 skipping to change at line 38
#include "client/dbclient.h" #include "client/dbclient.h"
#include "db/instance.h" #include "db/instance.h"
using std::string; using std::string;
namespace mongo { namespace mongo {
class Tool { class Tool {
public: public:
Tool( string name , bool localDBAllowed=true, string defaultDB="tes Tool( string name , bool localDBAllowed=true, string defaultDB="tes
t" , string defaultCollection=""); t" ,
string defaultCollection="", bool usesstdout=true );
virtual ~Tool(); virtual ~Tool();
int main( int argc , char ** argv ); int main( int argc , char ** argv );
boost::program_options::options_description_easy_init add_options() { boost::program_options::options_description_easy_init add_options() {
return _options->add_options(); return _options->add_options();
} }
boost::program_options::options_description_easy_init add_hidden_op tions(){ boost::program_options::options_description_easy_init add_hidden_op tions(){
return _hidden_options->add_options(); return _hidden_options->add_options();
} }
skipping to change at line 75 skipping to change at line 76
} }
string getNS(){ string getNS(){
if ( _coll.size() == 0 ){ if ( _coll.size() == 0 ){
cerr << "no collection specified!" << endl; cerr << "no collection specified!" << endl;
throw -1; throw -1;
} }
return _db + "." + _coll; return _db + "." + _coll;
} }
virtual void preSetup(){}
virtual int run() = 0; virtual int run() = 0;
virtual void printHelp(ostream &out); virtual void printHelp(ostream &out);
virtual void printExtraHelp( ostream & out ); virtual void printExtraHelp( ostream & out );
protected: protected:
mongo::DBClientBase &conn( bool slaveIfPaired = false ); mongo::DBClientBase &conn( bool slaveIfPaired = false );
void auth( string db = "" ); void auth( string db = "" );
string _name; string _name;
string _db; string _db;
string _coll; string _coll;
string _username; string _username;
string _password; string _password;
bool _usesstdout;
bool _noconnection;
void addFieldOptions(); void addFieldOptions();
void needFields(); void needFields();
vector<string> _fields; vector<string> _fields;
BSONObj _fieldsObj; BSONObj _fieldsObj;
private:
string _host; string _host;
protected:
mongo::DBClientBase * _conn; mongo::DBClientBase * _conn;
bool _paired; bool _paired;
boost::program_options::options_description * _options; boost::program_options::options_description * _options;
boost::program_options::options_description * _hidden_options; boost::program_options::options_description * _hidden_options;
boost::program_options::positional_options_description _positonalOp tions; boost::program_options::positional_options_description _positonalOp tions;
boost::program_options::variables_map _params; boost::program_options::variables_map _params;
}; };
 End of changes. 5 change blocks. 
3 lines changed or deleted 11 lines changed or added


 top.h   top.h 
skipping to change at line 22 skipping to change at line 22
* 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 <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#undef assert #undef assert
#define assert xassert #define assert MONGO_assert
namespace mongo { namespace mongo {
/** /**
* tracks usage by collection * tracks usage by collection
*/ */
class Top { class Top {
public: public:
class UsageData { class UsageData {
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 update.h   update.h 
skipping to change at line 19 skipping to change at line 19
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* 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/>.
*/ */
#include "../stdafx.h" #include "../pch.h"
#include "jsobj.h" #include "jsobj.h"
#include "../util/embedded_builder.h" #include "../util/embedded_builder.h"
#include "matcher.h" #include "matcher.h"
namespace mongo { namespace mongo {
class ModState; class ModState;
class ModSetState; class ModSetState;
/* Used for modifiers such as $inc, $set, $push, ... /* Used for modifiers such as $inc, $set, $push, ...
skipping to change at line 329 skipping to change at line 329
}; };
/** /**
* stores any information about a single Mod operating on a single Obje ct * stores any information about a single Mod operating on a single Obje ct
*/ */
class ModState { class ModState {
public: public:
const Mod * m; const Mod * m;
BSONElement old; BSONElement old;
const char * fixedName; const char * fixedOpName;
BSONElement * fixed; BSONElement * fixed;
int pushStartSize; int pushStartSize;
BSONType incType; BSONType incType;
int incint; int incint;
double incdouble; double incdouble;
long long inclong; long long inclong;
ModState(){ ModState(){
fixedName = 0; fixedOpName = 0;
fixed = 0; fixed = 0;
pushStartSize = -1; pushStartSize = -1;
incType = EOO; incType = EOO;
} }
Mod::Op op() const { Mod::Op op() const {
return m->op; return m->op;
} }
const char * fieldName() const { const char * fieldName() const {
return m->fieldName; return m->fieldName;
} }
bool needOpLogRewrite() const { bool needOpLogRewrite() const {
if ( fixed || fixedName || incType ) if ( fixed || fixedOpName || incType )
return true; return true;
switch( op() ){ switch( op() ){
case Mod::BIT: case Mod::BIT:
case Mod::BITAND: case Mod::BITAND:
case Mod::BITOR: case Mod::BITOR:
// TODO: should we convert this to $set? // TODO: should we convert this to $set?
return false; return false;
default: default:
return false; return false;
skipping to change at line 376 skipping to change at line 376
} }
void appendForOpLog( BSONObjBuilder& b ) const { void appendForOpLog( BSONObjBuilder& b ) const {
if ( incType ){ if ( incType ){
BSONObjBuilder bb( b.subobjStart( "$set" ) ); BSONObjBuilder bb( b.subobjStart( "$set" ) );
appendIncValue( bb ); appendIncValue( bb );
bb.done(); bb.done();
return; return;
} }
const char * name = fixedName ? fixedName : Mod::modNames[op()] ; const char * name = fixedOpName ? fixedOpName : Mod::modNames[o p()];
BSONObjBuilder bb( b.subobjStart( name ) ); BSONObjBuilder bb( b.subobjStart( name ) );
if ( fixed ) if ( fixed )
bb.appendAs( *fixed , m->fieldName ); bb.appendAs( *fixed , m->fieldName );
else else
bb.append( m->elt ); bb.appendAs( m->elt , m->fieldName );
bb.done(); bb.done();
} }
template< class Builder > template< class Builder >
void apply( Builder& b , BSONElement in ){ void apply( Builder& b , BSONElement in ){
m->apply( b , in , *this ); m->apply( b , in , *this );
} }
template< class Builder > template< class Builder >
void appendIncValue( Builder& b ) const { void appendIncValue( Builder& b ) const {
skipping to change at line 472 skipping to change at line 472
break; break;
} }
case Mod::UNSET: case Mod::UNSET:
case Mod::PULL: case Mod::PULL:
case Mod::PULL_ALL: case Mod::PULL_ALL:
// no-op b/c unset/pull of nothing does nothing // no-op b/c unset/pull of nothing does nothing
break; break;
case Mod::INC: case Mod::INC:
ms.fixedName = "$set"; ms.fixedOpName = "$set";
case Mod::SET: { case Mod::SET: {
m._checkForAppending( m.elt ); m._checkForAppending( m.elt );
b.appendAs( m.elt, m.shortFieldName ); b.appendAs( m.elt, m.shortFieldName );
break; break;
} }
default: default:
stringstream ss; stringstream ss;
ss << "unknown mod in appendNewFromMod: " << m.op; ss << "unknown mod in appendNewFromMod: " << m.op;
throw UserException( 9015, ss.str() ); throw UserException( 9015, ss.str() );
} }
 End of changes. 7 change blocks. 
7 lines changed or deleted 7 lines changed or added


 util.h   util.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 "../stdafx.h" #include "../pch.h"
#include "../client/dbclient.h" #include "../client/dbclient.h"
/** /**
some generic sharding utils that can be used in mongod or mongos some generic sharding utils that can be used in mongod or mongos
*/ */
namespace mongo { namespace mongo {
/** /**
your config info for a given shard/chunk is out of date */ your config info for a given shard/chunk is out of date */
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/