} */
class CmdReplSetHeartbeat : public Command {
public:
@@ -74,7 +78,7 @@ namespace mongo {
m->_health = 0.0;
if( m->_upSince ) {
m->_upSince = 0;
- log() << "replSet " << m->fullName() << " is now down" << endl;
+ log() << "replSet " << m->fullName() << " is now down" << rsLog;
}
}
@@ -94,7 +98,7 @@ namespace mongo {
m->_lastHeartbeat = time(0);
if( ok ) {
if( m->_upSince == 0 ) {
- log() << "replSet " << m->fullName() << " is now up" << endl;
+ log() << "replSet " << m->fullName() << " is now up" << rsLog;
m->_upSince = m->_lastHeartbeat;
}
m->_health = 1.0;
@@ -184,6 +188,14 @@ namespace mongo {
s << _table();
}
+ void fillRsLog(stringstream& s) {
+ s << "
\n";
+ vector v = _rsLog.get();
+ for( unsigned i = 0; i < v.size(); i++ )
+ s << v[i];
+ s << "
\n";
+ }
+
void ReplSet::summarizeStatus(BSONObjBuilder& b) const {
Member *m =_members.head();
vector v;
diff --git a/db/repl/replset.cpp b/db/repl/replset.cpp
index a1fd81af14f..a4d202317cc 100644
--- a/db/repl/replset.cpp
+++ b/db/repl/replset.cpp
@@ -25,6 +25,7 @@ namespace mongo {
ReplSet *theReplSet = 0;
void ReplSet::fillIsMaster(BSONObjBuilder& b) {
+ log() << "hellO" << rsLog;
b.append("ismaster", 0);
b.append("ok", false);
b.append("msg", "not yet implemented");
@@ -44,7 +45,7 @@ namespace mongo {
const char *slash = strchr(p, '/');
uassert(13093, "bad --replSet config string format is: /,[,...]", slash != 0 && p != slash);
_name = string(p, slash-p);
- log() << "replSet " << cfgString << endl;
+ log() << "replSet " << cfgString << rsLog;
set temp;
vector *seeds = new vector;
@@ -65,7 +66,7 @@ namespace mongo {
temp.insert(m);
uassert(13101, "can't use localhost in replset host list", !m.isLocalHost());
if( m.isSelf() )
- log() << "replSet ignoring seed " << m.toString() << " (=self)" << endl;
+ log() << "replSet ignoring seed " << m.toString() << " (=self)" << rsLog;
else
seeds->push_back(m);
if( *comma == 0 )
@@ -146,13 +147,13 @@ namespace mongo {
startupStatusMsg = "can't get admin.system.replset config from self or any seed (uninitialized?)";
log() << "replSet can't get admin.system.replset config from self or any seed (EMPTYCONFIG)\n";
log() << "replSet have you ran replSetInitiate yet?\n";
- log() << "replSet sleeping 1 minute and will try again." << endl;
+ log() << "replSet sleeping 1 minute and will try again." << rsLog;
}
else {
startupStatus = EMPTYUNREACHABLE;
startupStatusMsg = "can't currently get admin.system.replset config from self or any seed (EMPTYUNREACHABLE)";
log() << "replSet can't get admin.system.replset config from self or any seed.\n";
- log() << "replSet sleeping 1 minute and will try again." << endl;
+ log() << "replSet sleeping 1 minute and will try again." << rsLog;
}
sleepsecs(60);
@@ -164,7 +165,7 @@ namespace mongo {
startupStatus = BADCONFIG;
startupStatusMsg = "replSet error loading set config (BADCONFIG)";
log() << "replSet error loading configurations\n";
- log() << "replSet replication will not start" << endl;
+ log() << "replSet replication will not start" << rsLog;
fatal();
throw;
}
@@ -186,7 +187,7 @@ namespace mongo {
(theReplSet = new ReplSet(cmdLine.replSet))->go();
}
catch(std::exception& e) {
- log() << "replSet Caught exception in management thread: " << e.what() << endl;
+ log() << "replSet Caught exception in management thread: " << e.what() << rsLog;
if( theReplSet )
theReplSet->fatal();
}
diff --git a/db/repl/replset.h b/db/repl/replset.h
index 1b1f0972e40..d119ab1e950 100644
--- a/db/repl/replset.h
+++ b/db/repl/replset.h
@@ -28,6 +28,8 @@ namespace mongo {
extern bool replSet; // true if using repl sets
extern class ReplSet *theReplSet; // null until initialized
+ extern Tee *rsLog;
+
/* information about the entire repl set, such as the various servers in the set, and their state */
/* note: We currently do not free mem when the set goes away - it is assumed the replset is a
singleton and long lived.
@@ -142,7 +144,7 @@ namespace mongo {
friend class FeedbackThread;
public:
- void fatal() { _myState = FATAL; log() << "replSet fatal error, stopping replication" << endl; }
+ void fatal() { _myState = FATAL; log() << "replSet fatal error, stopping replication" << rsLog; }
};
diff --git a/db/repl/replset_commands.cpp b/db/repl/replset_commands.cpp
index 034cb42e221..a0c653df525 100644
--- a/db/repl/replset_commands.cpp
+++ b/db/repl/replset_commands.cpp
@@ -63,7 +63,7 @@ namespace mongo {
ReplSetConfig newConfig(cmdObj["replSetInitiate"].Obj());
- log() << newConfig.toString() << endl;
+ log() << newConfig.toString() << rsLog;
newConfig.save();
diff --git a/db/repl/rs_config.cpp b/db/repl/rs_config.cpp
index 2a598118c36..9e2faf7a69b 100644
--- a/db/repl/rs_config.cpp
+++ b/db/repl/rs_config.cpp
@@ -138,13 +138,13 @@ namespace mongo {
m.check();
}
catch( const char * p ) {
- log() << "replSet cfg parsing exception for members[" << i << "] " << p << endl;
+ log() << "replSet cfg parsing exception for members[" << i << "] " << p << rsLog;
stringstream ss;
ss << "replSet members[" << i << "] " << p;
uassert(13107, ss.str(), false);
}
catch(DBException& e) {
- log() << "replSet cfg parsing exception for members[" << i << "] " << e.what() << endl;
+ log() << "replSet cfg parsing exception for members[" << i << "] " << e.what() << rsLog;
stringstream ss;
ss << "replSet members[" << i << "] bad config object";
uassert(13135, ss.str(), false);
@@ -173,7 +173,7 @@ namespace mongo {
clear();
int level = 2;
DEV level = 0;
- log(0) << "replSet load config from: " << h.toString() << endl;
+ log(0) << "replSet load config from: " << h.toString() << rsLog;
auto_ptr c;
try {
@@ -207,7 +207,7 @@ namespace mongo {
version = -1;
}
catch( UserException& e) {
- log(level) << "replSet couldn't load config " << h.toString() << ' ' << e.what() << endl;
+ log(level) << "replSet couldn't load config " << h.toString() << ' ' << e.what() << rsLog;
return;
}
@@ -215,7 +215,7 @@ namespace mongo {
uassert(13109, "multiple rows in local.system.replset not supported", !c->more());
from(o);
_ok = true;
- log(level) << "replSet load ok" << endl;
+ log(level) << "replSet load ok" << rsLog;
}
}
diff --git a/util/log.h b/util/log.h
index c50e4bacc93..e2965e80aa4 100644
--- a/util/log.h
+++ b/util/log.h
@@ -41,8 +41,16 @@ namespace mongo {
const T& t_;
};
+ class Tee {
+ public:
+ virtual void write(const string& str) = 0;
+ };
+
class Nullstream {
public:
+ virtual Nullstream& operator<< (Tee* tee) {
+ return *this;
+ }
virtual ~Nullstream() {}
virtual Nullstream& operator<<(const char *) {
return *this;
@@ -111,15 +119,10 @@ namespace mongo {
virtual Nullstream& operator<< (ios_base& (*hex)(ios_base&)) {
return *this;
}
- virtual void flush(){}
+ virtual void flush(Tee *t = 0) {}
};
extern Nullstream nullstream;
- class Tee {
- public:
- virtual void write(const string& str) = 0;
- };
-
class Logstream : public Nullstream {
static mongo::mutex mutex;
static int doneSetup;
@@ -160,9 +163,9 @@ namespace mongo {
ss << x.val();
return *this;
}
- Logstream& operator<< (Tee& tee) {
+ Nullstream& operator<< (Tee* tee) {
ss << '\n';
- flush(&tee);
+ flush(tee);
return *this;
}
Logstream& operator<< (ostream& ( *_endl )(ostream&)) {
diff --git a/util/mongoutils/README b/util/mongoutils/README
new file mode 100755
index 00000000000..d3d874bfb12
--- /dev/null
+++ b/util/mongoutils/README
@@ -0,0 +1,7 @@
+mongoutils namespace requirements:
+
+(1) code is not database specific, rather, true utilities
+(2) are cross platform
+(3) may require boost headers, but not libs
+(4) are clean and easy to use in any c++ project without pulling in lots of other stuff
+(5) apache license
diff --git a/util/web/html.h b/util/mongoutils/html.h
similarity index 82%
rename from util/web/html.h
rename to util/mongoutils/html.h
index 2e9cd0597fe..e4e95e76875 100644
--- a/util/web/html.h
+++ b/util/mongoutils/html.h
@@ -9,6 +9,21 @@
(4) are clean and easy to use in any c++ project without pulling in lots of other stuff
*/
+/* Copyright 2010 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
#include
namespace mongoutils {
diff --git a/util/ramlog.h b/util/ramlog.h
new file mode 100644
index 00000000000..3f2a5ce76b4
--- /dev/null
+++ b/util/ramlog.h
@@ -0,0 +1,59 @@
+// log.h
+
+/* Copyright 2009 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "log.h"
+
+namespace mongo {
+
+ class RamLog : public Tee {
+ enum {
+ N = 128,
+ C = 256
+ };
+ char lines[N][C];
+ unsigned h, t;
+
+ public:
+ RamLog() {
+ h = 0; t = 1;
+ for( int i = 0; i < N; i++ )
+ lines[i][C-1] = 0;
+ }
+ virtual void write(const string& str) {
+ char *p = lines[t];
+ if( str.size() < C )
+ strcpy(p, str.c_str());
+ else
+ memcpy(p, str.c_str(), C-1);
+ t = (t+1) % N;
+ if( h == t )
+ h = (h+1) % N;
+ }
+ vector get() const {
+ vector v;
+ unsigned x = h;
+ while( x != t ) {
+ v.push_back(lines[x]);
+ x = (x+1) % N;
+ }
+ return v;
+ }
+ };
+
+}