Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Replace tab indentation with spaces

  • Loading branch information...
commit b7cbd301124045fccab665f939a68d703e70629b 1 parent b53f593
@astaple astaple authored
Showing with 11,126 additions and 10,426 deletions.
  1. +7 −7 client/connpool.cpp
  2. +22 −20 client/connpool.h
  3. +160 −158 client/dbclient.cpp
  4. +129 −115 client/dbclient.h
  5. +5 −5 client/model.cpp
  6. +6 −6 client/model.h
  7. +647 −638 db/btree.cpp
  8. +195 −161 db/btree.h
  9. +157 −157 db/btreecursor.cpp
  10. +145 −143 db/clientcursor.cpp
  11. +49 −47 db/clientcursor.h
  12. +106 −100 db/cloner.cpp
  13. +21 −21 db/commands.cpp
  14. +14 −10 db/commands.h
  15. +139 −110 db/cursor.h
  16. +68 −66 db/database.h
  17. +284 −284 db/db.cpp
  18. +68 −65 db/db.h
  19. +308 −251 db/dbcommands.cpp
  20. +53 −51 db/dbeval.cpp
  21. +7 −7 db/dbhelpers.cpp
  22. +13 −11 db/dbhelpers.h
  23. +8 −8 db/dbinfo.cpp
  24. +15 −13 db/dbinfo.h
  25. +82 −76 db/dbmessage.h
  26. +36 −32 db/dbwebserver.cpp
  27. +363 −359 db/instance.cpp
  28. +37 −33 db/instance.h
  29. +21 −21 db/introspect.cpp
  30. +35 −23 db/introspect.h
  31. +459 −457 db/javajs.cpp
  32. +148 −121 db/javajs.h
  33. +6 −6 db/javatest.cpp
  34. +481 −456 db/jsobj.cpp
  35. +524 −469 db/jsobj.h
  36. +48 −41 db/json.cpp
  37. +3 −3 db/json.h
  38. +340 −334 db/matcher.cpp
  39. +63 −56 db/matcher.h
  40. +88 −88 db/minilex.h
  41. +274 −271 db/namespace.cpp
  42. +232 −218 db/namespace.h
  43. +762 −756 db/pdfile.cpp
  44. +251 −233 db/pdfile.h
  45. +624 −622 db/query.cpp
  46. +9 −9 db/query.h
  47. +7 −7 db/queryoptimizer.cpp
  48. +9 −9 db/queryoptimizer.h
  49. +597 −575 db/repl.cpp
  50. +110 −92 db/repl.h
  51. +36 −36 db/replset.h
  52. +4 −4 db/resource.h
  53. +93 −90 db/scanandorder.h
  54. +104 −71 db/storage.h
  55. +41 −38 db/tests.cpp
  56. +71 −71 dbgrid/dbgrid.cpp
  57. +17 −11 dbgrid/dbgrid_commands.cpp
  58. +9 −9 dbgrid/gridconfig.cpp
  59. +22 −18 dbgrid/gridconfig.h
  60. +31 −31 dbgrid/griddatabase.cpp
  61. +6 −4 dbgrid/griddatabase.h
  62. +60 −60 dbgrid/request.cpp
  63. +3 −3 dbgrid/shard.cpp
  64. +8 −6 dbgrid/shard.h
  65. +202 −180 dbtests/btreetests.cpp
  66. +43 −43 dbtests/dbtests.cpp
  67. +3 −3 dbtests/dbtests.h
  68. +88 −88 dbtests/jsobjtests.cpp
  69. +58 −52 dbtests/mockdbclient.h
  70. +356 −338 dbtests/namespacetests.cpp
  71. +283 −275 dbtests/pairingtests.cpp
  72. +179 −175 grid/message.cpp
  73. +106 −89 grid/message.h
  74. +18 −18 stdafx.cpp
  75. +89 −58 stdafx.h
  76. +3 −3 targetver.h
  77. +11 −11 util/background.cpp
  78. +20 −13 util/background.h
  79. +73 −48 util/builder.h
  80. +144 −121 util/goodies.h
  81. +90 −86 util/hashtab.h
  82. +84 −43 util/log.h
  83. +43 −43 util/lruishmap.h
  84. +36 −36 util/miniwebserver.cpp
  85. +6 −6 util/miniwebserver.h
  86. +112 −107 util/mmap.cpp
  87. +19 −17 util/mmap.h
  88. +134 −134 util/sock.cpp
  89. +127 −107 util/sock.h
  90. +18 −18 util/unittest.h
  91. +41 −41 util/util.cpp
View
14 client/connpool.cpp
@@ -3,16 +3,16 @@
/**
* 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/>.
*/
@@ -24,16 +24,16 @@
DBConnectionPool pool;
-DBClientConnection* DBConnectionPool::get(const string& host) {
+DBClientConnection* DBConnectionPool::get(const string& host) {
boostlock L(poolMutex);
PoolForHost *&p = pools[host];
- if( p == 0 )
+ if ( p == 0 )
p = new PoolForHost();
- if( p->pool.empty() ) {
+ if ( p->pool.empty() ) {
string errmsg;
DBClientConnection *c = new DBClientConnection();
- if( !c->connect(host.c_str(), errmsg) ) {
+ if ( !c->connect(host.c_str(), errmsg) ) {
delete c;
uassert("dbconnectionpool: connect failed", false);
return 0;
View
42 client/connpool.h
@@ -2,16 +2,16 @@
/**
* 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/>.
*/
@@ -21,18 +21,18 @@
#include <queue>
#include "dbclient.h"
-struct PoolForHost {
+struct PoolForHost {
queue<DBClientConnection*> pool;
};
-class DBConnectionPool {
+class DBConnectionPool {
boost::mutex poolMutex;
map<string,PoolForHost*> pools;
public:
/* generally, use ScopedDbConnection and do not call these directly */
DBClientConnection *get(const string& host);
- void release(const string& host, DBClientConnection *c) {
+ void release(const string& host, DBClientConnection *c) {
boostlock L(poolMutex);
pools[host]->pool.push(c);
}
@@ -43,29 +43,31 @@ extern DBConnectionPool pool;
/* Use to get a connection from the pool. On exceptions things
clean up nicely.
*/
-class ScopedDbConnection {
- const string host;
+class ScopedDbConnection {
+ const string host;
DBClientConnection *_conn;
public:
- DBClientConnection& conn() { return *_conn; }
+ DBClientConnection& conn() {
+ return *_conn;
+ }
/* throws UserAssertionAcception if can't connect */
- ScopedDbConnection(const string& _host) :
- host(_host), _conn( pool.get(_host) ) { }
+ ScopedDbConnection(const string& _host) :
+ host(_host), _conn( pool.get(_host) ) { }
- /* Force closure of the connection. You should call this if you leave it in
+ /* Force closure of the connection. You should call this if you leave it in
a bad state. Destructor will do this too, but it is verbose.
*/
- void kill() {
+ void kill() {
delete _conn;
_conn = 0;
}
- /* Call this when you are done with the ocnnection.
+ /* Call this when you are done with the ocnnection.
Why? See note in the destructor below.
*/
- void done() {
- if( _conn->isFailed() )
+ void done() {
+ if ( _conn->isFailed() )
kill();
else
pool.release(host, _conn);
@@ -73,10 +75,10 @@ class ScopedDbConnection {
}
~ScopedDbConnection() {
- if( _conn ) {
- /* you are supposed to call done(). if you did that, correctly, we
- only get here if an exception was thrown. in such a scenario, we can't
- be sure we fully read all expected data of a reply on the socket. so
+ if ( _conn ) {
+ /* you are supposed to call done(). if you did that, correctly, we
+ only get here if an exception was thrown. in such a scenario, we can't
+ be sure we fully read all expected data of a reply on the socket. so
we don't try to reuse the connection. The cout is just informational.
*/
cout << "~ScopedDBConnection: _conn != null\n";
View
318 client/dbclient.cpp
@@ -2,16 +2,16 @@
/**
* 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/>.
*/
@@ -36,58 +36,58 @@ BSONObj DBClientWithCommands::cmdIsMaster(bool& isMaster) {
/* --- dbclientconnection --- */
-BSONObj DBClientConnection::findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn, int queryOptions) {
- auto_ptr<DBClientCursor> c =
- this->query(ns, query, 1, 0, fieldsToReturn, queryOptions);
+BSONObj DBClientConnection::findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn, int queryOptions) {
+ auto_ptr<DBClientCursor> c =
+ this->query(ns, query, 1, 0, fieldsToReturn, queryOptions);
massert( "DBClientConnection::findOne: transport error", c.get() );
- if( !c->more() )
- return BSONObj();
+ if ( !c->more() )
+ return BSONObj();
- return c->next().copy();
+ return c->next().copy();
}
-bool DBClientConnection::connect(const char *_serverAddress, string& errmsg) {
+bool DBClientConnection::connect(const char *_serverAddress, string& errmsg) {
serverAddress = _serverAddress;
- int port = DBPort;
- string ip = hostbyname(_serverAddress);
- if( ip.empty() )
- ip = serverAddress;
-
- size_t idx = ip.find( ":" );
- if ( idx != string::npos ){
- //cout << "port string:" << ip.substr( idx ) << endl;
- port = atoi( ip.substr( idx + 1 ).c_str() );
- ip = ip.substr( 0 , idx );
- ip = hostbyname(ip.c_str());
-
- }
- if( ip.empty() )
- ip = serverAddress;
-
+ int port = DBPort;
+ string ip = hostbyname(_serverAddress);
+ if ( ip.empty() )
+ ip = serverAddress;
+
+ size_t idx = ip.find( ":" );
+ if ( idx != string::npos ) {
+ //cout << "port string:" << ip.substr( idx ) << endl;
+ port = atoi( ip.substr( idx + 1 ).c_str() );
+ ip = ip.substr( 0 , idx );
+ ip = hostbyname(ip.c_str());
+
+ }
+ if ( ip.empty() )
+ ip = serverAddress;
+
// we keep around SockAddr for connection life -- maybe MessagingPort
// requires that?
- server = auto_ptr<SockAddr>(new SockAddr(ip.c_str(), port));
+ server = auto_ptr<SockAddr>(new SockAddr(ip.c_str(), port));
p = auto_ptr<MessagingPort>(new MessagingPort());
- if( !p->connect(*server) ) {
- stringstream ss;
- ss << "couldn't connect to server " << serverAddress << " " << ip << ":" << port;
+ if ( !p->connect(*server) ) {
+ stringstream ss;
+ ss << "couldn't connect to server " << serverAddress << " " << ip << ":" << port;
errmsg = ss.str();
failed = true;
- return false;
- }
- return true;
+ return false;
+ }
+ return true;
}
-void DBClientConnection::checkConnection() {
- if( !failed )
+void DBClientConnection::checkConnection() {
+ if ( !failed )
return;
- if( lastReconnectTry && time(0)-lastReconnectTry < 2 )
+ if ( lastReconnectTry && time(0)-lastReconnectTry < 2 )
return;
- if( !autoReconnect )
+ if ( !autoReconnect )
return;
lastReconnectTry = time(0);
@@ -95,131 +95,131 @@ void DBClientConnection::checkConnection() {
string errmsg;
string tmp = serverAddress;
failed = false;
- if( !connect(tmp.c_str(), errmsg) )
+ if ( !connect(tmp.c_str(), errmsg) )
log() << "reconnect " << serverAddress << " failed " << errmsg << endl;
else
log() << "reconnect " << serverAddress << " ok" << endl;
}
auto_ptr<DBClientCursor> DBClientConnection::query(const char *ns, BSONObj query, int nToReturn,
- int nToSkip, BSONObj *fieldsToReturn, int queryOptions) {
+ int nToSkip, BSONObj *fieldsToReturn, int queryOptions) {
checkConnection();
- auto_ptr<DBClientCursor> c( new DBClientCursor( new CursorConnector( this ),
- ns, query, nToReturn, nToSkip,
- fieldsToReturn, queryOptions ) );
- if( c->init() )
- return c;
- return auto_ptr< DBClientCursor >( 0 );
+ auto_ptr<DBClientCursor> c( new DBClientCursor( new CursorConnector( this ),
+ ns, query, nToReturn, nToSkip,
+ fieldsToReturn, queryOptions ) );
+ if ( c->init() )
+ return c;
+ return auto_ptr< DBClientCursor >( 0 );
}
/* -- DBClientCursor ---------------------------------------------- */
void assembleRequest( const string &ns, BSONObj query, int nToReturn, int nToSkip, BSONObj *fieldsToReturn, int queryOptions, Message &toSend ) {
- // see query.h for the protocol we are using here.
- BufBuilder b;
+ // see query.h for the protocol we are using here.
+ BufBuilder b;
int opts = queryOptions;
assert( (opts&Option_ALLMASK) == opts );
b.append(opts);
- b.append(ns.c_str());
- b.append(nToSkip);
- b.append(nToReturn);
- query.appendSelfToBufBuilder(b);
- if( fieldsToReturn )
- fieldsToReturn->appendSelfToBufBuilder(b);
- toSend.setData(dbQuery, b.buf(), b.len());
+ b.append(ns.c_str());
+ b.append(nToSkip);
+ b.append(nToReturn);
+ query.appendSelfToBufBuilder(b);
+ if ( fieldsToReturn )
+ fieldsToReturn->appendSelfToBufBuilder(b);
+ toSend.setData(dbQuery, b.buf(), b.len());
}
bool DBClientConnection::CursorConnector::send( Message &toSend, Message &response, bool assertOk ) {
- if( !conn->port().call(toSend, response) ) {
+ if ( !conn->port().call(toSend, response) ) {
conn->failed = true;
- if( assertOk )
- massert("dbclient error communicating with server", false);
- return false;
+ if ( assertOk )
+ massert("dbclient error communicating with server", false);
+ return false;
}
- return true;
+ return true;
}
void DBClientConnection::CursorConnector::checkResponse( const char *data, int nReturned ) {
- /* check for errors. the only one we really care about at
- this stage is "not master" */
- if( conn->clientPaired && nReturned ) {
+ /* check for errors. the only one we really care about at
+ this stage is "not master" */
+ if ( conn->clientPaired && nReturned ) {
BSONObj o(data);
BSONElement e = o.firstElement();
- if( strcmp(e.fieldName(), "$err") == 0 &&
- e.type() == String && strncmp(e.valuestr(), "not master", 10) == 0 ) {
- conn->clientPaired->isntMaster();
+ if ( strcmp(e.fieldName(), "$err") == 0 &&
+ e.type() == String && strncmp(e.valuestr(), "not master", 10) == 0 ) {
+ conn->clientPaired->isntMaster();
}
}
}
bool DBClientCursor::init() {
- Message toSend;
- assembleRequest( ns, query, nToReturn, nToSkip, fieldsToReturn, opts, toSend );
- if( !connector->send( toSend, *m, false ) )
- return false;
-
- dataReceived();
- return true;
+ Message toSend;
+ assembleRequest( ns, query, nToReturn, nToSkip, fieldsToReturn, opts, toSend );
+ if ( !connector->send( toSend, *m, false ) )
+ return false;
+
+ dataReceived();
+ return true;
}
-void DBClientCursor::requestMore() {
- assert( cursorId && pos == nReturned );
+void DBClientCursor::requestMore() {
+ assert( cursorId && pos == nReturned );
- BufBuilder b;
+ BufBuilder b;
b.append(opts);
- b.append(ns.c_str());
- b.append(nToReturn);
- b.append(cursorId);
+ b.append(ns.c_str());
+ b.append(nToReturn);
+ b.append(cursorId);
- Message toSend;
- toSend.setData(dbGetMore, b.buf(), b.len());
- auto_ptr<Message> response(new Message());
- connector->send( toSend, *response );
+ Message toSend;
+ toSend.setData(dbGetMore, b.buf(), b.len());
+ auto_ptr<Message> response(new Message());
+ connector->send( toSend, *response );
- m = response;
- dataReceived();
+ m = response;
+ dataReceived();
}
-void DBClientCursor::dataReceived() {
- QueryResult *qr = (QueryResult *) m->data;
- if( qr->resultFlags() & ResultFlag_CursorNotFound ) {
- // cursor id no longer valid at the server.
- assert( qr->cursorId == 0 );
- cursorId = 0; // 0 indicates no longer valid (dead)
- }
- if( cursorId == 0 ) {
- // only set initially: we don't want to kill it on end of data
+void DBClientCursor::dataReceived() {
+ QueryResult *qr = (QueryResult *) m->data;
+ if ( qr->resultFlags() & ResultFlag_CursorNotFound ) {
+ // cursor id no longer valid at the server.
+ assert( qr->cursorId == 0 );
+ cursorId = 0; // 0 indicates no longer valid (dead)
+ }
+ if ( cursorId == 0 ) {
+ // only set initially: we don't want to kill it on end of data
// if it's a tailable cursor
cursorId = qr->cursorId;
}
- nReturned = qr->nReturned;
- pos = 0;
- data = qr->data();
+ nReturned = qr->nReturned;
+ pos = 0;
+ data = qr->data();
- connector->checkResponse( data, nReturned );
- /* this assert would fire the way we currently work:
- assert( nReturned || cursorId == 0 );
+ connector->checkResponse( data, nReturned );
+ /* this assert would fire the way we currently work:
+ assert( nReturned || cursorId == 0 );
*/
}
-bool DBClientCursor::more() {
- if( pos < nReturned )
- return true;
+bool DBClientCursor::more() {
+ if ( pos < nReturned )
+ return true;
- if( cursorId == 0 )
- return false;
+ if ( cursorId == 0 )
+ return false;
- requestMore();
- return pos < nReturned;
+ requestMore();
+ return pos < nReturned;
}
BSONObj DBClientCursor::next() {
- assert( more() );
- pos++;
- BSONObj o(data);
- data += o.objsize();
- return o;
+ assert( more() );
+ pos++;
+ BSONObj o(data);
+ data += o.objsize();
+ return o;
}
/* ------------------------------------------------------ */
@@ -227,54 +227,54 @@ BSONObj DBClientCursor::next() {
// "./db testclient" to invoke
extern BSONObj emptyObj;
void testClient() {
- cout << "testClient()" << endl;
+ cout << "testClient()" << endl;
// DBClientConnection c(true);
DBClientPaired c;
- string err;
- if( !c.connect("10.211.55.2", "1.2.3.4") ) {
+ string err;
+ if ( !c.connect("10.211.55.2", "1.2.3.4") ) {
// if( !c.connect("10.211.55.2", err) ) {
cout << "testClient: connect() failed" << endl;
}
- else {
+ else {
// temp:
cout << "test query returns: " << c.findOne("foo.bar", fromjson("{}")).toString() << endl;
}
again:
- cout << "query foo.bar..." << endl;
- auto_ptr<DBClientCursor> cursor =
- c.query("foo.bar", emptyObj, 0, 0, 0, Option_CursorTailable);
- DBClientCursor *cc = cursor.get();
- if( cc == 0 ) {
+ cout << "query foo.bar..." << endl;
+ auto_ptr<DBClientCursor> cursor =
+ c.query("foo.bar", emptyObj, 0, 0, 0, Option_CursorTailable);
+ DBClientCursor *cc = cursor.get();
+ if ( cc == 0 ) {
cout << "query() returned 0, sleeping 10 secs" << endl;
sleepsecs(10);
goto again;
}
- while( 1 ) {
- bool m;
- try {
+ while ( 1 ) {
+ bool m;
+ try {
m = cc->more();
- } catch(AssertionException&) {
+ } catch (AssertionException&) {
cout << "more() asserted, sleeping 10 sec" << endl;
goto again;
}
- cout << "more: " << m << " dead:" << cc->isDead() << endl;
- if( !m ) {
- if( cc->isDead() )
- cout << "cursor dead, stopping" << endl;
- else {
- cout << "Sleeping 10 seconds" << endl;
- sleepsecs(10);
- continue;
- }
- break;
- }
- cout << cc->next().toString() << endl;
- }
+ cout << "more: " << m << " dead:" << cc->isDead() << endl;
+ if ( !m ) {
+ if ( cc->isDead() )
+ cout << "cursor dead, stopping" << endl;
+ else {
+ cout << "Sleeping 10 seconds" << endl;
+ sleepsecs(10);
+ continue;
+ }
+ break;
+ }
+ cout << cc->next().toString() << endl;
+ }
}
/* --- class dbclientpaired --- */
-string DBClientPaired::toString() {
+string DBClientPaired::toString() {
stringstream ss;
ss << "state: " << master << '\n';
ss << "left: " << left.toStringLong() << '\n';
@@ -282,30 +282,30 @@ string DBClientPaired::toString() {
return ss.str();
}
-DBClientPaired::DBClientPaired() :
- left(true), right(true)
-{
+DBClientPaired::DBClientPaired() :
+ left(true), right(true)
+{
master = NotSetL;
}
/* find which server, the left or right, is currently master mode */
void DBClientPaired::_checkMaster() {
- for( int retry = 0; retry < 2; retry++ ) {
+ for ( int retry = 0; retry < 2; retry++ ) {
int x = master;
- for( int pass = 0; pass < 2; pass++ ) {
+ for ( int pass = 0; pass < 2; pass++ ) {
DBClientConnection& c = x == 0 ? left : right;
try {
bool im;
BSONObj o = c.cmdIsMaster(im);
- if( retry )
+ if ( retry )
log() << "checkmaster: " << c.toString() << ' ' << o.toString() << '\n';
- if( im ) {
+ if ( im ) {
master = (State) (x + 2);
return;
}
}
- catch(AssertionException&) {
- if( retry )
+ catch (AssertionException&) {
+ if ( retry )
log() << "checkmaster: caught exception " << c.toString() << '\n';
}
x = x^1;
@@ -316,14 +316,14 @@ void DBClientPaired::_checkMaster() {
uassert("checkmaster: no master found", false);
}
-inline DBClientConnection& DBClientPaired::checkMaster() {
- if( master > NotSetR ) {
+inline DBClientConnection& DBClientPaired::checkMaster() {
+ if ( master > NotSetR ) {
// a master is selected. let's just make sure connection didn't die
DBClientConnection& c = master == Left ? left : right;
- if( !c.isFailed() )
+ if ( !c.isFailed() )
return c;
- // after a failure, on the next checkMaster, start with the other
- // server -- presumably it took over. (not critical which we check first,
+ // after a failure, on the next checkMaster, start with the other
+ // server -- presumably it took over. (not critical which we check first,
// just will make the failover slightly faster if we guess right)
master = master == Left ? NotSetR : NotSetL;
}
@@ -333,22 +333,24 @@ inline DBClientConnection& DBClientPaired::checkMaster() {
return master == Left ? left : right;
}
-bool DBClientPaired::connect(const char *serverHostname1, const char *serverHostname2) {
+bool DBClientPaired::connect(const char *serverHostname1, const char *serverHostname2) {
string errmsg;
bool l = left.connect(serverHostname1, errmsg);
bool r = right.connect(serverHostname2, errmsg);
master = l ? NotSetL : NotSetR;
- if( !l && !r ) // it would be ok to fall through, but checkMaster will then try an immediate reconnect which is slow
+ if ( !l && !r ) // it would be ok to fall through, but checkMaster will then try an immediate reconnect which is slow
return false;
- try { checkMaster(); }
- catch(UserAssertionException&) {
+ try {
+ checkMaster();
+ }
+ catch (UserAssertionException&) {
return false;
}
return true;
}
-auto_ptr<DBClientCursor> DBClientPaired::query(const char *a, BSONObj b, int c, int d,
- BSONObj *e, int f)
+auto_ptr<DBClientCursor> DBClientPaired::query(const char *a, BSONObj b, int c, int d,
+ BSONObj *e, int f)
{
return checkMaster().query(a,b,c,d,e,f);
}
View
244 client/dbclient.h
@@ -2,16 +2,16 @@
/**
* 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/>.
*/
@@ -22,13 +22,13 @@
#include "../db/jsobj.h"
/* the query field 'options' can have these bits set: */
-enum {
+enum {
/* Tailable means cursor is not closed when the last data is retrieved. rather, the cursor marks
- the final object's position. you can resume using the cursor later, from where it was located,
+ the final object's position. you can resume using the cursor later, from where it was located,
if more data were received. Set on dbQuery and dbGetMore.
- like any "latent cursor", the cursor may become invalid at some point -- for example if that
- final object it references were deleted. Thus, you should be prepared to requery if you get back
+ like any "latent cursor", the cursor may become invalid at some point -- for example if that
+ final object it references were deleted. Thus, you should be prepared to requery if you get back
ResultFlag_CursorNotFound.
*/
Option_CursorTailable = 2,
@@ -44,97 +44,105 @@ class BSONObj;
#pragma pack(push,1)
struct QueryResult : public MsgData {
- long long cursorId;
- int startingFrom;
- int nReturned;
- const char *data() { return (char *) (((int *)&nReturned)+1); }
- int& resultFlags() { return dataAsInt(); }
+ long long cursorId;
+ int startingFrom;
+ int nReturned;
+ const char *data() {
+ return (char *) (((int *)&nReturned)+1);
+ }
+ int& resultFlags() {
+ return dataAsInt();
+ }
};
#pragma pack(pop)
-class DBClientCursor : boost::noncopyable {
+class DBClientCursor : boost::noncopyable {
public:
- bool more(); // if true, safe to call next()
+ bool more(); // if true, safe to call next()
/* returns 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();
+ BSONObj next();
- BSONObj nextSafe() {
+ BSONObj nextSafe() {
BSONObj o = next();
BSONElement e = o.firstElement();
assert( strcmp(e.fieldName(), "$err") != 0 );
- return o;
+ return o;
}
- /* cursor no longer valid -- use with tailable cursors.
- note you should only rely on this once more() returns false;
+ /* 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 & Option_CursorTailable) != 0; }
-
- bool init();
-
- class Connector {
- public:
- virtual bool send( Message &toSend, Message &response, bool assertOk=true ) = 0;
- virtual void checkResponse( const char *data, int nReturned ) {}
- };
-
- DBClientCursor( Connector *_connector, const char * _ns, BSONObj _query, int _nToReturn,
- int _nToSkip, BSONObj *_fieldsToReturn, int queryOptions ) :
- connector(_connector),
- ns(_ns),
- query(_query),
- nToReturn(_nToReturn),
- nToSkip(_nToSkip),
- fieldsToReturn(_fieldsToReturn),
- opts(queryOptions),
- m(new Message()) {
- cursorId = 0;
- }
+ bool isDead() const {
+ return cursorId == 0;
+ }
+
+ bool tailable() const {
+ return (opts & Option_CursorTailable) != 0;
+ }
+
+ bool init();
+
+ class Connector {
+ public:
+ virtual bool send( Message &toSend, Message &response, bool assertOk=true ) = 0;
+ virtual void checkResponse( const char *data, int nReturned ) {}
+ };
+
+ DBClientCursor( Connector *_connector, const char * _ns, BSONObj _query, int _nToReturn,
+ int _nToSkip, BSONObj *_fieldsToReturn, int queryOptions ) :
+ connector(_connector),
+ ns(_ns),
+ query(_query),
+ nToReturn(_nToReturn),
+ nToSkip(_nToSkip),
+ fieldsToReturn(_fieldsToReturn),
+ opts(queryOptions),
+ m(new Message()) {
+ cursorId = 0;
+ }
private:
- auto_ptr< Connector > connector;
- string ns;
- BSONObj query;
- int nToReturn;
- int nToSkip;
- BSONObj *fieldsToReturn;
+ auto_ptr< Connector > connector;
+ string ns;
+ BSONObj query;
+ int nToReturn;
+ int nToSkip;
+ BSONObj *fieldsToReturn;
int opts;
- auto_ptr<Message> m;
-
- long long cursorId;
- int nReturned;
- int pos;
- const char *data;
- void dataReceived();
- void requestMore();
+ auto_ptr<Message> m;
+
+ long long cursorId;
+ int nReturned;
+ int pos;
+ const char *data;
+ void dataReceived();
+ void requestMore();
};
-class DBClientInterface : boost::noncopyable {
+class DBClientInterface : boost::noncopyable {
public:
- virtual
- auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
- BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0;
+ virtual
+ auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
+ BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0;
virtual
- BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0;
+ BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0) = 0;
};
-/* db "commands"
+/* db "commands"
basically just invocations of connection.$cmd.findOne({...});
*/
-class DBClientWithCommands : public DBClientInterface {
+class DBClientWithCommands : public DBClientInterface {
public:
- /* returns true in isMaster parm if this db is the master instance.
- BSONObj contains more details e.g.:
+ /* returns true in isMaster parm if this db is the master instance.
+ BSONObj contains more details e.g.:
{ "ismaster" : 1.0 , "msg" : "not paired" , "ok" : 1.0 }
*/
virtual
@@ -143,76 +151,82 @@ class DBClientWithCommands : public DBClientInterface {
class DBClientPaired;
-class DBClientConnection : public DBClientWithCommands {
+class DBClientConnection : public DBClientWithCommands {
DBClientPaired *clientPaired;
- auto_ptr<MessagingPort> p;
- auto_ptr<SockAddr> server;
+ auto_ptr<MessagingPort> p;
+ auto_ptr<SockAddr> server;
bool failed; // true if some sort of fatal error has ever happened
bool autoReconnect;
time_t lastReconnectTry;
string serverAddress; // remember for reconnects
void checkConnection();
public:
- string toStringLong() const {
+ string toStringLong() const {
stringstream ss;
ss << serverAddress;
- if( failed ) ss << " failed";
+ if ( failed ) ss << " failed";
return ss.str();
}
- string toString() const { return serverAddress; }
- MessagingPort& port() { return *p.get(); }
- bool isFailed() const { return failed; }
- DBClientConnection(bool _autoReconnect=false,DBClientPaired* cp=0) :
- clientPaired(cp), failed(false), autoReconnect(_autoReconnect), lastReconnectTry(0) { }
+ string toString() const {
+ return serverAddress;
+ }
+ MessagingPort& port() {
+ return *p.get();
+ }
+ bool isFailed() const {
+ return failed;
+ }
+ DBClientConnection(bool _autoReconnect=false,DBClientPaired* cp=0) :
+ clientPaired(cp), failed(false), autoReconnect(_autoReconnect), lastReconnectTry(0) { }
/* Returns false if fails to connect.
If autoReconnect is true, you can try to use the DBClientConnection even when
false was returned -- it will try to connect again.
*/
virtual
- bool connect(const char *serverHostname, string& errmsg);
+ bool connect(const char *serverHostname, string& errmsg);
- /* send a query to the database.
+ /* send a query to the database.
ns: namespace to query, format is <dbname>.<collectname>[.<collectname>]*
query: query to perform on the collection. this is a BSONObj (binary JSON)
- You may format as
- { query: { ... }, order: { ... } }
+ You may format as
+ { query: { ... }, order: { ... } }
to specify a sort order.
- nToReturn: n to return. 0 = unlimited
+ nToReturn: n to return. 0 = unlimited
nToSkip: start with the nth item
- fieldsToReturn:
+ fieldsToReturn:
optional template of which fields to select. if unspecified, returns all fields
queryOptions: see options enum at top of this file
- returns: cursor.
+ returns: cursor.
0 if error (connection failure)
- */
+ */
/*throws AssertionException*/
- auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
- BSONObj *fieldsToReturn = 0, int queryOptions = 0);
+ auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
+ BSONObj *fieldsToReturn = 0, int queryOptions = 0);
/*throws AssertionException*/
- virtual
- BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
+ virtual
+ BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
private:
- class CursorConnector : public DBClientCursor::Connector {
- DBClientConnection *conn;
- virtual bool send( Message &toSend, Message &response, bool assertOk = true );
- virtual void checkResponse( const char *data, int nReturned );
- public:
- CursorConnector( DBClientConnection *_conn ) :
- conn( _conn ) {
- }
- };
+ class CursorConnector : public DBClientCursor::Connector {
+ DBClientConnection *conn;
+ virtual bool send( Message &toSend, Message &response, bool assertOk = true );
+ virtual void checkResponse( const char *data, int nReturned );
+ public:
+ CursorConnector( DBClientConnection *_conn ) :
+ conn( _conn ) {
+ }
+ };
};
-/* Use this class to connect to a replica pair of servers. The class will manage
+/* Use this class to connect to a replica pair of servers. The class will manage
checking for which is master, and do failover automatically.
*/
-class DBClientPaired : public DBClientWithCommands {
+class DBClientPaired : public DBClientWithCommands {
DBClientConnection left,right;
- enum State {
- NotSetL=0,
+ enum State {
+ NotSetL=0,
NotSetR=1,
Left, Right
} master;
@@ -223,29 +237,29 @@ class DBClientPaired : public DBClientWithCommands {
public:
DBClientPaired();
- /* Returns false is neither member of the pair were reachable, or neither is
- master, although,
- when false returned, you can still try to use this connection object, it will
+ /* Returns false is neither member of the pair were reachable, or neither is
+ master, although,
+ when false returned, you can still try to use this connection object, it will
try reconnects.
*/
- bool connect(const char *serverHostname1, const char *serverHostname2);
+ bool connect(const char *serverHostname1, const char *serverHostname2);
/* throws userassertion "no master found" */
- virtual
- auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
- BSONObj *fieldsToReturn = 0, int queryOptions = 0);
+ virtual
+ auto_ptr<DBClientCursor> query(const char *ns, BSONObj query, int nToReturn = 0, int nToSkip = 0,
+ BSONObj *fieldsToReturn = 0, int queryOptions = 0);
/* throws userassertion "no master found" */
virtual
- BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
+ BSONObj findOne(const char *ns, BSONObj query, BSONObj *fieldsToReturn = 0, int queryOptions = 0);
string toString();
-
- /* notification that we got a "not master" error.
- */
- void isntMaster() {
- master = ( ( master == Left ) ? NotSetR : NotSetL );
- }
+
+ /* notification that we got a "not master" error.
+ */
+ void isntMaster() {
+ master = ( ( master == Left ) ? NotSetR : NotSetL );
+ }
};
View
10 client/model.cpp
@@ -2,16 +2,16 @@
/**
* 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/>.
*/
@@ -19,9 +19,9 @@
#include "stdafx.h"
#include "model.h"
-bool Model::load(BSONObj& query) {
+bool Model::load(BSONObj& query) {
BSONObj b = conn()->findOne(getNS(), query);
- if( b.isEmpty() )
+ if ( b.isEmpty() )
return false;
unserialize(b);
View
12 client/model.h
@@ -2,16 +2,16 @@
/**
* 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/>.
*/
@@ -24,15 +24,15 @@
database via the database driver.
*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.
*Loading*
- To load, first construct an (empty) objet. Then call load(). Do not load an object
+ To load, first construct an (empty) objet. Then call load(). Do not load an object
more than once.
*/
-class Model {
+class Model {
public:
Model() { }
virtual ~Model() { }
View
1,285 db/btree.cpp
@@ -2,16 +2,16 @@
/**
* 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/>.
*/
@@ -29,774 +29,783 @@ extern int otherTraceLevel;
int split_debug = 0;
int insert_debug = 0;
-KeyNode::KeyNode(BucketBasics& bb, _KeyNode &k) :
- prevChildBucket(k.prevChildBucket),
- recordLoc(k.recordLoc), key(bb.data+k.keyDataOfs())
+KeyNode::KeyNode(BucketBasics& bb, _KeyNode &k) :
+ prevChildBucket(k.prevChildBucket),
+ recordLoc(k.recordLoc), key(bb.data+k.keyDataOfs())
{ }
/* BucketBasics --------------------------------------------------- */
int BucketBasics::Size() const {
- assert( _Size == BucketSize );
- return _Size;
+ assert( _Size == BucketSize );
+ return _Size;
+}
+inline void BucketBasics::setNotPacked() {
+ flags &= ~Packed;
+}
+inline void BucketBasics::setPacked() {
+ flags |= Packed;
}
-inline void BucketBasics::setNotPacked() { flags &= ~Packed; }
-inline void BucketBasics::setPacked() { flags |= Packed; }
void BucketBasics::_shape(int level, stringstream& ss) {
- for( int i = 0; i < level; i++ ) ss << ' ';
- ss << "*\n";
- for( int i = 0; i < n; i++ )
- if( !k(i).prevChildBucket.isNull() )
- k(i).prevChildBucket.btree()->_shape(level+1,ss);
- if( !nextChild.isNull() )
- nextChild.btree()->_shape(level+1,ss);
+ for ( int i = 0; i < level; i++ ) ss << ' ';
+ ss << "*\n";
+ for ( int i = 0; i < n; i++ )
+ if ( !k(i).prevChildBucket.isNull() )
+ k(i).prevChildBucket.btree()->_shape(level+1,ss);
+ if ( !nextChild.isNull() )
+ nextChild.btree()->_shape(level+1,ss);
}
int bt_fv=0;
int bt_dmp=0;
-void BucketBasics::dumpTree(DiskLoc thisLoc) {
- bt_dmp=1;
- fullValidate(thisLoc);
- bt_dmp=0;
+void BucketBasics::dumpTree(DiskLoc thisLoc) {
+ bt_dmp=1;
+ fullValidate(thisLoc);
+ bt_dmp=0;
}
-int BucketBasics::fullValidate(const DiskLoc& thisLoc) {
- assertValid(true);
-// if( bt_fv==0 )
-// return;
-
- if( bt_dmp ) {
- cout << thisLoc.toString() << ' ';
- ((BtreeBucket *) this)->dump();
- }
-
- // keycount
- int kc = 0;
-
- for( int i = 0; i < n; i++ ) {
- _KeyNode& kn = k(i);
-
- if( kn.isUsed() ) kc++;
- if( !kn.prevChildBucket.isNull() ) {
- DiskLoc left = kn.prevChildBucket;
- BtreeBucket *b = left.btree();
- wassert( b->parent == thisLoc );
- kc += b->fullValidate(kn.prevChildBucket);
- }
- }
- if( !nextChild.isNull() ) {
- BtreeBucket *b = nextChild.btree();
- wassert( b->parent == thisLoc );
- kc += b->fullValidate(nextChild);
- }
-
- return kc;
+int BucketBasics::fullValidate(const DiskLoc& thisLoc) {
+ assertValid(true);
+// if( bt_fv==0 )
+// return;
+
+ if ( bt_dmp ) {
+ cout << thisLoc.toString() << ' ';
+ ((BtreeBucket *) this)->dump();
+ }
+
+ // keycount
+ int kc = 0;
+
+ for ( int i = 0; i < n; i++ ) {
+ _KeyNode& kn = k(i);
+
+ if ( kn.isUsed() ) kc++;
+ if ( !kn.prevChildBucket.isNull() ) {
+ DiskLoc left = kn.prevChildBucket;
+ BtreeBucket *b = left.btree();
+ wassert( b->parent == thisLoc );
+ kc += b->fullValidate(kn.prevChildBucket);
+ }
+ }
+ if ( !nextChild.isNull() ) {
+ BtreeBucket *b = nextChild.btree();
+ wassert( b->parent == thisLoc );
+ kc += b->fullValidate(nextChild);
+ }
+
+ return kc;
}
int nDumped = 0;
-void BucketBasics::assertValid(bool force) {
- if( !debug && !force )
- return;
- wassert( n >= 0 && n < Size() );
- wassert( emptySize >= 0 && emptySize < BucketSize );
- wassert( topSize >= n && topSize <= BucketSize );
- DEV {
- // slow:
- for( int i = 0; i < n-1; i++ ) {
- BSONObj k1 = keyNode(i).key;
- BSONObj k2 = keyNode(i+1).key;
- int z = k1.woCompare(k2); //OK
- if( z > 0 ) {
- cout << "ERROR: btree key order corrupt. Keys:" << endl;
- if( ++nDumped < 5 ) {
- for( int j = 0; j < n; j++ ) {
- cout << " " << keyNode(j).key.toString() << endl;
- }
- ((BtreeBucket *) this)->dump();
- }
- wassert(false);
- break;
- }
- else if( z == 0 ) {
- if( !(k(i).recordLoc < k(i+1).recordLoc) ) {
- cout << "ERROR: btree key order corrupt (recordloc's wrong). Keys:" << endl;
- cout << " k(" << i << "):" << keyNode(i).key.toString() << " RL:" << k(i).recordLoc.toString() << endl;
- cout << " k(" << i+1 << "):" << keyNode(i+1).key.toString() << " RL:" << k(i+1).recordLoc.toString() << endl;
- wassert( k(i).recordLoc < k(i+1).recordLoc );
- }
- }
- }
- }
- else {
- //faster:
- if( n > 1 ) {
- BSONObj k1 = keyNode(0).key;
- BSONObj k2 = keyNode(n-1).key;
- int z = k1.woCompare(k2);
- //wassert( z <= 0 );
- if( z > 0 ) {
+void BucketBasics::assertValid(bool force) {
+ if ( !debug && !force )
+ return;
+ wassert( n >= 0 && n < Size() );
+ wassert( emptySize >= 0 && emptySize < BucketSize );
+ wassert( topSize >= n && topSize <= BucketSize );
+ DEV {
+ // slow:
+ for ( int i = 0; i < n-1; i++ ) {
+ BSONObj k1 = keyNode(i).key;
+ BSONObj k2 = keyNode(i+1).key;
+ int z = k1.woCompare(k2); //OK
+ if ( z > 0 ) {
+ cout << "ERROR: btree key order corrupt. Keys:" << endl;
+ if ( ++nDumped < 5 ) {
+ for ( int j = 0; j < n; j++ ) {
+ cout << " " << keyNode(j).key.toString() << endl;
+ }
+ ((BtreeBucket *) this)->dump();
+ }
+ wassert(false);
+ break;
+ }
+ else if ( z == 0 ) {
+ if ( !(k(i).recordLoc < k(i+1).recordLoc) ) {
+ cout << "ERROR: btree key order corrupt (recordloc's wrong). Keys:" << endl;
+ cout << " k(" << i << "):" << keyNode(i).key.toString() << " RL:" << k(i).recordLoc.toString() << endl;
+ cout << " k(" << i+1 << "):" << keyNode(i+1).key.toString() << " RL:" << k(i+1).recordLoc.toString() << endl;
+ wassert( k(i).recordLoc < k(i+1).recordLoc );
+ }
+ }
+ }
+ }
+ else {
+ //faster:
+ if ( n > 1 ) {
+ BSONObj k1 = keyNode(0).key;
+ BSONObj k2 = keyNode(n-1).key;
+ int z = k1.woCompare(k2);
+ //wassert( z <= 0 );
+ if ( z > 0 ) {
problem() << "btree keys out of order" << '\n';
- ONCE {
+ ONCE {
((BtreeBucket *) this)->dump();
}
assert(false);
}
- }
- }
+ }
+ }
}
-inline void BucketBasics::markUnused(int keypos) {
- assert( keypos >= 0 && keypos < n );
- k(keypos).setUnused();
+inline void BucketBasics::markUnused(int keypos) {
+ assert( keypos >= 0 && keypos < n );
+ k(keypos).setUnused();
}
inline int BucketBasics::totalDataSize() const {
- return Size() - (data-(char*)this);
+ return Size() - (data-(char*)this);
}
-void BucketBasics::init(){
- parent.Null(); nextChild.Null();
- _Size = BucketSize;
- flags = Packed;
- n = 0;
- emptySize = totalDataSize(); topSize = 0;
- reserved = 0;
+void BucketBasics::init() {
+ parent.Null();
+ nextChild.Null();
+ _Size = BucketSize;
+ flags = Packed;
+ n = 0;
+ emptySize = totalDataSize();
+ topSize = 0;
+ reserved = 0;
}
/* we allocate space from the end of the buffer for data.
the keynodes grow from the front.
*/
inline int BucketBasics::_alloc(int bytes) {
- topSize += bytes;
- emptySize -= bytes;
- int ofs = totalDataSize() - topSize;
- assert( ofs > 0 );
- return ofs;
+ topSize += bytes;
+ emptySize -= bytes;
+ int ofs = totalDataSize() - topSize;
+ assert( ofs > 0 );
+ return ofs;
}
-void BucketBasics::_delKeyAtPos(int keypos) {
- assert( keypos >= 0 && keypos <= n );
- assert( childForPos(keypos).isNull() );
- n--;
- assert( n > 0 || nextChild.isNull() );
- for( int j = keypos; j < n; j++ )
- k(j) = k(j+1);
- emptySize += sizeof(_KeyNode);
- setNotPacked();
+void BucketBasics::_delKeyAtPos(int keypos) {
+ assert( keypos >= 0 && keypos <= n );
+ assert( childForPos(keypos).isNull() );
+ n--;
+ assert( n > 0 || nextChild.isNull() );
+ for ( int j = keypos; j < n; j++ )
+ k(j) = k(j+1);
+ emptySize += sizeof(_KeyNode);
+ setNotPacked();
}
/* add a key. must be > all existing. be careful to set next ptr right. */
-void BucketBasics::pushBack(const DiskLoc& recordLoc, BSONObj& key, DiskLoc prevChild) {
- int bytesNeeded = key.objsize() + sizeof(_KeyNode);
- assert( bytesNeeded <= emptySize );
- assert( n == 0 || keyNode(n-1).key.woCompare(key) <= 0 );
- emptySize -= sizeof(_KeyNode);
- _KeyNode& kn = k(n++);
- kn.prevChildBucket = prevChild;
- kn.recordLoc = recordLoc;
- kn.setKeyDataOfs( (short) _alloc(key.objsize()) );
- char *p = dataAt(kn.keyDataOfs());
- memcpy(p, key.objdata(), key.objsize());
+void BucketBasics::pushBack(const DiskLoc& recordLoc, BSONObj& key, DiskLoc prevChild) {
+ int bytesNeeded = key.objsize() + sizeof(_KeyNode);
+ assert( bytesNeeded <= emptySize );
+ assert( n == 0 || keyNode(n-1).key.woCompare(key) <= 0 );
+ emptySize -= sizeof(_KeyNode);
+ _KeyNode& kn = k(n++);
+ kn.prevChildBucket = prevChild;
+ kn.recordLoc = recordLoc;
+ kn.setKeyDataOfs( (short) _alloc(key.objsize()) );
+ char *p = dataAt(kn.keyDataOfs());
+ memcpy(p, key.objdata(), key.objsize());
}
bool BucketBasics::basicInsert(int keypos, const DiskLoc& recordLoc, BSONObj& key) {
- assert( keypos >= 0 && keypos <= n );
- int bytesNeeded = key.objsize() + sizeof(_KeyNode);
- if( bytesNeeded > emptySize ) {
- pack();
- if( bytesNeeded > emptySize )
- return false;
- }
- for( int j = n; j > keypos; j-- ) // make room
- k(j) = k(j-1);
- n++;
- emptySize -= sizeof(_KeyNode);
- _KeyNode& kn = k(keypos);
- kn.prevChildBucket.Null();
- kn.recordLoc = recordLoc;
- kn.setKeyDataOfs((short) _alloc(key.objsize()) );
- char *p = dataAt(kn.keyDataOfs());
- memcpy(p, key.objdata(), key.objsize());
- return true;
-}
-
-/* when we delete things we just leave empty space until the node is
+ assert( keypos >= 0 && keypos <= n );
+ int bytesNeeded = key.objsize() + sizeof(_KeyNode);
+ if ( bytesNeeded > emptySize ) {
+ pack();
+ if ( bytesNeeded > emptySize )
+ return false;
+ }
+ for ( int j = n; j > keypos; j-- ) // make room
+ k(j) = k(j-1);
+ n++;
+ emptySize -= sizeof(_KeyNode);
+ _KeyNode& kn = k(keypos);
+ kn.prevChildBucket.Null();
+ kn.recordLoc = recordLoc;
+ kn.setKeyDataOfs((short) _alloc(key.objsize()) );
+ char *p = dataAt(kn.keyDataOfs());
+ memcpy(p, key.objdata(), key.objsize());
+ return true;
+}
+
+/* when we delete things we just leave empty space until the node is
full and then we repack it.
*/
-void BucketBasics::pack() {
- if( flags & Packed )
- return;
-
- int tdz = totalDataSize();
- char temp[BucketSize];
- int ofs = tdz;
- topSize = 0;
- for( int j = 0; j < n; j++ ) {
- short ofsold = k(j).keyDataOfs();
- int sz = keyNode(j).key.objsize();
- ofs -= sz;
- topSize += sz;
- memcpy(temp+ofs, dataAt(ofsold), sz);
- k(j).setKeyDataOfsSavingUse( ofs );
- }
- int dataUsed = tdz - ofs;
- memcpy(data + ofs, temp + ofs, dataUsed);
- emptySize = tdz - dataUsed - n * sizeof(_KeyNode);
- assert( emptySize >= 0 );
-
- setPacked();
- assertValid();
+void BucketBasics::pack() {
+ if ( flags & Packed )
+ return;
+
+ int tdz = totalDataSize();
+ char temp[BucketSize];
+ int ofs = tdz;
+ topSize = 0;
+ for ( int j = 0; j < n; j++ ) {
+ short ofsold = k(j).keyDataOfs();
+ int sz = keyNode(j).key.objsize();
+ ofs -= sz;
+ topSize += sz;
+ memcpy(temp+ofs, dataAt(ofsold), sz);
+ k(j).setKeyDataOfsSavingUse( ofs );
+ }
+ int dataUsed = tdz - ofs;
+ memcpy(data + ofs, temp + ofs, dataUsed);
+ emptySize = tdz - dataUsed - n * sizeof(_KeyNode);
+ assert( emptySize >= 0 );
+
+ setPacked();
+ assertValid();
}
inline void BucketBasics::truncateTo(int N) {
- n = N;
- setNotPacked();
- pack();
+ n = N;
+ setNotPacked();
+ pack();
}
/* - BtreeBucket --------------------------------------------------- */
/* return largest key in the subtree. */
void BtreeBucket::findLargestKey(const DiskLoc& thisLoc, DiskLoc& largestLoc, int& largestKey) {
- DiskLoc loc = thisLoc;
- while( 1 ) {
- BtreeBucket *b = loc.btree();
- if( !b->nextChild.isNull() ) {
- loc = b->nextChild;
- continue;
- }
-
- assert(b->n>0);
- largestLoc = loc;
- largestKey = b->n-1;
-
- break;
- }
-}
+ DiskLoc loc = thisLoc;
+ while ( 1 ) {
+ BtreeBucket *b = loc.btree();
+ if ( !b->nextChild.isNull() ) {
+ loc = b->nextChild;
+ continue;
+ }
+
+ assert(b->n>0);
+ largestLoc = loc;
+ largestKey = b->n-1;
+
+ break;
+ }
+}
/* pos: for existing keys k0...kn-1.
returns # it goes BEFORE. so key[pos-1] < key < key[pos]
returns n if it goes after the last existing key.
note result might be Unused!
*/
-bool BtreeBucket::find(BSONObj& key, DiskLoc recordLoc, int& pos) {
- /* binary search for this key */
- int l=0; int h=n-1;
- while( l <= h ) {
- int m = (l+h)/2;
- KeyNode M = keyNode(m);
- int x = key.woCompare(M.key);
- if( x == 0 )
- x = recordLoc.compare(M.recordLoc);
- if( x < 0 ) // key < M.key
- h = m-1;
- else if( x > 0 )
- l = m+1;
- else {
- // found it. however, if dup keys are here, be careful we might have
- // found one in the middle. we want find() to return the leftmost instance.
-/*
- while( m >= 1 && keyNode(m-1).key.woEqual(key) )
- m--;
-*/
-
- pos = m;
-
-/*
- DiskLoc ch = k(m).prevChildBucket;
- if( !ch.isNull() ) {
- // if dup keys, might be dups to the left.
- DiskLoc largestLoc;
- int largestKey;
- ch.btree()->findLargestKey(ch, largestLoc, largestKey);
- if( !largestLoc.isNull() ) {
- if( largestLoc.btree()->keyAt(largestKey).woEqual(key) )
- return false;
- }
- }
-*/
-
- return true;
- }
+bool BtreeBucket::find(BSONObj& key, DiskLoc recordLoc, int& pos) {
+ /* binary search for this key */
+ int l=0;
+ int h=n-1;
+ while ( l <= h ) {
+ int m = (l+h)/2;
+ KeyNode M = keyNode(m);
+ int x = key.woCompare(M.key);
+ if ( x == 0 )
+ x = recordLoc.compare(M.recordLoc);
+ if ( x < 0 ) // key < M.key
+ h = m-1;
+ else if ( x > 0 )
+ l = m+1;
+ else {
+ // found it. however, if dup keys are here, be careful we might have
+ // found one in the middle. we want find() to return the leftmost instance.
+ /*
+ while( m >= 1 && keyNode(m-1).key.woEqual(key) )
+ m--;
+ */
+
+ pos = m;
+
+ /*
+ DiskLoc ch = k(m).prevChildBucket;
+ if( !ch.isNull() ) {
+ // if dup keys, might be dups to the left.
+ DiskLoc largestLoc;
+ int largestKey;
+ ch.btree()->findLargestKey(ch, largestLoc, largestKey);
+ if( !largestLoc.isNull() ) {
+ if( largestLoc.btree()->keyAt(largestKey).woEqual(key) )
+ return false;
+ }
+ }
+ */
+
+ return true;
+ }
//? x = key.woCompare(M.key);
- }
- // not found
- pos = l;
- if( pos != n ) {
- BSONObj keyatpos = keyNode(pos).key;
- wassert( key.woCompare(keyatpos) <= 0 );
- if( pos > 0 ) {
- wassert( keyNode(pos-1).key.woCompare(key) <= 0 );
- }
- }
-
- return false;
+ }
+ // not found
+ pos = l;
+ if ( pos != n ) {
+ BSONObj keyatpos = keyNode(pos).key;
+ wassert( key.woCompare(keyatpos) <= 0 );
+ if ( pos > 0 ) {
+ wassert( keyNode(pos-1).key.woCompare(key) <= 0 );
+ }
+ }
+
+ return false;
}
void aboutToDeleteBucket(const DiskLoc&);
-void BtreeBucket::delBucket(const DiskLoc& thisLoc, IndexDetails& id) {
- aboutToDeleteBucket(thisLoc);
-
- assert( !isHead() );
-
- BtreeBucket *p = parent.btree();
- if( p->nextChild == thisLoc ) {
- p->nextChild.Null();
- }
- else {
- for( int i = 0; i < p->n; i++ ) {
- if( p->k(i).prevChildBucket == thisLoc ) {
- p->k(i).prevChildBucket.Null();
- goto found;
- }
- }
- cout << "ERROR: can't find ref to deleted bucket.\n";
- cout << "To delete:\n";
- dump();
- cout << "Parent:\n";
- p->dump();
- assert(false);
- }
+void BtreeBucket::delBucket(const DiskLoc& thisLoc, IndexDetails& id) {
+ aboutToDeleteBucket(thisLoc);
+
+ assert( !isHead() );
+
+ BtreeBucket *p = parent.btree();
+ if ( p->nextChild == thisLoc ) {
+ p->nextChild.Null();
+ }
+ else {
+ for ( int i = 0; i < p->n; i++ ) {
+ if ( p->k(i).prevChildBucket == thisLoc ) {
+ p->k(i).prevChildBucket.Null();
+ goto found;
+ }
+ }
+ cout << "ERROR: can't find ref to deleted bucket.\n";
+ cout << "To delete:\n";
+ dump();
+ cout << "Parent:\n";
+ p->dump();
+ assert(false);
+ }
found:
#if 1
- /* as a temporary defensive measure, we zap the whole bucket, AND don't truly delete
+ /* as a temporary defensive measure, we zap the whole bucket, AND don't truly delete
it (meaning it is ineligible for reuse). temporary to see if it helps with some
- issues.
- */
- memset(this, 0, Size());
+ issues.
+ */
+ memset(this, 0, Size());
#else
- //defensive:
- n = -1;
- parent.Null();
- theDataFileMgr.deleteRecord(id.indexNamespace().c_str(), thisLoc.rec(), thisLoc);
+ //defensive:
+ n = -1;
+ parent.Null();
+ theDataFileMgr.deleteRecord(id.indexNamespace().c_str(), thisLoc.rec(), thisLoc);
#endif
}
/* note: may delete the entire bucket! this invalid upon return sometimes. */
-void BtreeBucket::delKeyAtPos(const DiskLoc& thisLoc, IndexDetails& id, int p) {
- dassert( thisLoc.btree() == this );
- assert(n>0);
- DiskLoc left = childForPos(p);
-
- if( n == 1 ) {
- if( left.isNull() && nextChild.isNull() ) {
- if( isHead() )
- _delKeyAtPos(p); // we don't delete the top bucket ever
- else
- delBucket(thisLoc, id);
- return;
- }
- markUnused(p);
- return;
- }
-
- if( left.isNull() )
- _delKeyAtPos(p);
- else
- markUnused(p);
+void BtreeBucket::delKeyAtPos(const DiskLoc& thisLoc, IndexDetails& id, int p) {
+ dassert( thisLoc.btree() == this );
+ assert(n>0);
+ DiskLoc left = childForPos(p);
+
+ if ( n == 1 ) {
+ if ( left.isNull() && nextChild.isNull() ) {
+ if ( isHead() )
+ _delKeyAtPos(p); // we don't delete the top bucket ever
+ else
+ delBucket(thisLoc, id);
+ return;
+ }
+ markUnused(p);
+ return;
+ }
+
+ if ( left.isNull() )
+ _delKeyAtPos(p);
+ else
+ markUnused(p);
}
int verbose = 0;
int qqq = 0;
bool BtreeBucket::unindex(const DiskLoc& thisLoc, IndexDetails& id, BSONObj& key, const DiskLoc& recordLoc ) {
- if( key.objsize() > KeyMax ) {
- OCCASIONALLY problem() << "unindex: key too large to index, skipping " << id.indexNamespace() << /* ' ' << key.toString() << */ '\n';
- return false;
- }
-
- int pos;
- bool found;
- DiskLoc loc = locate(thisLoc, key, pos, found, recordLoc, 1);
- if( found ) {
- loc.btree()->delKeyAtPos(loc, id, pos);
- return true;
- }
- return false;
+ if ( key.objsize() > KeyMax ) {
+ OCCASIONALLY problem() << "unindex: key too large to index, skipping " << id.indexNamespace() << /* ' ' << key.toString() << */ '\n';
+ return false;
+ }
+
+ int pos;
+ bool found;
+ DiskLoc loc = locate(thisLoc, key, pos, found, recordLoc, 1);
+ if ( found ) {
+ loc.btree()->delKeyAtPos(loc, id, pos);
+ return true;
+ }
+ return false;
}
-BtreeBucket* BtreeBucket::allocTemp() {
- BtreeBucket *b = (BtreeBucket*) malloc(BucketSize);
- b->init();
- return b;
+BtreeBucket* BtreeBucket::allocTemp() {
+ BtreeBucket *b = (BtreeBucket*) malloc(BucketSize);
+ b->init();
+ return b;
}
-inline void fix(const DiskLoc& thisLoc, const DiskLoc& child) {
- if( !child.isNull() ) {
- if( insert_debug )
- cout << " " << child.toString() << ".parent=" << thisLoc.toString() << endl;
- child.btree()->parent = thisLoc;
- }
+inline void fix(const DiskLoc& thisLoc, const DiskLoc& child) {
+ if ( !child.isNull() ) {
+ if ( insert_debug )
+ cout << " " << child.toString() << ".parent=" << thisLoc.toString() << endl;
+ child.btree()->parent = thisLoc;
+ }
}
/* this sucks. maybe get rid of parent ptrs. */
-void BtreeBucket::fixParentPtrs(const DiskLoc& thisLoc) {
- dassert( thisLoc.btree() == this );
- fix(thisLoc, nextChild);
- for( int i = 0; i < n; i++ )
- fix(thisLoc, k(i).prevChildBucket);
+void BtreeBucket::fixParentPtrs(const DiskLoc& thisLoc) {
+ dassert( thisLoc.btree() == this );
+ fix(thisLoc, nextChild);
+ for ( int i = 0; i < n; i++ )
+ fix(thisLoc, k(i).prevChildBucket);
}
/* keypos - where to insert the key i3n range 0..n. 0=make leftmost, n=make rightmost.
*/
-void BtreeBucket::insertHere(DiskLoc thisLoc, int keypos,
- DiskLoc recordLoc, BSONObj& key,
- DiskLoc lchild, DiskLoc rchild, IndexDetails& idx)
+void BtreeBucket::insertHere(DiskLoc thisLoc, int keypos,
+ DiskLoc recordLoc, BSONObj& key,
+ DiskLoc lchild, DiskLoc rchild, IndexDetails& idx)
{
- dassert( thisLoc.btree() == this );
- if( insert_debug )
- cout << " " << thisLoc.toString() << ".insertHere " << key.toString() << '/' << recordLoc.toString() << ' '
- << lchild.toString() << ' ' << rchild.toString() << " keypos:" << keypos << endl;
-
- DiskLoc oldLoc = thisLoc;
-
- if( basicInsert(keypos, recordLoc, key) ) {
- _KeyNode& kn = k(keypos);
- if( keypos+1 == n ) { // last key
- if( nextChild != lchild ) {
- cout << "ERROR nextChild != lchild" << endl;
- cout << " thisLoc: " << thisLoc.toString() << ' ' << idx.indexNamespace() << endl;
- cout << " keyPos: " << keypos << " n:" << n << endl;
- cout << " nextChild: " << nextChild.toString() << " lchild: " << lchild.toString() << endl;
- cout << " recordLoc: " << recordLoc.toString() << " rchild: " << rchild.toString() << endl;
- cout << " key: " << key.toString() << endl;
- dump();
+ dassert( thisLoc.btree() == this );
+ if ( insert_debug )
+ cout << " " << thisLoc.toString() << ".insertHere " << key.toString() << '/' << recordLoc.toString() << ' '
+ << lchild.toString() << ' ' << rchild.toString() << " keypos:" << keypos << endl;
+
+ DiskLoc oldLoc = thisLoc;
+
+ if ( basicInsert(keypos, recordLoc, key) ) {
+ _KeyNode& kn = k(keypos);
+ if ( keypos+1 == n ) { // last key
+ if ( nextChild != lchild ) {
+ cout << "ERROR nextChild != lchild" << endl;
+ cout << " thisLoc: " << thisLoc.toString() << ' ' << idx.indexNamespace() << endl;
+ cout << " keyPos: " << keypos << " n:" << n << endl;
+ cout << " nextChild: " << nextChild.toString() << " lchild: " << lchild.toString() << endl;
+ cout << " recordLoc: " << recordLoc.toString() << " rchild: " << rchild.toString() << endl;
+ cout << " key: " << key.toString() << endl;
+ dump();
#if defined(_WIN32)
- cout << "\n\nDUMPING FULL INDEX" << endl;
- bt_dmp=1;
- bt_fv=1;
- idx.head.btree()->fullValidate(idx.head);
+ cout << "\n\nDUMPING FULL INDEX" << endl;
+ bt_dmp=1;
+ bt_fv=1;
+ idx.head.btree()->fullValidate(idx.head);
#endif
- assert(false);
- }
- kn.prevChildBucket = nextChild;
- assert( kn.prevChildBucket == lchild );
- nextChild = rchild;
- if( !rchild.isNull() )
- rchild.btree()->parent = thisLoc;
- }
- else {
- k(keypos).prevChildBucket = lchild;
- if( k(keypos+1).prevChildBucket != lchild ) {
- cout << "ERROR k(keypos+1).prevChildBucket != lchild" << endl;
- cout << " thisLoc: " << thisLoc.toString() << ' ' << idx.indexNamespace() << endl;
- cout << " keyPos: " << keypos << " n:" << n << endl;
- cout << " k(keypos+1).pcb: " << k(keypos+1).prevChildBucket.toString() << " lchild: " << lchild.toString() << endl;
- cout << " recordLoc: " << recordLoc.toString() << " rchild: " << rchild.toString() << endl;
- cout << " key: " << key.toString() << endl;
- dump();
+ assert(false);
+ }
+ kn.prevChildBucket = nextChild;
+ assert( kn.prevChildBucket == lchild );
+ nextChild = rchild;
+ if ( !rchild.isNull() )
+ rchild.btree()->parent = thisLoc;
+ }
+ else {
+ k(keypos).prevChildBucket = lchild;
+ if ( k(keypos+1).prevChildBucket != lchild ) {
+ cout << "ERROR k(keypos+1).prevChildBucket != lchild" << endl;
+ cout << " thisLoc: " << thisLoc.toString() << ' ' << idx.indexNamespace() << endl;
+ cout << " keyPos: " << keypos << " n:" << n << endl;
+ cout << " k(keypos+1).pcb: " << k(keypos+1).prevChildBucket.toString() << " lchild: " << lchild.toString() << endl;
+ cout << " recordLoc: " << recordLoc.toString() << " rchild: " << rchild.toString() << endl;
+ cout << " key: " << key.toString() << endl;
+ dump();
#if defined(_WIN32)
- cout << "\n\nDUMPING FULL INDEX" << endl;
- bt_dmp=1;
- bt_fv=1;
- idx.head.btree()->fullValidate(idx.head);
+ cout << "\n\nDUMPING FULL INDEX" << endl;
+ bt_dmp=1;
+ bt_fv=1;
+ idx.head.btree()->fullValidate(idx.head);
#endif
- assert(false);
- }
- k(keypos+1).prevChildBucket = rchild;
- if( !rchild.isNull() )
- rchild.btree()->parent = thisLoc;
- }
- return;
- }
-
- // split
- if( split_debug )
- cout << " " << thisLoc.toString() << ".split" << endl;
-
- int mid = n / 2;
-
- /* on duplicate key, we need to ensure that they all end up on the RHS */
- if( 0 ) {
- assert(mid>0);
- while( 1 ) {
- KeyNode mn = keyNode(mid);
- KeyNode left = keyNode(mid-1);
- if( left.key < mn.key )
- break;
- mid--;
- if( mid < 3 ) {
- problem() << "Assertion failure - mid<3: duplicate key bug not fixed yet" << endl;
- cout << "Assertion failure - mid<3: duplicate key bug not fixed yet" << endl;
- cout << " ns:" << idx.indexNamespace() << endl;
- cout << " key:" << mn.key.toString() << endl;
- break;
- }
- }
- }
-
- BtreeBucket *r = allocTemp();
- DiskLoc rLoc;
-
- if( split_debug )
- cout << " mid:" << mid << ' ' << keyNode(mid).key.toString() << " n:" << n << endl;
- for( int i = mid+1; i < n; i++ ) {
- KeyNode kn = keyNode(i);
- r->pushBack(kn.recordLoc, kn.key, kn.prevChildBucket);
- }
- r->nextChild = nextChild;
- r->assertValid();
+ assert(false);
+ }
+ k(keypos+1).prevChildBucket = rchild;
+ if ( !rchild.isNull() )
+ rchild.btree()->parent = thisLoc;
+ }
+ return;
+ }
+
+ // split
+ if ( split_debug )
+ cout << " " << thisLoc.toString() << ".split" << endl;
+
+ int mid = n / 2;
+
+ /* on duplicate key, we need to ensure that they all end up on the RHS */
+ if ( 0 ) {
+ assert(mid>0);
+ while ( 1 ) {
+ KeyNode mn = keyNode(mid);
+ KeyNode left = keyNode(mid-1);
+ if ( left.key < mn.key )
+ break;
+ mid--;
+ if ( mid < 3 ) {
+ problem() << "Assertion failure - mid<3: duplicate key bug not fixed yet" << endl;
+ cout << "Assertion failure - mid<3: duplicate key bug not fixed yet" << endl;
+ cout << " ns:" << idx.indexNamespace() << endl;
+ cout << " key:" << mn.key.toString() << endl;
+ break;
+ }
+ }
+ }
+
+ BtreeBucket *r = allocTemp();
+ DiskLoc rLoc;
+
+ if ( split_debug )
+ cout << " mid:" << mid << ' ' << keyNode(mid).key.toString() << " n:" << n << endl;
+ for ( int i = mid+1; i < n; i++ ) {
+ KeyNode kn = keyNode(i);
+ r->pushBack(kn.recordLoc, kn.key, kn.prevChildBucket);
+ }
+ r->nextChild = nextChild;
+ r->assertValid();
//r->dump();
- rLoc = theDataFileMgr.insert(idx.indexNamespace().c_str(), r, r->Size(), true);
- if( split_debug )
- cout << " new rLoc:" << rLoc.toString() << endl;
- free(r); r = 0;
- rLoc.btree()->fixParentPtrs(rLoc);
-
- {
- KeyNode middle = keyNode(mid);
- nextChild = middle.prevChildBucket; // middle key gets promoted, its children will be thisLoc (l) and rLoc (r)
- if( split_debug ) {
- //rLoc.btree()->dump();
- cout << " middle key:" << middle.key.toString() << endl;
- }
-
- // promote middle to a parent node
- if( parent.isNull() ) {
- // make a new parent if we were the root
- BtreeBucket *p = allocTemp();
- p->pushBack(middle.recordLoc, middle.key, thisLoc);
- p->nextChild = rLoc;
- p->assertValid();
- parent = idx.head = theDataFileMgr.insert(idx.indexNamespace().c_str(), p, p->Size(), true);
- if( split_debug )
- cout << " we were root, making new root:" << hex << parent.getOfs() << dec << endl;
- free(p);
- rLoc.btree()->parent = parent;
- }
- else {
- /* set this before calling _insert - if it splits it will do fixParent() logic and fix the value,
- so we don't want to overwrite that if it happens.
- */
- rLoc.btree()->parent = parent;
- if( split_debug )
- cout << " promoting middle key " << middle.key.toString() << endl;
- parent.btree()->_insert(parent, middle.recordLoc, middle.key, false, thisLoc, rLoc, idx);
- }
+ rLoc = theDataFileMgr.insert(idx.indexNamespace().c_str(), r, r->Size(), true);
+ if ( split_debug )
+ cout << " new rLoc:" << rLoc.toString() << endl;
+ free(r);
+ r = 0;
+ rLoc.btree()->fixParentPtrs(rLoc);
+
+ {
+ KeyNode middle = keyNode(mid);
+ nextChild = middle.prevChildBucket; // middle key gets promoted, its children will be thisLoc (l) and rLoc (r)
+ if ( split_debug ) {
+ //rLoc.btree()->dump();
+ cout << " middle key:" << middle.key.toString() << endl;
+ }
+
+ // promote middle to a parent node
+ if ( parent.isNull() ) {
+ // make a new parent if we were the root
+ BtreeBucket *p = allocTemp();
+ p->pushBack(middle.recordLoc, middle.key, thisLoc);
+ p->nextChild = rLoc;
+ p->assertValid();
+ parent = idx.head = theDataFileMgr.insert(idx.indexNamespace().c_str(), p, p->Size(), true);
+ if ( split_debug )
+ cout << " we were root, making new root:" << hex << parent.getOfs() << dec << endl;
+ free(p);
+ rLoc.btree()->parent = parent;
+ }
+ else {
+ /* set this before calling _insert - if it splits it will do fixParent() logic and fix the value,
+ so we don't want to overwrite that if it happens.
+ */
+ rLoc.btree()->parent = parent;
+ if ( split_debug )
+ cout << " promoting middle key " << middle.