diff options
author | Aaron <aaron@10gen.com> | 2010-03-16 14:45:16 -0700 |
---|---|---|
committer | Aaron <aaron@10gen.com> | 2010-03-16 14:45:16 -0700 |
commit | c96de7cbb648f3d73759fab3e70c185244a57618 (patch) | |
tree | 6ddfd60055a611bba93dfba261feda286fe901c0 | |
parent | 3b46bf3fcca4813152fc57d063cac82739f00df0 (diff) | |
parent | 6ff986d3a53b20fe7b21c83f5265682acae4d7c1 (diff) | |
download | mongo-c96de7cbb648f3d73759fab3e70c185244a57618.tar.gz |
Merge branch 'master' of github.com:mongodb/mongo
-rw-r--r-- | db/client.cpp | 2 | ||||
-rw-r--r-- | db/index_geo2d.cpp | 120 | ||||
-rw-r--r-- | db/stats/top.cpp | 10 | ||||
-rw-r--r-- | db/stats/top.h | 1 | ||||
-rw-r--r-- | jstests/geo_box1.js | 28 |
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() ) +} + + + |