summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDwight <dmerriman@gmail.com>2008-06-27 18:35:03 -0400
committerDwight <dmerriman@gmail.com>2008-06-27 18:35:03 -0400
commitb1a480423bb8136f69a573413dcc097a900342a4 (patch)
tree96a705b2feec74d0bd624209cc19c46b3a36a514
parentd3e3876751b6becc9084b5508fd0a48178f30b1b (diff)
downloadmongo-b1a480423bb8136f69a573413dcc097a900342a4.tar.gz
first cut at "fast count"r0.0.6_rc1
-rw-r--r--db/btree.cpp7
-rw-r--r--db/db.vcproj8
-rw-r--r--db/jsobj.h8
-rw-r--r--db/json.cpp46
-rw-r--r--db/json.h8
-rw-r--r--db/makefile2
-rw-r--r--db/namespace.h5
-rw-r--r--db/pdfile.cpp6
-rw-r--r--db/query.cpp48
9 files changed, 125 insertions, 13 deletions
diff --git a/db/btree.cpp b/db/btree.cpp
index c4a36e2e0ea..d7f0c1e7c02 100644
--- a/db/btree.cpp
+++ b/db/btree.cpp
@@ -847,13 +847,6 @@ void BtreeCursor::checkUnused() {
cout << "btree unused skipped:" << u << endl;
}
-/*DiskLoc BtreeCursor::currLoc() {
- assert( !bucket.isNull() );
- _KeyNode& kn = bucket.btree()->k(keyOfs);
- assert( kn.isUsed() );
- return kn.recordLoc;
-}*/
-
bool BtreeCursor::advance() {
if( bucket.isNull() )
return false;
diff --git a/db/db.vcproj b/db/db.vcproj
index 446dda2e6a9..60d4da0b402 100644
--- a/db/db.vcproj
+++ b/db/db.vcproj
@@ -199,6 +199,10 @@
>
</File>
<File
+ RelativePath=".\json.cpp"
+ >
+ </File>
+ <File
RelativePath="..\grid\message.cpp"
>
</File>
@@ -281,6 +285,10 @@
>
</File>
<File
+ RelativePath=".\json.h"
+ >
+ </File>
+ <File
RelativePath="..\util\lruishmap.h"
>
</File>
diff --git a/db/jsobj.h b/db/jsobj.h
index cc7e570307a..50cc3a55fd6 100644
--- a/db/jsobj.h
+++ b/db/jsobj.h
@@ -330,6 +330,13 @@ public:
b.append(fieldName);
b.append(n);
}
+ void appendOID(const char *fieldName) {
+ b.append((char) jstOID);
+ b.append(fieldName);
+ b.append((long long) 0);
+ b.append((unsigned) 0);
+ }
+
void appendDate(const char *fieldName, unsigned long long dt) {
b.append((char) Date);
b.append(fieldName);
@@ -342,6 +349,7 @@ public:
b.append(str);
}
+ /* JSObj will free the buffer when it is finished. */
JSObj doneAndDecouple() {
int l;
return JSObj(decouple(l), true);
diff --git a/db/json.cpp b/db/json.cpp
new file mode 100644
index 00000000000..6c875ab95d4
--- /dev/null
+++ b/db/json.cpp
@@ -0,0 +1,46 @@
+// json.cpp
+
+#include "stdafx.h"
+#include "json.h"
+#include "../util/builder.h"
+
+/* partial implementation for now */
+
+void skipWhite(const char *&p) {
+ while( *p == ' ' || *p == '\r' || *p == '\n' || *p == '\t' )
+ p++;
+}
+
+void value(JSObjBuilder& b, const char *&p, string& id) {
+ if( strncmp(p, "ObjId()", 7) == 0 ) {
+ p += 7;
+ b.appendOID(id.c_str());
+ }
+}
+
+void _fromjson(JSObjBuilder& b, const char *&p) {
+ while( 1 ) {
+ skipWhite(p);
+ if( *p == 0 )
+ break;
+ if( *p == '{' ) { _fromjson(b,++p); continue; }
+ if( *p == '}' ) { ++p; break; }
+ if( *p == '_' || isalpha(*p) ) {
+ string id;
+ while( *p == '_' || isalpha(*p) || isdigit(*p) ) {
+ id += *p++;
+ }
+ skipWhite(p);
+ assert( *p == ':' ); p++;
+ skipWhite(p);
+ value(b, p, id);
+ continue;
+ }
+ }
+}
+
+JSObj fromjson(const char *str) {
+ JSObjBuilder b;
+ _fromjson(b,str);
+ return b.doneAndDecouple();
+}
diff --git a/db/json.h b/db/json.h
new file mode 100644
index 00000000000..febee18940e
--- /dev/null
+++ b/db/json.h
@@ -0,0 +1,8 @@
+// json.h
+
+#pragma once
+
+#include "../stdafx.h"
+#include "jsobj.h"
+
+JSObj fromjson(const char *str);
diff --git a/db/makefile b/db/makefile
index 76d8cbfdb2f..f8ea9ab2f4b 100644
--- a/db/makefile
+++ b/db/makefile
@@ -8,7 +8,7 @@ LIBS= $(LIB_DEPS) $(LIB_BOOST) -lstdc++
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
+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
# ../grid/protorecv.o ../grid/protosend.o
diff --git a/db/namespace.h b/db/namespace.h
index e8e056ed958..0854a666ed6 100644
--- a/db/namespace.h
+++ b/db/namespace.h
@@ -73,11 +73,12 @@ public:
extern int bucketSizes[];
+/* this is the "header" for a collection that has all its details. in the .ns file.
+*/
class NamespaceDetails {
public:
NamespaceDetails() {
- /* be sure to initialize new fields here, otherwise they will contain garbage by default.
- */
+ /* be sure to initialize new fields here -- doesn't default to zeroes the way we use it */
datasize = nrecords = 0;
lastExtentSize = 0;
nIndexes = 0;
diff --git a/db/pdfile.cpp b/db/pdfile.cpp
index 1ec6a11142d..28cd97f786c 100644
--- a/db/pdfile.cpp
+++ b/db/pdfile.cpp
@@ -576,7 +576,9 @@ auto_ptr<Cursor> DataFileMgr::findAll(const char *ns) {
return auto_ptr<Cursor>(new BasicCursor( e->firstRecord ));
}
-/* get a table scan cursor, but can be forward or reverse direction */
+/* get a table scan cursor, but can be forward or reverse direction.
+ order.$natural - if set, > 0 means forward (asc), < 0 backward (desc).
+*/
auto_ptr<Cursor> findTableScan(const char *ns, JSObj& order) {
Element el = order.findElement("$natural");
if( el.type() != Number || el.number() >= 0 )
@@ -919,7 +921,7 @@ DiskLoc DataFileMgr::insert(const char *ns, const void *buf, int len, bool god)
}
tableToIndex = nsdetails(tabletoidxns);
if( tableToIndex == 0 ) {
- cout << "user warning: bad add index attempt, no such table(ns):" << tabletoidxns << endl;
+ cout << "user warning: ignoring add index, no such collection:" << tabletoidxns << endl;
return DiskLoc();
}
if( tableToIndex->nIndexes >= MaxIndexes ) {
diff --git a/db/query.cpp b/db/query.cpp
index 3f76624dfb3..144c8d27f1a 100644
--- a/db/query.cpp
+++ b/db/query.cpp
@@ -10,6 +10,7 @@
#include "btree.h"
#include "../util/lruishmap.h"
#include "javajs.h"
+#include "json.h"
//ns->query->DiskLoc
LRUishMap<JSObj,DiskLoc,5> lrutest(123);
@@ -29,6 +30,7 @@ JSObj emptyObj((char *) &emptyObject);
int getGtLtOp(Element& e);
void appendElementHandlingGtLt(JSObjBuilder& b, Element& e);
+int runCount(const char *ns, const JSObj& cmd, string& err);
/* todo: _ cache query plans
_ use index on partial match with the query
@@ -552,9 +554,25 @@ inline bool _runCommands(const char *ns, JSObj& jsobj, stringstream& ss, BufBuil
}
}
else if( e.type() == String ) {
+ /* { count: "collectionname"[, query: <query>] } */
string us(ns, p-ns);
- if( strcmp( e.fieldName(), "create") == 0 ) {
+ if( strcmp( e.fieldName(), "count" ) == 0 ) {
+ valid = true;
+ string ns = us + '.' + e.valuestr();
+ string err;
+ int n = runCount(ns.c_str(), jsobj, err);
+ int nn = n;
+ ok = true;
+ if( n < 0 ) {
+ ok = false;
+ nn = 0;
+ if( !err.empty() )
+ anObjBuilder.append("errmsg", err.c_str());
+ }
+ anObjBuilder.append("n", (double) nn);
+ }
+ else if( strcmp( e.fieldName(), "create") == 0 ) {
valid = true;
string ns = us + '.' + e.valuestr();
string err;
@@ -684,8 +702,36 @@ void killCursors(int n, long long *ids) {
cout << "killCursors: found " << k << " of " << n << endl;
}
+// order.$natural sets natural order direction
auto_ptr<Cursor> findTableScan(const char *ns, JSObj& order);
+JSObj id_obj = fromjson("{_id:ObjId()}");
+JSObj empty_obj = fromjson("{}");
+
+/* { count: "collectionname"[, query: <query>] }
+ returns -1 on error.
+*/
+int runCount(const char *ns, const JSObj& cmd, string& err) {
+ NamespaceDetails *d = nsdetails(ns);
+ if( d == 0 ) {
+ err = "ns does not exist";
+ return -1;
+ }
+
+ auto_ptr<Cursor> c = getIndexCursor(ns, id_obj, empty_obj);
+ if( c.get() == 0 ) {
+ cout << "TEMP: table scan" << endl;
+ c = findTableScan(ns, empty_obj);
+ }
+ else cout << "TEMP: indexed scan" << endl;
+ int count = 0;
+ if( c->ok() ) {
+ count++;
+ while( c->advance() ) count++;
+ }
+ return count;
+}
+
QueryResult* runQuery(Message& message, const char *ns, int ntoskip, int _ntoreturn, JSObj jsobj,
auto_ptr< set<string> > filter, stringstream& ss)
{