summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/dbclient.cpp8
-rw-r--r--client/dbclient.h8
-rw-r--r--client/model.cpp29
-rw-r--r--client/model.h21
-rw-r--r--db/makefile3
-rw-r--r--dbgrid/dbgrid.vcproj16
-rw-r--r--dbgrid/dbgrid_commands.cpp74
-rw-r--r--dbgrid/gridconfig.cpp116
-rw-r--r--dbgrid/gridconfig.h65
-rw-r--r--dbgrid/griddb.cpp99
-rw-r--r--dbgrid/request.cpp17
-rw-r--r--grid/message.cpp23
-rw-r--r--util/sock.h11
13 files changed, 367 insertions, 123 deletions
diff --git a/client/dbclient.cpp b/client/dbclient.cpp
index 4182edc6fed..f0529e7ea1d 100644
--- a/client/dbclient.cpp
+++ b/client/dbclient.cpp
@@ -252,6 +252,14 @@ again:
/* --- class dbclientpaired --- */
+string DBClientPaired::toString() {
+ stringstream ss;
+ ss << "state: " << master << '\n';
+ ss << "left: " << left.toStringLong() << '\n';
+ ss << "right: " << right.toStringLong() << '\n';
+ return ss.str();
+}
+
DBClientPaired::DBClientPaired() :
left(true), right(true)
{
diff --git a/client/dbclient.h b/client/dbclient.h
index 2548c199c58..4fc5864ab36 100644
--- a/client/dbclient.h
+++ b/client/dbclient.h
@@ -135,6 +135,12 @@ class DBClientConnection : public DBClientCommands {
string serverAddress; // remember for reconnects
void checkConnection();
public:
+ string toStringLong() const {
+ stringstream ss;
+ ss << serverAddress;
+ if( failed ) ss << " failed";
+ return ss.str();
+ }
string toString() const { return serverAddress; }
MessagingPort& port() { return *p.get(); }
bool isFailed() const { return failed; }
@@ -208,6 +214,8 @@ public:
/* throws userassertion "no master found" */
virtual
BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
+
+ string toString();
};
diff --git a/client/model.cpp b/client/model.cpp
new file mode 100644
index 00000000000..45d13c3fbd0
--- /dev/null
+++ b/client/model.cpp
@@ -0,0 +1,29 @@
+// model.cpp
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+#include "model.h"
+
+bool Model::load(BSONObj& query) {
+ BSONObj b = conn()->findOne(getNS(), query);
+ if( b.isEmpty() )
+ return false;
+
+ unserialize(b);
+ return true;
+}
diff --git a/client/model.h b/client/model.h
index fc8a2bb8f22..942155a42b4 100644
--- a/client/model.h
+++ b/client/model.h
@@ -20,18 +20,35 @@
#include "dbclient.h"
+/* Model is a base class for defining objects which are serializable to the Mongo
+ database via the client driver.
+
+ *Definition*
+ Your serializable class should inherit from Model and implement the abstract methods
+ below.
+
+ *Loading*
+ To load, first construct an (empty) objet. Then call load(). Do not load an object
+ more than once.
+*/
+
class Model {
public:
Model() { }
virtual ~Model() { }
virtual const char * getNS() = 0;
+ virtual void serialize(BSONObjBuilder& to) = 0;
+ virtual void unserialize(BSONObj& from) = 0;
- /* define this as you see fit if you are using the default conn() implementation */
+ /* Define this as you see fit if you are using the default conn() implementation. */
static DBClientCommands *globalConn;
- /* you can override this if you need to do fancier connection management */
+ /* Override this if you need to do fancier connection management than simply using globalConn. */
virtual DBClientCommands* conn() {
return globalConn;
}
+
+ /* true if successful */
+ bool load(BSONObj& query);
};
diff --git a/db/makefile b/db/makefile
index 99bcf58d1d7..089e85f680a 100644
--- a/db/makefile
+++ b/db/makefile
@@ -1,6 +1,7 @@
# makefile for our db project
FLAGS= ${CFLAGS} -fPIC -ggdb -pthread -O3 -I .. -Isrc/p -I/src/p/db -L/usr/local/lib -L/usr/lib -rdynamic
+FLAGS= ${CFLAGS} -fPIC -ggdb -pthread -O0 -I .. -Isrc/p -I/src/p/db -L/usr/local/lib -L/usr/lib -rdynamic
LIB_DEPS = -lpcrecpp -lpcre
LIB_BOOST = -lboost_thread -lboost_filesystem
@@ -12,7 +13,7 @@ JVM_LIBS = -L/opt/java/lib/
OBJS=../stdafx.o ../util/sock.o ../grid/message.o ../util/mmap.o pdfile.o query.o jsobj.o introspect.o btree.o clientcursor.o ../util/util.o javajs.o tests.o json.o repl.o ../client/dbclient.o btreecursor.o cloner.o namespace.o commands.o matcher.o dbcommands.o dbeval.o
-DBGRID_OBJS=../stdafx.o json.o ../util/sock.o ../grid/message.o ../util/util.o jsobj.o ../client/dbclient.o ../dbgrid/dbgrid.o ../dbgrid/request.o ../dbgrid/connpool.o ../dbgrid/gridconfig.o commands.o
+DBGRID_OBJS=../stdafx.o json.o ../util/sock.o ../grid/message.o ../util/util.o jsobj.o ../client/dbclient.o ../dbgrid/dbgrid.o ../dbgrid/request.o ../dbgrid/connpool.o ../dbgrid/gridconfig.o commands.o ../dbgrid/dbgrid_commands.o ../dbgrid/griddb.o ../client/model.o
GPP = g++
diff --git a/dbgrid/dbgrid.vcproj b/dbgrid/dbgrid.vcproj
index e2428a8b19f..03948fd222d 100644
--- a/dbgrid/dbgrid.vcproj
+++ b/dbgrid/dbgrid.vcproj
@@ -183,10 +183,18 @@
>
</File>
<File
+ RelativePath=".\dbgrid_commands.cpp"
+ >
+ </File>
+ <File
RelativePath=".\gridconfig.cpp"
>
</File>
<File
+ RelativePath=".\griddb.cpp"
+ >
+ </File>
+ <File
RelativePath=".\request.cpp"
>
</File>
@@ -229,6 +237,10 @@
>
</File>
<File
+ RelativePath="..\client\model.h"
+ >
+ </File>
+ <File
RelativePath="..\stdafx.h"
>
</File>
@@ -279,6 +291,10 @@
>
</File>
<File
+ RelativePath="..\client\model.cpp"
+ >
+ </File>
+ <File
RelativePath="..\util\sock.cpp"
>
</File>
diff --git a/dbgrid/dbgrid_commands.cpp b/dbgrid/dbgrid_commands.cpp
new file mode 100644
index 00000000000..2a1e9b898c7
--- /dev/null
+++ b/dbgrid/dbgrid_commands.cpp
@@ -0,0 +1,74 @@
+// dbgrid/request.cpp
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* TODO
+ _ concurrency control.
+ _ connection pool
+ _ hostbyname_nonreentrant() problem
+ _ gridconfig object which gets config from the grid db.
+ connect to iad-sb-grid
+ _ limit() works right?
+ _ KillCursors
+
+ later
+ _ secondary indexes
+*/
+
+#include "stdafx.h"
+#include "../grid/message.h"
+#include "../db/dbmessage.h"
+#include "connpool.h"
+#include "../db/commands.h"
+#include "gridconfig.h"
+
+extern string ourHostname;
+
+namespace dbgrid_cmds {
+
+class NetStatCmd : public Command {
+public:
+ NetStatCmd() : Command("netstat") { }
+ bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result) {
+ result.append("griddb", gridDB.toString());
+ result.append("isdbgrid", 1);
+ return true;
+ }
+} netstat;
+
+class IsDbGridCmd : public Command {
+public:
+ IsDbGridCmd() : Command("isdbgrid") { }
+ bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result) {
+ result.append("isdbgrid", 1);
+ result.append("hostname", ourHostname);
+ return true;
+ }
+} isdbgrid;
+
+class CmdIsMaster : public Command {
+public:
+ CmdIsMaster() : Command("ismaster") { }
+
+ virtual bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result) {
+ result.append("ismaster", 0.0);
+ result.append("msg", "isdbgrid");
+ return true;
+ }
+} ismaster;
+
+}
diff --git a/dbgrid/gridconfig.cpp b/dbgrid/gridconfig.cpp
index 017946405b4..6f3a0cdeba3 100644
--- a/dbgrid/gridconfig.cpp
+++ b/dbgrid/gridconfig.cpp
@@ -23,110 +23,40 @@
#include "connpool.h"
#include "../db/pdfile.h"
#include "gridconfig.h"
+#include "../client/model.h"
-static boost::mutex loc_mutex;
-static boost::mutex griddb_mutex;
-GridDB gridDB;
-GridConfig gridConfig;
+/* --- Machine --- */
-GridDB::GridDB() { }
+map<string, Machine*> Machine::machines;
-void GridDB::init() {
- char buf[256];
- int ec = gethostname(buf, 127);
- if( ec || *buf == 0 ) {
- log() << "can't get this server's hostname errno:" << ec << endl;
- sleepsecs(5);
- exit(16);
- }
-
- const int DEBUG = 1;
- if( DEBUG ) {
- cout << "TEMPZ DEBUG mode on not for production" << endl;
- strcpy(buf, "iad-sb-n13.10gen.cc");
- }
-
- char *p = strchr(buf, '-');
- if( p )
- p = strchr(p+1, '-');
- if( !p ) {
- log() << "can't parse server's hostname, expect <acode>-<loc>-n<nodenum>, got: " << buf << endl;
- sleepsecs(5);
- exit(17);
- }
- p[1] = 0;
+/* --- GridConfig --- */
- stringstream sl, sr;
- sl << buf << "grid-l";
- sr << buf << "grid-r";
- string hostLeft = sl.str();
- string hostRight = sr.str();
- sl << ":" << Port;
- sr << ":" << Port;
- string left = sl.str();
- string right = sr.str();
+//static boost::mutex loc_mutex;
+Grid grid;
- if( DEBUG ) {
- left = "10.211.55.4:27017";
- right = "10.211.55.4:27018";
- }
- else
- /* this loop is not really necessary, we we print out if we can't connect
- but it gives much prettier error msg this way if the config is totally
- wrong so worthwhile.
- */
- while( 1 ) {
- if( hostbyname(hostLeft.c_str()).empty() ) {
- log() << "can't resolve DNS for " << hostLeft << ", sleeping and then trying again" << endl;
- sleepsecs(15);
- continue;
- }
- if( hostbyname(hostRight.c_str()).empty() ) {
- log() << "can't resolve DNS for " << hostRight << ", sleeping and then trying again" << endl;
- sleepsecs(15);
- continue;
+ClientConfig* GridConfig::getClientConfig(string client) {
+ ClientConfig*& cc = clients[client];
+ if( cc == 0 ) {
+ cc = new ClientConfig();
+ if( !cc->loadByName(client.c_str()) ) {
+ log() << "couldn't find client " << client << " in grid db" << endl;
+ // note here that cc->primary == 0.
}
- break;
}
-
- log() << "connecting to griddb " << left << ' ' << right << endl;
-
- bool ok = conn.connect(left.c_str(),right.c_str());
- if( !ok )
- log() << " griddb connect failure at startup (will retry)" << endl;
+ return cc;
}
-GridConfig::GridConfig() {
-}
+/* --- Grid --- */
-Machine* GridConfig::fetchOwner(string& client, const char *ns, BSONObj& objOrKey) {
- return 0;
-}
+Machine* Grid::owner(const char *ns, BSONObj& objOrKey) {
+ ClientConfig *cc = gc.getClientConfig( nsToClient(ns) );
+ if( cc == 0 )
+ return 0;
-/*threadsafe*/
-Machine* GridConfig::owner(const char *ns, BSONObj& objOrKey) {
- string client;
- {
- boostlock lk(loc_mutex);
- ObjLocs::iterator i = loc.find(ns);
- if( i != loc.end() ) {
- return i->second;
- }
- i = loc.find(client=nsToClient(ns));
- if( i != loc.end() ) {
- return i->second;
- }
+ if( !cc->partitioned ) {
+ return cc->primary;
}
- return fetchOwner(client, ns, objOrKey);
+ uassert("not implemented 100", false);
+ return 0;
}
-
-/*
-
-fetch client info
- -> specifies general homes
-fetch ns info
- -> defines ranges
-fetch range data
-
-*/
diff --git a/dbgrid/gridconfig.h b/dbgrid/gridconfig.h
index 9ed5244115c..d969c94d949 100644
--- a/dbgrid/gridconfig.h
+++ b/dbgrid/gridconfig.h
@@ -27,41 +27,84 @@
#include "../client/model.h"
class GridDB {
- DBClientPaired conn;
public:
+ DBClientPaired conn;
enum { Port = 27016 }; /* standard port # for a grid db */
GridDB();
void init();
+ string toString() { return conn.toString(); }
};
extern GridDB gridDB;
/* Machine is the concept of a host that runs the db process.
*/
class Machine {
+ static map<string, Machine*> machines;
+ string name;
public:
- enum { Port = 27018 /* default port # for dbs that are downstream of a dbgrid */
+ string getName() const { return name; }
+
+ Machine(string _name) : name(_name) { }
+
+ enum {
+ Port = 27018 /* default port # for dbs that are downstream of a dbgrid */
};
+
+ static Machine* get(string name) {
+ map<string,Machine*>::iterator i = machines.find(name);
+ if( i != machines.end() )
+ return i->second;
+ return machines[name] = new Machine(name);
+ }
};
-typedef map<string,Machine*> ObjLocs;
+//typedef map<string,Machine*> ObjLocs;
/* top level grid configuration */
class ClientConfig : public Model {
+public:
+ string name; // e.g. "alleyinsider"
+ Machine *primary;
+ bool partitioned;
+
+ ClientConfig() : primary(0), partitioned(false) { }
+
+ virtual const char * getNS() { return "grid.db.client"; }
+ virtual void serialize(BSONObjBuilder& to) {
+ to.append("name", name);
+ to.appendBool("partitioned", partitioned);
+ if( primary )
+ to.append("primary", primary->getName());
+ }
+ virtual void unserialize(BSONObj& from) {
+ name = from.getStringField("name");
+ partitioned = from.getBoolField("partitioned");
+ string p = from.getStringField("primary");
+ if( !p.empty() )
+ primary = Machine::get(p);
+ }
+
+ bool loadByName(const char *nm) {
+ BSONObjBuilder b;
+ b.append("name", nm);
+ BSONObj q = b.done();
+ return load(q);
+ }
};
class GridConfig {
- ObjLocs loc;
+ map<string,ClientConfig*> clients;
+public:
+ ClientConfig* getClientConfig(string client);
+};
- Machine* fetchOwner(string& client, const char *ns, BSONObj& objOrKey);
+class Grid {
+ GridConfig gc;
public:
/* return which machine "owns" the object in question -- ie which partition
we should go to.
-
- threadsafe.
- */
+ */
Machine* owner(const char *ns, BSONObj& objOrKey);
-
- GridConfig();
};
-extern GridConfig gridConfig;
+extern Grid grid;
diff --git a/dbgrid/griddb.cpp b/dbgrid/griddb.cpp
new file mode 100644
index 00000000000..0cc915085a3
--- /dev/null
+++ b/dbgrid/griddb.cpp
@@ -0,0 +1,99 @@
+// griddb.cpp
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+#include "../grid/message.h"
+#include "../util/unittest.h"
+#include "database.h"
+#include "connpool.h"
+#include "../db/pdfile.h"
+#include "gridconfig.h"
+#include "../client/model.h"
+
+static boost::mutex griddb_mutex;
+GridDB gridDB;
+DBClientCommands *Model::globalConn = &gridDB.conn;
+string ourHostname;
+
+GridDB::GridDB() { }
+
+void GridDB::init() {
+ char buf[256];
+ int ec = gethostname(buf, 127);
+ if( ec || *buf == 0 ) {
+ log() << "can't get this server's hostname errno:" << ec << endl;
+ sleepsecs(5);
+ exit(16);
+ }
+ ourHostname = buf;
+
+ const int DEBUG = 1;
+ if( DEBUG ) {
+ cout << "TEMPZ DEBUG mode on not for production" << endl;
+ strcpy(buf, "iad-sb-n13.10gen.cc");
+ }
+
+ char *p = strchr(buf, '-');
+ if( p )
+ p = strchr(p+1, '-');
+ if( !p ) {
+ log() << "can't parse server's hostname, expect <acode>-<loc>-n<nodenum>, got: " << buf << endl;
+ sleepsecs(5);
+ exit(17);
+ }
+ p[1] = 0;
+
+ stringstream sl, sr;
+ sl << buf << "grid-l";
+ sr << buf << "grid-r";
+ string hostLeft = sl.str();
+ string hostRight = sr.str();
+ sl << ":" << Port;
+ sr << ":" << Port;
+ string left = sl.str();
+ string right = sr.str();
+
+ if( DEBUG ) {
+ left = "iad-sb-n7.10gen.cc";
+ right = "iad-sb-n7.10gen.cc";
+ }
+ else
+ /* this loop is not really necessary, we we print out if we can't connect
+ but it gives much prettier error msg this way if the config is totally
+ wrong so worthwhile.
+ */
+ while( 1 ) {
+ if( hostbyname(hostLeft.c_str()).empty() ) {
+ log() << "can't resolve DNS for " << hostLeft << ", sleeping and then trying again" << endl;
+ sleepsecs(15);
+ continue;
+ }
+ if( hostbyname(hostRight.c_str()).empty() ) {
+ log() << "can't resolve DNS for " << hostRight << ", sleeping and then trying again" << endl;
+ sleepsecs(15);
+ continue;
+ }
+ break;
+ }
+
+ log() << "connecting to griddb " << left << ' ' << right << "..." << endl;
+
+ bool ok = conn.connect(left.c_str(),right.c_str());
+ if( !ok )
+ log() << " griddb connect failure at startup (will retry)" << endl;
+}
diff --git a/dbgrid/request.cpp b/dbgrid/request.cpp
index 160e897d3db..ba380b5fbe7 100644
--- a/dbgrid/request.cpp
+++ b/dbgrid/request.cpp
@@ -55,26 +55,15 @@ void getMore(Message& m, MessagingPort& p) {
bool runCommandAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder);
-#include "../db/commands.h"
-
-class IsDbGridCmd : public Command {
-public:
- IsDbGridCmd() : Command("isdbgrid") { }
- bool run(const char *ns, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result) {
- result.append("isdbgrid", 1);
- return true;
- }
-} isdbgridcmd;
-
void queryOp(Message& m, MessagingPort& p) {
DbMessage d(m);
QueryMessage q(d);
- cout << "TEMPns: " << q.ns << endl;
-
if( q.ntoreturn == -1 && strstr(q.ns, ".$cmd") ) {
BSONObjBuilder builder;
- if( runCommandAgainstRegistered(q.ns, q.query, builder) ) {
+ cout << q.query.toString() << endl;
+ bool ok = runCommandAgainstRegistered(q.ns, q.query, builder);
+ if( ok ) {
BufBuilder b(32768);
b.skip(sizeof(QueryResult));
BSONObj x = builder.done();
diff --git a/grid/message.cpp b/grid/message.cpp
index 5733a4d8fb0..ac6e702d27e 100644
--- a/grid/message.cpp
+++ b/grid/message.cpp
@@ -23,6 +23,7 @@
#include "message.h"
#include <time.h>
#include "../util/goodies.h"
+#include <fcntl.h>
// if you want trace output:
#define mmm(x)
@@ -111,11 +112,29 @@ bool MessagingPort::connect(SockAddr& _far)
log() << "ERROR: connect(): invalid socket? " << errno << endl;
return false;
}
- if( ::connect(sock, (sockaddr *) &farEnd.sa, farEnd.addressSize) ) {
-// log() << "connect(): failed errno:" << errno << ' ' << farEnd.getPort() << endl;
+
+#if 0
+ long fl = fcntl(sock, F_GETFL, 0);
+ assert( fl >= 0 );
+ fl |= O_NONBLOCK;
+ fcntl(sock, F_SETFL, fl);
+
+ int res = ::connect(sock, (sockaddr *) &farEnd.sa, farEnd.addressSize);
+ if( res ) {
+ if( errno == EINPROGRESS )
+ //log() << "connect(): failed errno:" << errno << ' ' << farEnd.getPort() << endl;
closesocket(sock); sock = -1;
return false;
}
+
+#else
+ int res = ::connect(sock, (sockaddr *) &farEnd.sa, farEnd.addressSize);
+ if( res ) {
+ closesocket(sock); sock = -1;
+ return false;
+ }
+#endif
+
disableNagle(sock);
return true;
}
diff --git a/util/sock.h b/util/sock.h
index 9187fe84785..f2be1b0f636 100644
--- a/util/sock.h
+++ b/util/sock.h
@@ -71,6 +71,17 @@ inline void prebindOptions( int sock ){
#endif
+inline void setSockReceiveTimeout(int sock, int secs) {
+// todo - finish - works?
+ struct timeval tv;
+ tv.tv_sec = 0;//secs;
+ tv.tv_usec = 1000;
+ int rc = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv));
+ if( rc ) {
+ cout << "ERROR: setsockopt RCVTIMEO failed rc:" << rc << " errno:" << getLastError() << " secs:" << secs << " sock:" << sock << endl;
+ }
+}
+
// .empty() if err
string hostbyname(const char *hostname);