summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDwight <dmerriman@gmail.com>2008-06-08 10:58:19 -0400
committerDwight <dmerriman@gmail.com>2008-06-08 10:58:19 -0400
commit5080d260b01f51dbf083245729763fedc9f5e8b8 (patch)
treec46ec0acf3cc609222bcd20cb588c0ec1b996d70
parent3ac43db818cff02d923383f13e07e4b4029b4d8a (diff)
downloadmongo-5080d260b01f51dbf083245729763fedc9f5e8b8.tar.gz
horrific cursor code gone
-rw-r--r--db/clientcursor.cpp133
-rw-r--r--db/clientcursor.h28
-rw-r--r--db/query.cpp4
-rw-r--r--stdafx.h9
-rw-r--r--util/goodies.h14
5 files changed, 89 insertions, 99 deletions
diff --git a/db/clientcursor.cpp b/db/clientcursor.cpp
index ce431cdeed3..d113bba9f78 100644
--- a/db/clientcursor.cpp
+++ b/db/clientcursor.cpp
@@ -1,9 +1,9 @@
-// clientcursor.cpp
-
-/* Cursor -- and its derived classes -- are our internal cursors.
+/* clientcursor.cpp
ClientCursor is a wrapper that represents a cursorid from our client
application's perspective.
+
+ Cursor -- and its derived classes -- are our internal cursors.
*/
#include "stdafx.h"
@@ -13,11 +13,30 @@
/* TODO: FIX cleanup of clientCursors when hit the end. (ntoreturn insufficient) */
-typedef map<DiskLoc, set<ClientCursor*>> DiskLocToCC;
-DiskLocToCC clientCursorsByLocation;
-
CCById clientCursorsById;
+/* ------------------------------------------- */
+
+typedef multimap<DiskLoc, ClientCursor*> ByLoc;
+ByLoc byLoc;
+
+void ClientCursor::setLastLoc(DiskLoc L) {
+ if( L == _lastLoc )
+ return;
+
+ if( !_lastLoc.isNull() ) {
+ ByLoc::iterator i = kv_find(byLoc, _lastLoc, this);
+ if( i != byLoc.end() )
+ byLoc.erase(i);
+ }
+
+ if( !L.isNull() )
+ byLoc.insert( make_pair(L, this) );
+ _lastLoc = L;
+}
+
+/* ------------------------------------------- */
+
/* must call this when a btree node is updated */
void removedKey(const DiskLoc& btreeLoc, int keyPos) {
// TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -25,56 +44,31 @@ void removedKey(const DiskLoc& btreeLoc, int keyPos) {
/* must call this on a delete so we clean up the cursors. */
void aboutToDelete(const DiskLoc& dl) {
- DiskLocToCC::iterator it = clientCursorsByLocation.find(dl);
-
- if( it != clientCursorsByLocation.end() ) {
- set<ClientCursor*>& ccs = it->second;
-
- set<ClientCursor*>::iterator it = ccs.begin();
- while( it != ccs.end() ) {
- ClientCursor *cc = *it;
- cc->c->checkLocation();
- cc->c->advance();
- assert( cc->currLoc() != dl ); // assert that we actually advanced
- cc->lastLoc.Null(); // updateLocation must not try to remove, we are cleaining up this list ourself.
- cc->updateLocation();
- }
+ vector<ClientCursor*> toAdvance;
- clientCursorsByLocation.erase(it);
+ for( ByLoc::iterator i = byLoc.lower_bound(dl);
+ i != byLoc.upper_bound(dl); ++i ) {
+ toAdvance.push_back(i->second);
}
-}
-
-void ClientCursor::cleanupByLocation(DiskLoc loc) {
- if( loc.isNull() )
- return;
- DiskToCC::iterator it = byLocation.find(loc);
- if( it != byLocation.end() ) {
- it->second.erase(this);
- if( it->second.empty() )
- it->erase();
+ for( vector<ClientCursor*>::iterator i = toAdvance.begin();
+ i != toAdvance.end(); ++i )
+ {
+ (*i)->c->checkLocation();
+ (*i)->c->advance();
+ wassert( (*i)->c->currLoc() != dl );
+ (*i)->updateLocation();
}
}
ClientCursor::~ClientCursor() {
-#if defined(_WIN32)
- cout << "~clientcursor " << cursorid << endl;
-#endif
- assert( pos != -2 );
- cleanupByLocation(lastLoc);
+ DEV cout << "~clientcursor " << cursorid << endl;
assert( pos != -2 );
-
- // defensive
- lastLoc.Null();
- cursorid = -1;
+ setLastLoc( DiskLoc() ); // removes us from bylocation multimap
+ clientCursorsById.erase(cursorid);
+ // defensive:
+ (CursorId&) cursorid = -1;
pos = -2;
- nextAtThisLocation = 0;
-}
-
-// note this doesn't set lastLoc -- caller should.
-void ClientCursor::addToByLocation(DiskLoc cl) {
- assert( cursorid );
- clientCursorsByLocation[cl].insert(this);
}
/* call when cursor's location changes so that we can update the
@@ -84,53 +78,23 @@ void ClientCursor::addToByLocation(DiskLoc cl) {
void ClientCursor::updateLocation() {
assert( cursorid );
DiskLoc cl = c->currLoc();
-
- if( lastLoc == cl ) {
+ if( lastLoc() == cl ) {
cout << "info: lastloc==curloc " << ns << '\n';
return;
}
-
- if( !lastLoc.isNull() )
- cleanupByLocation(lastLoc, cursorid);
-
- if( !cl.isNull() )
- addToByLocation(cl);
-
- lastLoc = cl;
+ setLastLoc(cl);
c->noteLocation();
}
-/* report to us that a new clientcursor exists so we can track it.
- note you still must call updateLocation (which likely should be changed)
-*/
-void ClientCursor::add(ClientCursor* cc) {
- clientCursors[cc->cursorid] = cc;
- updateLocation();
-}
-
-bool ClientCursor::erase(long long id) {
- CCById::iterator it = clientCursorsById.find(id);
- if( it != clientCursorsById.end() ) {
- ClientCursor *cc = it->second;
- it->second = 0; // defensive
- clientCursorsById.erase(it);
- delete cc; // destructor will fix byLocation map
- return true;
- }
- return false;
-}
-
-long long allocCursorId() {
+long long ClientCursor::allocCursorId() {
long long x;
while( 1 ) {
x = (((long long)rand()) << 32);
x = x | (int) curTimeMillis() | 0x80000000; // OR to make sure not zero
- if( clientCursors.count(x) == 0 )
+ if( ClientCursor::find(x) == 0 )
break;
}
-#if defined(_WIN32)
- cout << "alloccursorid " << x << endl;
-#endif
+ DEV cout << "alloccursorid " << x << endl;
return x;
}
@@ -139,9 +103,9 @@ class CursInspector : public SingleResultObjCursor {
return new CursInspector();
}
void fill() {
- b.append("byLocation_size", clientCursorsByLocation.size());
+ b.append("byLocation_size", byLoc.size());
b.append("clientCursors_size", clientCursorsById.size());
-
+/* todo update for new impl:
stringstream ss;
ss << '\n';
int x = 40;
@@ -172,6 +136,7 @@ class CursInspector : public SingleResultObjCursor {
it++;
}
b.append("dump", ss.str().c_str());
+*/
}
public:
CursInspector() { reg("intr.cursors"); }
diff --git a/db/clientcursor.h b/db/clientcursor.h
index a0d06f8557c..6fd5bb12155 100644
--- a/db/clientcursor.h
+++ b/db/clientcursor.h
@@ -16,28 +16,33 @@ class ClientCursor;
typedef map<CursorId, ClientCursor*> CCById;
extern CCById clientCursorsById;
+
class ClientCursor {
friend class CursInspector;
+ DiskLoc _lastLoc; // use getter and setter not this.
+ static CursorId allocCursorId();
public:
- ClientCursor() {
- cursorid=0; pos=0;
+ ClientCursor() : cursorid( allocCursorId() ), pos(0) {
+ clientCursorsById.insert( make_pair(cursorid, this) );
}
~ClientCursor();
- CursorId cursorid;
+ const CursorId cursorid;
string ns;
auto_ptr<JSMatcher> matcher;
auto_ptr<Cursor> c;
int pos;
- DiskLoc lastLoc;
+ DiskLoc lastLoc() const { return _lastLoc; }
+ void setLastLoc(DiskLoc);
auto_ptr< set<string> > filter; // which fields query wants returned
- /* report to us that a new clientcursor exists so we can track it.
- note you do not need to call updateLocation, but location should be set before
- calling.
- */
- static void add(ClientCursor*);
-
- static bool erase(CursorId cursorid);
+ static bool erase(CursorId id) {
+ ClientCursor *cc = find(id);
+ if( cc ) {
+ delete cc;
+ return true;
+ }
+ return false;
+ }
static ClientCursor* find(CursorId id) {
CCById::iterator it = clientCursorsById.find(id);
@@ -61,4 +66,3 @@ public:
// ClientCursor *nextAtThisLocation;
};
-CursorId allocCursorId();
diff --git a/db/query.cpp b/db/query.cpp
index 913a6612a5d..bfef39534fd 100644
--- a/db/query.cpp
+++ b/db/query.cpp
@@ -732,13 +732,11 @@ assert( debug.getN() < 5000 );
// more...so save a cursor
ClientCursor *cc = new ClientCursor();
cc->c = c;
- cursorid = allocCursorId();
- cc->cursorid = cursorid;
+ cursorid = cc->cursorid;
cc->matcher = matcher;
cc->ns = ns;
cc->pos = n;
cc->filter = filter;
- ClientCursor::add(cc);
cc->updateLocation();
}
}
diff --git a/stdafx.h b/stdafx.h
index d1f6d9d5071..88204ce7da4 100644
--- a/stdafx.h
+++ b/stdafx.h
@@ -105,6 +105,15 @@ inline ostream& problem() {
return problems;
}
+/* for now, running on win32 means development not production --
+ use this to log things just there.
+*/
+#if !defined(_WIN32)
+#define DEV if( 1 )
+#else
+#define DEV if( 0 )
+#endif
+
#define DEBUGGING if( 0 )
extern unsigned occasion;
diff --git a/util/goodies.h b/util/goodies.h
index 94ca721aa8b..af6fd3f20b0 100644
--- a/util/goodies.h
+++ b/util/goodies.h
@@ -13,6 +13,20 @@ inline pthread_t GetCurrentThreadId() { return pthread_self(); }
/* set to TRUE if we are exiting */
extern bool goingAway;
+/* find the multimap member which matches a particular key and value.
+
+ note this can be slow if there are a lot with the same key.
+*/
+template<class C,class K,class V> inline typename C::iterator kv_find(C& c, const K& k,const V& v) {
+ pair<typename C::iterator,typename C::iterator> p = c.equal_range(k);
+
+ for( typename C::iterator it=p.first; it!=p.second; ++it)
+ if( it->second == v )
+ return it;
+
+ return c.end();
+}
+
bool isPrime(int n);
int nextPrime(int n);