mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
Merge branch 'master' of github.com:mongodb/mongo
This commit is contained in:
commit
d26dff949e
@ -7,7 +7,7 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
SyncCluterConnection::SyncCluterConnection( string commaSeperated ){
|
||||
SyncClusterConnection::SyncClusterConnection( string commaSeperated ){
|
||||
string::size_type idx;
|
||||
while ( ( idx = commaSeperated.find( ',' ) ) != string::npos ){
|
||||
string h = commaSeperated.substr( 0 , idx );
|
||||
@ -15,27 +15,27 @@ namespace mongo {
|
||||
_connect( h );
|
||||
}
|
||||
_connect( commaSeperated );
|
||||
uassert( 8004 , "SyncCluterConnection needs 3 servers" , _conns.size() == 3 );
|
||||
uassert( 8004 , "SyncClusterConnection needs 3 servers" , _conns.size() == 3 );
|
||||
}
|
||||
|
||||
SyncCluterConnection::SyncCluterConnection( string a , string b , string c ){
|
||||
SyncClusterConnection::SyncClusterConnection( string a , string b , string c ){
|
||||
// connect to all even if not working
|
||||
_connect( a );
|
||||
_connect( b );
|
||||
_connect( c );
|
||||
}
|
||||
|
||||
SyncCluterConnection::~SyncCluterConnection(){
|
||||
SyncClusterConnection::~SyncClusterConnection(){
|
||||
for ( size_t i=0; i<_conns.size(); i++ )
|
||||
delete _conns[i];
|
||||
_conns.clear();
|
||||
}
|
||||
|
||||
bool SyncCluterConnection::prepare( string& errmsg ){
|
||||
bool SyncClusterConnection::prepare( string& errmsg ){
|
||||
return fsync( errmsg );
|
||||
}
|
||||
|
||||
bool SyncCluterConnection::fsync( string& errmsg ){
|
||||
bool SyncClusterConnection::fsync( string& errmsg ){
|
||||
bool ok = true;
|
||||
errmsg = "";
|
||||
for ( size_t i=0; i<_conns.size(); i++ ){
|
||||
@ -55,7 +55,7 @@ namespace mongo {
|
||||
return ok;
|
||||
}
|
||||
|
||||
void SyncCluterConnection::_checkLast(){
|
||||
void SyncClusterConnection::_checkLast(){
|
||||
vector<BSONObj> all;
|
||||
vector<string> errors;
|
||||
|
||||
@ -91,22 +91,22 @@ namespace mongo {
|
||||
|
||||
if ( ok )
|
||||
return;
|
||||
throw UserException( 8001 , (string)"SyncCluterConnection write op failed: " + err.str() );
|
||||
throw UserException( 8001 , (string)"SyncClusterConnection write op failed: " + err.str() );
|
||||
}
|
||||
|
||||
void SyncCluterConnection::_connect( string host ){
|
||||
log() << "SyncCluterConnection connecting to: " << host << endl;
|
||||
void SyncClusterConnection::_connect( string host ){
|
||||
log() << "SyncClusterConnection connecting to: " << host << endl;
|
||||
DBClientConnection * c = new DBClientConnection( true );
|
||||
string errmsg;
|
||||
if ( ! c->connect( host , errmsg ) )
|
||||
log() << "SyncCluterConnection connect fail to: " << host << " errmsg: " << errmsg << endl;
|
||||
log() << "SyncClusterConnection connect fail to: " << host << " errmsg: " << errmsg << endl;
|
||||
_conns.push_back( c );
|
||||
}
|
||||
|
||||
auto_ptr<DBClientCursor> SyncCluterConnection::query(const string &ns, Query query, int nToReturn, int nToSkip,
|
||||
auto_ptr<DBClientCursor> SyncClusterConnection::query(const string &ns, Query query, int nToReturn, int nToSkip,
|
||||
const BSONObj *fieldsToReturn, int queryOptions){
|
||||
|
||||
uassert( 10021 , "$cmd not support yet in SyncCluterConnection::query" , ns.find( "$cmd" ) == string::npos );
|
||||
uassert( 10021 , "$cmd not support yet in SyncClusterConnection::query" , ns.find( "$cmd" ) == string::npos );
|
||||
|
||||
for ( size_t i=0; i<_conns.size(); i++ ){
|
||||
try {
|
||||
@ -123,16 +123,16 @@ namespace mongo {
|
||||
throw UserException( 8002 , "all servers down!" );
|
||||
}
|
||||
|
||||
auto_ptr<DBClientCursor> SyncCluterConnection::getMore( const string &ns, long long cursorId, int nToReturn, int options ){
|
||||
uassert( 10022 , "SyncCluterConnection::getMore not supported yet" , 0);
|
||||
auto_ptr<DBClientCursor> SyncClusterConnection::getMore( const string &ns, long long cursorId, int nToReturn, int options ){
|
||||
uassert( 10022 , "SyncClusterConnection::getMore not supported yet" , 0);
|
||||
auto_ptr<DBClientCursor> c;
|
||||
return c;
|
||||
}
|
||||
|
||||
void SyncCluterConnection::insert( const string &ns, BSONObj obj ){
|
||||
void SyncClusterConnection::insert( const string &ns, BSONObj obj ){
|
||||
string errmsg;
|
||||
if ( ! prepare( errmsg ) )
|
||||
throw UserException( 8003 , (string)"SyncCluterConnection::insert prepare failed: " + errmsg );
|
||||
throw UserException( 8003 , (string)"SyncClusterConnection::insert prepare failed: " + errmsg );
|
||||
|
||||
for ( size_t i=0; i<_conns.size(); i++ ){
|
||||
_conns[i]->insert( ns , obj );
|
||||
@ -141,17 +141,17 @@ namespace mongo {
|
||||
_checkLast();
|
||||
}
|
||||
|
||||
void SyncCluterConnection::insert( const string &ns, const vector< BSONObj >& v ){
|
||||
uassert( 10023 , "SyncCluterConnection bulk insert not implemented" , 0);
|
||||
void SyncClusterConnection::insert( const string &ns, const vector< BSONObj >& v ){
|
||||
uassert( 10023 , "SyncClusterConnection bulk insert not implemented" , 0);
|
||||
}
|
||||
|
||||
void SyncCluterConnection::remove( const string &ns , Query query, bool justOne ){ assert(0); }
|
||||
void SyncClusterConnection::remove( const string &ns , Query query, bool justOne ){ assert(0); }
|
||||
|
||||
void SyncCluterConnection::update( const string &ns , Query query , BSONObj obj , bool upsert , bool multi ){ assert(0); }
|
||||
void SyncClusterConnection::update( const string &ns , Query query , BSONObj obj , bool upsert , bool multi ){ assert(0); }
|
||||
|
||||
string SyncCluterConnection::toString(){
|
||||
string SyncClusterConnection::toString(){
|
||||
stringstream ss;
|
||||
ss << "SyncCluterConnection [";
|
||||
ss << "SyncClusterConnection [";
|
||||
for ( size_t i=0; i<_conns.size(); i++ ){
|
||||
if ( i > 0 )
|
||||
ss << ",";
|
||||
|
@ -9,14 +9,14 @@ namespace mongo {
|
||||
* this is a connection to a cluster of servers that operate as one
|
||||
* for super high durability
|
||||
*/
|
||||
class SyncCluterConnection : public DBClientWithCommands {
|
||||
class SyncClusterConnection : public DBClientWithCommands {
|
||||
public:
|
||||
/**
|
||||
* @param commaSeperated should be 3 hosts comma seperated
|
||||
*/
|
||||
SyncCluterConnection( string commaSeperated );
|
||||
SyncCluterConnection( string a , string b , string c );
|
||||
~SyncCluterConnection();
|
||||
SyncClusterConnection( string commaSeperated );
|
||||
SyncClusterConnection( string a , string b , string c );
|
||||
~SyncClusterConnection();
|
||||
|
||||
|
||||
/**
|
||||
|
@ -926,12 +926,11 @@ namespace mongo {
|
||||
b->k(1).setUnused();
|
||||
|
||||
b->dumpTree(id.head, order);
|
||||
cout << "---\n";
|
||||
|
||||
b->bt_insert(id.head, A, key, order, false, id);
|
||||
|
||||
b->dumpTree(id.head, order);
|
||||
cout << "---\n";*/
|
||||
*/
|
||||
|
||||
// this should assert. does it? (it might "accidentally" though, not asserting proves a problem, asserting proves nothing)
|
||||
b->bt_insert(id.head, C, key, order, false, id);
|
||||
|
@ -217,7 +217,7 @@ namespace mongo {
|
||||
static bool inEmpty = false;
|
||||
if( test && !inEmpty ) {
|
||||
inEmpty = true;
|
||||
log() << "TEST: manipulate collection during remove" << endl;
|
||||
log() << "TEST: manipulate collection during cc:yield" << endl;
|
||||
if( test == 1 )
|
||||
Helpers::emptyCollection(ns.c_str());
|
||||
else if( test == 2 ) {
|
||||
|
@ -105,7 +105,12 @@ namespace mongo {
|
||||
int pos; // # objects into the cursor so far
|
||||
BSONObj query;
|
||||
|
||||
ClientCursor() : _idleAgeMillis(0), _pinValue(0), _doingDeletes(false), pos(0) {
|
||||
ClientCursor(auto_ptr<Cursor>& _c, const char *_ns) :
|
||||
_idleAgeMillis(0), _pinValue(0),
|
||||
_doingDeletes(false),
|
||||
ns(_ns), c(_c),
|
||||
pos(0)
|
||||
{
|
||||
recursive_boostlock lock(ccmutex);
|
||||
cursorid = allocCursorId_inlock();
|
||||
clientCursorsById.insert( make_pair(cursorid, this) );
|
||||
|
@ -206,6 +206,11 @@ namespace mongo {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( inShutdown() ) {
|
||||
log() << "got request after shutdown()" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
lastError.startRequest( m , le );
|
||||
|
||||
DbResponse dbresponse;
|
||||
|
@ -1342,7 +1342,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\client\quorum.cpp"
|
||||
RelativePath="..\client\syncclusterconnection.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
|
@ -1012,9 +1012,7 @@ namespace mongo {
|
||||
CursorId id;
|
||||
{
|
||||
auto_ptr< Cursor > c = theDataFileMgr.findAll( fromNs.c_str(), startLoc );
|
||||
ClientCursor *cc = new ClientCursor();
|
||||
cc->c = c;
|
||||
cc->ns = fromNs;
|
||||
ClientCursor *cc = new ClientCursor(c, fromNs.c_str());
|
||||
cc->matcher.reset( new CoveredIndexMatcher( BSONObj(), fromjson( "{$natural:1}" ) ) );
|
||||
id = cc->cursorid;
|
||||
}
|
||||
|
@ -84,12 +84,6 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ElementMatcher::~ElementMatcher(){
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
#include "pdfile.h"
|
||||
@ -307,8 +301,9 @@ namespace mongo {
|
||||
inline int Matcher::valuesMatch(const BSONElement& l, const BSONElement& r, int op, const ElementMatcher& bm) {
|
||||
assert( op != BSONObj::NE && op != BSONObj::NIN );
|
||||
|
||||
if ( op == BSONObj::Equality )
|
||||
if ( op == BSONObj::Equality ) {
|
||||
return l.valuesEqual(r);
|
||||
}
|
||||
|
||||
if ( op == BSONObj::opIN ) {
|
||||
// { $in : [1,2,3] }
|
||||
@ -383,16 +378,15 @@ namespace mongo {
|
||||
0 missing element
|
||||
1 match
|
||||
*/
|
||||
int Matcher::matchesDotted(const char *fieldName, const BSONElement& toMatch, const BSONObj& obj, int compareOp, const ElementMatcher& bm , bool isArr) {
|
||||
|
||||
int Matcher::matchesDotted(const char *fieldName, const BSONElement& toMatch, const BSONObj& obj, int compareOp, const ElementMatcher& em , bool isArr) {
|
||||
if ( compareOp == BSONObj::opALL ) {
|
||||
if ( bm.myset->size() == 0 )
|
||||
if ( em.myset->size() == 0 )
|
||||
return -1; // is this desired?
|
||||
BSONObjSetDefaultOrder actualKeys;
|
||||
IndexSpec( BSON( fieldName << 1 ) ).getKeys( obj, actualKeys );
|
||||
if ( actualKeys.size() == 0 )
|
||||
return 0;
|
||||
for( set< BSONElement, element_lt >::const_iterator i = bm.myset->begin(); i != bm.myset->end(); ++i ) {
|
||||
for( set< BSONElement, element_lt >::const_iterator i = em.myset->begin(); i != em.myset->end(); ++i ) {
|
||||
// ignore nulls
|
||||
if ( i->type() == jstNULL )
|
||||
continue;
|
||||
@ -406,10 +400,10 @@ namespace mongo {
|
||||
}
|
||||
|
||||
if ( compareOp == BSONObj::NE )
|
||||
return matchesNe( fieldName, toMatch, obj, bm );
|
||||
return matchesNe( fieldName, toMatch, obj, em );
|
||||
if ( compareOp == BSONObj::NIN ) {
|
||||
for( set<BSONElement,element_lt>::const_iterator i = bm.myset->begin(); i != bm.myset->end(); ++i ) {
|
||||
int ret = matchesNe( fieldName, *i, obj, bm );
|
||||
for( set<BSONElement,element_lt>::const_iterator i = em.myset->begin(); i != em.myset->end(); ++i ) {
|
||||
int ret = matchesNe( fieldName, *i, obj, em );
|
||||
if ( ret != 1 )
|
||||
return ret;
|
||||
}
|
||||
@ -422,14 +416,37 @@ namespace mongo {
|
||||
e = obj.getFieldUsingIndexNames(fieldName, constrainIndexKey_);
|
||||
assert( !e.eoo() );
|
||||
} else {
|
||||
|
||||
const char *p = strchr(fieldName, '.');
|
||||
if ( p ) {
|
||||
string left(fieldName, p-fieldName);
|
||||
|
||||
BSONElement se = obj.getField(left.c_str());
|
||||
if ( se.eoo() )
|
||||
;
|
||||
else if ( se.type() != Object && se.type() != Array )
|
||||
;
|
||||
else {
|
||||
BSONObj eo = se.embeddedObject();
|
||||
return matchesDotted(p+1, toMatch, eo, compareOp, em, se.type() == Array);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isArr ) {
|
||||
|
||||
BSONObjIterator ai(obj);
|
||||
bool found = false;
|
||||
while ( ai.moreWithEOO() ) {
|
||||
BSONElement z = ai.next();
|
||||
|
||||
if( strcmp(z.fieldName(),fieldName) == 0 && valuesMatch(z, toMatch, compareOp, em) ) {
|
||||
// "field.<n>" array notation was used
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( z.type() == Object ) {
|
||||
BSONObj eo = z.embeddedObject();
|
||||
int cmp = matchesDotted(fieldName, toMatch, eo, compareOp, bm, false);
|
||||
int cmp = matchesDotted(fieldName, toMatch, eo, compareOp, em, false);
|
||||
if ( cmp > 0 ) {
|
||||
return 1;
|
||||
} else if ( cmp < 0 ) {
|
||||
@ -437,21 +454,13 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
}
|
||||
return found ? -1 : retMissing( bm );
|
||||
return found ? -1 : retMissing( em );
|
||||
}
|
||||
const char *p = strchr(fieldName, '.');
|
||||
if ( p ) {
|
||||
string left(fieldName, p-fieldName);
|
||||
|
||||
BSONElement se = obj.getField(left.c_str());
|
||||
if ( se.eoo() )
|
||||
return retMissing( bm );
|
||||
if ( se.type() != Object && se.type() != Array )
|
||||
return retMissing( bm );
|
||||
|
||||
BSONObj eo = se.embeddedObject();
|
||||
return matchesDotted(p+1, toMatch, eo, compareOp, bm, se.type() == Array);
|
||||
} else {
|
||||
if( p ) {
|
||||
return retMissing( em );
|
||||
}
|
||||
else {
|
||||
e = obj.getField(fieldName);
|
||||
}
|
||||
}
|
||||
@ -459,7 +468,7 @@ namespace mongo {
|
||||
if ( compareOp == BSONObj::opEXISTS ) {
|
||||
return ( e.eoo() ^ toMatch.boolean() ) ? 1 : -1;
|
||||
} else if ( ( e.type() != Array || indexed || compareOp == BSONObj::opSIZE ) &&
|
||||
valuesMatch(e, toMatch, compareOp, bm ) ) {
|
||||
valuesMatch(e, toMatch, compareOp, em ) ) {
|
||||
return 1;
|
||||
} else if ( e.type() == Array && compareOp != BSONObj::opSIZE ) {
|
||||
|
||||
@ -470,11 +479,11 @@ namespace mongo {
|
||||
|
||||
if ( compareOp == BSONObj::opELEM_MATCH ){
|
||||
// SERVER-377
|
||||
if ( z.type() == Object && bm.subMatcher->matches( z.embeddedObject() ) )
|
||||
if ( z.type() == Object && em.subMatcher->matches( z.embeddedObject() ) )
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
if ( valuesMatch( z, toMatch, compareOp, bm) ) {
|
||||
if ( valuesMatch( z, toMatch, compareOp, em) ) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
|
||||
~ElementMatcher();
|
||||
~ElementMatcher() { }
|
||||
|
||||
BSONElement toMatch;
|
||||
int compareOp;
|
||||
@ -85,8 +85,7 @@ namespace mongo {
|
||||
shared_ptr<Matcher> subMatcher;
|
||||
};
|
||||
|
||||
// SQL where clause equivalent
|
||||
class Where;
|
||||
class Where; // used for $where javascript eval
|
||||
class DiskLoc;
|
||||
|
||||
/* Match BSON objects against a query pattern.
|
||||
@ -145,7 +144,6 @@ namespace mongo {
|
||||
BSONObj jsobj; // the query pattern. e.g., { name: "joe" }
|
||||
BSONObj constrainIndexKey_;
|
||||
vector<ElementMatcher> basics;
|
||||
// int n; // # of basicmatcher items
|
||||
bool haveSize;
|
||||
bool all;
|
||||
bool hasArray;
|
||||
|
@ -968,7 +968,6 @@ namespace mongo {
|
||||
RARELY killCurrentOp.checkForInterrupt();
|
||||
BSONObjExternalSorter::Data d = i->next();
|
||||
|
||||
//cout<<"TEMP SORTER next " << d.first.toString() << endl;
|
||||
try {
|
||||
btBuilder.addKey(d.first, d.second);
|
||||
}
|
||||
|
14
db/query.cpp
14
db/query.cpp
@ -136,10 +136,7 @@ namespace mongo {
|
||||
|
||||
CoveredIndexMatcher matcher(pattern, creal->indexKeyPattern());
|
||||
|
||||
auto_ptr<ClientCursor> cc;
|
||||
cc.reset( new ClientCursor() );
|
||||
cc->c = creal;
|
||||
cc->ns = ns;
|
||||
auto_ptr<ClientCursor> cc( new ClientCursor(creal,ns) );
|
||||
cc->noTimeout();
|
||||
cc->setDoingDeletes( true );
|
||||
|
||||
@ -514,10 +511,9 @@ namespace mongo {
|
||||
if ( findingStart_ ) {
|
||||
// Use a ClientCursor here so we can release db mutex while scanning
|
||||
// oplog (can take quite a while with large oplogs).
|
||||
findingStartCursor_ = new ClientCursor();
|
||||
auto_ptr<Cursor> c = qp().newReverseCursor();
|
||||
findingStartCursor_ = new ClientCursor(c, qp().ns());
|
||||
findingStartCursor_->noTimeout();
|
||||
findingStartCursor_->c = qp().newReverseCursor();
|
||||
findingStartCursor_->ns = qp().ns();
|
||||
} else {
|
||||
c_ = qp().newCursor();
|
||||
}
|
||||
@ -855,15 +851,13 @@ namespace mongo {
|
||||
auto_ptr< Cursor > c = dqo.cursor();
|
||||
log( 5 ) << " used cursor: " << c.get() << endl;
|
||||
if ( dqo.saveClientCursor() ) {
|
||||
ClientCursor *cc = new ClientCursor();
|
||||
ClientCursor *cc = new ClientCursor(c, ns); // the clientcursor now owns the Cursor* and 'c' is released.
|
||||
if ( queryOptions & QueryOption_NoCursorTimeout )
|
||||
cc->noTimeout();
|
||||
cc->c = c;
|
||||
cursorid = cc->cursorid;
|
||||
cc->query = jsobj.getOwned();
|
||||
DEV out() << " query has more, cursorid: " << cursorid << endl;
|
||||
cc->matcher = dqo.matcher();
|
||||
cc->ns = ns;
|
||||
cc->pos = n;
|
||||
cc->filter = filter;
|
||||
cc->originalMessage = m;
|
||||
|
@ -515,6 +515,37 @@ namespace JSTests {
|
||||
|
||||
};
|
||||
|
||||
class NumberLong {
|
||||
public:
|
||||
void run() {
|
||||
Scope * s = globalScriptEngine->newScope();
|
||||
s->localConnect( "blah" );
|
||||
BSONObjBuilder b;
|
||||
long long val = (long long)( 0xbabadeadbeefbaddULL );
|
||||
b.append( "a", val );
|
||||
BSONObj in = b.obj();
|
||||
s->setObject( "a", in );
|
||||
BSONObj out = s->getObject( "a" );
|
||||
ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() );
|
||||
|
||||
ASSERT( s->exec( "b = {b:a.a}", "foo", false, true, false ) );
|
||||
out = s->getObject( "b" );
|
||||
ASSERT_EQUALS( mongo::NumberLong, out.firstElement().type() );
|
||||
ASSERT_EQUALS( val, out.firstElement().numberLong() );
|
||||
|
||||
ASSERT( s->exec( "c = {c:a.a.toString()}", "foo", false, true, false ) );
|
||||
out = s->getObject( "c" );
|
||||
stringstream ss;
|
||||
ss << val;
|
||||
ASSERT_EQUALS( ss.str(), out.firstElement().valuestr() );
|
||||
|
||||
ASSERT( s->exec( "d = {d:a.a.toNumber()}", "foo", false, true, false ) );
|
||||
out = s->getObject( "d" );
|
||||
ASSERT_EQUALS( NumberDouble, out.firstElement().type() );
|
||||
ASSERT_EQUALS( double( val ), out.firstElement().number() );
|
||||
}
|
||||
};
|
||||
|
||||
class WeirdObjects {
|
||||
public:
|
||||
|
||||
@ -752,6 +783,7 @@ namespace JSTests {
|
||||
add< OtherJSTypes >();
|
||||
add< SpecialDBTypes >();
|
||||
add< TypeConservation >();
|
||||
add< NumberLong >();
|
||||
|
||||
add< WeirdObjects >();
|
||||
add< Utf8Check >();
|
||||
|
@ -1330,7 +1330,7 @@
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\client\quorum.cpp"
|
||||
RelativePath="..\client\syncclusterconnection.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
|
@ -6,7 +6,7 @@ before = db._adminCommand( "serverStatus" )
|
||||
if ( before.mem.supported ){
|
||||
db._adminCommand( "closeAllDatabases" );
|
||||
after = db._adminCommand( "serverStatus" );
|
||||
assert( before.mem.mapped > after.mem.mapped , "closeAllDatabases does something before:" + tojson( before ) + " after:" + tojson( after ) );
|
||||
assert( before.mem.mapped.toNumber() > after.mem.mapped.toNumber() , "closeAllDatabases does something before:" + tojson( before ) + " after:" + tojson( after ) );
|
||||
}
|
||||
else {
|
||||
print( "can't test serverStatus on this machine" );
|
||||
|
@ -9,3 +9,33 @@ assert.eq( 2 , t.find().count() , "A" );
|
||||
assert.eq( 1 , t.find( { b : null } ).count() , "B" );
|
||||
assert.eq( 1 , t.find( "function() { return this.b == null; }" ).itcount() , "C" );
|
||||
assert.eq( 1 , t.find( "function() { return this.b == null; }" ).count() , "D" );
|
||||
|
||||
/* test some stuff with dot array notation */
|
||||
q = db.find6a;
|
||||
q.drop();
|
||||
q.insert( { "a" : [ { "0" : 1 } ] } );
|
||||
q.insert( { "a" : [ { "0" : 2 } ] } );
|
||||
q.insert( { "a" : [ 1 ] } );
|
||||
q.insert( { "a" : [ 9, 1 ] } );
|
||||
|
||||
function f() {
|
||||
|
||||
assert.eq( 2, q.find( { 'a.0' : 1 } ).count(), "da1");
|
||||
assert.eq( 2, q.find( { 'a.0' : 1 } ).count(), "da2");
|
||||
|
||||
assert.eq( 1, q.find( { 'a.0' : { $gt : 8 } } ).count(), "da3");
|
||||
assert.eq( 0, q.find( { 'a.0' : { $lt : 0 } } ).count(), "da4");
|
||||
|
||||
}
|
||||
|
||||
for( var pass = 0; pass <= 1 ; pass++ ) {
|
||||
f();
|
||||
q.ensureIndex({a:1});
|
||||
}
|
||||
|
||||
t = db.multidim;
|
||||
t.drop();
|
||||
t.insert({"a" : [ [ ], 1, [ 3, 4 ] ] });
|
||||
assert.eq(1, t.find({"a.2":[3,4]}).count(), "md1");
|
||||
assert.eq(1, t.find({"a.2.1":4}).count(), "md2");
|
||||
assert.eq(0, t.find({"a.2.1":3}).count(), "md3");
|
||||
|
@ -4,6 +4,6 @@ t.drop();
|
||||
|
||||
t.save( { a : 1 } );
|
||||
|
||||
assert.lt( 0 , t.dataSize() , "A" );
|
||||
assert.lt( t.dataSize() , t.storageSize() , "B" );
|
||||
assert.lt( 0 , t.dataSize().toNumber() , "A" );
|
||||
assert.lt( t.dataSize() , t.storageSize().toNumber() , "B" );
|
||||
assert.lt( 0 , t.totalIndexSize() , "C" );
|
||||
|
@ -158,6 +158,14 @@ namespace mongo {
|
||||
return toString( JS_ValueToString( _context , v ) );
|
||||
}
|
||||
|
||||
// NOTE No validation of passed in object
|
||||
long long toNumberLongUnsafe( JSObject *o ) {
|
||||
unsigned long long val =
|
||||
( (unsigned long long)( getNumber( o , "top" ) ) << 32 ) +
|
||||
( unsigned )( getNumber( o , "bottom" ) );
|
||||
return val;
|
||||
}
|
||||
|
||||
double toNumber( jsval v ){
|
||||
double d;
|
||||
uassert( 10214 , "not a number" , JS_ValueToNumber( _context , v , &d ) );
|
||||
@ -469,7 +477,6 @@ namespace mongo {
|
||||
return JSVAL_NULL;
|
||||
case NumberDouble:
|
||||
case NumberInt:
|
||||
case NumberLong:
|
||||
return toval( e.number() );
|
||||
case Symbol: // TODO: should we make a special class for this
|
||||
case String:
|
||||
@ -557,7 +564,15 @@ namespace mongo {
|
||||
setProperty( o , "i" , toval( (double)(e.timestampInc()) ) );
|
||||
return OBJECT_TO_JSVAL( o );
|
||||
}
|
||||
|
||||
case NumberLong: {
|
||||
unsigned long long val = (unsigned long long)e.numberLong();
|
||||
JSObject * o = JS_NewObject( _context , &numberlong_class , 0 , 0 );
|
||||
// using 2 doubles here instead of a single double because certain double
|
||||
// bit patterns represent undefined values and sm might trash them
|
||||
setProperty( o , "top" , toval( (double)( val >> 32 ) ) );
|
||||
setProperty( o , "bottom" , toval( (double)( val & 0x00000000ffffffff ) ) );
|
||||
return OBJECT_TO_JSVAL( o );
|
||||
}
|
||||
case DBRef: {
|
||||
JSObject * o = JS_NewObject( _context , &dbpointer_class , 0 , 0 );
|
||||
setProperty( o , "ns" , toval( e.dbrefNS() ) );
|
||||
|
@ -93,6 +93,7 @@ namespace mongo {
|
||||
extern JSClass dbref_class;
|
||||
extern JSClass bindata_class;
|
||||
extern JSClass timestamp_class;
|
||||
extern JSClass numberlong_class;
|
||||
extern JSClass minkey_class;
|
||||
extern JSClass maxkey_class;
|
||||
|
||||
|
@ -101,7 +101,6 @@ namespace mongo {
|
||||
*rval = c.toval( &n );
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
|
||||
JSFunctionSpec internal_cursor_functions[] = {
|
||||
{ "hasNext" , internal_cursor_hasNext , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
|
||||
@ -173,7 +172,7 @@ namespace mongo {
|
||||
}
|
||||
}
|
||||
else if ( numCommas == 2 ){
|
||||
conn.reset( new SyncCluterConnection( host ) );
|
||||
conn.reset( new SyncClusterConnection( host ) );
|
||||
}
|
||||
else {
|
||||
JS_ReportError( cx , "1 (paired) or 2(quorum) commas are allowed" );
|
||||
@ -526,6 +525,7 @@ namespace mongo {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
// dbpointer
|
||||
|
||||
JSBool dbpointer_constructor( JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval ){
|
||||
@ -656,7 +656,33 @@ namespace mongo {
|
||||
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
JSClass numberlong_class = {
|
||||
"NumberLong" , JSCLASS_HAS_PRIVATE ,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
JS_EnumerateStub, JS_ResolveStub , JS_ConvertStub, JS_FinalizeStub,
|
||||
JSCLASS_NO_OPTIONAL_MEMBERS
|
||||
};
|
||||
|
||||
JSBool numberlong_tostring(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
|
||||
Convertor c(cx);
|
||||
stringstream ss;
|
||||
ss << c.toNumberLongUnsafe( obj );
|
||||
string ret = ss.str();
|
||||
return *rval = c.toval( ret.c_str() );
|
||||
}
|
||||
|
||||
JSBool numberlong_tonumber(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){
|
||||
Convertor c(cx);
|
||||
return *rval = c.toval( double( c.toNumberLongUnsafe( obj ) ) );
|
||||
}
|
||||
|
||||
JSFunctionSpec numberlong_functions[] = {
|
||||
{ "toString" , numberlong_tostring , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
|
||||
{ "toNumber" , numberlong_tonumber , 0 , JSPROP_READONLY | JSPROP_PERMANENT, 0 } ,
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
JSClass minkey_class = {
|
||||
"MinKey" , JSCLASS_HAS_PRIVATE ,
|
||||
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
|
||||
@ -748,6 +774,7 @@ namespace mongo {
|
||||
assert( JS_InitClass( cx , global , 0 , &bindata_class , bindata_constructor , 0 , 0 , bindata_functions , 0 , 0 ) );
|
||||
|
||||
assert( JS_InitClass( cx , global , 0 , ×tamp_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
|
||||
assert( JS_InitClass( cx , global , 0 , &numberlong_class , 0 , 0 , 0 , numberlong_functions , 0 , 0 ) );
|
||||
assert( JS_InitClass( cx , global , 0 , &minkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
|
||||
assert( JS_InitClass( cx , global , 0 , &maxkey_class , 0 , 0 , 0 , 0 , 0 , 0 ) );
|
||||
|
||||
@ -783,6 +810,11 @@ namespace mongo {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( JS_InstanceOf( c->_context , o , &numberlong_class , 0 ) ){
|
||||
b.append( name.c_str() , c->toNumberLongUnsafe( o ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( JS_InstanceOf( c->_context , o , &dbpointer_class , 0 ) ){
|
||||
b.appendDBRef( name.c_str() , c->getString( o , "ns" ).c_str() , c->toOID( c->getProperty( o , "id" ) ) );
|
||||
return true;
|
||||
|
@ -49,6 +49,17 @@ namespace mongo {
|
||||
return mongo;
|
||||
}
|
||||
|
||||
v8::Handle<v8::FunctionTemplate> getNumberLongFunctionTemplate() {
|
||||
v8::Local<v8::FunctionTemplate> numberLong = FunctionTemplate::New( numberLongInit );
|
||||
v8::Local<v8::Template> proto = numberLong->PrototypeTemplate();
|
||||
|
||||
proto->Set( v8::String::New( "toString" ) , FunctionTemplate::New( numberLongToString ) );
|
||||
proto->Set( v8::String::New( "toNumber" ) , FunctionTemplate::New( numberLongToNumber ) );
|
||||
|
||||
return numberLong;
|
||||
}
|
||||
|
||||
|
||||
void installDBTypes( Handle<ObjectTemplate>& global ){
|
||||
v8::Local<v8::FunctionTemplate> db = FunctionTemplate::New( dbInit );
|
||||
db->InstanceTemplate()->SetNamedPropertyHandler( collectionFallback );
|
||||
@ -71,6 +82,8 @@ namespace mongo {
|
||||
|
||||
global->Set( v8::String::New("BinData") , FunctionTemplate::New( binDataInit ) );
|
||||
|
||||
global->Set( v8::String::New("NumberLong") , getNumberLongFunctionTemplate() );
|
||||
|
||||
}
|
||||
|
||||
void installDBTypes( Handle<v8::Object>& global ){
|
||||
@ -95,6 +108,8 @@ namespace mongo {
|
||||
|
||||
global->Set( v8::String::New("BinData") , FunctionTemplate::New( binDataInit )->GetFunction() );
|
||||
|
||||
global->Set( v8::String::New("NumberLong") , getNumberLongFunctionTemplate()->GetFunction() );
|
||||
|
||||
BSONObjBuilder b;
|
||||
b.appendMaxKey( "" );
|
||||
b.appendMinKey( "" );
|
||||
@ -531,6 +546,59 @@ namespace mongo {
|
||||
return it;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> numberLongInit( const v8::Arguments& args ) {
|
||||
|
||||
if (args.Length() != 2) {
|
||||
return v8::ThrowException( v8::String::New( "NumberLong needs 2 arguments" ) );
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> it = args.This();
|
||||
|
||||
if ( it->IsUndefined() || it == v8::Context::GetCurrent()->Global() ){
|
||||
v8::Function* f = getNamedCons( "NumberLong" );
|
||||
it = f->NewInstance();
|
||||
}
|
||||
|
||||
it->Set( v8::String::New( "top" ) , args[0] );
|
||||
it->Set( v8::String::New( "bottom" ) , args[1] );
|
||||
it->SetHiddenValue( v8::String::New( "__NumberLong" ), v8::Number::New( 1 ) );
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> numberLongToString( const v8::Arguments& args ) {
|
||||
|
||||
if (args.Length() != 0) {
|
||||
return v8::ThrowException( v8::String::New( "toString needs 0 arguments" ) );
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> it = args.This();
|
||||
|
||||
unsigned long long val =
|
||||
( (unsigned long long)( it->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
|
||||
(unsigned)( it->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
|
||||
|
||||
stringstream ss;
|
||||
ss << (long long)val;
|
||||
string ret = ss.str();
|
||||
return v8::String::New( ret.c_str() );
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> numberLongToNumber( const v8::Arguments& args ) {
|
||||
|
||||
if (args.Length() != 0) {
|
||||
return v8::ThrowException( v8::String::New( "toNumber needs 0 arguments" ) );
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> it = args.This();
|
||||
|
||||
unsigned long long val =
|
||||
( (unsigned long long)( it->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
|
||||
(unsigned)( it->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
|
||||
|
||||
return v8::Number::New( double( (long long)val ) );
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> bsonsize( const v8::Arguments& args ) {
|
||||
|
||||
if (args.Length() != 1 || !args[ 0 ]->IsObject()) {
|
||||
|
@ -60,6 +60,9 @@ namespace mongo {
|
||||
v8::Handle<v8::Value> dbPointerInit( const v8::Arguments& args );
|
||||
|
||||
v8::Handle<v8::Value> binDataInit( const v8::Arguments& args );
|
||||
v8::Handle<v8::Value> numberLongInit( const v8::Arguments& args );
|
||||
v8::Handle<v8::Value> numberLongToString(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> numberLongToNumber(const v8::Arguments& args);
|
||||
|
||||
v8::Handle<v8::Value> dbQueryInit( const v8::Arguments& args );
|
||||
v8::Handle<v8::Value> dbQueryIndexAccess( uint32_t index , const v8::AccessorInfo& info );
|
||||
|
@ -149,7 +149,6 @@ namespace mongo {
|
||||
|
||||
case mongo::NumberDouble:
|
||||
case mongo::NumberInt:
|
||||
case mongo::NumberLong: // may lose information here - just copying sm engine behavior
|
||||
o->Set( v8::String::New( f.fieldName() ) , v8::Number::New( f.number() ) );
|
||||
break;
|
||||
|
||||
@ -208,6 +207,17 @@ namespace mongo {
|
||||
break;
|
||||
}
|
||||
|
||||
case mongo::NumberLong: {
|
||||
Local<v8::Object> sub = readOnly ? readOnlyObjects->NewInstance() : internalFieldObjects->NewInstance();
|
||||
unsigned long long val = f.numberLong();
|
||||
v8::Function* numberLong = getNamedCons( "NumberLong" );
|
||||
v8::Handle<v8::Value> argv[2];
|
||||
argv[0] = v8::Integer::New( val >> 32 );
|
||||
argv[1] = v8::Integer::New( (unsigned long)(val & 0x00000000ffffffff) );
|
||||
o->Set( v8::String::New( f.fieldName() ), numberLong->NewInstance(2, argv) );
|
||||
break;
|
||||
}
|
||||
|
||||
case mongo::MinKey: {
|
||||
Local<v8::Object> sub = readOnly ? readOnlyObjects->NewInstance() : internalFieldObjects->NewInstance();
|
||||
sub->Set( v8::String::New( "$MinKey" ), v8::Boolean::New( true ) );
|
||||
@ -325,6 +335,16 @@ namespace mongo {
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
case mongo::NumberLong: {
|
||||
Local<v8::Object> sub = internalFieldObjects->NewInstance();
|
||||
unsigned long long val = f.numberLong();
|
||||
v8::Function* numberLong = getNamedCons( "NumberLong" );
|
||||
v8::Handle<v8::Value> argv[2];
|
||||
argv[0] = v8::Integer::New( val >> 32 );
|
||||
argv[1] = v8::Integer::New( (unsigned long)(val & 0x00000000ffffffff) );
|
||||
return numberLong->NewInstance( 2, argv );
|
||||
}
|
||||
|
||||
case mongo::MinKey: {
|
||||
Local<v8::Object> sub = internalFieldObjects->NewInstance();
|
||||
@ -431,10 +451,16 @@ namespace mongo {
|
||||
oid.init( toSTLString( value ) );
|
||||
b.appendOID( sname.c_str() , &oid );
|
||||
}
|
||||
else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__DBPointer" ) ).IsEmpty() ) {
|
||||
else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__NumberLong" ) ).IsEmpty() ) {
|
||||
// TODO might be nice to potentially speed this up with an indexed internal
|
||||
// field, but I don't yet know how to use an ObjectTemplate with a
|
||||
// constructor.
|
||||
unsigned long long val =
|
||||
( (unsigned long long)( value->ToObject()->Get( v8::String::New( "top" ) )->ToInt32()->Value() ) << 32 ) +
|
||||
(unsigned)( value->ToObject()->Get( v8::String::New( "bottom" ) )->ToInt32()->Value() );
|
||||
b.append( sname.c_str(), (long long)val );
|
||||
}
|
||||
else if ( !value->ToObject()->GetHiddenValue( v8::String::New( "__DBPointer" ) ).IsEmpty() ) {
|
||||
OID oid;
|
||||
oid.init( toSTLString( value->ToObject()->Get( v8::String::New( "id" ) ) ) );
|
||||
string ns = toSTLString( value->ToObject()->Get( v8::String::New( "ns" ) ) );
|
||||
|
@ -32,6 +32,6 @@
|
||||
|
||||
namespace mongo {
|
||||
|
||||
const char versionString[] = "1.3.1";
|
||||
const char versionString[] = "1.3.2-";
|
||||
|
||||
} // namespace mongo
|
||||
|
Loading…
Reference in New Issue
Block a user