chunk_diff.hpp | chunk_diff.hpp | |||
---|---|---|---|---|
skipping to change at line 287 | skipping to change at line 287 | |||
// | // | |||
// We don't want to send a giant $or query to the server, so ju st get all the chunks | // We don't want to send a giant $or query to the server, so ju st get all the chunks | |||
// | // | |||
queryB.append( "ns", _ns ); | queryB.append( "ns", _ns ); | |||
} | } | |||
BSONObj query = queryB.obj(); | BSONObj query = queryB.obj(); | |||
// log() << "major version query from " << *_maxVersion << " and ov | LOG(2) << "major version query from " << *_maxVersion << " and over | |||
er " << _maxShardVersions->size() << " shards is " << query << endl; | " | |||
<< _maxShardVersions->size() << " shards is " << query << en | ||||
dl; | ||||
// | ||||
// NOTE: IT IS IMPORTANT FOR CONSISTENCY THAT WE SORT BY ASC VERSIO | ||||
N, TO HANDLE | ||||
// CURSOR YIELDING BETWEEN CHUNKS BEING MIGRATED. | ||||
// | ||||
Query queryObj(query); | ||||
queryObj.sort(BSON( "lastmod" << 1 )); | ||||
return Query( query ); | return Query( query ); | |||
} | } | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 13 lines changed or added | |||
client_info.h | client_info.h | |||
---|---|---|---|---|
skipping to change at line 108 | skipping to change at line 108 | |||
void noAutoSplit() { _autoSplitOk = false; } | void noAutoSplit() { _autoSplitOk = false; } | |||
static ClientInfo * get(); | static ClientInfo * get(); | |||
const AuthenticationInfo* getAuthenticationInfo() const { return (A uthenticationInfo*)&_ai; } | const AuthenticationInfo* getAuthenticationInfo() const { return (A uthenticationInfo*)&_ai; } | |||
AuthenticationInfo* getAuthenticationInfo() { return (Authenticatio nInfo*)&_ai; } | AuthenticationInfo* getAuthenticationInfo() { return (Authenticatio nInfo*)&_ai; } | |||
bool isAdmin() { return _ai.isAuthorized( "admin" ); } | bool isAdmin() { return _ai.isAuthorized( "admin" ); } | |||
private: | private: | |||
AuthenticationInfo _ai; | AuthenticationInfo _ai; | |||
struct WBInfo { | struct WBInfo { | |||
WBInfo( const WriteBackListener::ConnectionIdent& c , OID o ) : | WBInfo( const WriteBackListener::ConnectionIdent& c, OID o, boo | |||
ident( c ) , id( o ) {} | l fromLastOperation ) | |||
: ident( c ), id( o ), fromLastOperation( fromLastOperation | ||||
) {} | ||||
WriteBackListener::ConnectionIdent ident; | WriteBackListener::ConnectionIdent ident; | |||
OID id; | OID id; | |||
bool fromLastOperation; | ||||
}; | }; | |||
// for getLastError | // for getLastError | |||
void _addWriteBack( vector<WBInfo>& all , const BSONObj& o ); | void _addWriteBack( vector<WBInfo>& all , const BSONObj& o, bool fr | |||
vector<BSONObj> _handleWriteBacks( vector<WBInfo>& all , bool fromW | omLastOperation ); | |||
riteBackListener ); | vector<BSONObj> _handleWriteBacks( const vector<WBInfo>& all , bool | |||
fromWriteBackListener ); | ||||
int _id; // unique client id | int _id; // unique client id | |||
HostAndPort _remote; // server:port of remote socket end | HostAndPort _remote; // server:port of remote socket end | |||
// we use _a and _b to store shards we've talked to on the current request and the previous | // we use _a and _b to store shards we've talked to on the current request and the previous | |||
// we use 2 so we can flip for getLastError type operations | // we use 2 so we can flip for getLastError type operations | |||
set<string> _a; // actual set for _cur or _prev | set<string> _a; // actual set for _cur or _prev | |||
set<string> _b; // " | set<string> _b; // " | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 9 lines changed or added | |||
core.h | core.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "../jsobj.h" | #include "../jsobj.h" | |||
#include "shapes.h" | ||||
#include <cmath> | #include <cmath> | |||
#ifndef M_PI | #ifndef M_PI | |||
# define M_PI 3.14159265358979323846 | # define M_PI 3.14159265358979323846 | |||
#endif | #endif | |||
namespace mongo { | namespace mongo { | |||
class GeoBitSets { | class GeoBitSets { | |||
skipping to change at line 403 | skipping to change at line 404 | |||
} | } | |||
class GeoConvert { | class GeoConvert { | |||
public: | public: | |||
virtual ~GeoConvert() {} | virtual ~GeoConvert() {} | |||
virtual void unhash( const GeoHash& h , double& x , double& y ) con st = 0; | virtual void unhash( const GeoHash& h , double& x , double& y ) con st = 0; | |||
virtual GeoHash hash( double x , double y ) const = 0; | virtual GeoHash hash( double x , double y ) const = 0; | |||
}; | }; | |||
class Point { | ||||
public: | ||||
Point( const GeoConvert * g , const GeoHash& hash ) { | ||||
g->unhash( hash , _x , _y ); | ||||
} | ||||
explicit Point( const BSONElement& e ) { | ||||
BSONObjIterator i(e.Obj()); | ||||
_x = i.next().number(); | ||||
_y = i.next().number(); | ||||
} | ||||
explicit Point( const BSONObj& o ) { | ||||
BSONObjIterator i(o); | ||||
_x = i.next().number(); | ||||
_y = i.next().number(); | ||||
} | ||||
Point( double x , double y ) | ||||
: _x( x ) , _y( y ) { | ||||
} | ||||
Point() : _x(0),_y(0) { | ||||
} | ||||
GeoHash hash( const GeoConvert * g ) { | ||||
return g->hash( _x , _y ); | ||||
} | ||||
double distance( const Point& p ) const { | ||||
double a = _x - p._x; | ||||
double b = _y - p._y; | ||||
// Avoid numerical error if possible... | ||||
if( a == 0 ) return abs( _y - p._y ); | ||||
if( b == 0 ) return abs( _x - p._x ); | ||||
return sqrt( ( a * a ) + ( b * b ) ); | ||||
} | ||||
/** | ||||
* Distance method that compares x or y coords when other direction | ||||
is zero, | ||||
* avoids numerical error when distances are very close to radius b | ||||
ut axis-aligned. | ||||
* | ||||
* An example of the problem is: | ||||
* (52.0 - 51.9999) - 0.0001 = 3.31965e-15 and 52.0 - 51.9999 > 0.0 | ||||
001 in double arithmetic | ||||
* but: | ||||
* 51.9999 + 0.0001 <= 52.0 | ||||
* | ||||
* This avoids some (but not all!) suprising results in $center que | ||||
ries where points are | ||||
* ( radius + center.x, center.y ) or vice-versa. | ||||
*/ | ||||
bool distanceWithin( const Point& p, double radius ) const { | ||||
double a = _x - p._x; | ||||
double b = _y - p._y; | ||||
if( a == 0 ) { | ||||
// | ||||
// Note: For some, unknown reason, when a 32-bit g++ optim | ||||
izes this call, the sum is | ||||
// calculated imprecisely. We need to force the compiler t | ||||
o always evaluate it correctly, | ||||
// hence the weirdness. | ||||
// | ||||
// On some 32-bit linux machines, removing the volatile key | ||||
word or calculating the sum inline | ||||
// will make certain geo tests fail. Of course this check | ||||
will force volatile for all 32-bit systems, | ||||
// not just affected systems. | ||||
if( sizeof(void*) <= 4 ){ | ||||
volatile double sum = _y > p._y ? p._y + radius : _y + | ||||
radius; | ||||
return _y > p._y ? sum >= _y : sum >= p._y; | ||||
} | ||||
else { | ||||
// Original math, correct for most systems | ||||
return _y > p._y ? p._y + radius >= _y : _y + radius >= | ||||
p._y; | ||||
} | ||||
} | ||||
if( b == 0 ) { | ||||
if( sizeof(void*) <= 4 ){ | ||||
volatile double sum = _x > p._x ? p._x + radius : _x + | ||||
radius; | ||||
return _x > p._x ? sum >= _x : sum >= p._x; | ||||
} | ||||
else { | ||||
return _x > p._x ? p._x + radius >= _x : _x + radius >= | ||||
p._x; | ||||
} | ||||
} | ||||
return sqrt( ( a * a ) + ( b * b ) ) <= radius; | ||||
} | ||||
string toString() const { | ||||
StringBuilder buf; | ||||
buf << "(" << _x << "," << _y << ")"; | ||||
return buf.str(); | ||||
} | ||||
double _x; | ||||
double _y; | ||||
}; | ||||
extern const double EARTH_RADIUS_KM; | extern const double EARTH_RADIUS_KM; | |||
extern const double EARTH_RADIUS_MILES; | extern const double EARTH_RADIUS_MILES; | |||
// Technically lat/long bounds, not really tied to earth radius. | // Technically lat/long bounds, not really tied to earth radius. | |||
inline void checkEarthBounds( Point p ) { | inline void checkEarthBounds( Point p ) { | |||
uassert( 14808, str::stream() << "point " << p.toString() << " must be in earth-like bounds of long : [-180, 180], lat : [-90, 90] ", | uassert( 14808, str::stream() << "point " << p.toString() << " must be in earth-like bounds of long : [-180, 180], lat : [-90, 90] ", | |||
p._x >= -180 && p._x <= 180 && p._y >= -90 && p._y <= 90 ) ; | p._x >= -180 && p._x <= 180 && p._y >= -90 && p._y <= 90 ) ; | |||
} | } | |||
inline double deg2rad(double deg) { return deg * (M_PI/180); } | inline double deg2rad(double deg) { return deg * (M_PI/180); } | |||
End of changes. 2 change blocks. | ||||
111 lines changed or deleted | 1 lines changed or added | |||
dbclientinterface.h | dbclientinterface.h | |||
---|---|---|---|---|
skipping to change at line 250 | skipping to change at line 250 | |||
string toString() const { return _string; } | string toString() const { return _string; } | |||
DBClientBase* connect( string& errmsg, double socketTimeout = 0 ) c onst; | DBClientBase* connect( string& errmsg, double socketTimeout = 0 ) c onst; | |||
string getSetName() const { return _setName; } | string getSetName() const { return _setName; } | |||
vector<HostAndPort> getServers() const { return _servers; } | vector<HostAndPort> getServers() const { return _servers; } | |||
ConnectionType type() const { return _type; } | ConnectionType type() const { return _type; } | |||
/** | ||||
* This returns true if this and other point to the same logical en | ||||
tity. | ||||
* For single nodes, thats the same address. | ||||
* For replica sets, thats just the same replica set name. | ||||
* For pair (deprecated) or sync cluster connections, that's the sa | ||||
me hosts in any ordering. | ||||
*/ | ||||
bool sameLogicalEndpoint( const ConnectionString& other ) const; | ||||
static ConnectionString parse( const string& url , string& errmsg ) ; | static ConnectionString parse( const string& url , string& errmsg ) ; | |||
static string typeToString( ConnectionType type ); | static string typeToString( ConnectionType type ); | |||
// | // | |||
// Allow overriding the default connection behavior | // Allow overriding the default connection behavior | |||
// This is needed for some tests, which otherwise would fail becaus e they are unable to contact | // This is needed for some tests, which otherwise would fail becaus e they are unable to contact | |||
// the correct servers. | // the correct servers. | |||
// | // | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 10 lines changed or added | |||
hostandport.h | hostandport.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* | * | |||
* Unless required by applicable law or agreed to in writing, software | * Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli ed. | |||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "sock.h" | #include "mongo/db/cmdline.h" | |||
#include "../../db/cmdline.h" | #include "mongo/util/mongoutils/str.h" | |||
#include "../mongoutils/str.h" | #include "mongo/util/net/sock.h" | |||
#include "mongo/bson/util/builder.h" | ||||
namespace mongo { | namespace mongo { | |||
using namespace mongoutils; | using namespace mongoutils; | |||
/** helper for manipulating host:port connection endpoints. | /** helper for manipulating host:port connection endpoints. | |||
*/ | */ | |||
struct HostAndPort { | struct HostAndPort { | |||
HostAndPort() : _port(-1) { } | HostAndPort() : _port(-1) { } | |||
skipping to change at line 75 | skipping to change at line 76 | |||
bool isLocalHost() const; | bool isLocalHost() const; | |||
/** | /** | |||
* @param includePort host:port if true, host otherwise | * @param includePort host:port if true, host otherwise | |||
*/ | */ | |||
string toString( bool includePort=true ) const; | string toString( bool includePort=true ) const; | |||
operator string() const { return toString(); } | operator string() const { return toString(); } | |||
void append( StringBuilder& ss ) const; | ||||
bool empty() const { | bool empty() const { | |||
return _host.empty() && _port < 0; | return _host.empty() && _port < 0; | |||
} | } | |||
string host() const { | string host() const { | |||
return _host; | return _host; | |||
} | } | |||
int port() const { | int port() const { | |||
if (hasPort()) | if (hasPort()) | |||
return _port; | return _port; | |||
return CmdLine::DefaultDBPort; | return CmdLine::DefaultDBPort; | |||
skipping to change at line 125 | skipping to change at line 128 | |||
} | } | |||
} | } | |||
string h = getHostName(); | string h = getHostName(); | |||
verify( !h.empty() ); | verify( !h.empty() ); | |||
verify( h != "localhost" ); | verify( h != "localhost" ); | |||
return HostAndPort(h, cmdLine.port); | return HostAndPort(h, cmdLine.port); | |||
} | } | |||
inline string HostAndPort::toString( bool includePort ) const { | inline string HostAndPort::toString( bool includePort ) const { | |||
string h = host(); | ||||
int p = port(); | ||||
if ( ! includePort ) | if ( ! includePort ) | |||
return h; | return host(); | |||
StringBuilder ss; | ||||
append( ss ); | ||||
return ss.str(); | ||||
} | ||||
inline void HostAndPort::append( StringBuilder& ss ) const { | ||||
ss << host(); | ||||
int p = port(); | ||||
stringstream ss; | ||||
ss << h; | ||||
if ( p != -1 ) { | if ( p != -1 ) { | |||
ss << ':'; | ss << ':'; | |||
#if defined(_DEBUG) | #if defined(_DEBUG) | |||
if( p >= 44000 && p < 44100 ) { | if( p >= 44000 && p < 44100 ) { | |||
log() << "warning: special debug port 44xxx used" << endl; | log() << "warning: special debug port 44xxx used" << endl; | |||
ss << p+1; | ss << p+1; | |||
} | } | |||
else | else | |||
ss << p; | ss << p; | |||
#else | #else | |||
ss << p; | ss << p; | |||
#endif | #endif | |||
} | } | |||
return ss.str(); | ||||
} | } | |||
inline bool HostAndPort::isLocalHost() const { | inline bool HostAndPort::isLocalHost() const { | |||
string _host = host(); | string _host = host(); | |||
return ( _host == "localhost" | return ( _host == "localhost" | |||
|| startsWith(_host.c_str(), "127.") | || startsWith(_host.c_str(), "127.") | |||
|| _host == "::1" | || _host == "::1" | |||
|| _host == "anonymous unix socket" | || _host == "anonymous unix socket" | |||
|| _host.c_str()[0] == '/' // unix socket | || _host.c_str()[0] == '/' // unix socket | |||
); | ); | |||
End of changes. 6 change blocks. | ||||
10 lines changed or deleted | 18 lines changed or added | |||
lasterror.h | lasterror.h | |||
---|---|---|---|---|
skipping to change at line 32 | skipping to change at line 32 | |||
namespace mongo { | namespace mongo { | |||
class BSONObjBuilder; | class BSONObjBuilder; | |||
class Message; | class Message; | |||
struct LastError { | struct LastError { | |||
int code; | int code; | |||
string msg; | string msg; | |||
enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; | enum UpdatedExistingType { NotUpdate, True, False } updatedExisting ; | |||
OID upsertedId; | OID upsertedId; | |||
OID writebackId; // this shouldn't get reset so that old GLE are ha ndled | OID writebackId; // this shouldn't get reset so that old GLE are ha ndled | |||
int writebackSince; | ||||
long long nObjects; | long long nObjects; | |||
int nPrev; | int nPrev; | |||
bool valid; | bool valid; | |||
bool disabled; | bool disabled; | |||
void writeback( OID& oid ) { | void writeback( OID& oid ) { | |||
reset( true ); | reset( true ); | |||
writebackId = oid; | writebackId = oid; | |||
writebackSince = 0; | ||||
} | } | |||
void raiseError(int _code , const char *_msg) { | void raiseError(int _code , const char *_msg) { | |||
reset( true ); | reset( true ); | |||
code = _code; | code = _code; | |||
msg = _msg; | msg = _msg; | |||
} | } | |||
void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ) { | void recordUpdate( bool _updateObjects , long long _nObjects , OID _upsertedId ) { | |||
reset( true ); | reset( true ); | |||
nObjects = _nObjects; | nObjects = _nObjects; | |||
updatedExisting = _updateObjects ? True : False; | updatedExisting = _updateObjects ? True : False; | |||
if ( _upsertedId.isSet() ) | if ( _upsertedId.isSet() ) | |||
upsertedId = _upsertedId; | upsertedId = _upsertedId; | |||
} | } | |||
void recordDelete( long long nDeleted ) { | void recordDelete( long long nDeleted ) { | |||
reset( true ); | reset( true ); | |||
nObjects = nDeleted; | nObjects = nDeleted; | |||
} | } | |||
LastError() { | LastError() { | |||
reset(); | reset(); | |||
writebackSince = 0; | ||||
} | } | |||
void reset( bool _valid = false ) { | void reset( bool _valid = false ) { | |||
code = 0; | code = 0; | |||
msg.clear(); | msg.clear(); | |||
updatedExisting = NotUpdate; | updatedExisting = NotUpdate; | |||
nObjects = 0; | nObjects = 0; | |||
nPrev = 1; | nPrev = 1; | |||
valid = _valid; | valid = _valid; | |||
disabled = false; | disabled = false; | |||
upsertedId.clear(); | upsertedId.clear(); | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 3 lines changed or added | |||
matcher.h | matcher.h | |||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
* GNU Affero General Public License for more details. | * GNU Affero General Public License for more details. | |||
* | * | |||
* You should have received a copy of the GNU Affero General Public Licen se | * You should have received a copy of the GNU Affero General Public Licen se | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "jsobj.h" | #include "jsobj.h" | |||
#include "pcrecpp.h" | #include "pcrecpp.h" | |||
#include "geo/shapes.h" | ||||
namespace mongo { | namespace mongo { | |||
class Cursor; | class Cursor; | |||
class CoveredIndexMatcher; | class CoveredIndexMatcher; | |||
class ElementMatcher; | class ElementMatcher; | |||
class Matcher; | class Matcher; | |||
class FieldRangeVector; | class FieldRangeVector; | |||
class RegexMatcher { | class RegexMatcher { | |||
public: | public: | |||
const char *_fieldName; | const char *_fieldName; | |||
const char *_regex; | const char *_regex; | |||
const char *_flags; | const char *_flags; | |||
string _prefix; | string _prefix; | |||
shared_ptr< pcrecpp::RE > _re; | shared_ptr< pcrecpp::RE > _re; | |||
bool _isNot; | bool _isNot; | |||
RegexMatcher() : _isNot() {} | RegexMatcher() : _isNot() {} | |||
}; | }; | |||
class GeoMatcher { | ||||
private: | ||||
GeoMatcher(const string& field) : _isBox(false), _isCircle(false), | ||||
_isPolygon(false), | ||||
_fieldName(field) {} | ||||
bool _isBox; | ||||
Box _box; | ||||
bool _isCircle; | ||||
Point _center; | ||||
double _radius; | ||||
bool _isPolygon; | ||||
Polygon _polygon; | ||||
string _fieldName; | ||||
public: | ||||
const string& getFieldName() const { return _fieldName; } | ||||
static GeoMatcher makeBox(const string& field, const BSONObj &min, | ||||
const BSONObj &max) { | ||||
GeoMatcher m(field); | ||||
m._isBox = true; | ||||
uassert(16470, "Malformed coord: " + min.toString(), pointFrom( | ||||
min, &m._box._min)); | ||||
uassert(16471, "Malformed coord: " + max.toString(), pointFrom( | ||||
max, &m._box._max)); | ||||
return m; | ||||
} | ||||
static GeoMatcher makeCircle(const string& field, const BSONObj &ce | ||||
nter, double rad) { | ||||
GeoMatcher m(field); | ||||
m._isCircle = true; | ||||
uassert(16472, "Malformed coord: " + center.toString(), pointFr | ||||
om(center, &m._center)); | ||||
m._radius = rad; | ||||
return m; | ||||
} | ||||
static GeoMatcher makePolygon(const string& field, const BSONObj &p | ||||
oly) { | ||||
GeoMatcher m(field); | ||||
vector<Point> points; | ||||
m._isPolygon = true; | ||||
BSONObjIterator coordIt(poly); | ||||
while (coordIt.more()) { | ||||
BSONElement coord = coordIt.next(); | ||||
const BSONObj& obj = coord.Obj(); | ||||
Point p; | ||||
uassert(16480, "Malformed coord: " + obj.toString(), pointF | ||||
rom(obj, &p)); | ||||
points.push_back(p); | ||||
} | ||||
m._polygon = Polygon(points); | ||||
return m; | ||||
} | ||||
bool containsPoint(Point p) const { | ||||
if (_isBox) { | ||||
return _box.inside(p, 0); | ||||
} else if (_isCircle) { | ||||
return _center.distance(p) <= _radius; | ||||
} else if (_isPolygon) { | ||||
return _polygon.contains(p); | ||||
} else { | ||||
return false; | ||||
} | ||||
} | ||||
string toString() const { | ||||
stringstream ss; | ||||
if (_isBox) { | ||||
ss << "GeoMatcher Box: " << _box.toString(); | ||||
} else if (_isCircle) { | ||||
ss << "GeoMatcher Circle @ " << _center.toString() << " r = | ||||
" << _radius; | ||||
} else { | ||||
ss << "GeoMatcher UNKNOWN"; | ||||
} | ||||
return ss.str(); | ||||
} | ||||
static bool pointFrom(const BSONObj o, Point *p) { | ||||
BSONObjIterator i(o); | ||||
if (!i.more()) { return false; } | ||||
BSONElement xe = i.next(); | ||||
if (!i.more()) { return false; } | ||||
BSONElement ye = i.next(); | ||||
if (!xe.isNumber() || !ye.isNumber()) { return false; } | ||||
p->_x = xe.number(); | ||||
p->_y = ye.number(); | ||||
return true; | ||||
} | ||||
}; | ||||
struct element_lt { | struct element_lt { | |||
bool operator()(const BSONElement& l, const BSONElement& r) const { | bool operator()(const BSONElement& l, const BSONElement& r) const { | |||
int x = (int) l.canonicalType() - (int) r.canonicalType(); | int x = (int) l.canonicalType() - (int) r.canonicalType(); | |||
if ( x < 0 ) return true; | if ( x < 0 ) return true; | |||
else if ( x > 0 ) return false; | else if ( x > 0 ) return false; | |||
return compareElementValues(l,r) < 0; | return compareElementValues(l,r) < 0; | |||
} | } | |||
}; | }; | |||
/** | /** | |||
skipping to change at line 269 | skipping to change at line 358 | |||
bool _haveNeg; | bool _haveNeg; | |||
/* $atomic - if true, a multi document operation (some removes, upd ates) | /* $atomic - if true, a multi document operation (some removes, upd ates) | |||
should be done atomically. in that case, we do not yi eld - | should be done atomically. in that case, we do not yi eld - | |||
i.e. we stay locked the whole time. | i.e. we stay locked the whole time. | |||
http://dochub.mongodb.org/core/remove | http://dochub.mongodb.org/core/remove | |||
*/ | */ | |||
bool _atomic; | bool _atomic; | |||
vector<RegexMatcher> _regexs; | vector<RegexMatcher> _regexs; | |||
vector<GeoMatcher> _geo; | ||||
// so we delete the mem when we're done: | // so we delete the mem when we're done: | |||
vector< shared_ptr< BSONObjBuilder > > _builders; | vector< shared_ptr< BSONObjBuilder > > _builders; | |||
list< shared_ptr< Matcher > > _andMatchers; | list< shared_ptr< Matcher > > _andMatchers; | |||
list< shared_ptr< Matcher > > _orMatchers; | list< shared_ptr< Matcher > > _orMatchers; | |||
list< shared_ptr< Matcher > > _norMatchers; | list< shared_ptr< Matcher > > _norMatchers; | |||
friend class CoveredIndexMatcher; | friend class CoveredIndexMatcher; | |||
}; | }; | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 99 lines changed or added | |||
queryutil.h | queryutil.h | |||
---|---|---|---|---|
skipping to change at line 361 | skipping to change at line 361 | |||
string getSpecial() const { return _special; } | string getSpecial() const { return _special; } | |||
/** Make component intervals noninclusive. */ | /** Make component intervals noninclusive. */ | |||
void setExclusiveBounds(); | void setExclusiveBounds(); | |||
/** | /** | |||
* Constructs a range where all FieldIntervals and FieldBounds are in | * Constructs a range where all FieldIntervals and FieldBounds are in | |||
* the opposite order of the current range. | * the opposite order of the current range. | |||
* NOTE the resulting intervals might not be strictValid(). | * NOTE the resulting intervals might not be strictValid(). | |||
*/ | */ | |||
void reverse( FieldRange &ret ) const; | void reverse( FieldRange &ret ) const; | |||
bool hasSpecialThatNeedsIndex() const { verify( _special.size() ); | ||||
return _specialNeedsIndex; } | ||||
string toString() const; | string toString() const; | |||
private: | private: | |||
BSONObj addObj( const BSONObj &o ); | BSONObj addObj( const BSONObj &o ); | |||
void finishOperation( const vector<FieldInterval> &newIntervals, co nst FieldRange &other, | void finishOperation( const vector<FieldInterval> &newIntervals, co nst FieldRange &other, | |||
bool exactMatchRepresentation ); | bool exactMatchRepresentation ); | |||
vector<FieldInterval> _intervals; | vector<FieldInterval> _intervals; | |||
// Owns memory for our BSONElements. | // Owns memory for our BSONElements. | |||
vector<BSONObj> _objData; | vector<BSONObj> _objData; | |||
string _special; | string _special; | |||
bool _specialNeedsIndex; | ||||
bool _exactMatchRepresentation; | bool _exactMatchRepresentation; | |||
}; | }; | |||
/** | /** | |||
* A BoundList contains intervals specified by inclusive start | * A BoundList contains intervals specified by inclusive start | |||
* and end bounds. The intervals should be nonoverlapping and occur in | * and end bounds. The intervals should be nonoverlapping and occur in | |||
* the specified direction of traversal. For example, given a simple i ndex {i:1} | * the specified direction of traversal. For example, given a simple i ndex {i:1} | |||
* and direction +1, one valid BoundList is: (1, 2); (4, 6). The same BoundList | * and direction +1, one valid BoundList is: (1, 2); (4, 6). The same BoundList | |||
* would be valid for index {i:-1} with direction -1. | * would be valid for index {i:-1} with direction -1. | |||
*/ | */ | |||
skipping to change at line 459 | skipping to change at line 462 | |||
/** | /** | |||
* @return a simplified query from the extreme values of the non un iversal | * @return a simplified query from the extreme values of the non un iversal | |||
* fields. | * fields. | |||
* @param fields If specified, the fields of the returned object ar e | * @param fields If specified, the fields of the returned object ar e | |||
* ordered to match those of 'fields'. | * ordered to match those of 'fields'. | |||
*/ | */ | |||
BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const; | BSONObj simplifiedQuery( const BSONObj &fields = BSONObj() ) const; | |||
QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; | QueryPattern pattern( const BSONObj &sort = BSONObj() ) const; | |||
string getSpecial() const; | string getSpecial() const; | |||
bool hasSpecialThatNeedsIndex() const; | ||||
/** | /** | |||
* @return a FieldRangeSet approximation of the documents in 'this' but | * @return a FieldRangeSet approximation of the documents in 'this' but | |||
* not in 'other'. The approximation will be a superset of the doc uments | * not in 'other'. The approximation will be a superset of the doc uments | |||
* in 'this' but not 'other'. | * in 'this' but not 'other'. | |||
*/ | */ | |||
const FieldRangeSet &operator-=( const FieldRangeSet &other ); | const FieldRangeSet &operator-=( const FieldRangeSet &other ); | |||
/** @return intersection of 'this' with 'other'. */ | /** @return intersection of 'this' with 'other'. */ | |||
const FieldRangeSet &operator&=( const FieldRangeSet &other ); | const FieldRangeSet &operator&=( const FieldRangeSet &other ); | |||
skipping to change at line 580 | skipping to change at line 584 | |||
bool matchPossible() const { return _multiKey.matchPossible(); } | bool matchPossible() const { return _multiKey.matchPossible(); } | |||
/** | /** | |||
* @return false if a match is impossible on the specified index. | * @return false if a match is impossible on the specified index. | |||
* @param idxNo -1 for non index scan. | * @param idxNo -1 for non index scan. | |||
*/ | */ | |||
bool matchPossibleForIndex( NamespaceDetails *d, int idxNo, const B SONObj &keyPattern ) const; | bool matchPossibleForIndex( NamespaceDetails *d, int idxNo, const B SONObj &keyPattern ) const; | |||
const char *ns() const { return _singleKey.ns(); } | const char *ns() const { return _singleKey.ns(); } | |||
string getSpecial() const { return _singleKey.getSpecial(); } | string getSpecial() const { return _singleKey.getSpecial(); } | |||
bool hasSpecialThatNeedsIndex() const { return _singleKey.hasSpecia lThatNeedsIndex(); } | ||||
/** Intersect with another FieldRangeSetPair. */ | /** Intersect with another FieldRangeSetPair. */ | |||
FieldRangeSetPair &operator&=( const FieldRangeSetPair &other ); | FieldRangeSetPair &operator&=( const FieldRangeSetPair &other ); | |||
/** | /** | |||
* Subtract a FieldRangeSet, generally one expressing a range that has | * Subtract a FieldRangeSet, generally one expressing a range that has | |||
* already been scanned. | * already been scanned. | |||
*/ | */ | |||
FieldRangeSetPair &operator-=( const FieldRangeSet &scanned ); | FieldRangeSetPair &operator-=( const FieldRangeSet &scanned ); | |||
BoundList shardKeyIndexBounds( const BSONObj &keyPattern ) const { | BoundList shardKeyIndexBounds( const BSONObj &keyPattern ) const { | |||
End of changes. 4 change blocks. | ||||
0 lines changed or deleted | 6 lines changed or added | |||
shard.h | shard.h | |||
---|---|---|---|---|
skipping to change at line 102 | skipping to change at line 102 | |||
string toString() const { | string toString() const { | |||
return _name + ":" + _addr; | return _name + ":" + _addr; | |||
} | } | |||
friend ostream& operator << (ostream& out, const Shard& s) { | friend ostream& operator << (ostream& out, const Shard& s) { | |||
return (out << s.toString()); | return (out << s.toString()); | |||
} | } | |||
bool operator==( const Shard& s ) const { | bool operator==( const Shard& s ) const { | |||
bool n = _name == s._name; | if ( _name != s._name ) | |||
bool a = _addr == s._addr; | return false; | |||
return _cs.sameLogicalEndpoint( s._cs ); | ||||
verify( n == a ); // names and address are 1 to 1 | ||||
return n; | ||||
} | } | |||
bool operator!=( const Shard& s ) const { | bool operator!=( const Shard& s ) const { | |||
bool n = _name == s._name; | return ! ( *this == s ); | |||
bool a = _addr == s._addr; | ||||
return ! ( n && a ); | ||||
} | } | |||
bool operator==( const string& s ) const { | bool operator==( const string& s ) const { | |||
return _name == s || _addr == s; | return _name == s || _addr == s; | |||
} | } | |||
bool operator!=( const string& s ) const { | bool operator!=( const string& s ) const { | |||
return _name != s && _addr != s; | return _name != s && _addr != s; | |||
} | } | |||
skipping to change at line 274 | skipping to change at line 270 | |||
ChunkManagerPtr getManager() const { | ChunkManagerPtr getManager() const { | |||
return _manager; | return _manager; | |||
} | } | |||
bool setVersion() { | bool setVersion() { | |||
_finishInit(); | _finishInit(); | |||
return _setVersion; | return _setVersion; | |||
} | } | |||
static void sync(); | static void sync( const string& db ); | |||
void donotCheckVersion() { | void donotCheckVersion() { | |||
_setVersion = false; | _setVersion = false; | |||
_finishedInit = true; | _finishedInit = true; | |||
} | } | |||
bool ok() const { return _conn > 0; } | bool ok() const { return _conn > 0; } | |||
/** | /** | |||
this just passes through excpet it checks for stale configs | this just passes through excpet it checks for stale configs | |||
skipping to change at line 315 | skipping to change at line 311 | |||
extern DBConnectionPool shardConnectionPool; | extern DBConnectionPool shardConnectionPool; | |||
class ShardingConnectionHook : public DBConnectionHook { | class ShardingConnectionHook : public DBConnectionHook { | |||
public: | public: | |||
ShardingConnectionHook( bool shardedConnections ) | ShardingConnectionHook( bool shardedConnections ) | |||
: _shardedConnections( shardedConnections ) { | : _shardedConnections( shardedConnections ) { | |||
} | } | |||
virtual void onCreate( DBClientBase * conn ); | virtual void onCreate( DBClientBase * conn ); | |||
virtual void onHandedOut( DBClientBase * conn ); | ||||
virtual void onDestroy( DBClientBase * conn ); | virtual void onDestroy( DBClientBase * conn ); | |||
bool _shardedConnections; | bool _shardedConnections; | |||
}; | }; | |||
} | } | |||
End of changes. 4 change blocks. | ||||
10 lines changed or deleted | 5 lines changed or added | |||
sock.h | sock.h | |||
---|---|---|---|---|
skipping to change at line 207 | skipping to change at line 207 | |||
Socket(int sock, const SockAddr& farEnd); | Socket(int sock, const SockAddr& farEnd); | |||
/** In some cases the timeout will actually be 2x this value - eg w e do a partial send, | /** In some cases the timeout will actually be 2x this value - eg w e do a partial send, | |||
then the timeout fires, then we try to send again, then the tim eout fires again with | then the timeout fires, then we try to send again, then the tim eout fires again with | |||
no data sent, then we detect that the other side is down. | no data sent, then we detect that the other side is down. | |||
Generally you don't want a timeout, you should be very prepared for errors if you set one. | Generally you don't want a timeout, you should be very prepared for errors if you set one. | |||
*/ | */ | |||
Socket(double so_timeout = 0, int logLevel = 0 ); | Socket(double so_timeout = 0, int logLevel = 0 ); | |||
~Socket() { | ~Socket(); | |||
close(); | ||||
} | ||||
bool connect(SockAddr& farEnd); | bool connect(SockAddr& farEnd); | |||
void close(); | void close(); | |||
void send( const char * data , int len, const char *context ); | void send( const char * data , int len, const char *context ); | |||
void send( const vector< pair< char *, int > > &data, const char *c ontext ); | void send( const vector< pair< char *, int > > &data, const char *c ontext ); | |||
// recv len or throw SocketException | // recv len or throw SocketException | |||
void recv( char * data , int len ); | void recv( char * data , int len ); | |||
int unsafe_recv( char *buf, int max ); | int unsafe_recv( char *buf, int max ); | |||
End of changes. 1 change blocks. | ||||
3 lines changed or deleted | 1 lines changed or added | |||
update_internal.h | update_internal.h | |||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
#include "mongo/db/jsobjmanipulator.h" | #include "mongo/db/jsobjmanipulator.h" | |||
#include "mongo/db/matcher.h" | #include "mongo/db/matcher.h" | |||
#include "mongo/util/embedded_builder.h" | #include "mongo/util/embedded_builder.h" | |||
#include "mongo/util/stringutils.h" | #include "mongo/util/stringutils.h" | |||
namespace mongo { | namespace mongo { | |||
class ModState; | class ModState; | |||
class ModSetState; | class ModSetState; | |||
/** | ||||
* a.$ -> a | ||||
* @return true if out is set and we made a change | ||||
*/ | ||||
bool getCanonicalIndexField( const string& fullName, string* out ); | ||||
/* Used for modifiers such as $inc, $set, $push, ... | /* Used for modifiers such as $inc, $set, $push, ... | |||
* stores the info about a single operation | * stores the info about a single operation | |||
* once created should never be modified | * once created should never be modified | |||
*/ | */ | |||
struct Mod { | struct Mod { | |||
// See opFromStr below | // See opFromStr below | |||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 | |||
enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO } op; | enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO } op; | |||
static const char* modNames[]; | static const char* modNames[]; | |||
skipping to change at line 146 | skipping to change at line 152 | |||
static bool isIndexed( const string& fullName , const set<string>& idxKeys ) { | static bool isIndexed( const string& fullName , const set<string>& idxKeys ) { | |||
const char * fieldName = fullName.c_str(); | const char * fieldName = fullName.c_str(); | |||
// check if there is an index key that is a parent of mod | // check if there is an index key that is a parent of mod | |||
for( const char* dot = strchr( fieldName, '.' ); dot; dot = str chr( dot + 1, '.' ) ) | for( const char* dot = strchr( fieldName, '.' ); dot; dot = str chr( dot + 1, '.' ) ) | |||
if ( idxKeys.count( string( fieldName, dot - fieldName ) ) ) | if ( idxKeys.count( string( fieldName, dot - fieldName ) ) ) | |||
return true; | return true; | |||
// check if there is an index key equal to mod | // check if there is an index key equal to mod | |||
if ( idxKeys.count(fullName) ) | if ( idxKeys.count(fullName) ) | |||
return true; | return true; | |||
// check if there is an index key that is a child of mod | // check if there is an index key that is a child of mod | |||
set< string >::const_iterator j = idxKeys.upper_bound( fullName ); | set< string >::const_iterator j = idxKeys.upper_bound( fullName ); | |||
if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful lName.size()] == '.' ) | if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful lName.size()] == '.' ) | |||
return true; | return true; | |||
return false; | return false; | |||
} | } | |||
/** | ||||
* checks if mod is in the index by inspecting fieldName, and remov | ||||
ing | ||||
* .$ or .### substrings (#=digit) with any number of digits. | ||||
* | ||||
* @return true iff the mod is indexed | ||||
*/ | ||||
bool isIndexed( const set<string>& idxKeys ) const { | bool isIndexed( const set<string>& idxKeys ) const { | |||
string fullName = fieldName; | string myFieldName = fieldName; | |||
if ( isIndexed( fullName , idxKeys ) ) | // first, check if full name is in idxKeys | |||
if ( isIndexed( myFieldName , idxKeys ) ) | ||||
return true; | return true; | |||
if ( strstr( fieldName , "." ) ) { | string x; | |||
// check for a.0.1 | if ( getCanonicalIndexField( myFieldName, &x ) ) { | |||
StringBuilder buf; | if ( isIndexed( x, idxKeys ) ) | |||
for ( size_t i=0; i<fullName.size(); i++ ) { | ||||
char c = fullName[i]; | ||||
if ( c == '$' && | ||||
i > 0 && fullName[i-1] == '.' && | ||||
i+1<fullName.size() && | ||||
fullName[i+1] == '.' ) { | ||||
i++; | ||||
continue; | ||||
} | ||||
buf << c; | ||||
if ( c != '.' ) | ||||
continue; | ||||
if ( ! isdigit( fullName[i+1] ) ) | ||||
continue; | ||||
bool possible = true; | ||||
size_t j=i+2; | ||||
for ( ; j<fullName.size(); j++ ) { | ||||
char d = fullName[j]; | ||||
if ( d == '.' ) | ||||
break; | ||||
if ( isdigit( d ) ) | ||||
continue; | ||||
possible = false; | ||||
break; | ||||
} | ||||
if ( possible ) | ||||
i = j; | ||||
} | ||||
string x = buf.str(); | ||||
if ( isIndexed( x , idxKeys ) ) | ||||
return true; | return true; | |||
} | } | |||
return false; | return false; | |||
} | } | |||
void apply( BSONBuilderBase& b , BSONElement in , ModState& ms ) co nst; | void apply( BSONBuilderBase& b , BSONElement in , ModState& ms ) co nst; | |||
/** | /** | |||
* @return true iff toMatch should be removed from the array | * @return true iff toMatch should be removed from the array | |||
End of changes. 6 change blocks. | ||||
41 lines changed or deleted | 20 lines changed or added | |||