summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron <aaron@10gen.com>2010-03-16 14:45:16 -0700
committerAaron <aaron@10gen.com>2010-03-16 14:45:16 -0700
commitc96de7cbb648f3d73759fab3e70c185244a57618 (patch)
tree6ddfd60055a611bba93dfba261feda286fe901c0
parent3b46bf3fcca4813152fc57d063cac82739f00df0 (diff)
parent6ff986d3a53b20fe7b21c83f5265682acae4d7c1 (diff)
downloadmongo-c96de7cbb648f3d73759fab3e70c185244a57618.tar.gz
Merge branch 'master' of github.com:mongodb/mongo
-rw-r--r--db/client.cpp2
-rw-r--r--db/index_geo2d.cpp120
-rw-r--r--db/stats/top.cpp10
-rw-r--r--db/stats/top.h1
-rw-r--r--jstests/geo_box1.js28
5 files changed, 153 insertions, 8 deletions
diff --git a/db/client.cpp b/db/client.cpp
index 27c137e1dbc..294ceecc17d 100644
--- a/db/client.cpp
+++ b/db/client.cpp
@@ -69,6 +69,8 @@ namespace mongo {
didAnything = true;
for ( list<string>::iterator i = _tempCollections.begin(); i!=_tempCollections.end(); i++ ){
string ns = *i;
+ Top::global.collectionDropped( ns );
+
dblock l;
Client::Context ctx( ns );
if ( ! nsdetails( ns.c_str() ) )
diff --git a/db/index_geo2d.cpp b/db/index_geo2d.cpp
index 11e0a104342..effc80937be 100644
--- a/db/index_geo2d.cpp
+++ b/db/index_geo2d.cpp
@@ -499,6 +499,9 @@ namespace mongo {
: _x( x ) , _y( y ){
}
+ Point() : _x(0),_y(0){
+ }
+
string toString() const {
StringBuilder buf(32);
buf << "(" << _x << "," << _y << ")";
@@ -527,6 +530,8 @@ namespace mongo {
: _min( min ) , _max( max ){
}
+ Box(){}
+
string toString() const {
StringBuilder buf(64);
buf << _min.toString() << " -->> " << _max.toString();
@@ -538,7 +543,7 @@ namespace mongo {
}
bool between( double min , double max , double val ) const {
- return val >= min && val <= min;
+ return val >= min && val <= max;
}
bool mid( double amin , double amax , double bmin , double bmax , bool min , double& res ) const {
@@ -577,6 +582,21 @@ namespace mongo {
return ( _max._x - _min._x ) * ( _max._y - _min._y );
}
+ Point center() const {
+ return Point( ( _min._x + _max._x ) / 2 ,
+ ( _min._y + _max._y ) / 2 );
+ }
+
+ bool inside( Point p ){
+ return inside( p._x , p._y );
+ }
+
+ bool inside( double x , double y ){
+ return
+ between( _min._x , _max._x , x ) &&
+ between( _min._y , _max._y , y );
+ }
+
Point _min;
Point _max;
};
@@ -755,7 +775,8 @@ namespace mongo {
_matcher.reset( new CoveredIndexMatcher( filter , g->keyPattern() ) );
}
- virtual ~GeoAccumulator(){}
+ virtual ~GeoAccumulator(){
+ }
virtual void add( const KeyNode& node ){
// when looking at other boxes, don't want to look at some object twice
@@ -1038,6 +1059,8 @@ namespace mongo {
return false;
}
+ virtual string toString() const = 0;
+
const Geo2dType * _spec;
const IndexDetails * _id;
};
@@ -1213,7 +1236,6 @@ namespace mongo {
virtual bool checkDistance( const GeoHash& h , double& d ){
d = _g->distance( _start , h );
- _lastDistance = d;
return d <= ( _maxDistance + .01 );
}
@@ -1226,7 +1248,91 @@ namespace mongo {
BtreeLocation _min;
BtreeLocation _max;
- double _lastDistance;
+ };
+
+ class GeoBoxBrowse : public GeoBrowse {
+ public:
+
+ enum State {
+ START ,
+ DOING_EXPAND ,
+ DONE
+ } _state;
+
+ GeoBoxBrowse( const Geo2dType * g , const BSONObj& box , BSONObj filter = BSONObj() )
+ : GeoBrowse( g , "box" , filter ){
+
+ uassert( 13063 , "$box needs 2 fields (bottomLeft,topRight)" , box.nFields() == 2 );
+ BSONObjIterator i(box);
+ _bl = g->_tohash( i.next() );
+ _tr = g->_tohash( i.next() );
+
+ _want._min = Point( _g , _bl );
+ _want._max = Point( _g , _tr );
+
+ uassert( 13064 , "need an area > 0 " , _want.area() > 0 );
+
+ _state = START;
+ _found = 0;
+
+ Point center = _want.center();
+ _prefix = _g->_hash( center._x , center._y );
+
+ ok();
+ }
+
+ virtual bool moreToDo(){
+ return _state != DONE;
+ }
+
+ virtual void fillStack(){
+ if ( _state == START ){
+
+ if ( ! BtreeLocation::initial( *_id , _spec , _min , _max ,
+ _prefix , _found , this ) ){
+ _state = DONE;
+ return;
+ }
+ _state = DOING_EXPAND;
+ }
+
+ if ( _state == DOING_EXPAND ){
+ while ( _min.hasPrefix( _prefix ) && _min.advance( -1 , _found , this ) );
+ while ( _max.hasPrefix( _prefix ) && _max.advance( 1 , _found , this ) );
+
+ if ( ! _prefix.constrains() ){
+ // we've exhausted the btree
+ _state = DONE;
+ return;
+ }
+
+ Box cur( _g , _prefix );
+ if ( cur._min._x < _want._min._x &&
+ cur._min._y < _want._min._y &&
+ cur._max._x > _want._max._x &&
+ cur._max._y > _want._max._y ){
+ _state = DONE;
+ }
+ else
+ _prefix = _prefix.up();
+ return;
+ }
+
+ }
+
+ virtual bool checkDistance( const GeoHash& h , double& d ){
+ return _want.inside( Point( _g , h ) );
+ }
+
+ GeoHash _bl;
+ GeoHash _tr;
+ Box _want;
+
+ int _found;
+
+ GeoHash _prefix;
+ BtreeLocation _min;
+ BtreeLocation _max;
};
@@ -1266,6 +1372,12 @@ namespace mongo {
c.reset( new GeoCircleBrowse( this , e.embeddedObjectUserCheck() , query ) );
return c;
}
+ else if ( type == "$box" ){
+ uassert( 13065 , "$box has to take an object or array" , e.isABSONObj() );
+ auto_ptr<Cursor> c;
+ c.reset( new GeoBoxBrowse( this , e.embeddedObjectUserCheck() , query ) );
+ return c;
+ }
throw UserException( 13058 , (string)"unknown $with type: " + type );
}
default:
diff --git a/db/stats/top.cpp b/db/stats/top.cpp
index 0c1bd1900af..0f27943df06 100644
--- a/db/stats/top.cpp
+++ b/db/stats/top.cpp
@@ -44,9 +44,15 @@ namespace mongo {
}
-
+
void Top::record( const string& ns , int op , int lockType , long long micros , bool command ){
+ //cout << "record: " << ns << "\t" << op << "\t" << command << endl;
scoped_lock lk(_lock);
+
+ if ( ( command || op == dbQuery ) && ns == _lastDropped ){
+ _lastDropped = "";
+ return;
+ }
CollectionData& coll = _usage[ns];
_record( coll , op , lockType , micros , command );
@@ -54,8 +60,10 @@ namespace mongo {
}
void Top::collectionDropped( const string& ns ){
+ //cout << "collectionDropped: " << ns << endl;
scoped_lock lk(_lock);
_usage.erase(ns);
+ _lastDropped = ns;
}
void Top::_record( CollectionData& c , int op , int lockType , long long micros , bool command ){
diff --git a/db/stats/top.h b/db/stats/top.h
index 1f977061666..8dab3b0136d 100644
--- a/db/stats/top.h
+++ b/db/stats/top.h
@@ -85,6 +85,7 @@ namespace mongo {
mongo::mutex _lock;
CollectionData _global;
UsageMap _usage;
+ string _lastDropped;
};
/* Records per namespace utilization of the mongod process.
diff --git a/jstests/geo_box1.js b/jstests/geo_box1.js
index 20ab8882888..0801f6c916b 100644
--- a/jstests/geo_box1.js
+++ b/jstests/geo_box1.js
@@ -2,11 +2,33 @@
t = db.geo_box1;
t.drop();
-for ( x=0; x<=20; x++ )
- for ( y=0; y<=20; y++ )
- t.save( { loc : [ x , y ] } )
+num = 0;
+for ( x=0; x<=20; x++ ){
+ for ( y=0; y<=20; y++ ){
+ o = { _id : num++ , loc : [ x , y ] }
+ t.save( o )
+ }
+}
t.ensureIndex( { loc : "2d" } );
+searches = [
+ [ [ 1 , 2 ] , [ 4 , 5 ] ] ,
+ [ [ 1 , 1 ] , [ 2 , 2 ] ] ,
+ [ [ 0 , 2 ] , [ 4 , 5 ] ] ,
+ [ [ 1 , 1 ] , [ 2 , 8 ] ] ,
+];
+
+for ( i=0; i<searches.length; i++ ){
+ b = searches[i];
+ //printjson( b );
+ q = { loc : { $within : { $box : b } } }
+ numWanetd = ( 1 + b[1][0] - b[0][0] ) * ( 1 + b[1][1] - b[0][1] );
+ assert.eq( numWanetd , t.find(q).itcount() , "itcount: " + q );
+ printjson( t.find(q).explain() )
+}
+
+
+