Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddb73290a4 | ||
|
|
fe1743177a | ||
|
|
139e40b500 | ||
|
|
7d75e95bc0 | ||
|
|
716d31016d | ||
|
|
022affc651 | ||
|
|
0b48ec01cb | ||
|
|
52c1e65d6f | ||
|
|
0239789a5b | ||
|
|
e01102d1df | ||
|
|
036337a5c0 | ||
|
|
be1e22fea5 | ||
|
|
37f2062420 | ||
|
|
757fe510df | ||
|
|
9d5de58e4f | ||
|
|
6397087303 | ||
|
|
ccaf58fccf |
@@ -3,7 +3,7 @@
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = MongoDB
|
||||
PROJECT_NUMBER = 2.4.2
|
||||
PROJECT_NUMBER = 2.4.4-pre-
|
||||
OUTPUT_DIRECTORY = docs/doxygen
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
16
jstests/server9385.js
Normal file
16
jstests/server9385.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// SERVER-9385 ensure saving a document derived from bson->js conversion doesn't lose it's _id
|
||||
t = db.server9385;
|
||||
t.drop();
|
||||
|
||||
t.insert( { _id : 1, x : 1 } );
|
||||
x = t.findOne();
|
||||
x._id = 2;
|
||||
t.save( x );
|
||||
|
||||
t.find().forEach( printjson );
|
||||
|
||||
assert.eq( 2, t.find().count() );
|
||||
assert.eq( 2, t.find().itcount() );
|
||||
|
||||
assert( t.findOne( { _id : 1 } ), "original insert missing" );
|
||||
assert( t.findOne( { _id : 2 } ), "save didn't work?" );
|
||||
@@ -164,7 +164,7 @@ namespace mongo {
|
||||
|
||||
// create index so remove is fast even with a lot of servers
|
||||
if ( loops++ == 0 ) {
|
||||
conn->ensureIndex( LockpingsType::ConfigNS, BSON( LockpingsType::ping(1) ) );
|
||||
conn->ensureIndex( LockpingsType::ConfigNS, BSON( LockpingsType::ping() << 1 ) );
|
||||
}
|
||||
|
||||
LOG( DistributedLock::logLvl - ( loops % 10 == 0 ? 1 : 0 ) ) << "cluster " << addr << " pinged successfully at " << pingTime
|
||||
|
||||
@@ -762,7 +762,7 @@ namespace mongo {
|
||||
// source DB.
|
||||
ActionSet actions;
|
||||
actions.addAction(ActionType::copyDBTarget);
|
||||
out->push_back(Privilege(dbname, actions));
|
||||
out->push_back(Privilege(dbname, actions)); // NOTE: dbname is always admin
|
||||
}
|
||||
virtual void help( stringstream &help ) const {
|
||||
help << "copy a database from another host to this host\n";
|
||||
|
||||
@@ -187,32 +187,6 @@ namespace mongo {
|
||||
static int testCommandsEnabled;
|
||||
};
|
||||
|
||||
// This will be registered instead of the real implementations of any commands that don't work
|
||||
// when auth is enabled.
|
||||
class NotWithAuthCmd : public Command {
|
||||
public:
|
||||
NotWithAuthCmd(const char* cmdName) : Command(cmdName) { }
|
||||
virtual bool slaveOk() const { return true; }
|
||||
virtual LockType locktype() const { return NONE; }
|
||||
virtual bool requiresAuth() { return false; }
|
||||
virtual void addRequiredPrivileges(const std::string& dbname,
|
||||
const BSONObj& cmdObj,
|
||||
std::vector<Privilege>* out) {}
|
||||
virtual void help( stringstream &help ) const {
|
||||
help << name << " is not supported when running with authentication enabled";
|
||||
}
|
||||
virtual bool run(const string&,
|
||||
BSONObj& cmdObj,
|
||||
int,
|
||||
string& errmsg,
|
||||
BSONObjBuilder& result,
|
||||
bool fromRepl) {
|
||||
errmsg = name + " is not supported when running with authentication enabled";
|
||||
log() << errmsg << std::endl;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class CmdShutdown : public Command {
|
||||
public:
|
||||
virtual bool requiresAuth() { return true; }
|
||||
|
||||
@@ -80,8 +80,8 @@ namespace mongo {
|
||||
extern string repairpath;
|
||||
|
||||
static void setupSignalHandlers();
|
||||
static void startInterruptThread();
|
||||
void startReplication();
|
||||
static void startSignalProcessingThread();
|
||||
void exitCleanly( ExitCode code );
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -1280,9 +1280,9 @@ static int mongoDbMain(int argc, char* argv[], char **envp) {
|
||||
if (!initializeServerGlobalState())
|
||||
::_exit(EXIT_FAILURE);
|
||||
|
||||
// Per SERVER-7434, startInterruptThread() must run after any forks
|
||||
// Per SERVER-7434, startSignalProcessingThread() must run after any forks
|
||||
// (initializeServerGlobalState()) and before creation of any other threads.
|
||||
startInterruptThread();
|
||||
startSignalProcessingThread();
|
||||
|
||||
dataFileSync.go();
|
||||
|
||||
@@ -1350,15 +1350,27 @@ namespace mongo {
|
||||
}
|
||||
|
||||
sigset_t asyncSignals;
|
||||
// The above signals will be processed by this thread only, in order to
|
||||
// The signals in asyncSignals will be processed by this thread only, in order to
|
||||
// ensure the db and log mutexes aren't held.
|
||||
void interruptThread() {
|
||||
int actualSignal;
|
||||
sigwait( &asyncSignals, &actualSignal );
|
||||
log() << "got signal " << actualSignal << " (" << strsignal( actualSignal )
|
||||
<< "), will terminate after current cmd ends" << endl;
|
||||
Client::initThread( "interruptThread" );
|
||||
exitCleanly( EXIT_CLEAN );
|
||||
void signalProcessingThread() {
|
||||
while (true) {
|
||||
int actualSignal = 0;
|
||||
int status = sigwait( &asyncSignals, &actualSignal );
|
||||
fassert(16781, status == 0);
|
||||
switch (actualSignal) {
|
||||
case SIGUSR1:
|
||||
// log rotate signal
|
||||
fassert(16782, rotateLogs());
|
||||
break;
|
||||
default:
|
||||
// interrupt/terminate signal
|
||||
Client::initThread( "signalProcessingThread" );
|
||||
log() << "got signal " << actualSignal << " (" << strsignal( actualSignal )
|
||||
<< "), will terminate after current cmd ends" << endl;
|
||||
exitCleanly( EXIT_CLEAN );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this will be called in certain c++ error cases, for example if there are two active
|
||||
@@ -1399,19 +1411,20 @@ namespace mongo {
|
||||
setupSIGTRAPforGDB();
|
||||
|
||||
// asyncSignals is a global variable listing the signals that should be handled by the
|
||||
// interrupt thread, once it is started via startInterruptThread().
|
||||
// interrupt thread, once it is started via startSignalProcessingThread().
|
||||
sigemptyset( &asyncSignals );
|
||||
sigaddset( &asyncSignals, SIGHUP );
|
||||
sigaddset( &asyncSignals, SIGINT );
|
||||
sigaddset( &asyncSignals, SIGTERM );
|
||||
sigaddset( &asyncSignals, SIGUSR1 );
|
||||
|
||||
set_terminate( myterminate );
|
||||
set_new_handler( my_new_handler );
|
||||
}
|
||||
|
||||
void startInterruptThread() {
|
||||
void startSignalProcessingThread() {
|
||||
verify( pthread_sigmask( SIG_SETMASK, &asyncSignals, 0 ) == 0 );
|
||||
boost::thread it( interruptThread );
|
||||
boost::thread it( signalProcessingThread );
|
||||
}
|
||||
|
||||
#else // WIN32
|
||||
@@ -1486,7 +1499,7 @@ namespace mongo {
|
||||
_set_purecall_handler( myPurecallHandler );
|
||||
}
|
||||
|
||||
void startInterruptThread() {}
|
||||
void startSignalProcessingThread() {}
|
||||
|
||||
#endif // if !defined(_WIN32)
|
||||
|
||||
|
||||
@@ -230,8 +230,7 @@ namespace mongo {
|
||||
out->push_back(Privilege(AuthorizationManager::SERVER_RESOURCE_NAME, actions));
|
||||
}
|
||||
virtual bool run(const string& ns, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool fromRepl) {
|
||||
fassert(16175, rotateLogs());
|
||||
return 1;
|
||||
return rotateLogs();
|
||||
}
|
||||
|
||||
} logRotateCmd;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace mongo {
|
||||
bool inNegation = false;
|
||||
bool inPhrase = false;
|
||||
|
||||
str::stream phrase;
|
||||
unsigned quoteOffset = 0;
|
||||
|
||||
Tokenizer i( _language, query );
|
||||
while ( i.more() ) {
|
||||
@@ -48,12 +48,6 @@ namespace mongo {
|
||||
if ( t.type == Token::TEXT ) {
|
||||
string s = t.data.toString();
|
||||
|
||||
if ( inPhrase ) {
|
||||
if ( phrase.ss.len() > 0 )
|
||||
phrase << ' ';
|
||||
phrase << s;
|
||||
}
|
||||
|
||||
if ( inPhrase && inNegation ) {
|
||||
// don't add term
|
||||
}
|
||||
@@ -73,6 +67,10 @@ namespace mongo {
|
||||
else if ( c == '"' ) {
|
||||
if ( inPhrase ) {
|
||||
// end of a phrase
|
||||
unsigned phraseStart = quoteOffset + 1;
|
||||
unsigned phraseLength = t.offset - phraseStart;
|
||||
StringData phrase = StringData( query ).substr( phraseStart,
|
||||
phraseLength );
|
||||
if ( inNegation )
|
||||
_negatedPhrases.push_back( tolowerString( phrase ) );
|
||||
else
|
||||
@@ -83,7 +81,7 @@ namespace mongo {
|
||||
else {
|
||||
// start of a phrase
|
||||
inPhrase = true;
|
||||
phrase.ss.reset();
|
||||
quoteOffset = t.offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,13 @@ namespace mongo {
|
||||
ASSERT_EQUALS( "fun|phrase|test||||phrase test||", q.debugString() );
|
||||
}
|
||||
|
||||
TEST( FTSQuery, Phrase2 ) {
|
||||
FTSQuery q;
|
||||
ASSERT( q.parse( "doing a \"phrase-test\" for fun", "english" ).isOK() );
|
||||
ASSERT_EQUALS( 1U, q.getPhr().size() );
|
||||
ASSERT_EQUALS( "phrase-test", q.getPhr()[0] );
|
||||
}
|
||||
|
||||
TEST( FTSQuery, NegPhrase1 ) {
|
||||
FTSQuery q;
|
||||
ASSERT( q.parse( "doing a -\"phrase test\" for fun", "english" ).isOK() );
|
||||
|
||||
@@ -193,14 +193,10 @@ namespace mongo {
|
||||
|
||||
static void ignoreSignal( int sig ) {}
|
||||
|
||||
static void rotateLogsOrDie(int sig) {
|
||||
fassert(16176, rotateLogs());
|
||||
}
|
||||
|
||||
void setupCoreSignals() {
|
||||
#if !defined(_WIN32)
|
||||
verify( signal(SIGUSR1 , rotateLogsOrDie ) != SIG_ERR );
|
||||
verify( signal(SIGHUP , ignoreSignal ) != SIG_ERR );
|
||||
verify( signal(SIGUSR2, ignoreSignal ) != SIG_ERR );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -857,6 +857,9 @@ namespace replset {
|
||||
}
|
||||
|
||||
try {
|
||||
// haveCursor() does not necessarily tell us if we have a non-dead cursor, so we check
|
||||
// tailCheck() as well; see SERVER-8420
|
||||
slave->reader.tailCheck();
|
||||
if (!slave->reader.haveCursor()) {
|
||||
if (!slave->reader.connect(id, slave->slave->id(), target->fullName())) {
|
||||
// error message logged in OplogReader::connect
|
||||
|
||||
@@ -522,12 +522,18 @@ namespace mongo {
|
||||
class CopyDBCmd : public PublicGridCommand {
|
||||
public:
|
||||
CopyDBCmd() : PublicGridCommand( "copydb" ) {}
|
||||
virtual bool adminOnly() const {
|
||||
return true;
|
||||
}
|
||||
virtual void addRequiredPrivileges(const std::string& dbname,
|
||||
const BSONObj& cmdObj,
|
||||
std::vector<Privilege>* out) {
|
||||
// Should never get here because this command shouldn't get registered when auth is
|
||||
// enabled
|
||||
verify(0);
|
||||
// Note: privileges required are currently only granted to old-style users for
|
||||
// backwards compatibility, since we can't properly handle auth checking for the
|
||||
// read from the source DB.
|
||||
ActionSet actions;
|
||||
actions.addAction(ActionType::copyDBTarget);
|
||||
out->push_back(Privilege(dbname, actions)); // NOTE: dbname is always admin
|
||||
}
|
||||
bool run(const string& dbName, BSONObj& cmdObj, int, string& errmsg, BSONObjBuilder& result, bool) {
|
||||
string todb = cmdObj.getStringField("todb");
|
||||
@@ -562,12 +568,9 @@ namespace mongo {
|
||||
}
|
||||
};
|
||||
MONGO_INITIALIZER(RegisterCopyDBCommand)(InitializerContext* context) {
|
||||
if (noauth) {
|
||||
// Leaked intentionally: a Command registers itself when constructed.
|
||||
new CopyDBCmd();
|
||||
} else {
|
||||
new NotWithAuthCmd("copydb");
|
||||
}
|
||||
// Leaked intentionally: a Command registers itself when constructed.
|
||||
// NOTE: this initializer block cannot be removed due to SERVER-9167
|
||||
new CopyDBCmd();
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,33 @@ namespace mongo {
|
||||
::_exit(EXIT_ABRUPT);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
sigset_t asyncSignals;
|
||||
|
||||
void signalProcessingThread() {
|
||||
while (true) {
|
||||
int actualSignal = 0;
|
||||
int status = sigwait( &asyncSignals, &actualSignal );
|
||||
fassert(16779, status == 0);
|
||||
switch (actualSignal) {
|
||||
case SIGUSR1:
|
||||
// log rotate signal
|
||||
fassert(16780, rotateLogs());
|
||||
break;
|
||||
default:
|
||||
// no one else should be here
|
||||
fassertFailed(16778);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void startSignalProcessingThread() {
|
||||
verify( pthread_sigmask( SIG_SETMASK, &asyncSignals, 0 ) == 0 );
|
||||
boost::thread it( signalProcessingThread );
|
||||
}
|
||||
#endif // not _WIN32
|
||||
|
||||
void setupSignalHandlers() {
|
||||
setupSIGTRAPforGDB();
|
||||
setupCoreSignals();
|
||||
@@ -183,6 +210,12 @@ namespace mongo {
|
||||
signal( SIGPIPE , SIG_IGN );
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
sigemptyset( &asyncSignals );
|
||||
sigaddset( &asyncSignals, SIGUSR1 );
|
||||
startSignalProcessingThread();
|
||||
#endif
|
||||
|
||||
setWindowsUnhandledExceptionFilter();
|
||||
set_new_handler( my_new_handler );
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ namespace mongo {
|
||||
|
||||
string key = toSTLString(name);
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (holder->_removed.count(key))
|
||||
if (!holder || holder->_removed.count(key))
|
||||
return handle_scope.Close(v8::Handle<v8::Value>());
|
||||
|
||||
BSONObj obj = holder->_obj;
|
||||
@@ -100,7 +100,7 @@ namespace mongo {
|
||||
if (elmt.type() == mongo::Object || elmt.type() == mongo::Array) {
|
||||
// if accessing a subobject, it may get modified and base obj would not know
|
||||
// have to set base as modified, which means some optim is lost
|
||||
unwrapHolder(info.Holder())->_modified = true;
|
||||
holder->_modified = true;
|
||||
}
|
||||
}
|
||||
catch (const DBException &dbEx) {
|
||||
@@ -143,6 +143,7 @@ namespace mongo {
|
||||
const v8::AccessorInfo& info) {
|
||||
string key = toSTLString(name);
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (!holder) return v8::Handle<v8::Value>();
|
||||
holder->_removed.erase(key);
|
||||
holder->_modified = true;
|
||||
|
||||
@@ -154,6 +155,7 @@ namespace mongo {
|
||||
static v8::Handle<v8::Array> namedEnumerator(const v8::AccessorInfo &info) {
|
||||
v8::HandleScope handle_scope;
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (!holder) return v8::Handle<v8::Array>();
|
||||
BSONObj obj = holder->_obj;
|
||||
v8::Handle<v8::Array> out = v8::Array::New();
|
||||
int outIndex = 0;
|
||||
@@ -191,6 +193,7 @@ namespace mongo {
|
||||
v8::HandleScope handle_scope;
|
||||
string key = toSTLString(name);
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (!holder) return v8::Handle<v8::Boolean>();
|
||||
holder->_removed.insert(key);
|
||||
holder->_modified = true;
|
||||
|
||||
@@ -213,6 +216,7 @@ namespace mongo {
|
||||
V8Scope* scope = (V8Scope*)(scp->Value());
|
||||
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (!holder) return v8::Handle<v8::Value>();
|
||||
if (holder->_removed.count(key))
|
||||
return handle_scope.Close(v8::Handle<v8::Value>());
|
||||
|
||||
@@ -226,7 +230,7 @@ namespace mongo {
|
||||
if (elmt.type() == mongo::Object || elmt.type() == mongo::Array) {
|
||||
// if accessing a subobject, it may get modified and base obj would not know
|
||||
// have to set base as modified, which means some optim is lost
|
||||
unwrapHolder(info.Holder())->_modified = true;
|
||||
holder->_modified = true;
|
||||
}
|
||||
}
|
||||
catch (const DBException &dbEx) {
|
||||
@@ -242,6 +246,7 @@ namespace mongo {
|
||||
v8::Handle<v8::Boolean> indexedDelete(uint32_t index, const v8::AccessorInfo& info) {
|
||||
string key = str::stream() << index;
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (!holder) return v8::Handle<v8::Boolean>();
|
||||
holder->_removed.insert(key);
|
||||
holder->_modified = true;
|
||||
|
||||
@@ -285,6 +290,7 @@ namespace mongo {
|
||||
const v8::AccessorInfo& info) {
|
||||
string key = str::stream() << index;
|
||||
BSONHolder* holder = unwrapHolder(info.Holder());
|
||||
if (!holder) return v8::Handle<v8::Value>();
|
||||
holder->_removed.erase(key);
|
||||
holder->_modified = true;
|
||||
|
||||
@@ -1648,15 +1654,18 @@ namespace mongo {
|
||||
if (o->Has(v8::String::New("_bson"))) {
|
||||
originalBSON = unwrapBSONObj(o);
|
||||
BSONHolder* holder = unwrapHolder(o);
|
||||
if (!holder->_modified) {
|
||||
if (holder && !holder->_modified) {
|
||||
// object was not modified, use bson as is
|
||||
return originalBSON;
|
||||
}
|
||||
}
|
||||
|
||||
BSONObjBuilder b;
|
||||
|
||||
// We special case the _id field in top-level objects and move it to the front.
|
||||
// This matches other drivers behavior and makes finding the _id field quicker in BSON.
|
||||
if (depth == 0) {
|
||||
if (o->HasRealNamedProperty(v8::String::New("_id"))) {
|
||||
if (o->HasOwnProperty(v8::String::New("_id"))) {
|
||||
v8ToMongoElement(b, "_id", o->Get(v8::String::New("_id")), 0, &originalBSON);
|
||||
}
|
||||
}
|
||||
@@ -1667,7 +1676,7 @@ namespace mongo {
|
||||
v8::Local<v8::Value> value = o->Get(name);
|
||||
const string sname = toSTLString(name);
|
||||
if (depth == 0 && sname == "_id")
|
||||
continue;
|
||||
continue; // already handled above
|
||||
|
||||
v8ToMongoElement(b, sname, value, depth + 1, &originalBSON);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ namespace mongo {
|
||||
|
||||
bool rotate() {
|
||||
if ( ! _enabled ) {
|
||||
cout << "LoggingManager not enabled" << endl;
|
||||
cout << "logRotate is not possible: loggingManager not enabled" << endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace mongo {
|
||||
ss << _path << "." << terseCurrentTime( false );
|
||||
string s = ss.str();
|
||||
if (0 != rename(_path.c_str(), s.c_str())) {
|
||||
error() << "Failed to rename '" << _path
|
||||
error() << "failed to rename '" << _path
|
||||
<< "' to '" << s
|
||||
<< "': " << errnoWithDescription() << endl;
|
||||
return false;
|
||||
@@ -187,7 +187,7 @@ namespace mongo {
|
||||
tmp = freopen(_path.c_str(), _append ? "a" : "w", stdout);
|
||||
#endif
|
||||
if ( !tmp ) {
|
||||
cerr << "can't open: " << _path.c_str() << " for log file" << endl;
|
||||
error() << "can't open: " << _path.c_str() << " for log file" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +150,15 @@ namespace mongo {
|
||||
// Note: this is for blocking sockets only.
|
||||
SSL_CTX_set_mode(_context, SSL_MODE_AUTO_RETRY);
|
||||
|
||||
// Set context within which session can be reused
|
||||
int status = SSL_CTX_set_session_id_context(
|
||||
_context,
|
||||
static_cast<unsigned char*>(static_cast<void*>(&_context)),
|
||||
sizeof(_context));
|
||||
if (!status) {
|
||||
uasserted(16768,"ssl initialization problem");
|
||||
}
|
||||
|
||||
SSLThreadInfo::init();
|
||||
SSLThreadInfo::get();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace mongo {
|
||||
|
||||
void joinStringDelim( const std::vector<std::string>& strs , std::string* res , char delim );
|
||||
|
||||
inline std::string tolowerString( const std::string& input ) {
|
||||
inline std::string tolowerString( StringData input ) {
|
||||
std::string::size_type sz = input.size();
|
||||
|
||||
boost::scoped_array<char> line(new char[sz+1]);
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace mongo {
|
||||
* 1.2.3-rc4-pre-
|
||||
* If you really need to do something else you'll need to fix _versionArray()
|
||||
*/
|
||||
const char versionString[] = "2.4.2";
|
||||
const char versionString[] = "2.4.4-pre-";
|
||||
|
||||
// See unit test for example outputs
|
||||
BSONArray toVersionArray(const char* version){
|
||||
|
||||
Reference in New Issue
Block a user