cursors
This commit is contained in:
parent
78bba21722
commit
94b2fe996f
19
db/db.cpp
19
db/db.cpp
@ -56,6 +56,13 @@ public:
|
||||
nextjsobj += 4;
|
||||
return i;
|
||||
}
|
||||
long long pullInt64() {
|
||||
if( nextjsobj == data )
|
||||
nextjsobj += strlen(data) + 1; // skip namespace
|
||||
long long i = *((long long *)nextjsobj);
|
||||
nextjsobj += 8;
|
||||
return i;
|
||||
}
|
||||
|
||||
OID* getOID() {
|
||||
return (OID *) (data + strlen(data) + 1); // skip namespace
|
||||
@ -135,7 +142,6 @@ void receivedDelete(Message& m) {
|
||||
|
||||
void receivedQuery(Message& m) {
|
||||
DbMessage d(m);
|
||||
|
||||
const char *ns = d.getns();
|
||||
int ntoreturn = d.pullInt();
|
||||
assert( d.moreJSObjs() );
|
||||
@ -145,6 +151,17 @@ void receivedQuery(Message& m) {
|
||||
dbMsgPort.reply(m, resp);
|
||||
}
|
||||
|
||||
void receivedGetMore(Message& m) {
|
||||
DbMessage d(m);
|
||||
const char *ns = d.getns();
|
||||
int ntoreturn = d.pullInt();
|
||||
long long cursorid = d.pullInt64();
|
||||
QueryResult* msgdata = getMore(ns, ntoreturn, cursorid);
|
||||
Message resp;
|
||||
resp.setData(msgdata, true);
|
||||
dbMsgPort.reply(m, resp);
|
||||
}
|
||||
|
||||
/*void getbyoid(Message& m) {
|
||||
DbMessage d(m);
|
||||
Record *r = findByOID(d.getns(), d.getOID());
|
||||
|
||||
BIN
db/db.vcproj
BIN
db/db.vcproj
Binary file not shown.
15
db/jsobj.cpp
15
db/jsobj.cpp
@ -91,19 +91,16 @@ JSMatcher::JSMatcher(JSObj &_jsobj) :
|
||||
|
||||
struct RXTest {
|
||||
RXTest() {
|
||||
// pcre_compile(0, 0, 0, 0, 0);
|
||||
//pcre_compile(const char *, int, const char **, int *,
|
||||
// const unsigned char *);
|
||||
|
||||
/*
|
||||
/*
|
||||
static const boost::regex e("(\\d{4}[- ]){3}\\d{4}");
|
||||
static const boost::regex b(".....");
|
||||
cout << "regex result: " << regex_match("hello", e) << endl;
|
||||
cout << "regex result: " << regex_match("abcoo", b) << endl;
|
||||
*/
|
||||
pcrecpp::RE re("h.*o");
|
||||
cout << "regex test: " << re.FullMatch("hello") << endl;
|
||||
cout << "regex test: " << re.FullMatch("blah") << endl;
|
||||
*/
|
||||
pcrecpp::RE re1(")({a}h.*o");
|
||||
pcrecpp::RE re("h.llo");
|
||||
assert( re.FullMatch("hello") );
|
||||
assert( !re1.FullMatch("hello") );
|
||||
}
|
||||
} rxtest;
|
||||
|
||||
|
||||
97
db/query.cpp
97
db/query.cpp
@ -5,6 +5,7 @@
|
||||
#include "pdfile.h"
|
||||
#include "jsobj.h"
|
||||
#include "../util/builder.h"
|
||||
#include <time.h>
|
||||
|
||||
int nextCursorId = 1;
|
||||
|
||||
@ -65,13 +66,28 @@ void updateObjects(const char *ns, JSObj updateobj, JSObj pattern, bool upsert)
|
||||
theDataFileMgr.insert(ns, (void*) updateobj.objdata(), updateobj.objsize());
|
||||
}
|
||||
|
||||
typedef map<long long, ClientCursor*> CCMap;
|
||||
CCMap clientCursors;
|
||||
|
||||
long long allocCursorId() {
|
||||
long long x;
|
||||
while( 1 ) {
|
||||
x = (((long long)rand()) << 32);
|
||||
x = x | time(0);
|
||||
if( clientCursors.count(x) == 0 )
|
||||
break;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj) {
|
||||
|
||||
cout << "runQuery ns:" << ns << " ntoreturn:" << ntoreturn << " queryobjsize:" <<
|
||||
jsobj.objsize() << endl;
|
||||
|
||||
BufBuilder b;
|
||||
JSMatcher matcher(jsobj);
|
||||
|
||||
auto_ptr<JSMatcher> matcher(new JSMatcher(jsobj));
|
||||
|
||||
QueryResult *qr = 0;
|
||||
b.skip(sizeof(QueryResult));
|
||||
@ -79,17 +95,28 @@ QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj) {
|
||||
int n = 0;
|
||||
|
||||
auto_ptr<Cursor> c =
|
||||
// strcmp(ns, "system.namespaces") == 0 ?
|
||||
// makeNamespaceCursor() :
|
||||
// strcmp(ns, "system.namespaces") == 0 ?
|
||||
// makeNamespaceCursor() :
|
||||
theDataFileMgr.findAll(ns);
|
||||
|
||||
long long cursorid = 0;
|
||||
while( c->ok() ) {
|
||||
JSObj js = c->current();
|
||||
if( matcher.matches(js) ) {
|
||||
if( matcher->matches(js) ) {
|
||||
b.append((void*) js.objdata(), js.objsize());
|
||||
n++;
|
||||
if( n >= ntoreturn && ntoreturn != 0 )
|
||||
if( n >= ntoreturn && ntoreturn != 0 ) {
|
||||
// more...so save a cursor
|
||||
ClientCursor *cc = new ClientCursor();
|
||||
cc->c = c;
|
||||
cursorid = allocCursorId();
|
||||
cc->cursorid = cursorid;
|
||||
cc->matcher = matcher;
|
||||
cc->ns = ns;
|
||||
cc->pos = n;
|
||||
clientCursors[cursorid] = cc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->advance();
|
||||
}
|
||||
@ -98,10 +125,68 @@ QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj) {
|
||||
qr->len = b.len();
|
||||
qr->reserved = 0;
|
||||
qr->operation = opReply;
|
||||
qr->cursorId = 0; //nextCursorId++;
|
||||
qr->cursorId = cursorid;
|
||||
qr->startingFrom = 0;
|
||||
qr->nReturned = n;
|
||||
b.decouple();
|
||||
|
||||
return qr;
|
||||
}
|
||||
|
||||
QueryResult* getMore(const char *ns, int ntoreturn, long long cursorid) {
|
||||
|
||||
cout << "getMore ns:" << ns << " ntoreturn:" << ntoreturn << " cursorid:" <<
|
||||
cursorid << endl;
|
||||
|
||||
BufBuilder b;
|
||||
|
||||
ClientCursor *cc = 0;
|
||||
CCMap::iterator it = clientCursors.find(cursorid);
|
||||
if( it == clientCursors.end() ) {
|
||||
cout << "Cursor not found in map. cursorid: " << cursorid << endl;
|
||||
}
|
||||
else {
|
||||
cc = it->second;
|
||||
}
|
||||
|
||||
b.skip(sizeof(QueryResult));
|
||||
|
||||
int start = 0;
|
||||
int n = 0;
|
||||
|
||||
if( cc ) {
|
||||
start = cc->pos;
|
||||
Cursor *c = cc->c.get();
|
||||
while( 1 ) {
|
||||
if( !c->ok() ) {
|
||||
// done! kill cursor.
|
||||
cursorid = 0;
|
||||
clientCursors.erase(it);
|
||||
delete cc;
|
||||
cc = 0;
|
||||
break;
|
||||
}
|
||||
JSObj js = c->current();
|
||||
if( cc->matcher->matches(js) ) {
|
||||
b.append((void*) js.objdata(), js.objsize());
|
||||
n++;
|
||||
if( n >= ntoreturn && ntoreturn != 0 ) {
|
||||
cc->pos += n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c->advance();
|
||||
}
|
||||
|
||||
QueryResult *qr = (QueryResult *) b.buf();
|
||||
qr->cursorId = cursorid;
|
||||
qr->startingFrom = start;
|
||||
qr->len = b.len();
|
||||
qr->reserved = 0;
|
||||
qr->operation = opReply;
|
||||
qr->nReturned = n;
|
||||
b.decouple();
|
||||
|
||||
return qr;
|
||||
}
|
||||
|
||||
18
db/query.h
18
db/query.h
@ -25,9 +25,10 @@
|
||||
int nToReturn; // how many you want back as the beginning of the cursor data
|
||||
JSObject query;
|
||||
dbGetMore:
|
||||
int reserved;;
|
||||
int64 cursorID;
|
||||
int reserved;
|
||||
string collection; // redundant, might use for security.
|
||||
int nToReturn;
|
||||
int64 cursorID;
|
||||
|
||||
Note that on Update, there is only one object, which is different
|
||||
from insert where you can pass a list of objects to insert in the db.
|
||||
@ -51,7 +52,20 @@ struct QueryResult : public MsgData {
|
||||
const char *data() { return (char *) (((int *)&nReturned)+1); }
|
||||
};
|
||||
|
||||
QueryResult* getMore(const char *ns, int ntoreturn, long long cursorid);
|
||||
QueryResult* runQuery(const char *ns, int ntoreturn, JSObj);
|
||||
|
||||
void updateObjects(const char *ns, JSObj updateobj, JSObj pattern, bool upsert);
|
||||
void deleteObjects(const char *ns, JSObj pattern, bool justOne);
|
||||
|
||||
class Cursor;
|
||||
class ClientCursor {
|
||||
public:
|
||||
ClientCursor() { cursorid=0; pos=0; }
|
||||
long long cursorid;
|
||||
string ns;
|
||||
auto_ptr<JSMatcher> matcher;
|
||||
auto_ptr<Cursor> c;
|
||||
int pos;
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user