summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db/btree.cpp180
-rw-r--r--db/btree.h23
-rw-r--r--db/pdfile.cpp33
-rw-r--r--db/query.cpp11
-rw-r--r--db/storage.h2
-rw-r--r--db/testdb.js46
6 files changed, 250 insertions, 45 deletions
diff --git a/db/btree.cpp b/db/btree.cpp
index e6459a40b98..3de47fbdecb 100644
--- a/db/btree.cpp
+++ b/db/btree.cpp
@@ -19,6 +19,34 @@ inline KeyNode::KeyNode(BucketBasics& bb, _KeyNode &k) :
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);
+}
+
+void BucketBasics::fullValidate(const DiskLoc& thisLoc) {
+ assertValid();
+ for( int i = 0; i < n; i++ ) {
+ _KeyNode& kn = k(i);
+ if( !kn.prevChildBucket.isNull() ) {
+ DiskLoc left = kn.prevChildBucket;
+ BtreeBucket *b = left.btree();
+ assert( b->parent == thisLoc );
+ b->fullValidate(kn.prevChildBucket);
+ }
+ }
+ if( !nextChild.isNull() ) {
+ BtreeBucket *b = nextChild.btree();
+ assert( b->parent == thisLoc );
+ b->fullValidate(nextChild);
+ }
+}
+
void BucketBasics::assertValid() {
if( !debug )
return;
@@ -52,6 +80,11 @@ void BucketBasics::assertValid() {
}
}
+inline void BucketBasics::markUnused(int keypos) {
+ assert( keypos >= 0 && keypos < n );
+ k(keypos).setUnused();
+}
+
inline int BucketBasics::totalDataSize() const {
return Size - (data-(char*)this);
}
@@ -76,10 +109,11 @@ inline int BucketBasics::_alloc(int bytes) {
return ofs;
}
-void BucketBasics::del(int keypos) {
+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);
@@ -94,8 +128,8 @@ void BucketBasics::pushBack(const DiskLoc& recordLoc, JSObj& key, DiskLoc prevCh
emptySize -= sizeof(_KeyNode);
_KeyNode& kn = k(n++);
kn.prevChildBucket = prevChild;
- kn.recordLoc = recordLoc;
- kn.keyDataOfs = (short) _alloc(key.objsize());
+ kn.recordLoc = recordLoc;
+ kn.setKeyDataOfs( (short) _alloc(key.objsize()) );
char *p = dataAt(kn.keyDataOfs);
memcpy(p, key.objdata(), key.objsize());
}
@@ -115,7 +149,7 @@ bool BucketBasics::basicInsert(int keypos, const DiskLoc& recordLoc, JSObj& key)
_KeyNode& kn = k(keypos);
kn.prevChildBucket.Null();
kn.recordLoc = recordLoc;
- kn.keyDataOfs = (short) _alloc(key.objsize());
+ kn.setKeyDataOfs((short) _alloc(key.objsize()) );
char *p = dataAt(kn.keyDataOfs);
memcpy(p, key.objdata(), key.objsize());
return true;
@@ -138,7 +172,7 @@ void BucketBasics::pack() {
ofs -= sz;
topSize += sz;
memcpy(temp+ofs, dataAt(ofsold), sz);
- k(j).keyDataOfs = ofs;
+ k(j).setKeyDataOfs( ofs );
}
int dataUsed = tdz - ofs;
memcpy(data + ofs, temp + ofs, dataUsed);
@@ -160,6 +194,7 @@ inline void BucketBasics::truncateTo(int N) {
/* 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(JSObj& key, int& pos) {
/* binary search for this key */
@@ -190,40 +225,107 @@ bool BtreeBucket::find(JSObj& key, int& pos) {
return false;
}
+void BtreeBucket::delBucket(const DiskLoc& thisLoc, const char *ns) {
+ 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:
+ //defensive:
+ n = -1;
+ parent.Null();
+ theDataFileMgr.deleteRecord(ns, thisLoc.rec(), thisLoc);
+}
+
+/* note: may delete the entire bucket! this invalid upon return sometimes. */
+void BtreeBucket::delKeyAtPos(const DiskLoc& thisLoc, const char *ns, int p) {
+ 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, ns);
+ return;
+ } markUnused(p);
+ return;
+ }
+
+ if( left.isNull() )
+ _delKeyAtPos(p);
+ else
+ markUnused(p);
+}
+
/*
e j p
| | | |
b g h i l n o q r s
*/
-bool BtreeBucket::unindex(JSObj& key ) {
+bool BtreeBucket::unindex(const DiskLoc& thisLoc, const char *ns, JSObj& key ) {
int pos;
- cout << key.toString() << endl;
if( otherTraceLevel >= 10 )
dump();
if( find(key, pos) ) {
+ //todo:dup key support
+ if( k(pos).isUnused() )
+ return false;
if( otherTraceLevel >= 2 )
cout << "unindex(): found key to delete:" << key.toString() << endl;
- del(pos);
+ delKeyAtPos(thisLoc, ns, pos);
+ /*
if( otherTraceLevel >= 10 ) {
cout << "AFTER delete:" << endl;
dump();
}
assertValid();
+ */
return true;
}
DiskLoc l = childForPos(pos);
if( l.isNull() )
return false;
- return l.btree()->unindex(key);
+ return l.btree()->unindex(l, ns, key);
}
-
BtreeBucket* BtreeBucket::allocTemp() {
BtreeBucket *b = (BtreeBucket*) malloc(BucketSize);
b->init();
return b;
}
+inline void fix(const DiskLoc& thisLoc, const DiskLoc& child) {
+ if( !child.isNull() )
+ child.btree()->parent = thisLoc;
+}
+
+/* this sucks. maybe get rid of parent ptrs. */
+void BtreeBucket::fixParentPtrs(const DiskLoc& thisLoc) {
+ 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(const DiskLoc& thisLoc, const char *ns, int keypos,
const DiskLoc& recordLoc, JSObj& key,
DiskLoc lchild, DiskLoc rchild, IndexDetails& idx) {
@@ -243,9 +345,11 @@ void BtreeBucket::insertHere(const DiskLoc& thisLoc, const char *ns, int keypos,
}
// split
+ cout << "split begin " << hex << thisLoc.getOfs() << dec << endl;
BtreeBucket *r = allocTemp();
DiskLoc rLoc;
int mid = n / 2;
+ cout << " mid:" << mid << " n:" << n << endl;
for( int i = mid+1; i < n; i++ ) {
KeyNode kn = keyNode(i);
if( i == keypos ) {
@@ -259,7 +363,9 @@ void BtreeBucket::insertHere(const DiskLoc& thisLoc, const char *ns, int keypos,
r->nextChild = nextChild;
r->assertValid();
rLoc = theDataFileMgr.insert(ns, r, r->Size, true);
+ cout << " new rLoc:" << hex << rLoc.getOfs() << dec << endl;
free(r); r = 0;
+ rLoc.btree()->fixParentPtrs(rLoc);
{
KeyNode middle = keyNode(mid);
@@ -273,9 +379,11 @@ void BtreeBucket::insertHere(const DiskLoc& thisLoc, const char *ns, int keypos,
p->nextChild = rLoc;
p->assertValid();
parent = idx.head = theDataFileMgr.insert(ns, p, p->Size, true);
+ cout << " we were root, making new root:" << hex << parent.getOfs() << dec << endl;
free(p);
}
else {
+ cout << " promoting middle key" << endl;
parent.btree()->_insert(parent, ns, middle.recordLoc, middle.key, false, thisLoc, rLoc, idx);
}
rLoc.btree()->parent = parent;
@@ -287,6 +395,7 @@ void BtreeBucket::insertHere(const DiskLoc& thisLoc, const char *ns, int keypos,
// add our new key, there is room now
{
if( keypos < mid ) {
+ cout << " keypos<mid, insertHere() the new key" << endl;
insertHere(thisLoc, ns, keypos, recordLoc, key, lchild, rchild, idx);
} else {
// handled above already.
@@ -294,6 +403,8 @@ void BtreeBucket::insertHere(const DiskLoc& thisLoc, const char *ns, int keypos,
//rLoc.btree()->insertHere(rLoc, ns, kp, recordLoc, key, lchild, rchild, idx);
}
}
+
+ cout << "split end " << hex << thisLoc.getOfs() << dec << endl;
}
DiskLoc BtreeBucket::addHead(const char *ns) {
@@ -404,25 +515,38 @@ int BtreeBucket::_insert(const DiskLoc& thisLoc, const char *ns, const DiskLoc&
void BtreeBucket::dump() {
cout << "DUMP btreebucket:\n";
+ cout << " parent:" << hex << parent.getOfs() << dec << '\n';
for( int i = 0; i < n; i++ ) {
KeyNode k = keyNode(i);
- cout << '\t' << i << '\t' << k.key.toString() << endl;
+ cout << '\t' << i << '\t' << k.key.toString() << '\t' << hex <<
+ k.prevChildBucket.getOfs() << '\t' << k.recordLoc.getOfs() << dec;
+ if( this->k(i).isUnused() )
+ cout << " UNUSED";
+ cout << endl;
}
+ cout << " nextChild:" << hex << nextChild.getOfs() << dec << endl;
}
int BtreeBucket::insert(const DiskLoc& thisLoc, const char *ns, const DiskLoc& recordLoc,
JSObj& key, bool dupsAllowed, IndexDetails& idx)
{
- ninserts++;
-// if( ninserts == 0x7cf ) {
-// dump();
-// }
-// assertValid();
int x = _insert(thisLoc, ns, recordLoc, key, dupsAllowed, DiskLoc(), DiskLoc(), idx);
- assertValid();
+ assertValid();
+
+#if defined(_WIN32)
+ if( isHead() ) {
+ ninserts++;
+ fullValidate(thisLoc);
+ }
+#endif
+
return x;
}
+void BtreeBucket::shape(stringstream& ss) {
+ _shape(0, ss);
+}
+
/* - BtreeCursor --------------------------------------------------- */
BtreeCursor::BtreeCursor(DiskLoc head, JSObj k, int _direction, bool sm) :
@@ -436,18 +560,38 @@ BtreeCursor::BtreeCursor(DiskLoc head, JSObj k, int _direction, bool sm) :
}
bucket = head.btree()->locate(head, k, keyOfs, found, direction);
+ checkUnused();
}
+/* skip unused keys. */
+void BtreeCursor::checkUnused() {
+ int u = 0;
+ while( 1 ) {
+ if( !ok() )
+ break;
+ BtreeBucket *b = bucket.btree();
+ _KeyNode& kn = b->k(keyOfs);
+ if( kn.isUsed() )
+ break;
+ bucket = b->advance(bucket, keyOfs, direction);
+ u++;
+ }
+ if( u > 10 )
+ cout << "btree unused skipped:" << u << endl;
+}
DiskLoc BtreeCursor::currLoc() {
assert( !bucket.isNull() );
- return bucket.btree()->k(keyOfs).recordLoc;
+ _KeyNode& kn = bucket.btree()->k(keyOfs);
+ assert( kn.isUsed() );
+ return kn.recordLoc;
}
bool BtreeCursor::advance() {
if( bucket.isNull() )
return false;
bucket = bucket.btree()->advance(bucket, keyOfs, direction);
+ checkUnused();
return !bucket.isNull();
}
diff --git a/db/btree.h b/db/btree.h
index fc3018b542f..da1c5240cd4 100644
--- a/db/btree.h
+++ b/db/btree.h
@@ -14,6 +14,10 @@ struct _KeyNode {
DiskLoc prevChildBucket;
DiskLoc recordLoc;
short keyDataOfs;
+ void setKeyDataOfs(short s) { keyDataOfs = s; }
+ void setUnused() { recordLoc.Null(); }
+ bool isUnused() { return recordLoc.isNull(); }
+ bool isUsed() { return !isUnused(); }
};
#pragma pack(pop)
@@ -38,6 +42,7 @@ class BucketBasics {
public:
bool isHead() { return parent.isNull(); }
void assertValid();
+ void fullValidate(const DiskLoc& thisLoc); /* traverses everything */
protected:
DiskLoc& getChild(int pos) {
assert( pos >= 0 && pos <= n );
@@ -57,7 +62,7 @@ protected:
*/
bool basicInsert(int keypos, const DiskLoc& recordLoc, JSObj& key);
void pushBack(const DiskLoc& recordLoc, JSObj& key, DiskLoc prevChild);
- void del(int keypos);
+ void _delKeyAtPos(int keypos); // low level version that doesn't deal with child ptrs.
/* !Packed means there is deleted fragment space within the bucket.
We "repack" when we run out of space before considering the node
@@ -73,9 +78,12 @@ protected:
void pack(); void setNotPacked(); void setPacked();
int _alloc(int bytes);
void truncateTo(int N);
-
+ void markUnused(int keypos);
+public:
DiskLoc parent;
- DiskLoc nextChild; // the next bucket
+protected:
+ void _shape(int level, stringstream&);
+ DiskLoc nextChild; // child bucket off and to the right of the highest key.
int Size; // total size of this btree node in bytes. constant.
int flags;
int emptySize; // size of the empty region
@@ -95,12 +103,18 @@ public:
int insert(const DiskLoc& thisLoc, const char *ns, const DiskLoc& recordLoc,
JSObj& key, bool dupsAllowed, IndexDetails& idx);
void update(const DiskLoc& recordLoc, JSObj& key);
- bool unindex(JSObj& key);
+ bool unindex(const DiskLoc& thisLoc, const char *ns, JSObj& key);
DiskLoc locate(const DiskLoc& thisLoc, JSObj& key, int& pos, bool& found, int direction=1);
/* advance one key position in the index: */
DiskLoc advance(const DiskLoc& thisLoc, int& keyOfs, int direction);
DiskLoc getHead(const DiskLoc& thisLoc);
+
+ /* get tree shape */
+ void shape(stringstream&);
private:
+ void fixParentPtrs(const DiskLoc& thisLoc);
+ void delBucket(const DiskLoc& thisLoc, const char *ns);
+ void delKeyAtPos(const DiskLoc& thisLoc, const char *ns, int p);
JSObj keyAt(int keyOfs) { return keyOfs >= n ? JSObj() : keyNode(keyOfs).key; }
static BtreeBucket* allocTemp(); /* caller must release with free() */
void insertHere(const DiskLoc& thisLoc, const char *ns, int keypos,
@@ -125,6 +139,7 @@ public:
virtual void noteLocation(); // updates keyAtKeyOfs...
virtual void checkLocation();
private:
+ void checkUnused();
DiskLoc bucket;
int keyOfs;
int direction; // 1=fwd,-1=reverse
diff --git a/db/pdfile.cpp b/db/pdfile.cpp
index 95e3151b8c5..ceeea409ad8 100644
--- a/db/pdfile.cpp
+++ b/db/pdfile.cpp
@@ -333,7 +333,9 @@ void IndexDetails::getKeysFromObject(JSObj& obj, set<JSObj>& keys) {
}
}
-void _unindexRecord(IndexDetails& id, JSObj& obj) {
+int nUnindexes = 0;
+
+void _unindexRecord(const char *ns, IndexDetails& id, JSObj& obj) {
set<JSObj> keys;
id.getKeysFromObject(obj, keys);
for( set<JSObj>::iterator i=keys.begin(); i != keys.end(); i++ ) {
@@ -342,28 +344,27 @@ void _unindexRecord(IndexDetails& id, JSObj& obj) {
cout << "_unindexRecord() " << obj.toString();
cout << "\n unindex:" << j.toString() << endl;
}
- bool ok = id.head.btree()->unindex(j);
+ nUnindexes++;
+ bool ok = id.head.btree()->unindex(id.head, ns, j);
+
+#if defined(_WIN32)
+ //TMEPTEMPTEMPTEMP TEMP
+ id.head.btree()->fullValidate(id.head);
+#endif
if( !ok ) {
- cout << "ERROR: _unindex failed" << endl;
+ cout << "Warning: _unindex failed" << endl;
cout << " " << obj.toString() << endl;
cout << " " << j.toString() << endl;
cout << " if you added dup keys this can happen until we support that" << endl;
}
}
-/*
- JSObj idxInfo = id.info.obj();
- JSObjBuilder b;
- JSObj key = obj.extractFields(idxInfo.getObjectField("key"), b);
- if( !key.isEmpty() )
- id.head.btree()->unindex(key);
-*/
}
-void unindexRecord(NamespaceDetails *d, Record *todelete) {
+void unindexRecord(const char *ns, NamespaceDetails *d, Record *todelete) {
if( d->nIndexes == 0 ) return;
JSObj obj(todelete);
for( int i = 0; i < d->nIndexes; i++ ) {
- _unindexRecord(d->indexes[i], obj);
+ _unindexRecord(ns, d->indexes[i], obj);
}
}
@@ -373,7 +374,7 @@ void DataFileMgr::deleteRecord(const char *ns, Record *todelete, const DiskLoc&
aboutToDelete(dl);
NamespaceDetails* d = namespaceIndex.details(ns);
- unindexRecord(d, todelete);
+ unindexRecord(ns, d, todelete);
/* remove ourself from the record next/prev chain */
{
@@ -445,12 +446,13 @@ void DataFileMgr::update(
idx.getKeysFromObject(newObj, newkeys);
vector<JSObj*> removed;
setDifference(oldkeys, newkeys, removed);
+ string idxns = idx.indexNamespace();
for( unsigned i = 0; i < removed.size(); i++ ) {
- idx.head.btree()->unindex(*removed[i]);
+ idx.head.btree()->unindex(idx.head, idxns.c_str(), *removed[i]);
}
vector<JSObj*> added;
setDifference(newkeys, oldkeys, added);
- string idxns = idx.indexNamespace();
+ assert( !dl.isNull() );
for( unsigned i = 0; i < added.size(); i++ ) {
idx.head.btree()->insert(
idx.head, idxns.c_str(),
@@ -512,6 +514,7 @@ void _indexRecord(IndexDetails& idx, JSObj& obj, DiskLoc newRecordLoc) {
idx.getKeysFromObject(obj, keys);
for( set<JSObj>::iterator i=keys.begin(); i != keys.end(); i++ ) {
// cout << "_indexRecord " << i->toString() << endl;
+ assert( !newRecordLoc.isNull() );
idx.head.btree()->insert(idx.head, idx.indexNamespace().c_str(), newRecordLoc,
(JSObj&) *i, false, idx);
}
diff --git a/db/query.cpp b/db/query.cpp
index 3fc94287357..72838f8890c 100644
--- a/db/query.cpp
+++ b/db/query.cpp
@@ -34,6 +34,15 @@ auto_ptr<Cursor> getIndexCursor(const char *ns, JSObj& query, JSObj& order) {
order.firstElement().type() == Number &&
order.firstElement().number() < 0;
JSObjBuilder b;
+#if defined(_WIN32)
+cout<< "TEMP FULLVALIDATE" << endl;
+d->indexes[i].head.btree()->fullValidate(d->indexes[i].head);
+{
+ stringstream ss;
+ d->indexes[i].head.btree()->shape(ss);
+ cout << ss.str() << endl;
+}
+#endif
return auto_ptr<Cursor>(new BtreeCursor(d->indexes[i].head, reverse ? maxKey : JSObj(), reverse ? -1 : 1, false));
}
}
@@ -212,7 +221,9 @@ QueryResult* runQuery(const char *ns, int ntoreturn, JSObj jsobj,
int n = 0;
+ int aa = 123;
auto_ptr<Cursor> c = getSpecialCursor(ns);
+ int bb = 456;
if( c.get() == 0 ) {
c = getIndexCursor(ns, query, order);
}
diff --git a/db/storage.h b/db/storage.h
index e2170568364..0db87b7fb6c 100644
--- a/db/storage.h
+++ b/db/storage.h
@@ -25,7 +25,7 @@ public:
DiskLoc() { reserved = -1; ofs = NullOfs; }
DiskLoc(const DiskLoc& l) { reserved=l.reserved; ofs=l.ofs; }
- bool isNull() { return ofs == NullOfs; }
+ bool isNull() const { return ofs == NullOfs; }
void Null() { reserved = -1; ofs = NullOfs; }
void assertOk() { assert(!isNull()); }
diff --git a/db/testdb.js b/db/testdb.js
index d8fdfd2aeff..8a9abae3c91 100644
--- a/db/testdb.js
+++ b/db/testdb.js
@@ -2,7 +2,7 @@
var fail = 0;
-var t = connect("test", "192.168.37.1");
+var t = connect("test", "192.168.79.1");
var z = 0;
function progress() {}// print(++z); }
@@ -48,21 +48,52 @@ function testdelete() {
assert( t.testkeys.find().toArray().length == 4, "testkeys" );
}
+function bigIndexTest() {
+ t.big.remove({});
+ t.big.save( { name: "Dwight" } );
+ t.big.ensureIndex({name: true});
+ for( var i = 0; i < 1000; i++ ) {
+ var x = { name: "e" + Math.random() + "abcdefasdflkjfdslkjdslkjfdslkjfdslkjfdslkjdflkj fdslkjfdslkjdsljfdslkjdsl fdslkfdslkjfdslkjlkjdsf fdslkjfds",
+ addr: "1234 main", phone: 7 };
+ t.big.save(x);
+ }
+ for( var i = 0; i < 1000; i++ ) {
+ var x = { name: "c" + Math.random() + "abcdefasdflkjfdslkjdslkjfdslkjfdslkjfdslkjdflkj fdslkjfdslkjdsljfdslkjdsl fdslkfdslkjfdslkjlkjdsf fdslkjfds",
+ addr: "1234 main", phone: 7 };
+ t.big.save(x);
+ }
+}
+
function runall() {
- print("runall");
+ runquick();
+
+ print("bigindextest stuff:");
+ t.big.remove( { } );
+ bigIndexTest();
+ t.big.find().sort({name:true});
+ t.big.remove( { } );
+ t.big.find().sort({name:true});
+ bigIndexTest();
+ t.big.find().sort({name:true});
+ t.big.remove( { } );
+}
+
+function runquick() {
+ print("runquick");
t.nullcheck.remove({});
- t.nullcheck.save( { a : 3 } );
- oneresult( t.nullcheck.find() ); progress();
- print("runall 1");
+ t.nullcheck.save( { a : 3 } );
+ oneresult( t.nullcheck.find() ); progress();
+ /* todo uncomment when eliot fixes!
assert( t.nullcheck.find({a:3})[0].a == 3, "a3" );
oneresult( t.nullcheck.find( { b: null } ) ); progress();
noresult( t.nullcheck.find( { b: 1 } ) ); progress();
oneresult( t.nullcheck.find( { a : "3" } ) ); progress();
-
+ */
// regex
print("regex");
+ t.reg.remove({});
t.reg.save( { name: "Dwight" } );
for( i = 0; i < 2; i++ ) {
oneresult( t.reg.find( { name: /Dwi./ } ), "re1" );
@@ -72,7 +103,8 @@ function runall() {
}
testdelete();
-
}
print("testdb.js: try runall()");
+print(" runquick()");
+print(" bigIndexTest()");