2d.h | 2d.h | |||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* 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/>. | |||
*/ | */ | |||
namespace mongo { | namespace mongo { | |||
bool run2DGeoNear(const IndexDetails &id, BSONObj& cmdObj, string& errm | // We need cmdObj and parsedArgs so we can print a useful error msg | |||
sg, | // and pull other args out. | |||
bool run2DGeoNear(const IndexDetails &id, const BSONObj& cmdObj, | ||||
const GeoNearArguments &parsedArgs, string& errmsg, | ||||
BSONObjBuilder& result); | BSONObjBuilder& result); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
action_type.h | action_type.h | |||
---|---|---|---|---|
skipping to change at line 51 | skipping to change at line 51 | |||
std::string toString() const; | std::string toString() const; | |||
// Takes the string representation of a single action type and retu rns the corresponding | // Takes the string representation of a single action type and retu rns the corresponding | |||
// ActionType enum. | // ActionType enum. | |||
static Status parseActionFromString(const std::string& actionString , ActionType* result); | static Status parseActionFromString(const std::string& actionString , ActionType* result); | |||
// Takes an ActionType and returns the string representation | // Takes an ActionType and returns the string representation | |||
static std::string actionToString(const ActionType& action); | static std::string actionToString(const ActionType& action); | |||
static const ActionType addShard; | static const ActionType addShard; | |||
static const ActionType applyOps; | ||||
static const ActionType captrunc; | static const ActionType captrunc; | |||
static const ActionType clean; | static const ActionType clean; | |||
static const ActionType clone; | static const ActionType clone; | |||
static const ActionType cloneCollectionLocalSource; | static const ActionType cloneCollectionLocalSource; | |||
static const ActionType cloneCollectionTarget; | static const ActionType cloneCollectionTarget; | |||
static const ActionType closeAllDatabases; | static const ActionType closeAllDatabases; | |||
static const ActionType collMod; | static const ActionType collMod; | |||
static const ActionType collStats; | static const ActionType collStats; | |||
static const ActionType compact; | static const ActionType compact; | |||
static const ActionType connPoolStats; | static const ActionType connPoolStats; | |||
static const ActionType connPoolSync; | static const ActionType connPoolSync; | |||
static const ActionType convertToCapped; | static const ActionType convertToCapped; | |||
static const ActionType copyDBTarget; | ||||
static const ActionType cpuProfiler; | static const ActionType cpuProfiler; | |||
static const ActionType createCollection; | static const ActionType createCollection; | |||
static const ActionType cursorInfo; | static const ActionType cursorInfo; | |||
static const ActionType dbHash; | static const ActionType dbHash; | |||
static const ActionType dbStats; | static const ActionType dbStats; | |||
static const ActionType diagLogging; | static const ActionType diagLogging; | |||
static const ActionType dropCollection; | static const ActionType dropCollection; | |||
static const ActionType dropDatabase; | static const ActionType dropDatabase; | |||
static const ActionType dropIndexes; | static const ActionType dropIndexes; | |||
static const ActionType emptycapped; | static const ActionType emptycapped; | |||
skipping to change at line 86 | skipping to change at line 86 | |||
static const ActionType find; | static const ActionType find; | |||
static const ActionType flushRouterConfig; | static const ActionType flushRouterConfig; | |||
static const ActionType fsync; | static const ActionType fsync; | |||
static const ActionType getCmdLineOpts; | static const ActionType getCmdLineOpts; | |||
static const ActionType getLog; | static const ActionType getLog; | |||
static const ActionType getParameter; | static const ActionType getParameter; | |||
static const ActionType getShardMap; | static const ActionType getShardMap; | |||
static const ActionType getShardVersion; | static const ActionType getShardVersion; | |||
static const ActionType handshake; | static const ActionType handshake; | |||
static const ActionType hostInfo; | static const ActionType hostInfo; | |||
static const ActionType indexRead; | ||||
static const ActionType indexStats; | static const ActionType indexStats; | |||
static const ActionType inprog; | static const ActionType inprog; | |||
static const ActionType insert; | static const ActionType insert; | |||
static const ActionType killCursors; | ||||
static const ActionType killop; | static const ActionType killop; | |||
static const ActionType listDatabases; | static const ActionType listDatabases; | |||
static const ActionType listShards; | static const ActionType listShards; | |||
static const ActionType logRotate; | static const ActionType logRotate; | |||
static const ActionType mapReduceShardedFinish; | static const ActionType mapReduceShardedFinish; | |||
static const ActionType moveChunk; | static const ActionType moveChunk; | |||
static const ActionType movePrimary; | static const ActionType movePrimary; | |||
static const ActionType netstat; | static const ActionType netstat; | |||
static const ActionType profileEnable; | static const ActionType profileEnable; | |||
static const ActionType profileRead; | static const ActionType profileRead; | |||
skipping to change at line 144 | skipping to change at line 146 | |||
static const ActionType writeBacksQueued; | static const ActionType writeBacksQueued; | |||
static const ActionType _migrateClone; | static const ActionType _migrateClone; | |||
static const ActionType _recvChunkAbort; | static const ActionType _recvChunkAbort; | |||
static const ActionType _recvChunkCommit; | static const ActionType _recvChunkCommit; | |||
static const ActionType _recvChunkStart; | static const ActionType _recvChunkStart; | |||
static const ActionType _recvChunkStatus; | static const ActionType _recvChunkStatus; | |||
static const ActionType _transferMods; | static const ActionType _transferMods; | |||
enum ActionTypeIdentifier { | enum ActionTypeIdentifier { | |||
addShardValue, | addShardValue, | |||
applyOpsValue, | ||||
captruncValue, | captruncValue, | |||
cleanValue, | cleanValue, | |||
cloneValue, | cloneValue, | |||
cloneCollectionLocalSourceValue, | cloneCollectionLocalSourceValue, | |||
cloneCollectionTargetValue, | cloneCollectionTargetValue, | |||
closeAllDatabasesValue, | closeAllDatabasesValue, | |||
collModValue, | collModValue, | |||
collStatsValue, | collStatsValue, | |||
compactValue, | compactValue, | |||
connPoolStatsValue, | connPoolStatsValue, | |||
connPoolSyncValue, | connPoolSyncValue, | |||
convertToCappedValue, | convertToCappedValue, | |||
copyDBTargetValue, | ||||
cpuProfilerValue, | cpuProfilerValue, | |||
createCollectionValue, | createCollectionValue, | |||
cursorInfoValue, | cursorInfoValue, | |||
dbHashValue, | dbHashValue, | |||
dbStatsValue, | dbStatsValue, | |||
diagLoggingValue, | diagLoggingValue, | |||
dropCollectionValue, | dropCollectionValue, | |||
dropDatabaseValue, | dropDatabaseValue, | |||
dropIndexesValue, | dropIndexesValue, | |||
emptycappedValue, | emptycappedValue, | |||
skipping to change at line 179 | skipping to change at line 181 | |||
findValue, | findValue, | |||
flushRouterConfigValue, | flushRouterConfigValue, | |||
fsyncValue, | fsyncValue, | |||
getCmdLineOptsValue, | getCmdLineOptsValue, | |||
getLogValue, | getLogValue, | |||
getParameterValue, | getParameterValue, | |||
getShardMapValue, | getShardMapValue, | |||
getShardVersionValue, | getShardVersionValue, | |||
handshakeValue, | handshakeValue, | |||
hostInfoValue, | hostInfoValue, | |||
indexReadValue, | ||||
indexStatsValue, | indexStatsValue, | |||
inprogValue, | inprogValue, | |||
insertValue, | insertValue, | |||
killCursorsValue, | ||||
killopValue, | killopValue, | |||
listDatabasesValue, | listDatabasesValue, | |||
listShardsValue, | listShardsValue, | |||
logRotateValue, | logRotateValue, | |||
mapReduceShardedFinishValue, | mapReduceShardedFinishValue, | |||
moveChunkValue, | moveChunkValue, | |||
movePrimaryValue, | movePrimaryValue, | |||
netstatValue, | netstatValue, | |||
profileEnableValue, | profileEnableValue, | |||
profileReadValue, | profileReadValue, | |||
End of changes. 8 change blocks. | ||||
2 lines changed or deleted | 6 lines changed or added | |||
atomic_intrinsics_win32.h | atomic_intrinsics_win32.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
/** | /** | |||
* Implementation of the AtomicIntrinsics<T>::* operations for Windows syst ems. | * Implementation of the AtomicIntrinsics<T>::* operations for Windows syst ems. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <boost/utility.hpp> | #include <boost/utility.hpp> | |||
#include "mongo/platform/windows_basic.h" | #include "mongo/platform/windows_basic.h" | |||
#include <intrin.h> | ||||
#pragma intrinsic(_InterlockedCompareExchange64) | ||||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* Default instantiation of AtomicIntrinsics<>, for unsupported types. | * Default instantiation of AtomicIntrinsics<>, for unsupported types. | |||
*/ | */ | |||
template <typename T, typename _IsTSupported=void> | template <typename T, typename _IsTSupported=void> | |||
class AtomicIntrinsics { | class AtomicIntrinsics { | |||
private: | private: | |||
AtomicIntrinsics(); | AtomicIntrinsics(); | |||
~AtomicIntrinsics(); | ~AtomicIntrinsics(); | |||
skipping to change at line 87 | skipping to change at line 90 | |||
AtomicIntrinsics(); | AtomicIntrinsics(); | |||
~AtomicIntrinsics(); | ~AtomicIntrinsics(); | |||
}; | }; | |||
/** | /** | |||
* Instantiation of AtomicIntrinsics<> for 64-bit word sizes. | * Instantiation of AtomicIntrinsics<> for 64-bit word sizes. | |||
*/ | */ | |||
template <typename T> | template <typename T> | |||
class AtomicIntrinsics<T, typename boost::enable_if_c<sizeof(T) == size of(LONGLONG)>::type> { | class AtomicIntrinsics<T, typename boost::enable_if_c<sizeof(T) == size of(LONGLONG)>::type> { | |||
public: | public: | |||
static const bool kHaveInterlocked64 = (_WIN32_WINNT >= _WIN32_WINN T_VISTA); | ||||
static T compareAndSwap(volatile T* dest, T expected, T newValue) { | static T compareAndSwap(volatile T* dest, T expected, T newValue) { | |||
return InterlockedCompareExchange64(reinterpret_cast<volatile L | return InterlockedImpl<kHaveInterlocked64>::compareAndSwap(dest | |||
ONGLONG*>(dest), | , expected, newValue); | |||
LONGLONG(newValue), | ||||
LONGLONG(expected)); | ||||
} | } | |||
static T swap(volatile T* dest, T newValue) { | static T swap(volatile T* dest, T newValue) { | |||
return InterlockedExchange64(reinterpret_cast<volatile LONGLONG | return InterlockedImpl<kHaveInterlocked64>::swap(dest, newValue | |||
*>(dest), | ); | |||
LONGLONG(newValue)); | ||||
} | } | |||
static T load(volatile const T* value) { | static T load(volatile const T* value) { | |||
return LoadStoreImpl<T>::load(value); | return LoadStoreImpl<T>::load(value); | |||
} | } | |||
static void store(volatile T* dest, T newValue) { | static void store(volatile T* dest, T newValue) { | |||
LoadStoreImpl<T>::store(dest, newValue); | LoadStoreImpl<T>::store(dest, newValue); | |||
} | } | |||
static T fetchAndAdd(volatile T* dest, T increment) { | static T fetchAndAdd(volatile T* dest, T increment) { | |||
return InterlockedExchangeAdd64(reinterpret_cast<volatile LONGL | return InterlockedImpl<kHaveInterlocked64>::fetchAndAdd(dest, i | |||
ONG*>(dest), | ncrement); | |||
LONGLONG(increment)); | ||||
} | } | |||
private: | private: | |||
AtomicIntrinsics(); | AtomicIntrinsics(); | |||
~AtomicIntrinsics(); | ~AtomicIntrinsics(); | |||
template <bool> | ||||
struct InterlockedImpl; | ||||
// Implementation of 64-bit Interlocked operations via Windows API | ||||
calls. | ||||
template<> | ||||
struct InterlockedImpl<true> { | ||||
static T compareAndSwap(volatile T* dest, T expected, T newValu | ||||
e) { | ||||
return InterlockedCompareExchange64( | ||||
reinterpret_cast<volatile LONGLONG*>(dest), | ||||
LONGLONG(newValue), | ||||
LONGLONG(expected)); | ||||
} | ||||
static T swap(volatile T* dest, T newValue) { | ||||
return InterlockedExchange64( | ||||
reinterpret_cast<volatile LONGLONG*>(dest), | ||||
LONGLONG(newValue)); | ||||
} | ||||
static T fetchAndAdd(volatile T* dest, T increment) { | ||||
return InterlockedExchangeAdd64( | ||||
reinterpret_cast<volatile LONGLONG*>(dest), | ||||
LONGLONG(increment)); | ||||
} | ||||
}; | ||||
// Implementation of 64-bit Interlocked operations for systems wher | ||||
e the API does not | ||||
// yet provide the Interlocked...64 operations. | ||||
template<> | ||||
struct InterlockedImpl<false> { | ||||
static T compareAndSwap(volatile T* dest, T expected, T newValu | ||||
e) { | ||||
// NOTE: We must use the compiler intrinsic here: WinXP doe | ||||
s not offer | ||||
// InterlockedCompareExchange64 as an API call. | ||||
return _InterlockedCompareExchange64( | ||||
reinterpret_cast<volatile LONGLONG*>(dest), | ||||
LONGLONG(newValue), | ||||
LONGLONG(expected)); | ||||
} | ||||
static T swap(volatile T* dest, T newValue) { | ||||
// NOTE: You may be tempted to replace this with | ||||
// 'InterlockedExchange64'. Resist! It will compile just fi | ||||
ne despite not being | ||||
// listed in the docs as available on XP, but the compiler | ||||
may replace it with | ||||
// calls to the non-intrinsic 'InterlockedCompareExchange64 | ||||
', which does not | ||||
// exist on XP. We work around this by rolling our own synt | ||||
hetic in terms of | ||||
// compareAndSwap which we have explicitly formulated in te | ||||
rms of the compiler | ||||
// provided _InterlockedCompareExchange64 intrinsic. | ||||
T currentValue = *dest; | ||||
while (true) { | ||||
const T result = compareAndSwap(dest, currentValue, new | ||||
Value); | ||||
if (result == currentValue) | ||||
return result; | ||||
currentValue = result; | ||||
} | ||||
} | ||||
static T fetchAndAdd(volatile T* dest, T increment) { | ||||
// NOTE: See note for 'swap' on why we roll this ourselves. | ||||
T currentValue = *dest; | ||||
while (true) { | ||||
const T incremented = currentValue + increment; | ||||
const T result = compareAndSwap(dest, currentValue, inc | ||||
remented); | ||||
if (result == currentValue) | ||||
return result; | ||||
currentValue = result; | ||||
} | ||||
} | ||||
}; | ||||
// On 32-bit IA-32 systems, 64-bit load and store must be implement ed in terms of | // On 32-bit IA-32 systems, 64-bit load and store must be implement ed in terms of | |||
// Interlocked operations, but on 64-bit systems they support a sim pler, native | // Interlocked operations, but on 64-bit systems they support a sim pler, native | |||
// implementation. The LoadStoreImpl type represents the abstract implementation of | // implementation. The LoadStoreImpl type represents the abstract implementation of | |||
// loading and storing 64-bit values. | // loading and storing 64-bit values. | |||
template <typename T, typename _IsTTooBig=void> | template <typename U, typename _IsTTooBig=void> | |||
class LoadStoreImpl{}; | class LoadStoreImpl{}; | |||
// Implementation on 64-bit systems. | // Implementation on 64-bit systems. | |||
template <typename U> | template <typename U> | |||
class LoadStoreImpl<U, typename boost::enable_if_c<sizeof(U) <= siz eof(void*)>::type> { | class LoadStoreImpl<U, typename boost::enable_if_c<sizeof(U) <= siz eof(void*)>::type> { | |||
public: | public: | |||
static U load(volatile const U* value) { | static U load(volatile const U* value) { | |||
MemoryBarrier(); | MemoryBarrier(); | |||
U result = *value; | U result = *value; | |||
MemoryBarrier(); | MemoryBarrier(); | |||
End of changes. 7 change blocks. | ||||
11 lines changed or deleted | 92 lines changed or added | |||
authorization_manager.h | authorization_manager.h | |||
---|---|---|---|---|
skipping to change at line 112 | skipping to change at line 112 | |||
// Adds a new principal with the given principal name and authorize s it with full access. | // Adds a new principal with the given principal name and authorize s it with full access. | |||
// Used to grant internal threads full access. | // Used to grant internal threads full access. | |||
void grantInternalAuthorization(const std::string& principalName); | void grantInternalAuthorization(const std::string& principalName); | |||
// Checks if this connection has been authenticated as an internal user. | // Checks if this connection has been authenticated as an internal user. | |||
bool hasInternalAuthorization(); | bool hasInternalAuthorization(); | |||
// Checks if this connection has the privileges required to perform the given action | // Checks if this connection has the privileges required to perform the given action | |||
// on the given resource. Contains all the authorization logic inc luding handling things | // on the given resource. Contains all the authorization logic inc luding handling things | |||
// like the localhost exception. Returns true if the action may pr oceed on the resource. | // like the localhost exception. Returns true if the action may pr oceed on the resource. | |||
// Note: this may acquire a database read lock (for automatic privi lege acquisition). | ||||
bool checkAuthorization(const std::string& resource, ActionType act ion); | bool checkAuthorization(const std::string& resource, ActionType act ion); | |||
// Same as above but takes an ActionSet instead of a single ActionT ype. Returns true if | // Same as above but takes an ActionSet instead of a single ActionT ype. Returns true if | |||
// all of the actions may proceed on the resource. | // all of the actions may proceed on the resource. | |||
bool checkAuthorization(const std::string& resource, ActionSet acti ons); | bool checkAuthorization(const std::string& resource, ActionSet acti ons); | |||
// Parses the privilege documents and acquires all privileges that the privilege document | // Parses the privilege documents and acquires all privileges that the privilege document | |||
// grants | // grants | |||
Status acquirePrivilegesFromPrivilegeDocument(const std::string& db name, | Status acquirePrivilegesFromPrivilegeDocument(const std::string& db name, | |||
const PrincipalName& principal, | const PrincipalName& principal, | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
balancer_policy.h | balancer_policy.h | |||
---|---|---|---|---|
skipping to change at line 59 | skipping to change at line 59 | |||
TagRange( const BSONObj& a_min, const BSONObj& a_max, const string& a_tag ) | TagRange( const BSONObj& a_min, const BSONObj& a_max, const string& a_tag ) | |||
: min( a_min.getOwned() ), max( a_max.getOwned() ), tag( a_tag ){} | : min( a_min.getOwned() ), max( a_max.getOwned() ), tag( a_tag ){} | |||
string toString() const; | string toString() const; | |||
}; | }; | |||
class ShardInfo { | class ShardInfo { | |||
public: | public: | |||
ShardInfo(); | ShardInfo(); | |||
ShardInfo( long long maxSize, long long currSize, | ShardInfo( long long maxSize, long long currSize, | |||
bool draining, bool opsQueued, | bool draining, bool opsQueued, | |||
const set<string>& tags = set<string>() ); | const set<string>& tags = set<string>(), | |||
const string& _mongoVersion = string("") ); | ||||
void addTag( const string& tag ); | void addTag( const string& tag ); | |||
/** @return true if we have the tag OR if the tag is "" */ | /** @return true if we have the tag OR if the tag is "" */ | |||
bool hasTag( const string& tag ) const; | bool hasTag( const string& tag ) const; | |||
/** | /** | |||
* @return true if a shard cannot receive any new chunks because it reaches 'shardLimits'. | * @return true if a shard cannot receive any new chunks because it reaches 'shardLimits'. | |||
* Expects the optional fields "maxSize", can in size in MB, and "u sedSize", currently used size | * Expects the optional fields "maxSize", can in size in MB, and "u sedSize", currently used size | |||
* in MB, on 'shardLimits'. | * in MB, on 'shardLimits'. | |||
skipping to change at line 88 | skipping to change at line 89 | |||
/** | /** | |||
* @return true if a shard currently has operations in any of its w riteback queues | * @return true if a shard currently has operations in any of its w riteback queues | |||
*/ | */ | |||
bool hasOpsQueued() const { return _hasOpsQueued; } | bool hasOpsQueued() const { return _hasOpsQueued; } | |||
long long getMaxSize() const { return _maxSize; } | long long getMaxSize() const { return _maxSize; } | |||
long long getCurrSize() const { return _currSize; } | long long getCurrSize() const { return _currSize; } | |||
string getMongoVersion() const { return _mongoVersion; } | ||||
string toString() const; | string toString() const; | |||
private: | private: | |||
long long _maxSize; | long long _maxSize; | |||
long long _currSize; | long long _currSize; | |||
bool _draining; | bool _draining; | |||
bool _hasOpsQueued; | bool _hasOpsQueued; | |||
set<string> _tags; | set<string> _tags; | |||
string _mongoVersion; | ||||
}; | }; | |||
struct MigrateInfo { | struct MigrateInfo { | |||
const string ns; | const string ns; | |||
const string to; | const string to; | |||
const string from; | const string from; | |||
const ChunkInfo chunk; | const ChunkInfo chunk; | |||
MigrateInfo( const string& a_ns , const string& a_to , const string & a_from , const BSONObj& a_chunk ) | MigrateInfo( const string& a_ns , const string& a_to , const string & a_from , const BSONObj& a_chunk ) | |||
: ns( a_ns ) , to( a_to ) , from( a_from ), chunk( a_chunk ) {} | : ns( a_ns ) , to( a_to ) , from( a_from ), chunk( a_chunk ) {} | |||
End of changes. 3 change blocks. | ||||
1 lines changed or deleted | 5 lines changed or added | |||
bench.h | bench.h | |||
---|---|---|---|---|
/* | /* | |||
* Copyright (C) 2010 10gen Inc. | * Copyright (C) 2010 10gen Inc. | |||
* | * | |||
* This program is free software: you can redistribute it and/or modify | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
* it under the terms of the GNU Affero General Public License, version | * you may not use this file except in compliance with the License. | |||
3, | * You may obtain a copy of the License at | |||
* as published by the Free Software Foundation. | ||||
* | * | |||
* This program is distributed in the hope that it will be useful, | * http://www.apache.org/licenses/LICENSE-2.0 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
* GNU Affero General Public License for more details. | ||||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice | * Unless required by applicable law or agreed to in writing, software | |||
nse | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli | |||
ed. | ||||
* See the License for the specific language governing permissions and | ||||
* limitations under the License. | ||||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <string> | #include <string> | |||
#include <boost/shared_ptr.hpp> | #include <boost/shared_ptr.hpp> | |||
#include <boost/thread/condition.hpp> | #include <boost/thread/condition.hpp> | |||
#include <boost/thread/mutex.hpp> | #include <boost/thread/mutex.hpp> | |||
#include <pcrecpp.h> | #include <pcrecpp.h> | |||
skipping to change at line 398 | skipping to change at line 398 | |||
* Store the collected event data from a completed bench run activi ty into "stats." | * Store the collected event data from a completed bench run activi ty into "stats." | |||
* | * | |||
* Illegal to call until after stop() returns. | * Illegal to call until after stop() returns. | |||
*/ | */ | |||
void populateStats(BenchRunStats *stats); | void populateStats(BenchRunStats *stats); | |||
OID oid() const { return _oid; } | OID oid() const { return _oid; } | |||
const BenchRunConfig &config() const { return *_config; } // TODO: Remove this function. | const BenchRunConfig &config() const { return *_config; } // TODO: Remove this function. | |||
// JS bindings | ||||
static BSONObj benchFinish(const BSONObj& argsFake, void* data); | ||||
static BSONObj benchStart(const BSONObj& argsFake, void* data); | ||||
static BSONObj benchRunSync(const BSONObj& argsFake, void* data); | ||||
private: | private: | |||
// TODO: Same as for createWithConfig. | // TODO: Same as for createWithConfig. | |||
static boost::mutex _staticMutex; | static boost::mutex _staticMutex; | |||
static map< OID, BenchRunner* > _activeRuns; | static map< OID, BenchRunner* > _activeRuns; | |||
OID _oid; | OID _oid; | |||
BenchRunState _brState; | BenchRunState _brState; | |||
boost::scoped_ptr<BenchRunConfig> _config; | boost::scoped_ptr<BenchRunConfig> _config; | |||
vector<BenchRunWorker *> _workers; | vector<BenchRunWorker *> _workers; | |||
End of changes. 4 change blocks. | ||||
11 lines changed or deleted | 15 lines changed or added | |||
bgsync.h | bgsync.h | |||
---|---|---|---|---|
skipping to change at line 91 | skipping to change at line 91 | |||
// Notifier thread | // Notifier thread | |||
// used to wait until another op has been replicated | // used to wait until another op has been replicated | |||
boost::condition_variable _lastOpCond; | boost::condition_variable _lastOpCond; | |||
boost::mutex _lastOpMutex; | boost::mutex _lastOpMutex; | |||
const Member* _oplogMarkerTarget; | const Member* _oplogMarkerTarget; | |||
OplogReader _oplogMarker; // not locked, only used by notifier thre ad | OplogReader _oplogMarker; // not locked, only used by notifier thre ad | |||
OpTime _consumedOpTime; // not locked, only used by notifier thread | OpTime _consumedOpTime; // not locked, only used by notifier thread | |||
struct QueueCounter { | ||||
QueueCounter(); | ||||
unsigned long long waitTime; | ||||
unsigned int numElems; | ||||
} _queueCounter; | ||||
BackgroundSync(); | BackgroundSync(); | |||
BackgroundSync(const BackgroundSync& s); | BackgroundSync(const BackgroundSync& s); | |||
BackgroundSync operator=(const BackgroundSync& s); | BackgroundSync operator=(const BackgroundSync& s); | |||
// Production thread | // Production thread | |||
void _producerThread(); | void _producerThread(); | |||
// Adds elements to the list, up to maxSize. | // Adds elements to the list, up to maxSize. | |||
void produce(); | void produce(); | |||
// Check if rollback is necessary | // Check if rollback is necessary | |||
bool isRollbackRequired(OplogReader& r); | bool isRollbackRequired(OplogReader& r); | |||
End of changes. 1 change blocks. | ||||
6 lines changed or deleted | 0 lines changed or added | |||
bson_field.h | bson_field.h | |||
---|---|---|---|---|
skipping to change at line 77 | skipping to change at line 77 | |||
const std::string& name() const { return _name; } | const std::string& name() const { return _name; } | |||
private: | private: | |||
std::string _name; | std::string _name; | |||
T _t; | T _t; | |||
}; | }; | |||
template<typename T> | template<typename T> | |||
class BSONField { | class BSONField { | |||
public: | public: | |||
BSONField(const std::string& name, const std::string& longName="") | BSONField(const std::string& name) | |||
: _name(name), _longName(longName) {} | : _name(name), _defaultSet(false) {} | |||
BSONField(const std::string& name, const T& defaultVal) | ||||
: _name(name), _default(defaultVal), _defaultSet(true) {} | ||||
BSONFieldValue<T> make(const T& t) const { | BSONFieldValue<T> make(const T& t) const { | |||
return BSONFieldValue<T>(_name, t); | return BSONFieldValue<T>(_name, t); | |||
} | } | |||
BSONFieldValue<T> operator()(const T& t) const { | BSONFieldValue<T> operator()(const T& t) const { | |||
return BSONFieldValue<T>(_name, t); | return BSONFieldValue<T>(_name, t); | |||
} | } | |||
const std::string& name() const { | const std::string& name() const { | |||
return _name; | return _name; | |||
} | } | |||
const T& getDefault() const { | ||||
return _default; | ||||
} | ||||
const bool hasDefault() const { | ||||
return _defaultSet; | ||||
} | ||||
std::string operator()() const { | std::string operator()() const { | |||
return _name; | return _name; | |||
} | } | |||
BSONFieldValue<BSONObj> query(const char * q, const T& t) const; | BSONFieldValue<BSONObj> query(const char * q, const T& t) const; | |||
BSONFieldValue<BSONObj> gt(const T& t) const { | BSONFieldValue<BSONObj> gt(const T& t) const { | |||
return query("$gt", t); | return query("$gt", t); | |||
} | } | |||
BSONFieldValue<BSONObj> lt(const T& t) const { | BSONFieldValue<BSONObj> lt(const T& t) const { | |||
return query("$lt", t); | return query("$lt", t); | |||
} | } | |||
BSONFieldValue<BSONObj> ne(const T& t) const { | BSONFieldValue<BSONObj> ne(const T& t) const { | |||
return query("$ne", t); | return query("$ne", t); | |||
} | } | |||
private: | private: | |||
std::string _name; | std::string _name; | |||
std::string _longName; | T _default; | |||
bool _defaultSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 15 lines changed or added | |||
bson_template_evaluator.h | bson_template_evaluator.h | |||
---|---|---|---|---|
/** @file templateevaluator.h */ | ||||
/* | /* | |||
* Copyright (C) 2012 10gen Inc. | * Copyright (C) 2012 10gen Inc. | |||
* | * | |||
* This program is free software: you can redistribute it and/or modify | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
* it under the terms of the GNU Affero General Public License, version | * you may not use this file except in compliance with the License. | |||
3, | * You may obtain a copy of the License at | |||
* as published by the Free Software Foundation. | ||||
* | * | |||
* This program is distributed in the hope that it will be useful, | * http://www.apache.org/licenses/LICENSE-2.0 | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
* GNU Affero General Public License for more details. | ||||
* | * | |||
* You should have received a copy of the GNU Affero General Public Lice | * Unless required by applicable law or agreed to in writing, software | |||
nse | * distributed under the License is distributed on an "AS IS" BASIS, | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or impli | |||
ed. | ||||
* See the License for the specific language governing permissions and | ||||
* limitations under the License. | ||||
*/ | */ | |||
/* | /* | |||
* This library supports a templating language that helps in generating BSO N documents from a | * This library supports a templating language that helps in generating BSO N documents from a | |||
* template. The language supports the following template: | * template. The language supports the following template: | |||
* #RAND_INT, #RAND_STRING and #CONCAT. | * #RAND_INT, #RAND_STRING and #CONCAT. | |||
* | * | |||
* The language will help in quickly expressing richer documents for use i n benchRun. | * The language will help in quickly expressing richer documents for use i n benchRun. | |||
* Ex. : { key : { #RAND_INT: [10, 20] } } or { key : { #CONCAT: ["hello", " ", "world"] } } | * Ex. : { key : { #RAND_INT: [10, 20] } } or { key : { #CONCAT: ["hello", " ", "world"] } } | |||
* | * | |||
End of changes. 4 change blocks. | ||||
13 lines changed or deleted | 10 lines changed or added | |||
bson_validate.h | bson_validate.h | |||
---|---|---|---|---|
skipping to change at line 31 | skipping to change at line 31 | |||
#include "mongo/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/bson/bsontypes.h" | #include "mongo/bson/bsontypes.h" | |||
#include "mongo/platform/cstdint.h" | #include "mongo/platform/cstdint.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* @param buf - bson data | * @param buf - bson data | |||
* @param maxLength - maxLength of buffer | * @param maxLength - maxLength of buffer | |||
* this is NOT the bson size, but how far we know th e buffer is valid | * this is NOT the bson size, but how far we know th e buffer is valid | |||
* @param bsonLength - OUT size of bson, set if bsonLength != NULL _and _ data is valid | ||||
*/ | */ | |||
Status validateBSON( const char* buf, uint64_t maxLength, int* bsonLeng th = NULL ); | Status validateBSON( const char* buf, uint64_t maxLength ); | |||
} | } | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 1 lines changed or added | |||
btree.h | btree.h | |||
---|---|---|---|---|
skipping to change at line 628 | skipping to change at line 628 | |||
* as a result of deallocation. A separate class representing a btree would | * as a result of deallocation. A separate class representing a btree would | |||
* alleviate some fragile cases where the implementation must currently | * alleviate some fragile cases where the implementation must currently | |||
* behave correctly if the 'this' pointer is suddenly invalidated by a | * behave correctly if the 'this' pointer is suddenly invalidated by a | |||
* callee. | * callee. | |||
*/ | */ | |||
template< class V > | template< class V > | |||
class BtreeBucket : public BucketBasics<V> { | class BtreeBucket : public BucketBasics<V> { | |||
friend class BtreeCursor; | friend class BtreeCursor; | |||
friend struct IndexInsertionContinuationImpl<V>; | friend struct IndexInsertionContinuationImpl<V>; | |||
public: | public: | |||
// make compiler happy: | // make compiler happy: | |||
typedef typename V::Key Key; | typedef typename V::Key Key; | |||
typedef typename V::KeyOwned KeyOwned; | typedef typename V::KeyOwned KeyOwned; | |||
typedef typename BucketBasics<V>::KeyNode KeyNode; | typedef typename BucketBasics<V>::KeyNode KeyNode; | |||
typedef typename BucketBasics<V>::_KeyNode _KeyNode; | typedef typename BucketBasics<V>::_KeyNode _KeyNode; | |||
typedef typename BucketBasics<V>::Loc Loc; | typedef typename BucketBasics<V>::Loc Loc; | |||
const _KeyNode& k(int i) const { return static_cast< const Buck etBasics<V> * >(this)->k(i); } | const _KeyNode& k(int i) const { return static_cast< const Buck etBasics<V> * >(this)->k(i); } | |||
protected: | protected: | |||
_KeyNode& k(int i) { return static_cast< BucketBasi cs<V> * >(this)->_k(i); } | _KeyNode& k(int i) { return static_cast< BucketBasi cs<V> * >(this)->_k(i); } | |||
public: | public: | |||
const KeyNode keyNode(int i) const { return static_cast< const Buck etBasics<V> * >(this)->keyNode(i); } | const KeyNode keyNode(int i) const { return static_cast< const Buck etBasics<V> * >(this)->keyNode(i); } | |||
bool isHead() const { return this->parent.isNull(); } | bool isHead() const { return this->parent.isNull(); } | |||
void dumpTree(const DiskLoc &thisLoc, const BSONObj &order) const; | void dumpTree(const DiskLoc &thisLoc, const BSONObj &order) const; | |||
long long fullValidate(const DiskLoc& thisLoc, const BSONObj &order , long long *unusedCount = 0, bool strict = false, unsigned depth=0) const; /* traverses everything */ | long long fullValidate(const DiskLoc& thisLoc, const BSONObj &order , long long *unusedCount = 0, bool strict = false, unsigned depth=0) const; /* traverses everything */ | |||
End of changes. 2 change blocks. | ||||
4 lines changed or deleted | 4 lines changed or added | |||
chunk.h | chunk.h | |||
---|---|---|---|---|
skipping to change at line 100 | skipping to change at line 100 | |||
void appendShortVersion( const char * name , BSONObjBuilder& b ) co nst; | void appendShortVersion( const char * name , BSONObjBuilder& b ) co nst; | |||
ChunkVersion getLastmod() const { return _lastmod; } | ChunkVersion getLastmod() const { return _lastmod; } | |||
void setLastmod( ChunkVersion v ) { _lastmod = v; } | void setLastmod( ChunkVersion v ) { _lastmod = v; } | |||
// | // | |||
// split support | // split support | |||
// | // | |||
long getBytesWritten() const { return _dataWritten; } | ||||
// Const since _dataWritten is mutable and a heuristic | ||||
// TODO: Split data tracking and chunk information | ||||
void setBytesWritten( long bytesWritten ) const { _dataWritten = by | ||||
tesWritten; } | ||||
/** | /** | |||
* if the amount of data written nears the max size of a shard | * if the amount of data written nears the max size of a shard | |||
* then we check the real size, and if its too big, we split | * then we check the real size, and if its too big, we split | |||
* @return if something was split | * @return if something was split | |||
*/ | */ | |||
bool splitIfShould( long dataWritten ) const; | bool splitIfShould( long dataWritten ) const; | |||
/** | /** | |||
* Splits this chunk at a non-specificed split key to be chosen by the mongod holding this chunk. | * Splits this chunk at a non-specificed split key to be chosen by the mongod holding this chunk. | |||
* | * | |||
skipping to change at line 178 | skipping to change at line 183 | |||
* marks this chunk as a jumbo chunk | * marks this chunk as a jumbo chunk | |||
* that means the chunk will be inelligble for migrates | * that means the chunk will be inelligble for migrates | |||
*/ | */ | |||
void markAsJumbo() const; | void markAsJumbo() const; | |||
bool isJumbo() const { return _jumbo; } | bool isJumbo() const { return _jumbo; } | |||
/** | /** | |||
* Attempt to refresh maximum chunk size from config. | * Attempt to refresh maximum chunk size from config. | |||
*/ | */ | |||
static void refreshChunkSize(); | static void refreshChunkSize(); | |||
/** | ||||
* sets MaxChunkSize | ||||
* 1 <= newMaxChunkSize <= 1024 | ||||
* @return true if newMaxChunkSize is valid and was set | ||||
*/ | ||||
static bool setMaxChunkSizeSizeMB( int newMaxChunkSize ); | ||||
// | // | |||
// public constants | // public constants | |||
// | // | |||
static int MaxChunkSize; | static int MaxChunkSize; | |||
static int MaxObjectPerChunk; | static int MaxObjectPerChunk; | |||
static bool ShouldAutoSplit; | static bool ShouldAutoSplit; | |||
// | // | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 14 lines changed or added | |||
chunk_version.h | chunk_version.h | |||
---|---|---|---|---|
skipping to change at line 197 | skipping to change at line 197 | |||
} | } | |||
if( el.isNumber() ){ | if( el.isNumber() ){ | |||
return ChunkVersion( static_cast<unsigned long long>(el.num berLong()), OID() ); | return ChunkVersion( static_cast<unsigned long long>(el.num berLong()), OID() ); | |||
} | } | |||
if( type == Timestamp || type == Date ){ | if( type == Timestamp || type == Date ){ | |||
return ChunkVersion( el._numberLong(), OID() ); | return ChunkVersion( el._numberLong(), OID() ); | |||
} | } | |||
// Note - we used to throw here, we can't anymore b/c debug bui | ||||
lds will be unhappy | ||||
warning() << "can't load version from element type (" << (int)( | ||||
el.type()) << ") " | ||||
<< el << endl; | ||||
*canParse = false; | *canParse = false; | |||
return ChunkVersion( 0, OID() ); | return ChunkVersion( 0, OID() ); | |||
} | } | |||
// | // | |||
// { version : <TS>, versionEpoch : <OID> } object format | // { version : <TS>, versionEpoch : <OID> } object format | |||
// | // | |||
static bool canParseBSON( const BSONObj& obj, const string& prefix= "" ){ | static bool canParseBSON( const BSONObj& obj, const string& prefix= "" ){ | |||
End of changes. 1 change blocks. | ||||
6 lines changed or deleted | 0 lines changed or added | |||
client.h | client.h | |||
---|---|---|---|---|
skipping to change at line 87 | skipping to change at line 87 | |||
/** this has to be called as the client goes away, but before threa d termination | /** this has to be called as the client goes away, but before threa d termination | |||
* @return true if anything was done | * @return true if anything was done | |||
*/ | */ | |||
bool shutdown(); | bool shutdown(); | |||
string clientAddress(bool includePort=false) const; | string clientAddress(bool includePort=false) const; | |||
CurOp* curop() const { return _curOp; } | CurOp* curop() const { return _curOp; } | |||
Context* getContext() const { return _context; } | Context* getContext() const { return _context; } | |||
Database* database() const { return _context ? _context->db() : 0; } | Database* database() const { return _context ? _context->db() : 0; } | |||
const char *ns() const { return _context->ns(); } | const char *ns() const { return _context->ns(); } | |||
const std::string desc() const { return _desc; } | const StringData desc() const { return _desc; } | |||
void setLastOp( OpTime op ) { _lastOp = op; } | void setLastOp( OpTime op ) { _lastOp = op; } | |||
OpTime getLastOp() const { return _lastOp; } | OpTime getLastOp() const { return _lastOp; } | |||
/** caution -- use Context class instead */ | /** caution -- use Context class instead */ | |||
void setContext(Context *c) { _context = c; } | void setContext(Context *c) { _context = c; } | |||
/* report what the last operation was. used by getlasterror */ | /* report what the last operation was. used by getlasterror */ | |||
void appendLastOp( BSONObjBuilder& b ) const; | void appendLastOp( BSONObjBuilder& b ) const; | |||
bool isGod() const { return _god; } /* this is for map/reduce write s */ | bool isGod() const { return _god; } /* this is for map/reduce write s */ | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
clientcursor.h | clientcursor.h | |||
---|---|---|---|---|
skipping to change at line 126 | skipping to change at line 126 | |||
_id = c->_cursorid; | _id = c->_cursorid; | |||
} | } | |||
else { | else { | |||
_c = 0; | _c = 0; | |||
_id = INVALID_CURSOR_ID; | _id = INVALID_CURSOR_ID; | |||
} | } | |||
} | } | |||
~Holder() { | ~Holder() { | |||
DESTRUCTOR_GUARD ( reset(); ); | DESTRUCTOR_GUARD ( reset(); ); | |||
} | } | |||
ClientCursor* get() { return _c; } | ||||
operator bool() { return _c; } | operator bool() { return _c; } | |||
ClientCursor * operator-> () { return _c; } | ClientCursor * operator-> () { return _c; } | |||
const ClientCursor * operator-> () const { return _c; } | const ClientCursor * operator-> () const { return _c; } | |||
/** Release ownership of the ClientCursor. */ | /** Release ownership of the ClientCursor. */ | |||
void release() { | void release() { | |||
_c = 0; | _c = 0; | |||
_id = INVALID_CURSOR_ID; | _id = INVALID_CURSOR_ID; | |||
} | } | |||
private: | private: | |||
ClientCursor *_c; | ClientCursor *_c; | |||
skipping to change at line 332 | skipping to change at line 333 | |||
} | } | |||
/** | /** | |||
* Deletes the cursor with the provided @param 'id' if one exists. | * Deletes the cursor with the provided @param 'id' if one exists. | |||
* @throw if the cursor with the provided id is pinned. | * @throw if the cursor with the provided id is pinned. | |||
* This does not do any auth checking and should be used only when erasing cursors as part | * This does not do any auth checking and should be used only when erasing cursors as part | |||
* of cleaning up internal operations. | * of cleaning up internal operations. | |||
*/ | */ | |||
static bool erase(CursorId id); | static bool erase(CursorId id); | |||
// Same as erase but checks to make sure this thread has read permi ssion on the cursor's | // Same as erase but checks to make sure this thread has read permi ssion on the cursor's | |||
// namespace. This should be called when receiving killCursors fro | // namespace. This should be called when receiving killCursors fro | |||
m a client. | m a client. This should | |||
// not be called when ccmutex is held. | ||||
static bool eraseIfAuthorized(CursorId id); | static bool eraseIfAuthorized(CursorId id); | |||
/** | /** | |||
* @return number of cursors found | * @return number of cursors found | |||
*/ | */ | |||
static int erase(int n, long long* ids); | static int erase(int n, long long* ids); | |||
static int eraseIfAuthorized(int n, long long* ids); | static int eraseIfAuthorized(int n, long long* ids); | |||
void mayUpgradeStorage() { | void mayUpgradeStorage() { | |||
/* if ( !ids_.get() ) | /* if ( !ids_.get() ) | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
cmdline.h | cmdline.h | |||
---|---|---|---|---|
skipping to change at line 140 | skipping to change at line 140 | |||
pid_t parentProc; // --fork pid of initial process | pid_t parentProc; // --fork pid of initial process | |||
pid_t leaderProc; // --fork pid of leader process | pid_t leaderProc; // --fork pid of leader process | |||
#endif | #endif | |||
#ifdef MONGO_SSL | #ifdef MONGO_SSL | |||
bool sslOnNormalPorts; // --sslOnNormalPorts | bool sslOnNormalPorts; // --sslOnNormalPorts | |||
std::string sslPEMKeyFile; // --sslPEMKeyFile | std::string sslPEMKeyFile; // --sslPEMKeyFile | |||
std::string sslPEMKeyPassword; // --sslPEMKeyPassword | std::string sslPEMKeyPassword; // --sslPEMKeyPassword | |||
std::string sslCAFile; // --sslCAFile | std::string sslCAFile; // --sslCAFile | |||
std::string sslCRLFile; // --sslCRLFile | std::string sslCRLFile; // --sslCRLFile | |||
bool sslForceCertificateValidation; | bool sslWeakCertificateValidation; | |||
bool sslFIPSMode; | ||||
#endif | #endif | |||
/** | /** | |||
* Switches to enable experimental (unsupported) features. | * Switches to enable experimental (unsupported) features. | |||
*/ | */ | |||
struct ExperimentalFeatures { | struct ExperimentalFeatures { | |||
ExperimentalFeatures() | ExperimentalFeatures() | |||
: indexStatsCmdEnabled(false) | : indexStatsCmdEnabled(false) | |||
, storageDetailsCmdEnabled(false) | , storageDetailsCmdEnabled(false) | |||
{} | {} | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 2 lines changed or added | |||
collection_manager.h | collection_manager.h | |||
---|---|---|---|---|
skipping to change at line 50 | skipping to change at line 50 | |||
class CollectionManager { | class CollectionManager { | |||
MONGO_DISALLOW_COPYING(CollectionManager); | MONGO_DISALLOW_COPYING(CollectionManager); | |||
public: | public: | |||
~CollectionManager(); | ~CollectionManager(); | |||
// | // | |||
// cloning support | // cloning support | |||
// | // | |||
/** | /** | |||
* Returns a new manager's instance based on 'this's state by remov | * Returns a new manager's instance based on 'this's state by remov | |||
ing 'chunk'. The new | ing 'chunk'. | |||
* manager will be at 'newShardVersion', which should be higher tha | * When cloning away the last chunk, 'newShardVersion' must be zero | |||
n the current | . In any case, | |||
* one. When cloning away the last chunk, 'newShardVersion' must be | * the caller owns the new manager when the cloning is successful. | |||
zero. In any case, | ||||
* the caller owns the new manager when the cloning is succesful. | ||||
* | * | |||
* If a new manager can't be created, returns NULL and fills in 'er rMsg', if it was | * If a new manager can't be created, returns NULL and fills in 'er rMsg', if it was | |||
* provided. | * provided. | |||
*/ | */ | |||
CollectionManager* cloneMinus(const ChunkType& chunk, | CollectionManager* cloneMinus(const ChunkType& chunk, | |||
const ChunkVersion& newShardVersion, | const ChunkVersion& newShardVersion, | |||
string* errMsg) const; | string* errMsg) const; | |||
/** | /** | |||
* Returns a new manager's instance based on 'this's state by addin g 'chunk'. The new | * Returns a new manager's instance based on 'this's state by addin g 'chunk'. The new | |||
* manager will be at 'newShardVersion', which should be higher tha | * manager can never be zero, though (see cloneMinus). The caller o | |||
n the current | wns the new manager. | |||
* one. It can never be zero, though (see cloneMinus). The caller o | ||||
wns the new manager. | ||||
* | * | |||
* If a new manager can't be created, returns NULL and fills in 'er rMsg', if it was | * If a new manager can't be created, returns NULL and fills in 'er rMsg', if it was | |||
* provided. | * provided. | |||
*/ | */ | |||
CollectionManager* clonePlus(const ChunkType& chunk, | CollectionManager* clonePlus(const ChunkType& chunk, | |||
const ChunkVersion& newShardVersion, | const ChunkVersion& newShardVersion, | |||
string* errMsg) const; | string* errMsg) const; | |||
/** | /** | |||
* Returns a new manager's instance by splitting an existing 'chunk ' at the points | * Returns a new manager's instance by splitting an existing 'chunk ' at the points | |||
skipping to change at line 105 | skipping to change at line 103 | |||
* collection / chunkset yet. 'doc' must contain the sharding key a nd, optionally, | * collection / chunkset yet. 'doc' must contain the sharding key a nd, optionally, | |||
* other attributes. | * other attributes. | |||
*/ | */ | |||
bool belongsToMe(const BSONObj& doc) const; | bool belongsToMe(const BSONObj& doc) const; | |||
/** | /** | |||
* Given the chunk's min key (or empty doc) in 'lookupKey', gets th e boundaries of the | * Given the chunk's min key (or empty doc) in 'lookupKey', gets th e boundaries of the | |||
* chunk following that one (the first), and fills in 'foundChunk' with those | * chunk following that one (the first), and fills in 'foundChunk' with those | |||
* boundaries. If the next chunk happens to be the last one, retur ns true otherwise | * boundaries. If the next chunk happens to be the last one, retur ns true otherwise | |||
* false. | * false. | |||
* | ||||
* @param lookupKey passing a doc that does not belong to this mana | ||||
ger is undefined. | ||||
* An empty doc is special and the chunk with the lowest range | ||||
will be set on | ||||
* foundChunk. | ||||
*/ | */ | |||
bool getNextChunk(const BSONObj& lookupKey, ChunkType* foundChunk) const; | bool getNextChunk(const BSONObj& lookupKey, ChunkType* foundChunk) const; | |||
// | // | |||
// accessors | // accessors | |||
// | // | |||
ChunkVersion getMaxCollVersion() const { return _maxCollVersion; } | ChunkVersion getMaxCollVersion() const { return _maxCollVersion; } | |||
ChunkVersion getMaxShardVersion() const { return _maxShardVersion; } | ChunkVersion getMaxShardVersion() const { return _maxShardVersion; } | |||
skipping to change at line 132 | skipping to change at line 134 | |||
private: | private: | |||
// Effectively, the MetadataLoader is this class's builder. So we o pen an exception | // Effectively, the MetadataLoader is this class's builder. So we o pen an exception | |||
// and grant it friendship. | // and grant it friendship. | |||
friend class MetadataLoader; | friend class MetadataLoader; | |||
// a version for this collection that identifies the collection inc arnation (ie, a | // a version for this collection that identifies the collection inc arnation (ie, a | |||
// dropped and recreated collection with the same name would have a different version) | // dropped and recreated collection with the same name would have a different version) | |||
ChunkVersion _maxCollVersion; | ChunkVersion _maxCollVersion; | |||
// | // | |||
// sharded state below, for when the colelction gets sharded | // sharded state below, for when the collection gets sharded | |||
// | // | |||
// highest ChunkVersion for which this manager's information is acc urate | // highest ChunkVersion for which this manager's information is acc urate | |||
ChunkVersion _maxShardVersion; | ChunkVersion _maxShardVersion; | |||
// key pattern for chunks under this range | // key pattern for chunks under this range | |||
BSONObj _key; | BSONObj _key; | |||
// a map from a min key into the chunk's (or range's) max boundary | // a map from a min key into the chunk's (or range's) max boundary | |||
typedef map< BSONObj, BSONObj , BSONObjCmp > RangeMap; | typedef map< BSONObj, BSONObj , BSONObjCmp > RangeMap; | |||
End of changes. 4 change blocks. | ||||
12 lines changed or deleted | 14 lines changed or added | |||
counter.h | counter.h | |||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
* 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/platform/atomic_word.h" | #include "mongo/platform/atomic_word.h" | |||
#include "mongo/platform/cstdint.h" | #include "mongo/platform/cstdint.h" | |||
namespace mongo { | namespace mongo { | |||
/** | ||||
* A 64bit (atomic) counter. | ||||
* | ||||
* The constructor allows setting the start value, and increment([int]) | ||||
is used to change it. | ||||
* | ||||
* The value can be returned using get() or the (long long) function op | ||||
erator. | ||||
*/ | ||||
class Counter64 { | class Counter64 { | |||
public: | public: | |||
/** Atomically increment. */ | ||||
void increment( uint64_t n = 1 ) { _counter.addAndFetch(n); } | void increment( uint64_t n = 1 ) { _counter.addAndFetch(n); } | |||
/** Atomically decrement. */ | ||||
void decrement( uint64_t n = 1 ) { _counter.subtractAndFetch(n); } | ||||
/** Return the current value */ | ||||
long long get() const { return _counter.load(); } | long long get() const { return _counter.load(); } | |||
operator long long() const { return get(); } | operator long long() const { return get(); } | |||
private: | private: | |||
AtomicInt64 _counter; | AtomicInt64 _counter; | |||
}; | }; | |||
} | } | |||
End of changes. 3 change blocks. | ||||
1 lines changed or deleted | 14 lines changed or added | |||
d_logic.h | d_logic.h | |||
---|---|---|---|---|
skipping to change at line 46 | skipping to change at line 46 | |||
// -------------- | // -------------- | |||
class ShardingState { | class ShardingState { | |||
public: | public: | |||
ShardingState(); | ShardingState(); | |||
bool enabled() const { return _enabled; } | bool enabled() const { return _enabled; } | |||
const string& getConfigServer() const { return _configServer; } | const string& getConfigServer() const { return _configServer; } | |||
void enable( const string& server ); | void enable( const string& server ); | |||
// Initialize sharding state and begin authenticating outgoing conn | ||||
ections and handling | ||||
// shard versions. If this is not run before sharded operations oc | ||||
cur auth will not work | ||||
// and versions will not be tracked. | ||||
static void initialize(const string& server); | ||||
void gotShardName( const string& name ); | void gotShardName( const string& name ); | |||
void gotShardHost( string host ); | void gotShardHost( string host ); | |||
string getShardName() { return _shardName; } | string getShardName() { return _shardName; } | |||
string getShardHost() { return _shardHost; } | string getShardHost() { return _shardHost; } | |||
/** Reverts back to a state where this mongod is not sharded. */ | /** Reverts back to a state where this mongod is not sharded. */ | |||
void resetShardingState(); | void resetShardingState(); | |||
// versioning support | // versioning support | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 7 lines changed or added | |||
database.h | database.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
class Extent; | class Extent; | |||
class MongoDataFile; | class MongoDataFile; | |||
/** | /** | |||
* Database represents a database database | * Database represents a database database | |||
* Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ... | * Each database database has its own set of files -- dbname.ns, dbname .0, dbname.1, ... | |||
* NOT memory mapped | * NOT memory mapped | |||
*/ | */ | |||
class Database { | class Database { | |||
public: | public: | |||
static bool _openAllFiles; | ||||
// you probably need to be in dbHolderMutex when constructing this | // you probably need to be in dbHolderMutex when constructing this | |||
Database(const char *nm, /*out*/ bool& newDb, const string& _path = dbpath); | Database(const char *nm, /*out*/ bool& newDb, const string& _path = dbpath); | |||
private: | private: | |||
~Database(); // closes files and other cleanup see below. | ~Database(); // closes files and other cleanup see below. | |||
public: | public: | |||
/* you must use this to close - there is essential code in this met hod that is not in the ~Database destructor. | /* you must use this to close - there is essential code in this met hod that is not in the ~Database destructor. | |||
thus the destructor is private. this could be cleaned up one da y... | thus the destructor is private. this could be cleaned up one da y... | |||
*/ | */ | |||
static void closeDatabase( const char *db, const string& path ); | static void closeDatabase( const char *db, const string& path ); | |||
void openAllFiles(); | void openAllFiles(); | |||
void clearTmpCollections(); | ||||
/** | /** | |||
* tries to make sure that this hasn't been deleted | * tries to make sure that this hasn't been deleted | |||
*/ | */ | |||
bool isOk() const { return magic == 781231; } | bool isOk() const { return magic == 781231; } | |||
bool isEmpty() { return ! namespaceIndex.allocated(); } | bool isEmpty() { return ! namespaceIndex.allocated(); } | |||
/** | /** | |||
* total file size of Database in bytes | * total file size of Database in bytes | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 1 lines changed or added | |||
dbclient.h | dbclient.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
#include "mongo/client/redef_macros.h" | #include "mongo/client/redef_macros.h" | |||
#include "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "mongo/client/connpool.h" | #include "mongo/client/connpool.h" | |||
#include "mongo/client/dbclient_rs.h" | #include "mongo/client/dbclient_rs.h" | |||
#include "mongo/client/dbclientcursor.h" | #include "mongo/client/dbclientcursor.h" | |||
#include "mongo/client/dbclientinterface.h" | #include "mongo/client/dbclientinterface.h" | |||
#include "mongo/client/gridfs.h" | #include "mongo/client/gridfs.h" | |||
#include "mongo/client/model.h" | #include "mongo/client/model.h" | |||
#include "mongo/client/sasl_client_authenticate.h" | ||||
#include "mongo/client/syncclusterconnection.h" | #include "mongo/client/syncclusterconnection.h" | |||
#include "mongo/client/undef_macros.h" | #include "mongo/client/undef_macros.h" | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
dbclient_rs.h | dbclient_rs.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
#include <set> | #include <set> | |||
#include <utility> | #include <utility> | |||
#include "mongo/client/dbclientinterface.h" | #include "mongo/client/dbclientinterface.h" | |||
#include "mongo/util/net/hostandport.h" | #include "mongo/util/net/hostandport.h" | |||
namespace mongo { | namespace mongo { | |||
class ReplicaSetMonitor; | class ReplicaSetMonitor; | |||
class TagSet; | class TagSet; | |||
struct ReadPreferenceSetting; | ||||
typedef shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr; | typedef shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr; | |||
typedef pair<set<string>,set<int> > NodeDiff; | typedef pair<set<string>,set<int> > NodeDiff; | |||
/** | /** | |||
* manages state about a replica set for client | * manages state about a replica set for client | |||
* keeps tabs on whose master and what slaves are up | * keeps tabs on whose master and what slaves are up | |||
* can hand a slave to someone for SLAVE_OK | * can hand a slave to someone for SLAVE_OK | |||
* one instance per process per replica set | * one instance per process per replica set | |||
* TODO: we might be able to use a regular Node * to avoid _lock | * TODO: we might be able to use a regular Node * to avoid _lock | |||
*/ | */ | |||
skipping to change at line 434 | skipping to change at line 435 | |||
DBClientReplicaSet( const string& name , const vector<HostAndPort>& servers, double so_timeout=0 ); | DBClientReplicaSet( const string& name , const vector<HostAndPort>& servers, double so_timeout=0 ); | |||
virtual ~DBClientReplicaSet(); | virtual ~DBClientReplicaSet(); | |||
/** | /** | |||
* Returns false if no member of the set were reachable. This objec t | * Returns false if no member of the set were reachable. This objec t | |||
* can still be used even when false was returned as it will try to | * can still be used even when false was returned as it will try to | |||
* reconnect when you use it later. | * reconnect when you use it later. | |||
*/ | */ | |||
bool connect(); | bool connect(); | |||
/** Authorize. Authorizes all nodes as needed | ||||
*/ | ||||
virtual bool auth(const string &dbname, const string &username, con | ||||
st string &pwd, string& errmsg, bool digestPassword = true, Auth::Level * l | ||||
evel = NULL); | ||||
/** | /** | |||
* Logs out the connection for the given database. | * Logs out the connection for the given database. | |||
* | * | |||
* @param dbname the database to logout from. | * @param dbname the database to logout from. | |||
* @param info the result object for the logout command (provided f or backwards | * @param info the result object for the logout command (provided f or backwards | |||
* compatibility with mongo shell) | * compatibility with mongo shell) | |||
*/ | */ | |||
virtual void logout(const string& dbname, BSONObj& info); | virtual void logout(const string& dbname, BSONObj& info); | |||
// ----------- simple functions -------------- | // ----------- simple functions -------------- | |||
skipping to change at line 477 | skipping to change at line 474 | |||
// ---- access raw connections ---- | // ---- access raw connections ---- | |||
/** | /** | |||
* WARNING: this method is very dangerous - this object can decide to free the | * WARNING: this method is very dangerous - this object can decide to free the | |||
* returned master connection any time. | * returned master connection any time. | |||
* | * | |||
* @return the reference to the address that points to the master c onnection. | * @return the reference to the address that points to the master c onnection. | |||
*/ | */ | |||
DBClientConnection& masterConn(); | DBClientConnection& masterConn(); | |||
/** | ||||
* WARNING: this method is very dangerous - this object can decide | ||||
to free the | ||||
* returned master connection any time. This can also unpin the | ||||
cached | ||||
* slaveOk/read preference connection. | ||||
* | ||||
* @return the reference to the address that points to a secondary | ||||
connection. | ||||
*/ | ||||
DBClientConnection& slaveConn(); | DBClientConnection& slaveConn(); | |||
// ---- callback pieces ------- | // ---- callback pieces ------- | |||
virtual void say( Message &toSend, bool isRetry = false , string* a ctualServer = 0); | virtual void say( Message &toSend, bool isRetry = false , string* a ctualServer = 0); | |||
virtual bool recv( Message &toRecv ); | virtual bool recv( Message &toRecv ); | |||
virtual void checkResponse( const char* data, int nReturned, bool* retry = NULL, string* targetHost = NULL ); | virtual void checkResponse( const char* data, int nReturned, bool* retry = NULL, string* targetHost = NULL ); | |||
/* this is the callback from our underlying connections to notify u s that we got a "not master" error. | /* this is the callback from our underlying connections to notify u s that we got a "not master" error. | |||
*/ | */ | |||
skipping to change at line 514 | skipping to change at line 519 | |||
virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SET; } | virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SET; } | |||
virtual bool lazySupported() const { return true; } | virtual bool lazySupported() const { return true; } | |||
// ---- low level ------ | // ---- low level ------ | |||
virtual bool call( Message &toSend, Message &response, bool assertO k=true , string * actualServer = 0 ); | virtual bool call( Message &toSend, Message &response, bool assertO k=true , string * actualServer = 0 ); | |||
virtual bool callRead( Message& toSend , Message& response ) { retu rn checkMaster()->callRead( toSend , response ); } | virtual bool callRead( Message& toSend , Message& response ) { retu rn checkMaster()->callRead( toSend , response ); } | |||
protected: | protected: | |||
/** Authorize. Authorizes all nodes as needed | ||||
*/ | ||||
virtual void _auth(const BSONObj& params); | ||||
virtual void sayPiggyBack( Message &toSend ) { checkMaster()->say( toSend ); } | virtual void sayPiggyBack( Message &toSend ) { checkMaster()->say( toSend ); } | |||
private: | private: | |||
/** | /** | |||
* Used to simplify slave-handling logic on errors | * Used to simplify slave-handling logic on errors | |||
* | * | |||
* @return back the passed cursor | * @return back the passed cursor | |||
* @throws DBException if the directed node cannot accept the query because it | * @throws DBException if the directed node cannot accept the query because it | |||
* is not a master | * is not a master | |||
*/ | */ | |||
auto_ptr<DBClientCursor> checkSlaveQueryResult( auto_ptr<DBClientCu rsor> result ); | auto_ptr<DBClientCursor> checkSlaveQueryResult( auto_ptr<DBClientCu rsor> result ); | |||
DBClientConnection * checkMaster(); | DBClientConnection * checkMaster(); | |||
/** | /** | |||
* Helper method for selecting a node based on the read preference. Will advance | * Helper method for selecting a node based on the read preference. Will advance | |||
* the tag tags object if it cannot find a node that matches the cu rrent tag. | * the tag tags object if it cannot find a node that matches the cu rrent tag. | |||
* | * | |||
* @param preference the preference to use for selecting a node | * @param readPref the preference to use for selecting a node. | |||
* @param tags pointer to the list of tags. | ||||
* | * | |||
* @return a pointer to the new connection object if it can find a good connection. | * @return a pointer to the new connection object if it can find a good connection. | |||
* Otherwise it returns NULL. | * Otherwise it returns NULL. | |||
* | * | |||
* @throws DBException when an error occurred either when trying to connect to | * @throws DBException when an error occurred either when trying to connect to | |||
* a node that was thought to be ok or when an assertion happen ed. | * a node that was thought to be ok or when an assertion happen ed. | |||
*/ | */ | |||
DBClientConnection* selectNodeUsingTags(ReadPreference preference, | DBClientConnection* selectNodeUsingTags(shared_ptr<ReadPreferenceSe | |||
TagSet* tags); | tting> readPref); | |||
/** | /** | |||
* @return true if the last host used in the last slaveOk query is still in the | * @return true if the last host used in the last slaveOk query is still in the | |||
* set and can be used for the given read preference. | * set and can be used for the given read preference. | |||
*/ | */ | |||
bool checkLastHost( ReadPreference preference, const TagSet* tags ) ; | bool checkLastHost(const ReadPreferenceSetting* readPref); | |||
/** | /** | |||
* Destroys all cached information about the last slaveOk operation . | * Destroys all cached information about the last slaveOk operation . | |||
*/ | */ | |||
void invalidateLastSlaveOkCache(); | void invalidateLastSlaveOkCache(); | |||
void _auth( DBClientConnection * conn ); | void _auth( DBClientConnection * conn ); | |||
/** | /** | |||
* Maximum number of retries to make for auto-retry logic when perf orming a slave ok | * Maximum number of retries to make for auto-retry logic when perf orming a slave ok | |||
skipping to change at line 581 | skipping to change at line 588 | |||
// This is because the primary connection is special in mongos - it is the only | // This is because the primary connection is special in mongos - it is the only | |||
// connection that is versioned. | // connection that is versioned. | |||
// WARNING: do not assign this variable (which will increment the i nternal ref | // WARNING: do not assign this variable (which will increment the i nternal ref | |||
// counter) to any other variable other than _lastSlaveOkConn. | // counter) to any other variable other than _lastSlaveOkConn. | |||
boost::shared_ptr<DBClientConnection> _master; | boost::shared_ptr<DBClientConnection> _master; | |||
// Last used host in a slaveOk query (can be a primary) | // Last used host in a slaveOk query (can be a primary) | |||
HostAndPort _lastSlaveOkHost; | HostAndPort _lastSlaveOkHost; | |||
// Last used connection in a slaveOk query (can be a primary) | // Last used connection in a slaveOk query (can be a primary) | |||
boost::shared_ptr<DBClientConnection> _lastSlaveOkConn; | boost::shared_ptr<DBClientConnection> _lastSlaveOkConn; | |||
boost::shared_ptr<ReadPreferenceSetting> _lastReadPref; | ||||
double _so_timeout; | double _so_timeout; | |||
/** | ||||
* for storing authentication info | ||||
* fields are exactly for DBClientConnection::auth | ||||
*/ | ||||
struct AuthInfo { | ||||
// Default constructor provided only to make it compatible with | ||||
std::map::operator[] | ||||
AuthInfo(): digestPassword(false) { } | ||||
AuthInfo( string d , string u , string p , bool di ) | ||||
: dbname( d ) , username( u ) , pwd( p ) , digestPassword( | ||||
di ) {} | ||||
string dbname; | ||||
string username; | ||||
string pwd; | ||||
bool digestPassword; | ||||
}; | ||||
// we need to store so that when we connect to a new node on failur e | // we need to store so that when we connect to a new node on failur e | |||
// we can re-auth | // we can re-auth | |||
// this could be a security issue, as the password is stored in mem ory | // this could be a security issue, as the password is stored in mem ory | |||
// not sure if/how we should handle | // not sure if/how we should handle | |||
std::map<string, AuthInfo> _auths; // dbName -> AuthInfo | std::map<string, BSONObj> _auths; // dbName -> auth parameters | |||
protected: | protected: | |||
/** | /** | |||
* for storing (non-threadsafe) information between lazy calls | * for storing (non-threadsafe) information between lazy calls | |||
*/ | */ | |||
class LazyState { | class LazyState { | |||
public: | public: | |||
LazyState() : _lastClient( NULL ), _lastOp( -1 ), _slaveOk( fal se ), _retries( 0 ) {} | LazyState() : _lastClient( NULL ), _lastOp( -1 ), _slaveOk( fal se ), _retries( 0 ) {} | |||
DBClientConnection* _lastClient; | DBClientConnection* _lastClient; | |||
skipping to change at line 669 | skipping to change at line 662 | |||
* @return true if the iterator has been exhausted. | * @return true if the iterator has been exhausted. | |||
*/ | */ | |||
bool isExhausted() const; | bool isExhausted() const; | |||
/** | /** | |||
* @return an unordered iterator to the tag list. The caller is res ponsible for | * @return an unordered iterator to the tag list. The caller is res ponsible for | |||
* destroying the returned iterator. | * destroying the returned iterator. | |||
*/ | */ | |||
BSONObjIterator* getIterator() const; | BSONObjIterator* getIterator() const; | |||
/** | ||||
* Create a new copy of this tag set and wuth the iterator pointing | ||||
at the | ||||
* head. | ||||
*/ | ||||
TagSet* clone() const; | ||||
/** | ||||
* @returns true if the other TagSet has the same tag set specifica | ||||
tion with | ||||
* this tag set, disregarding where the current iterator is poi | ||||
nting to. | ||||
*/ | ||||
bool equals(const TagSet& other) const; | ||||
private: | private: | |||
BSONObj _currentTag; | BSONObj _currentTag; | |||
bool _isExhausted; | bool _isExhausted; | |||
// Important: do not re-order _tags & _tagIterator | // Important: do not re-order _tags & _tagIterator | |||
BSONArray _tags; | BSONArray _tags; | |||
BSONArrayIteratorSorted _tagIterator; | BSONArrayIteratorSorted _tagIterator; | |||
}; | }; | |||
struct ReadPreferenceSetting { | ||||
/** | ||||
* @param tag cannot be NULL. | ||||
*/ | ||||
ReadPreferenceSetting(ReadPreference pref, TagSet* tag): | ||||
pref(pref), tags(tag->clone()) { | ||||
} | ||||
~ReadPreferenceSetting() { | ||||
delete tags; | ||||
} | ||||
inline bool equals(const ReadPreferenceSetting& other) const { | ||||
return pref == other.pref && tags->equals(*other.tags); | ||||
} | ||||
const ReadPreference pref; | ||||
/** | ||||
* Note: This object owns this memory. | ||||
*/ | ||||
TagSet* tags; | ||||
}; | ||||
} | } | |||
End of changes. 12 change blocks. | ||||
29 lines changed or deleted | 61 lines changed or added | |||
dbclientcursor.h | dbclientcursor.h | |||
---|---|---|---|---|
skipping to change at line 65 | skipping to change at line 65 | |||
then perhaps stop. | then perhaps stop. | |||
*/ | */ | |||
int objsLeftInBatch() const { _assertIfNull(); return _putBack.size () + batch.nReturned - batch.pos; } | int objsLeftInBatch() const { _assertIfNull(); return _putBack.size () + batch.nReturned - batch.pos; } | |||
bool moreInCurrentBatch() { return objsLeftInBatch() > 0; } | bool moreInCurrentBatch() { return objsLeftInBatch() > 0; } | |||
/** next | /** next | |||
@return next object in the result cursor. | @return next object in the result cursor. | |||
on an error at the remote server, you will get back: | on an error at the remote server, you will get back: | |||
{ $err: <string> } | { $err: <string> } | |||
if you do not want to handle that yourself, call nextSafe(). | if you do not want to handle that yourself, call nextSafe(). | |||
Warning: The returned BSONObj will become invalid after the next | ||||
batch | ||||
is fetched or when this cursor is destroyed. | ||||
*/ | */ | |||
BSONObj next(); | BSONObj next(); | |||
/** | /** | |||
restore an object previously returned by next() to the cursor | restore an object previously returned by next() to the cursor | |||
*/ | */ | |||
void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); } | void putBack( const BSONObj &o ) { _putBack.push( o.getOwned() ); } | |||
/** throws AssertionException if get back { $err : ... } */ | /** throws AssertionException if get back { $err : ... } */ | |||
BSONObj nextSafe() { | BSONObj nextSafe() { | |||
skipping to change at line 141 | skipping to change at line 144 | |||
int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) : | int _nToSkip, const BSONObj *_fieldsToReturn, int q ueryOptions , int bs ) : | |||
_client(client), | _client(client), | |||
ns(_ns), | ns(_ns), | |||
query(_query), | query(_query), | |||
nToReturn(_nToReturn), | nToReturn(_nToReturn), | |||
haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_Curso rTailable)), | haveLimit( _nToReturn > 0 && !(queryOptions & QueryOption_Curso rTailable)), | |||
nToSkip(_nToSkip), | nToSkip(_nToSkip), | |||
fieldsToReturn(_fieldsToReturn), | fieldsToReturn(_fieldsToReturn), | |||
opts(queryOptions), | opts(queryOptions), | |||
batchSize(bs==1?2:bs), | batchSize(bs==1?2:bs), | |||
resultFlags(0), | ||||
cursorId(), | cursorId(), | |||
_ownCursor( true ), | _ownCursor( true ), | |||
wasError( false ) { | wasError( false ) { | |||
_finishConsInit(); | _finishConsInit(); | |||
} | } | |||
DBClientCursor( DBClientBase* client, const string &_ns, long long _cursorId, int _nToReturn, int options ) : | DBClientCursor( DBClientBase* client, const string &_ns, long long _cursorId, int _nToReturn, int options ) : | |||
_client(client), | _client(client), | |||
ns(_ns), | ns(_ns), | |||
nToReturn( _nToReturn ), | nToReturn( _nToReturn ), | |||
haveLimit( _nToReturn > 0 && !(options & QueryOption_CursorTail able)), | haveLimit( _nToReturn > 0 && !(options & QueryOption_CursorTail able)), | |||
nToSkip(0), | ||||
fieldsToReturn(0), | ||||
opts( options ), | opts( options ), | |||
batchSize(0), | ||||
resultFlags(0), | ||||
cursorId(_cursorId), | cursorId(_cursorId), | |||
_ownCursor( true ) { | _ownCursor(true), | |||
wasError(false) { | ||||
_finishConsInit(); | _finishConsInit(); | |||
} | } | |||
virtual ~DBClientCursor(); | virtual ~DBClientCursor(); | |||
long long getCursorId() const { return cursorId; } | long long getCursorId() const { return cursorId; } | |||
/** by default we "own" the cursor and will send the server a KillC ursor | /** by default we "own" the cursor and will send the server a KillC ursor | |||
message when ~DBClientCursor() is called. This function overrid es that. | message when ~DBClientCursor() is called. This function overrid es that. | |||
*/ | */ | |||
End of changes. 5 change blocks. | ||||
1 lines changed or deleted | 11 lines changed or added | |||
dbclientinterface.h | dbclientinterface.h | |||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
* 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 "mongo/pch.h" | #include "mongo/pch.h" | |||
#include "mongo/client/authlevel.h" | ||||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/platform/atomic_word.h" | #include "mongo/platform/atomic_word.h" | |||
#include "mongo/util/net/message.h" | #include "mongo/util/net/message.h" | |||
#include "mongo/util/net/message_port.h" | #include "mongo/util/net/message_port.h" | |||
namespace mongo { | namespace mongo { | |||
/** the query field 'options' can have these bits set: */ | /** the query field 'options' can have these bits set: */ | |||
enum QueryOptions { | enum QueryOptions { | |||
/** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks | /** Tailable means cursor is not closed when the last data is retri eved. rather, the cursor marks | |||
skipping to change at line 167 | skipping to change at line 166 | |||
* Read from a secondary if available, otherwise read from the prim ary. | * Read from a secondary if available, otherwise read from the prim ary. | |||
*/ | */ | |||
ReadPreference_SecondaryPreferred, | ReadPreference_SecondaryPreferred, | |||
/** | /** | |||
* Read from any member. | * Read from any member. | |||
*/ | */ | |||
ReadPreference_Nearest, | ReadPreference_Nearest, | |||
}; | }; | |||
/** | ||||
* @return true if the query object contains a read preference specific | ||||
ation object. | ||||
*/ | ||||
bool hasReadPreference(const BSONObj& queryObj); | ||||
class DBClientBase; | class DBClientBase; | |||
class DBClientConnection; | class DBClientConnection; | |||
/** | /** | |||
* ConnectionString handles parsing different ways to connect to mongo and determining method | * ConnectionString handles parsing different ways to connect to mongo and determining method | |||
* samples: | * samples: | |||
* server | * server | |||
* server:port | * server:port | |||
* foo/server:port,server:port SET | * foo/server:port,server:port SET | |||
* server,server,server SYNC | * server,server,server SYNC | |||
skipping to change at line 332 | skipping to change at line 326 | |||
class DBClientCursor; | class DBClientCursor; | |||
class DBClientCursorBatchIterator; | class DBClientCursorBatchIterator; | |||
/** Represents a Mongo query expression. Typically one uses the QUERY( ...) macro to construct a Query object. | /** Represents a Mongo query expression. Typically one uses the QUERY( ...) macro to construct a Query object. | |||
Examples: | Examples: | |||
QUERY( "age" << 33 << "school" << "UCLA" ).sort("name") | QUERY( "age" << 33 << "school" << "UCLA" ).sort("name") | |||
QUERY( "age" << GT << 30 << LT << 50 ) | QUERY( "age" << GT << 30 << LT << 50 ) | |||
*/ | */ | |||
class Query { | class Query { | |||
public: | public: | |||
static const BSONField<BSONObj> ReadPrefField; | ||||
static const BSONField<std::string> ReadPrefModeField; | ||||
static const BSONField<BSONArray> ReadPrefTagsField; | ||||
BSONObj obj; | BSONObj obj; | |||
Query() : obj(BSONObj()) { } | Query() : obj(BSONObj()) { } | |||
Query(const BSONObj& b) : obj(b) { } | Query(const BSONObj& b) : obj(b) { } | |||
Query(const string &json); | Query(const string &json); | |||
Query(const char * json); | Query(const char * json); | |||
/** Add a sort (ORDER BY) criteria to the query expression. | /** Add a sort (ORDER BY) criteria to the query expression. | |||
@param sortPattern the sort order template. For example to ord er by name ascending, time descending: | @param sortPattern the sort order template. For example to ord er by name ascending, time descending: | |||
{ name : 1, ts : -1 } | { name : 1, ts : -1 } | |||
i.e. | i.e. | |||
skipping to change at line 407 | skipping to change at line 405 | |||
of these as "bind variables". | of these as "bind variables". | |||
Examples: | Examples: | |||
conn.findOne("test.coll", Query("{a:3}").where("this.b == 2 | | this.c == 3")); | conn.findOne("test.coll", Query("{a:3}").where("this.b == 2 | | this.c == 3")); | |||
Query badBalance = Query().where("this.debits - this.credits < 0"); | Query badBalance = Query().where("this.debits - this.credits < 0"); | |||
*/ | */ | |||
Query& where(const string &jscode, BSONObj scope); | Query& where(const string &jscode, BSONObj scope); | |||
Query& where(const string &jscode) { return where(jscode, BSONObj() ); } | Query& where(const string &jscode) { return where(jscode, BSONObj() ); } | |||
/** | /** | |||
* Sets the read preference for this query. | ||||
* | ||||
* @param pref the read preference mode for this query. | ||||
* @param tags the set of tags to use for this query. | ||||
*/ | ||||
Query& readPref(ReadPreference pref, const BSONArray& tags); | ||||
/** | ||||
* @return true if this query has an orderby, hint, or some other f ield | * @return true if this query has an orderby, hint, or some other f ield | |||
*/ | */ | |||
bool isComplex( bool * hasDollar = 0 ) const; | bool isComplex( bool * hasDollar = 0 ) const; | |||
static bool isComplex(const BSONObj& obj, bool* hasDollar = 0); | ||||
BSONObj getFilter() const; | BSONObj getFilter() const; | |||
BSONObj getSort() const; | BSONObj getSort() const; | |||
BSONObj getHint() const; | BSONObj getHint() const; | |||
bool isExplain() const; | bool isExplain() const; | |||
/** | ||||
* @return true if the query object contains a read preference spec | ||||
ification object. | ||||
*/ | ||||
static bool hasReadPreference(const BSONObj& queryObj); | ||||
string toString() const; | string toString() const; | |||
operator string() const { return toString(); } | operator string() const { return toString(); } | |||
private: | private: | |||
void makeComplex(); | void makeComplex(); | |||
template< class T > | template< class T > | |||
void appendComplex( const char *fieldName, const T& val ) { | void appendComplex( const char *fieldName, const T& val ) { | |||
makeComplex(); | makeComplex(); | |||
BSONObjBuilder b; | BSONObjBuilder b; | |||
b.appendElements(obj); | b.appendElements(obj); | |||
b.append(fieldName, val); | b.append(fieldName, val); | |||
skipping to change at line 595 | skipping to change at line 607 | |||
@param info the result object the database returns. Typically h as { ok : ..., errmsg : ... } fields | @param info the result object the database returns. Typically h as { ok : ..., errmsg : ... } fields | |||
set. | set. | |||
@param options see enum QueryOptions - normally not needed to r un a command | @param options see enum QueryOptions - normally not needed to r un a command | |||
@param auth if set, the BSONObj representation will be appended to the command object sent | @param auth if set, the BSONObj representation will be appended to the command object sent | |||
@return true if the command returned "ok". | @return true if the command returned "ok". | |||
*/ | */ | |||
virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info, | virtual bool runCommand(const string &dbname, const BSONObj& cmd, B SONObj &info, | |||
int options=0); | int options=0); | |||
/** | ||||
* Authenticate a user. | ||||
* | ||||
* The "params" BSONObj should be initialized with some of the fiel | ||||
ds below. Which fields | ||||
* are required depends on the mechanism, which is mandatory. | ||||
* | ||||
* "mechanism": The string name of the sasl mechanism to use. | ||||
Mandatory. | ||||
* "user": The string name of the principal to authenticate. M | ||||
andatory. | ||||
* "userSource": The database target of the auth command, which | ||||
identifies the location | ||||
* of the credential information for the principal. May be | ||||
"$external" if | ||||
* credential information is stored outside of the mongo cl | ||||
uster. Mandatory. | ||||
* "pwd": The password data. | ||||
* "digestPassword": Boolean, set to true if the "pwd" is undig | ||||
ested (default). | ||||
* "serviceName": The GSSAPI service name to use. Defaults to | ||||
"mongodb". | ||||
* "serviceHostname": The GSSAPI hostname to use. Defaults to | ||||
the name of the remote | ||||
* host. | ||||
* | ||||
* Other fields in "params" are silently ignored. | ||||
* | ||||
* Returns normally on success, and throws on error. Throws a DBEx | ||||
ception with getCode() == | ||||
* ErrorCodes::AuthenticationFailed if authentication is rejected. | ||||
All other exceptions are | ||||
* tantamount to authentication failure, but may also indicate more | ||||
serious problems. | ||||
*/ | ||||
void auth(const BSONObj& params); | ||||
/** Authorize access to a particular database. | /** Authorize access to a particular database. | |||
Authentication is separate for each database on the server -- y ou may authenticate for any | Authentication is separate for each database on the server -- y ou may authenticate for any | |||
number of databases on a single connection. | number of databases on a single connection. | |||
The "admin" database is special and once authenticated provides access to all databases on the | The "admin" database is special and once authenticated provides access to all databases on the | |||
server. | server. | |||
@param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested | @param digestPassword if password is plain text, set this to true. otherwise assumed to be pre-digested | |||
@param[out] authLevel level of authentication for the giv en user | @param[out] authLevel level of authentication for the giv en user | |||
@return true if successful | @return true if successful | |||
*/ | */ | |||
virtual bool auth(const string &dbname, const string &username, con st string &pwd, string& errmsg, bool digestPassword = true, Auth::Level * l evel = NULL); | bool auth(const string &dbname, const string &username, const strin g &pwd, string& errmsg, bool digestPassword = true); | |||
/** | /** | |||
* Logs out the connection for the given database. | * Logs out the connection for the given database. | |||
* | * | |||
* @param dbname the database to logout from. | * @param dbname the database to logout from. | |||
* @param info the result object for the logout command (provided f or backwards | * @param info the result object for the logout command (provided f or backwards | |||
* compatibility with mongo shell) | * compatibility with mongo shell) | |||
*/ | */ | |||
virtual void logout(const string& dbname, BSONObj& info); | virtual void logout(const string& dbname, BSONObj& info); | |||
skipping to change at line 869 | skipping to change at line 906 | |||
bool exists( const string& ns ); | bool exists( const string& ns ); | |||
/** Create an index if it does not already exist. | /** Create an index if it does not already exist. | |||
ensureIndex calls are remembered so it is safe/fast to call thi s function many | ensureIndex calls are remembered so it is safe/fast to call thi s function many | |||
times in your code. | times in your code. | |||
@param ns collection to be indexed | @param ns collection to be indexed | |||
@param keys the "key pattern" for the index. e.g., { name : 1 } | @param keys the "key pattern" for the index. e.g., { name : 1 } | |||
@param unique if true, indicates that key uniqueness should be e nforced for this index | @param unique if true, indicates that key uniqueness should be e nforced for this index | |||
@param name if not specified, it will be created from the keys a utomatically (which is recommended) | @param name if not specified, it will be created from the keys a utomatically (which is recommended) | |||
@param cache if set to false, the index cache for the connection won't remember this call | @param cache if set to false, the index cache for the connection won't remember this call | |||
@param background build index in the background (see mongodb doc s/wiki for details) | @param background build index in the background (see mongodb doc s for details) | |||
@param v index version. leave at default value. (unit tests set this parameter.) | @param v index version. leave at default value. (unit tests set this parameter.) | |||
@param ttl. The value of how many seconds before data should be removed from a collection. | @param ttl. The value of how many seconds before data should be removed from a collection. | |||
@return whether or not sent message to db. | @return whether or not sent message to db. | |||
should be true on first call, false on subsequent unless reset IndexCache was called | should be true on first call, false on subsequent unless reset IndexCache was called | |||
*/ | */ | |||
virtual bool ensureIndex( const string &ns, | virtual bool ensureIndex( const string &ns, | |||
BSONObj keys, | BSONObj keys, | |||
bool unique = false, | bool unique = false, | |||
const string &name = "", | const string &name = "", | |||
bool cache = true, | bool cache = true, | |||
skipping to change at line 928 | skipping to change at line 965 | |||
BSONObj _countCmd(const string &ns, const BSONObj& query, int optio ns, int limit, int skip ); | BSONObj _countCmd(const string &ns, const BSONObj& query, int optio ns, int limit, int skip ); | |||
/** | /** | |||
* Look up the options available on this client. Caches the answer from | * Look up the options available on this client. Caches the answer from | |||
* _lookupAvailableOptions(), below. | * _lookupAvailableOptions(), below. | |||
*/ | */ | |||
QueryOptions availableOptions(); | QueryOptions availableOptions(); | |||
virtual QueryOptions _lookupAvailableOptions(); | virtual QueryOptions _lookupAvailableOptions(); | |||
virtual void _auth(const BSONObj& params); | ||||
/** | ||||
* Use the MONGODB-CR protocol to authenticate as "username" agains | ||||
t the database "dbname", | ||||
* with the given password. If digestPassword is false, the passwo | ||||
rd is assumed to be | ||||
* pre-digested. Returns false on failure, and sets "errmsg". | ||||
*/ | ||||
bool _authMongoCR(const string &dbname, | ||||
const string &username, | ||||
const string &pwd, | ||||
string& errmsg, | ||||
bool digestPassword); | ||||
private: | private: | |||
enum QueryOptions _cachedAvailableOptions; | enum QueryOptions _cachedAvailableOptions; | |||
bool _haveCachedAvailableOptions; | bool _haveCachedAvailableOptions; | |||
}; | }; | |||
/** | /** | |||
abstract class that implements the core db operations | abstract class that implements the core db operations | |||
*/ | */ | |||
class DBClientBase : public DBClientWithCommands, public DBConnector { | class DBClientBase : public DBClientWithCommands, public DBConnector { | |||
protected: | protected: | |||
skipping to change at line 1115 | skipping to change at line 1165 | |||
false was returned -- it will try to connect again. | false was returned -- it will try to connect again. | |||
@param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) | @param serverHostname host to connect to. can include port numb er ( 127.0.0.1 , 127.0.0.1:5555 ) | |||
*/ | */ | |||
void connect(const string& serverHostname) { | void connect(const string& serverHostname) { | |||
string errmsg; | string errmsg; | |||
if( !connect(HostAndPort(serverHostname), errmsg) ) | if( !connect(HostAndPort(serverHostname), errmsg) ) | |||
throw ConnectException(string("can't connect ") + errmsg); | throw ConnectException(string("can't connect ") + errmsg); | |||
} | } | |||
virtual bool auth(const string &dbname, const string &username, con | ||||
st string &pwd, string& errmsg, bool digestPassword = true, Auth::Level* le | ||||
vel=NULL); | ||||
virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0, | virtual auto_ptr<DBClientCursor> query(const string &ns, Query quer y=Query(), int nToReturn = 0, int nToSkip = 0, | |||
const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) { | const BSONObj *fieldsToRetur n = 0, int queryOptions = 0 , int batchSize = 0 ) { | |||
checkConnection(); | checkConnection(); | |||
return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize ); | return DBClientBase::query( ns, query, nToReturn, nToSkip, fiel dsToReturn, queryOptions , batchSize ); | |||
} | } | |||
virtual unsigned long long query( boost::function<void(DBClientCurs orBatchIterator &)> f, | virtual unsigned long long query( boost::function<void(DBClientCurs orBatchIterator &)> f, | |||
const string& ns, | const string& ns, | |||
Query query, | Query query, | |||
const BSONObj *fieldsToReturn, | const BSONObj *fieldsToReturn, | |||
skipping to change at line 1189 | skipping to change at line 1237 | |||
*/ | */ | |||
void setReplSetClientCallback(DBClientReplicaSet* rsClient); | void setReplSetClientCallback(DBClientReplicaSet* rsClient); | |||
static void setLazyKillCursor( bool lazy ) { _lazyKillCursor = lazy ; } | static void setLazyKillCursor( bool lazy ) { _lazyKillCursor = lazy ; } | |||
static bool getLazyKillCursor() { return _lazyKillCursor; } | static bool getLazyKillCursor() { return _lazyKillCursor; } | |||
uint64_t getSockCreationMicroSec() const; | uint64_t getSockCreationMicroSec() const; | |||
protected: | protected: | |||
friend class SyncClusterConnection; | friend class SyncClusterConnection; | |||
virtual void _auth(const BSONObj& params); | ||||
virtual void sayPiggyBack( Message &toSend ); | virtual void sayPiggyBack( Message &toSend ); | |||
DBClientReplicaSet *clientSet; | DBClientReplicaSet *clientSet; | |||
boost::scoped_ptr<MessagingPort> p; | boost::scoped_ptr<MessagingPort> p; | |||
boost::scoped_ptr<SockAddr> server; | boost::scoped_ptr<SockAddr> server; | |||
bool _failed; | bool _failed; | |||
const bool autoReconnect; | const bool autoReconnect; | |||
time_t lastReconnectTry; | time_t lastReconnectTry; | |||
HostAndPort _server; // remember for reconnects | HostAndPort _server; // remember for reconnects | |||
string _serverString; | string _serverString; | |||
void _checkConnection(); | void _checkConnection(); | |||
// throws SocketException if in failed state and not reconnecting o r if waiting to reconnect | // throws SocketException if in failed state and not reconnecting o r if waiting to reconnect | |||
void checkConnection() { if( _failed ) _checkConnection(); } | void checkConnection() { if( _failed ) _checkConnection(); } | |||
map< string, pair<string,string> > authCache; | map<string, BSONObj> authCache; | |||
double _so_timeout; | double _so_timeout; | |||
bool _connect( string& errmsg ); | bool _connect( string& errmsg ); | |||
static AtomicUInt _numConnections; | static AtomicUInt _numConnections; | |||
static bool _lazyKillCursor; // lazy means we piggy back kill curso rs on next op | static bool _lazyKillCursor; // lazy means we piggy back kill curso rs on next op | |||
#ifdef MONGO_SSL | #ifdef MONGO_SSL | |||
SSLManager* sslManager(); | SSLManager* sslManager(); | |||
#endif | #endif | |||
}; | }; | |||
End of changes. 13 change blocks. | ||||
14 lines changed or deleted | 75 lines changed or added | |||
dbmessage.h | dbmessage.h | |||
---|---|---|---|---|
skipping to change at line 204 | skipping to change at line 204 | |||
BSONObj nextJsObj() { | BSONObj nextJsObj() { | |||
if ( nextjsobj == data ) { | if ( nextjsobj == data ) { | |||
nextjsobj += strlen(data) + 1; // skip namespace | nextjsobj += strlen(data) + 1; // skip namespace | |||
massert( 13066 , "Message contains no documents", theEnd > nextjsobj ); | massert( 13066 , "Message contains no documents", theEnd > nextjsobj ); | |||
} | } | |||
massert( 10304, | massert( 10304, | |||
"Client Error: Remaining data too small for BSON objec t", | "Client Error: Remaining data too small for BSON objec t", | |||
theEnd - nextjsobj >= 5 ); | theEnd - nextjsobj >= 5 ); | |||
if ( cmdLine.objcheck ) { | if ( cmdLine.objcheck ) { | |||
Status status = validateBSON( nextjsobj, theEnd - nextjsobj , NULL ); | Status status = validateBSON( nextjsobj, theEnd - nextjsobj ); | |||
massert( 10307, | massert( 10307, | |||
str::stream() << "Client Error: bad object in mess age: " << status.reason(), | str::stream() << "Client Error: bad object in mess age: " << status.reason(), | |||
status.isOK() ); | status.isOK() ); | |||
} | } | |||
BSONObj js(nextjsobj); | BSONObj js(nextjsobj); | |||
verify( js.objsize() >= 5 ); | verify( js.objsize() >= 5 ); | |||
verify( js.objsize() < ( theEnd - data ) ); | verify( js.objsize() < ( theEnd - data ) ); | |||
nextjsobj += js.objsize(); | nextjsobj += js.objsize(); | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
document_source.h | document_source.h | |||
---|---|---|---|---|
skipping to change at line 508 | skipping to change at line 508 | |||
virtual ~DocumentSourceFilterBase(); | virtual ~DocumentSourceFilterBase(); | |||
virtual bool eof(); | virtual bool eof(); | |||
virtual bool advance(); | virtual bool advance(); | |||
virtual Document getCurrent(); | virtual Document getCurrent(); | |||
/** | /** | |||
Create a BSONObj suitable for Matcher construction. | Create a BSONObj suitable for Matcher construction. | |||
This is used after filter analysis has moved as many filters to | This is used after filter analysis has moved as many filters to | |||
as early a point as possible in the document processing pipeline. | as early a point as possible in the document processing pipeline. | |||
See db/Matcher.h and the associated wiki documentation for the | See db/Matcher.h and the associated documentation for the format. | |||
format. This conversion is used to move back to the low-level | This conversion is used to move back to the low-level find() | |||
find() Cursor mechanism. | Cursor mechanism. | |||
@param pBuilder the builder to write to | @param pBuilder the builder to write to | |||
*/ | */ | |||
virtual void toMatcherBson(BSONObjBuilder *pBuilder) const = 0; | virtual void toMatcherBson(BSONObjBuilder *pBuilder) const = 0; | |||
protected: | protected: | |||
DocumentSourceFilterBase( | DocumentSourceFilterBase( | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
/** | /** | |||
skipping to change at line 574 | skipping to change at line 574 | |||
*/ | */ | |||
static intrusive_ptr<DocumentSourceFilter> create( | static intrusive_ptr<DocumentSourceFilter> create( | |||
const intrusive_ptr<Expression> &pFilter, | const intrusive_ptr<Expression> &pFilter, | |||
const intrusive_ptr<ExpressionContext> &pExpCtx); | const intrusive_ptr<ExpressionContext> &pExpCtx); | |||
/** | /** | |||
Create a BSONObj suitable for Matcher construction. | Create a BSONObj suitable for Matcher construction. | |||
This is used after filter analysis has moved as many filters to | This is used after filter analysis has moved as many filters to | |||
as early a point as possible in the document processing pipeline. | as early a point as possible in the document processing pipeline. | |||
See db/Matcher.h and the associated wiki documentation for the | See db/Matcher.h and the associated documentation for the format. | |||
format. This conversion is used to move back to the low-level | This conversion is used to move back to the low-level find() | |||
find() Cursor mechanism. | Cursor mechanism. | |||
@param pBuilder the builder to write to | @param pBuilder the builder to write to | |||
*/ | */ | |||
void toMatcherBson(BSONObjBuilder *pBuilder) const; | void toMatcherBson(BSONObjBuilder *pBuilder) const; | |||
static const char filterName[]; | static const char filterName[]; | |||
protected: | protected: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; | virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; | |||
skipping to change at line 734 | skipping to change at line 734 | |||
*/ | */ | |||
static intrusive_ptr<DocumentSource> createFromBson( | static intrusive_ptr<DocumentSource> createFromBson( | |||
BSONElement *pBsonElement, | BSONElement *pBsonElement, | |||
const intrusive_ptr<ExpressionContext> &pCtx); | const intrusive_ptr<ExpressionContext> &pCtx); | |||
/** | /** | |||
Create a BSONObj suitable for Matcher construction. | Create a BSONObj suitable for Matcher construction. | |||
This is used after filter analysis has moved as many filters to | This is used after filter analysis has moved as many filters to | |||
as early a point as possible in the document processing pipeline. | as early a point as possible in the document processing pipeline. | |||
See db/Matcher.h and the associated wiki documentation for the | See db/Matcher.h and the associated documentation for the format. | |||
format. This conversion is used to move back to the low-level | This conversion is used to move back to the low-level find() | |||
find() Cursor mechanism. | Cursor mechanism. | |||
@param pBuilder the builder to write to | @param pBuilder the builder to write to | |||
*/ | */ | |||
void toMatcherBson(BSONObjBuilder *pBuilder) const; | void toMatcherBson(BSONObjBuilder *pBuilder) const; | |||
static const char matchName[]; | static const char matchName[]; | |||
protected: | protected: | |||
// virtuals from DocumentSource | // virtuals from DocumentSource | |||
virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; | virtual void sourceToBson(BSONObjBuilder *pBuilder, bool explain) c onst; | |||
End of changes. 3 change blocks. | ||||
9 lines changed or deleted | 9 lines changed or added | |||
dur_commitjob.h | dur_commitjob.h | |||
---|---|---|---|---|
skipping to change at line 111 | skipping to change at line 111 | |||
wassert( _intents.size() < 2000000 ); | wassert( _intents.size() < 2000000 ); | |||
} | } | |||
#if defined(DEBUG_WRITE_INTENT) | #if defined(DEBUG_WRITE_INTENT) | |||
map<void*,int> _debug; | map<void*,int> _debug; | |||
#endif | #endif | |||
}; | }; | |||
/** so we don't have to lock the groupCommitMutex too often */ | /** so we don't have to lock the groupCommitMutex too often */ | |||
class ThreadLocalIntents { | class ThreadLocalIntents { | |||
enum { N = 21 }; | enum { N = 21 }; | |||
dur::WriteIntent i[N]; | std::vector<dur::WriteIntent> intents; | |||
int n; | bool condense(); | |||
public: | public: | |||
ThreadLocalIntents() : n(0) { } | ThreadLocalIntents() : intents(N) { intents.clear(); } | |||
~ThreadLocalIntents(); | ||||
void _unspool(); | void _unspool(); | |||
void unspool(); | void unspool(); | |||
void push(const WriteIntent& i); | void push(const WriteIntent& i); | |||
int n_informational() const { return n; } | int n_informational() const { return intents.size(); } | |||
static AtomicUInt nSpooled; | static AtomicUInt nSpooled; | |||
}; | }; | |||
/** A commit job object for a group commit. Currently there is one instance of this object. | /** A commit job object for a group commit. Currently there is one instance of this object. | |||
concurrency: assumption is caller is appropriately locking. | concurrency: assumption is caller is appropriately locking. | |||
for example note() invocations are from the write lock. | for example note() invocations are from the write lock. | |||
other uses are in a read lock from a single thread (durThread) | other uses are in a read lock from a single thread (durThread) | |||
*/ | */ | |||
class CommitJob : boost::noncopyable { | class CommitJob : boost::noncopyable { | |||
End of changes. 3 change blocks. | ||||
4 lines changed or deleted | 5 lines changed or added | |||
engine.h | engine.h | |||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
typedef unsigned long long ScriptingFunction; | typedef unsigned long long ScriptingFunction; | |||
typedef BSONObj (*NativeFunction)(const BSONObj& args, void* data); | typedef BSONObj (*NativeFunction)(const BSONObj& args, void* data); | |||
typedef map<string, ScriptingFunction> FunctionCacheMap; | ||||
class DBClientWithCommands; | class DBClientWithCommands; | |||
static const unsigned kMaxJsFileLength = std::numeric_limits<unsigned>: | ||||
:max() - 1; | ||||
struct JSFile { | struct JSFile { | |||
const char* name; | const char* name; | |||
const StringData& source; | const StringData& source; | |||
}; | }; | |||
class Scope : boost::noncopyable { | class Scope : boost::noncopyable { | |||
public: | public: | |||
Scope(); | Scope(); | |||
virtual ~Scope(); | virtual ~Scope(); | |||
virtual void reset() = 0; | virtual void reset() = 0; | |||
virtual void init(const BSONObj* data) = 0; | virtual void init(const BSONObj* data) = 0; | |||
void init(const char* data) { | void init(const char* data) { | |||
BSONObj o(data); | BSONObj o(data); | |||
init(&o); | init(&o); | |||
} | } | |||
virtual void localConnect(const char* dbName) = 0; | virtual void localConnect(const char* dbName) = 0; | |||
virtual void externalSetup() = 0; | virtual void externalSetup() = 0; | |||
virtual void setLocalDB(const string& localDBName) { _localDBName = localDBName; } | ||||
virtual BSONObj getObject(const char* field) = 0; | virtual BSONObj getObject(const char* field) = 0; | |||
virtual string getString(const char* field) = 0; | virtual string getString(const char* field) = 0; | |||
virtual bool getBoolean(const char* field) = 0; | virtual bool getBoolean(const char* field) = 0; | |||
virtual double getNumber(const char* field) = 0; | virtual double getNumber(const char* field) = 0; | |||
virtual int getNumberInt(const char* field) { return (int)getNumber (field); } | virtual int getNumberInt(const char* field) { return (int)getNumber (field); } | |||
virtual long long getNumberLongLong(const char* field) { | virtual long long getNumberLongLong(const char* field) { | |||
return static_cast<long long>(getNumber(field)); | return static_cast<long long>(getNumber(field)); | |||
} | } | |||
virtual void setElement(const char* field, const BSONElement& e) = 0; | virtual void setElement(const char* field, const BSONElement& e) = 0; | |||
skipping to change at line 76 | skipping to change at line 75 | |||
virtual int type(const char* field) = 0; | virtual int type(const char* field) = 0; | |||
virtual void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName); | virtual void append(BSONObjBuilder& builder, const char* fieldName, const char* scopeName); | |||
virtual void rename(const char* from, const char* to) = 0; | virtual void rename(const char* from, const char* to) = 0; | |||
virtual string getError() = 0; | virtual string getError() = 0; | |||
virtual bool hasOutOfMemoryException() = 0; | virtual bool hasOutOfMemoryException() = 0; | |||
virtual void installBenchRun(); | ||||
virtual bool isKillPending() const = 0; | virtual bool isKillPending() const = 0; | |||
virtual void gc() = 0; | virtual void gc() = 0; | |||
virtual ScriptingFunction createFunction(const char* code); | virtual ScriptingFunction createFunction(const char* code); | |||
/** | /** | |||
* @return 0 on success | * @return 0 on success | |||
*/ | */ | |||
int invoke(const char* code, const BSONObj* args, const BSONObj* re cv, int timeoutMs = 0); | int invoke(const char* code, const BSONObj* args, const BSONObj* re cv, int timeoutMs = 0); | |||
skipping to change at line 126 | skipping to change at line 127 | |||
void execSetup(const JSFile& file) { | void execSetup(const JSFile& file) { | |||
execSetup(file.source, file.name); | execSetup(file.source, file.name); | |||
} | } | |||
virtual bool execFile(const string& filename, bool printResult, boo l reportError, | virtual bool execFile(const string& filename, bool printResult, boo l reportError, | |||
int timeoutMs = 0); | int timeoutMs = 0); | |||
void execCoreFiles(); | void execCoreFiles(); | |||
void loadStored(bool ignoreNotConnected = false); | virtual void loadStored(bool ignoreNotConnected = false); | |||
/** | /** | |||
* if any changes are made to .system.js, call this | * if any changes are made to .system.js, call this | |||
* right now its just global - slightly inefficient, but a lot simp ler | * right now its just global - slightly inefficient, but a lot simp ler | |||
*/ | */ | |||
static void storedFuncMod(); | static void storedFuncMod(); | |||
static void validateObjectIdString(const string& str); | static void validateObjectIdString(const string& str); | |||
/** increments the number of times a scope was used */ | /** increments the number of times a scope was used */ | |||
void incTimeUsed() { ++_numTimeUsed; } | void incTimeUsed() { ++_numTimeUsed; } | |||
/** gets the number of times a scope was used */ | /** gets the number of times a scope was used */ | |||
int getTimeUsed() { return _numTimeUsed; } | int getTimeUsed() { return _numTimeUsed; } | |||
/** return true if last invoke() return'd native code */ | ||||
virtual bool isLastRetNativeCode() { return _lastRetIsNativeCode; } | ||||
class NoDBAccess { | class NoDBAccess { | |||
Scope* _s; | Scope* _s; | |||
public: | public: | |||
NoDBAccess(Scope* s) : _s(s) { | NoDBAccess(Scope* s) : _s(s) { | |||
} | } | |||
~NoDBAccess() { | ~NoDBAccess() { | |||
_s->rename("____db____", "db"); | _s->rename("____db____", "db"); | |||
} | } | |||
}; | }; | |||
NoDBAccess disableDBAccess(const char* why) { | NoDBAccess disableDBAccess(const char* why) { | |||
rename("db", "____db____"); | rename("db", "____db____"); | |||
return NoDBAccess(this); | return NoDBAccess(this); | |||
} | } | |||
protected: | protected: | |||
virtual ScriptingFunction _createFunction(const char* code) = 0; | friend class PooledScope; | |||
virtual FunctionCacheMap& getFunctionCache() { return _cachedFuncti | ||||
ons; } | ||||
virtual ScriptingFunction _createFunction(const char* code, | ||||
ScriptingFunction functio | ||||
nNumber = 0) = 0; | ||||
string _localDBName; | string _localDBName; | |||
long long _loadedVersion; | long long _loadedVersion; | |||
set<string> _storedNames; | set<string> _storedNames; | |||
static long long _lastVersion; | static long long _lastVersion; | |||
map<string, ScriptingFunction> _cachedFunctions; | FunctionCacheMap _cachedFunctions; | |||
int _numTimeUsed; | int _numTimeUsed; | |||
bool _lastRetIsNativeCode; // v8 only: set to true if eval'd script returns a native func | ||||
}; | }; | |||
class ScriptEngine : boost::noncopyable { | class ScriptEngine : boost::noncopyable { | |||
public: | public: | |||
ScriptEngine(); | ScriptEngine(); | |||
virtual ~ScriptEngine(); | virtual ~ScriptEngine(); | |||
virtual Scope* newScope() { | virtual Scope* newScope() { | |||
return createScope(); | return createScope(); | |||
} | } | |||
skipping to change at line 186 | skipping to change at line 194 | |||
virtual void runTest() = 0; | virtual void runTest() = 0; | |||
virtual bool utf8Ok() const = 0; | virtual bool utf8Ok() const = 0; | |||
static void setup(); | static void setup(); | |||
/** gets a scope from the pool or a new one if pool is empty | /** gets a scope from the pool or a new one if pool is empty | |||
* @param pool An identifier for the pool, usually the db name | * @param pool An identifier for the pool, usually the db name | |||
* @return the scope | * @return the scope | |||
*/ | */ | |||
auto_ptr<Scope> getPooledScope(const string& pool); | auto_ptr<Scope> getPooledScope(const string& pool, const string& sc opeType); | |||
/** | /** | |||
* call this method to release some JS resources when a thread is d one | * call this method to release some JS resources when a thread is d one | |||
*/ | */ | |||
void threadDone(); | void threadDone(); | |||
void setScopeInitCallback(void (*func)(Scope&)) { _scopeInitCallbac k = func; } | void setScopeInitCallback(void (*func)(Scope&)) { _scopeInitCallbac k = func; } | |||
static void setConnectCallback(void (*func)(DBClientWithCommands&)) { | static void setConnectCallback(void (*func)(DBClientWithCommands&)) { | |||
_connectCallback = func; | _connectCallback = func; | |||
} | } | |||
End of changes. 10 change blocks. | ||||
8 lines changed or deleted | 17 lines changed or added | |||
engine_spidermonkey_internal.h | engine_spidermonkey_internal.h | |||
---|---|---|---|---|
skipping to change at line 228 | skipping to change at line 228 | |||
void setNumber( const char *field , double val ); | void setNumber( const char *field , double val ); | |||
void setString( const char *field , const char * val ); | void setString( const char *field , const char * val ); | |||
void setObject( const char *field , const BSONObj& obj , bool readO nly ); | void setObject( const char *field , const BSONObj& obj , bool readO nly ); | |||
void setBoolean( const char *field , bool val ); | void setBoolean( const char *field , bool val ); | |||
void setThis( const BSONObj * obj ); | void setThis( const BSONObj * obj ); | |||
void setFunction( const char *field , const char * code ); | void setFunction( const char *field , const char * code ); | |||
void rename( const char * from , const char * to ); | void rename( const char * from , const char * to ); | |||
// ---- functions ----- | // ---- functions ----- | |||
ScriptingFunction _createFunction( const char * code ); | ScriptingFunction _createFunction(const char* code, ScriptingFuncti on functionNumber); | |||
struct TimeoutSpec { | struct TimeoutSpec { | |||
boost::posix_time::ptime start; | boost::posix_time::ptime start; | |||
boost::posix_time::time_duration timeout; | boost::posix_time::time_duration timeout; | |||
int count; | int count; | |||
}; | }; | |||
// should not generate exceptions, as those can be caught in | // should not generate exceptions, as those can be caught in | |||
// javascript code; returning false without an exception exits | // javascript code; returning false without an exception exits | |||
// immediately | // immediately | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
engine_v8.h | engine_v8.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* 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 <v8.h> | #include <v8.h> | |||
#include <vector> | #include <vector> | |||
#include "mongo/scripting/engine.h" | ||||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/client/dbclientinterface.h" | ||||
#include "mongo/client/dbclientcursor.h" | ||||
#include "mongo/scripting/engine.h" | ||||
#include "mongo/scripting/v8_deadline_monitor.h" | ||||
#include "mongo/scripting/v8_profiler.h" | ||||
/** | /** | |||
* V8_SIMPLE_HEADER must be placed in any function called from a public API | * V8_SIMPLE_HEADER must be placed in any function called from a public API | |||
* that work with v8 handles (and/or must be within the V8Scope's isolate | * that work with v8 handles (and/or must be within the V8Scope's isolate | |||
* and context). Be sure to close the handle_scope if returning a v8::Hand le! | * and context). Be sure to close the handle_scope if returning a v8::Hand le! | |||
*/ | */ | |||
#define V8_SIMPLE_HEADER \ | #define V8_SIMPLE_HEADER \ | |||
v8::Locker v8lock(_isolate); /* acquire isolate lock */ \ | v8::Locker v8lock(_isolate); /* acquire isolate lock */ \ | |||
v8::Isolate::Scope iscope(_isolate); /* enter the isolate; exit wh en out of scope */ \ | v8::Isolate::Scope iscope(_isolate); /* enter the isolate; exit wh en out of scope */ \ | |||
v8::HandleScope handle_scope; /* make the current scope own local handles */ \ | v8::HandleScope handle_scope; /* make the current scope own local handles */ \ | |||
v8::Context::Scope context_scope(_context); /* enter the context; e xit when out of scope */ | v8::Context::Scope context_scope(_context); /* enter the context; e xit when out of scope */ | |||
namespace mongo { | namespace mongo { | |||
class V8ScriptEngine; | class V8ScriptEngine; | |||
class V8Scope; | class V8Scope; | |||
class BSONHolder; | ||||
typedef v8::Handle<v8::Value> (*v8Function)(V8Scope* scope, const v8::A rguments& args); | typedef v8::Handle<v8::Value> (*v8Function)(V8Scope* scope, const v8::A rguments& args); | |||
class BSONHolder { | /** | |||
* The ObjTracker class keeps track of all weakly referenced v8 objects | ||||
. This is | ||||
* required because v8 does not invoke the WeakReferenceCallback when s | ||||
hutting down | ||||
* the context/isolate. To track a new object, add an ObjTracker<MyObj | ||||
Type> member | ||||
* variable to the V8Scope (if one does not already exist for that type | ||||
). Instead | ||||
* of calling v8::Persistent::MakeWeak() directly, simply invoke track( | ||||
) with the | ||||
* persistent handle and the pointer to be freed. | ||||
*/ | ||||
template <typename _ObjType> | ||||
class ObjTracker { | ||||
public: | public: | |||
BSONHolder(BSONObj obj) { | /** Track an object to be freed when it is no longer referenced in | |||
_obj = obj.getOwned(); | JavaScript. | |||
_modified = false; | * @param instanceHandle persistent handle to the weakly referenc | |||
v8::V8::AdjustAmountOfExternalAllocatedMemory(_obj.objsize()); | ed object | |||
* @param rawData pointer to the object instance | ||||
*/ | ||||
void track(v8::Persistent<v8::Value> instanceHandle, _ObjType* inst | ||||
ance) { | ||||
TrackedPtr* collectionHandle = new TrackedPtr(instance, this); | ||||
instanceHandle.MakeWeak(collectionHandle, deleteOnCollect); | ||||
} | } | |||
~BSONHolder() { | /** | |||
v8::V8::AdjustAmountOfExternalAllocatedMemory(-_obj.objsize()); | * Free any remaining objects which are being tracked. Invoked whe | |||
n | ||||
* the V8Scope is destructed. | ||||
*/ | ||||
~ObjTracker() { | ||||
if (!_container.empty()) | ||||
LOG(1) << "freeing " << _container.size() << " uncollected | ||||
" | ||||
<< typeid(_ObjType).name() << " objects" << endl; | ||||
typename set<_ObjType*>::iterator it = _container.begin(); | ||||
while (it != _container.end()) { | ||||
delete *it; | ||||
_container.erase(it++); | ||||
} | ||||
} | } | |||
BSONObj _obj; | private: | |||
bool _modified; | /** | |||
list<string> _extra; | * Simple struct which contains a pointer to the tracked object, an | |||
set<string> _removed; | d a pointer | |||
* to the ObjTracker which owns it. This is the argument supplied | ||||
to v8's | ||||
* WeakReferenceCallback and MakeWeak(). | ||||
*/ | ||||
struct TrackedPtr { | ||||
public: | ||||
TrackedPtr(_ObjType* instance, ObjTracker<_ObjType>* tracker) : | ||||
_objPtr(instance), | ||||
_tracker(tracker) { } | ||||
_ObjType* _objPtr; | ||||
ObjTracker<_ObjType>* _tracker; | ||||
}; | ||||
/** | ||||
* v8 callback for weak persistent handles that have been marked fo | ||||
r removal by the | ||||
* garbage collector. Signature conforms to v8's WeakReferenceCall | ||||
back. | ||||
* @param instanceHandle persistent handle to the weakly referenc | ||||
ed object | ||||
* @param rawData pointer to the TrackedPtr instance | ||||
*/ | ||||
static void deleteOnCollect(v8::Persistent<v8::Value> instanceHandl | ||||
e, void* rawData) { | ||||
TrackedPtr* trackedPtr = static_cast<TrackedPtr*>(rawData); | ||||
trackedPtr->_tracker->_container.erase(trackedPtr->_objPtr); | ||||
delete trackedPtr->_objPtr; | ||||
delete trackedPtr; | ||||
instanceHandle.Dispose(); | ||||
} | ||||
// container for all instances of the tracked _ObjType | ||||
set<_ObjType*> _container; | ||||
}; | }; | |||
/** | /** | |||
* A V8Scope represents a unit of javascript execution environment; spe cifically a single | * A V8Scope represents a unit of javascript execution environment; spe cifically a single | |||
* isolate and a single context executing in a single mongo thread. A V8Scope can be reused | * isolate and a single context executing in a single mongo thread. A V8Scope can be reused | |||
* in another thread only after reset() has been called. | * in another thread only after reset() has been called. | |||
* | * | |||
* NB: | * NB: | |||
* - v8 objects/handles/etc. cannot be shared between V8Scopes | * - v8 objects/handles/etc. cannot be shared between V8Scopes | |||
* - in mongod, each scope is associated with an opId (for KillOp sup port) | * - in mongod, each scope is associated with an opId (for KillOp sup port) | |||
skipping to change at line 94 | skipping to change at line 148 | |||
virtual void reset(); | virtual void reset(); | |||
/** | /** | |||
* Terminate this scope | * Terminate this scope | |||
*/ | */ | |||
virtual void kill(); | virtual void kill(); | |||
/** check if there is a pending killOp request */ | /** check if there is a pending killOp request */ | |||
bool isKillPending() const; | bool isKillPending() const; | |||
/** | ||||
* Connect to a local database, create a Mongo object instance, and | ||||
load any | ||||
* server-side js into the global object | ||||
*/ | ||||
virtual void localConnect(const char* dbName); | virtual void localConnect(const char* dbName); | |||
virtual void externalSetup(); | virtual void externalSetup(); | |||
virtual void installDBAccess(); | ||||
virtual void installBSONTypes(); | ||||
virtual string getError() { return _error; } | virtual string getError() { return _error; } | |||
virtual bool hasOutOfMemoryException(); | virtual bool hasOutOfMemoryException(); | |||
/** | /** | |||
* Run the garbage collector on this scope (native function). @see GCV8 for the | * Run the garbage collector on this scope (native function). @see GCV8 for the | |||
* javascript binding version. | * javascript binding version. | |||
*/ | */ | |||
void gc(); | void gc(); | |||
skipping to change at line 146 | skipping to change at line 208 | |||
bool reportError, bool assertOnError, int timeout Ms); | bool reportError, bool assertOnError, int timeout Ms); | |||
// functions to create v8 object and function templates | // functions to create v8 object and function templates | |||
virtual void injectNative(const char* field, NativeFunction func, v oid* data = 0); | virtual void injectNative(const char* field, NativeFunction func, v oid* data = 0); | |||
void injectNative(const char* field, NativeFunction func, v8::Handl e<v8::Object>& obj, | void injectNative(const char* field, NativeFunction func, v8::Handl e<v8::Object>& obj, | |||
void* data = 0); | void* data = 0); | |||
void injectV8Function(const char* field, v8Function func); | void injectV8Function(const char* field, v8Function func); | |||
void injectV8Function(const char* field, v8Function func, v8::Handl e<v8::Object>& obj); | void injectV8Function(const char* field, v8Function func, v8::Handl e<v8::Object>& obj); | |||
void injectV8Function(const char* field, v8Function func, v8::Handl e<v8::Template>& t); | void injectV8Function(const char* field, v8Function func, v8::Handl e<v8::Template>& t); | |||
v8::Handle<v8::FunctionTemplate> createV8Function(v8Function func); | v8::Handle<v8::FunctionTemplate> createV8Function(v8Function func); | |||
virtual ScriptingFunction _createFunction(const char* code); | virtual ScriptingFunction _createFunction(const char* code, | |||
v8::Local<v8::Function> __createFunction(const char* code); | ScriptingFunction functio | |||
nNumber = 0); | ||||
v8::Local<v8::Function> __createFunction(const char* code, | ||||
ScriptingFunction function | ||||
Number = 0); | ||||
/** | /** | |||
* Convert BSON types to v8 Javascript types | * Convert BSON types to v8 Javascript types | |||
*/ | */ | |||
v8::Local<v8::Object> mongoToV8(const mongo::BSONObj& m, bool array = 0, | v8::Local<v8::Object> mongoToV8(const mongo::BSONObj& m, bool array = 0, | |||
bool readOnly = false); | bool readOnly = false); | |||
v8::Persistent<v8::Object> mongoToLZV8(const mongo::BSONObj& m, boo l readOnly = false); | v8::Persistent<v8::Object> mongoToLZV8(const mongo::BSONObj& m, boo l readOnly = false); | |||
v8::Handle<v8::Value> mongoToV8Element(const BSONElement& f, bool r eadOnly = false); | v8::Handle<v8::Value> mongoToV8Element(const BSONElement& f, bool r eadOnly = false); | |||
/** | /** | |||
skipping to change at line 183 | skipping to change at line 247 | |||
v8::Handle<v8::Value> value, | v8::Handle<v8::Value> value, | |||
BSONObj* originalParent); | BSONObj* originalParent); | |||
void v8ToMongoNumberLong(BSONObjBuilder& b, | void v8ToMongoNumberLong(BSONObjBuilder& b, | |||
const string& elementName, | const string& elementName, | |||
v8::Handle<v8::Object> obj); | v8::Handle<v8::Object> obj); | |||
void v8ToMongoInternal(BSONObjBuilder& b, | void v8ToMongoInternal(BSONObjBuilder& b, | |||
const string& elementName, | const string& elementName, | |||
v8::Handle<v8::Object> obj); | v8::Handle<v8::Object> obj); | |||
void v8ToMongoRegex(BSONObjBuilder& b, | void v8ToMongoRegex(BSONObjBuilder& b, | |||
const string& elementName, | const string& elementName, | |||
string& regex); | v8::Handle<v8::Object> v8Regex); | |||
void v8ToMongoDBRef(BSONObjBuilder& b, | void v8ToMongoDBRef(BSONObjBuilder& b, | |||
const string& elementName, | const string& elementName, | |||
v8::Handle<v8::Object> obj); | v8::Handle<v8::Object> obj); | |||
void v8ToMongoBinData(BSONObjBuilder& b, | void v8ToMongoBinData(BSONObjBuilder& b, | |||
const string& elementName, | const string& elementName, | |||
v8::Handle<v8::Object> obj); | v8::Handle<v8::Object> obj); | |||
void v8ToMongoObjectID(BSONObjBuilder& b, | void v8ToMongoObjectID(BSONObjBuilder& b, | |||
const string& elementName, | const string& elementName, | |||
v8::Handle<v8::Object> obj); | v8::Handle<v8::Object> obj); | |||
v8::Function* getNamedCons(const char* name); | v8::Function* getNamedCons(const char* name); | |||
v8::Function* getObjectIdCons(); | v8::Function* getObjectIdCons(); | |||
v8::Local<v8::Value> newId(const OID& id); | v8::Local<v8::Value> newId(const OID& id); | |||
/** | /** | |||
* GC callback for weak references to BSON objects (via BSONHolder) | * Convert a JavaScript exception to a stl string. Requires | |||
* access to the V8Scope instance to report source context informat | ||||
ion. | ||||
*/ | */ | |||
v8::Persistent<v8::Object> wrapBSONObject(v8::Local<v8::Object> obj | std::string v8ExceptionToSTLString(const v8::TryCatch* try_catch); | |||
, BSONHolder* data); | ||||
v8::Persistent<v8::Object> wrapArrayObject(v8::Local<v8::Object> ob | ||||
j, char* data); | ||||
/** | /** | |||
* Get a V8 string from the scope's cache, creating one if needed ( | * GC callback for weak references to BSON objects (via BSONHolder) | |||
NOTE: this may be | ||||
* dangerous due to use in multiple threads without changing the v8 | ||||
Locker) | ||||
*/ | */ | |||
v8::Handle<v8::String> getV8Str(string str); | v8::Persistent<v8::Object> wrapBSONObject(v8::Local<v8::Object> obj , BSONHolder* data); | |||
/** | /** | |||
* Create a V8 string with a local handle | * Create a V8 string with a local handle | |||
*/ | */ | |||
inline v8::Handle<v8::String> getLocalV8Str(string str) { | static inline v8::Handle<v8::String> v8StringData(StringData str) { | |||
return v8::String::New(str.c_str()); | return v8::String::New(str.rawData()); | |||
} | } | |||
/** | /** | |||
* Get the isolate this scope belongs to (can be called from any th read, but v8 requires | * Get the isolate this scope belongs to (can be called from any th read, but v8 requires | |||
* the new thread enter the isolate and context. Only one thread can enter the isolate. | * the new thread enter the isolate and context. Only one thread can enter the isolate. | |||
*/ | */ | |||
v8::Isolate* getIsolate() { return _isolate; } | v8::Isolate* getIsolate() { return _isolate; } | |||
/** | /** | |||
* Get the JS context this scope executes within. | * Get the JS context this scope executes within. | |||
*/ | */ | |||
v8::Persistent<v8::Context> getContext() { return _context; } | v8::Persistent<v8::Context> getContext() { return _context; } | |||
/** | ObjTracker<BSONHolder> bsonHolderTracker; | |||
* Static v8 strings for various identifiers | ObjTracker<DBClientWithCommands> dbClientWithCommandsTracker; | |||
*/ | ObjTracker<DBClientBase> dbClientBaseTracker; | |||
v8::Handle<v8::String> V8STR_CONN; | ObjTracker<DBClientCursor> dbClientCursorTracker; | |||
v8::Handle<v8::String> V8STR_ID; | ||||
v8::Handle<v8::String> V8STR_LENGTH; | ||||
v8::Handle<v8::String> V8STR_LEN; | ||||
v8::Handle<v8::String> V8STR_TYPE; | ||||
v8::Handle<v8::String> V8STR_ISOBJECTID; | ||||
v8::Handle<v8::String> V8STR_NATIVE_FUNC; | ||||
v8::Handle<v8::String> V8STR_NATIVE_DATA; | ||||
v8::Handle<v8::String> V8STR_V8_FUNC; | ||||
v8::Handle<v8::String> V8STR_RETURN; | ||||
v8::Handle<v8::String> V8STR_ARGS; | ||||
v8::Handle<v8::String> V8STR_T; | ||||
v8::Handle<v8::String> V8STR_I; | ||||
v8::Handle<v8::String> V8STR_EMPTY; | ||||
v8::Handle<v8::String> V8STR_MINKEY; | ||||
v8::Handle<v8::String> V8STR_MAXKEY; | ||||
v8::Handle<v8::String> V8STR_NUMBERLONG; | ||||
v8::Handle<v8::String> V8STR_NUMBERINT; | ||||
v8::Handle<v8::String> V8STR_DBPTR; | ||||
v8::Handle<v8::String> V8STR_BINDATA; | ||||
v8::Handle<v8::String> V8STR_WRAPPER; | ||||
v8::Handle<v8::String> V8STR_RO; | ||||
v8::Handle<v8::String> V8STR_FULLNAME; | ||||
v8::Handle<v8::String> V8STR_BSON; | ||||
private: | private: | |||
/** | /** | |||
* Trampoline to call a c++ function with a specific signature (V8S cope*, v8::Arguments&). | * Trampoline to call a c++ function with a specific signature (V8S cope*, v8::Arguments&). | |||
* Handles interruption, exceptions, etc. | * Handles interruption, exceptions, etc. | |||
*/ | */ | |||
static v8::Handle<v8::Value> v8Callback(const v8::Arguments& args); | static v8::Handle<v8::Value> v8Callback(const v8::Arguments& args); | |||
/** | /** | |||
skipping to change at line 280 | skipping to change at line 320 | |||
static v8::Handle<v8::Value> nativeCallback(V8Scope* scope, const v 8::Arguments& args); | static v8::Handle<v8::Value> nativeCallback(V8Scope* scope, const v 8::Arguments& args); | |||
/** | /** | |||
* v8-specific implementations of basic global functions | * v8-specific implementations of basic global functions | |||
*/ | */ | |||
static v8::Handle<v8::Value> load(V8Scope* scope, const v8::Argumen ts& args); | static v8::Handle<v8::Value> load(V8Scope* scope, const v8::Argumen ts& args); | |||
static v8::Handle<v8::Value> Print(V8Scope* scope, const v8::Argume nts& args); | static v8::Handle<v8::Value> Print(V8Scope* scope, const v8::Argume nts& args); | |||
static v8::Handle<v8::Value> Version(V8Scope* scope, const v8::Argu ments& args); | static v8::Handle<v8::Value> Version(V8Scope* scope, const v8::Argu ments& args); | |||
static v8::Handle<v8::Value> GCV8(V8Scope* scope, const v8::Argumen ts& args); | static v8::Handle<v8::Value> GCV8(V8Scope* scope, const v8::Argumen ts& args); | |||
static v8::Handle<v8::Value> startCpuProfiler(V8Scope* scope, const | ||||
v8::Arguments& args); | ||||
static v8::Handle<v8::Value> stopCpuProfiler(V8Scope* scope, const | ||||
v8::Arguments& args); | ||||
static v8::Handle<v8::Value> getCpuProfile(V8Scope* scope, const v8 | ||||
::Arguments& args); | ||||
/** Signal that this scope has entered a native (C++) execution con text. | /** Signal that this scope has entered a native (C++) execution con text. | |||
* @return false if execution has been interrupted | * @return false if execution has been interrupted | |||
*/ | */ | |||
bool nativePrologue(); | bool nativePrologue(); | |||
/** Signal that this scope has completed native execution and is re turning to v8. | /** Signal that this scope has completed native execution and is re turning to v8. | |||
* @return false if execution has been interrupted | * @return false if execution has been interrupted | |||
*/ | */ | |||
bool nativeEpilogue(); | bool nativeEpilogue(); | |||
skipping to change at line 303 | skipping to change at line 347 | |||
* be supported. | * be supported. | |||
*/ | */ | |||
void registerOpId(); | void registerOpId(); | |||
/** | /** | |||
* Unregister this scope with the mongo op id. | * Unregister this scope with the mongo op id. | |||
*/ | */ | |||
void unregisterOpId(); | void unregisterOpId(); | |||
/** | /** | |||
* Creates a new instance of the MinKey object | ||||
*/ | ||||
v8::Local<v8::Object> newMinKeyInstance(); | ||||
/** | ||||
* Creates a new instance of the MaxKey object | ||||
*/ | ||||
v8::Local<v8::Object> newMaxKeyInstance(); | ||||
/** | ||||
* Create a new function; primarily used for BSON/V8 conversion. | * Create a new function; primarily used for BSON/V8 conversion. | |||
*/ | */ | |||
v8::Local<v8::Value> newFunction(const char *code); | v8::Local<v8::Value> newFunction(const char *code); | |||
template <typename _HandleType> | ||||
bool checkV8ErrorState(const _HandleType& resultHandle, | ||||
const v8::TryCatch& try_catch, | ||||
bool reportError = true, | ||||
bool assertOnError = true); | ||||
V8ScriptEngine* _engine; | V8ScriptEngine* _engine; | |||
v8::Persistent<v8::Context> _context; | v8::Persistent<v8::Context> _context; | |||
v8::Persistent<v8::Object> _global; | v8::Persistent<v8::Object> _global; | |||
string _error; | string _error; | |||
vector<v8::Persistent<v8::Value> > _funcs; | vector<v8::Persistent<v8::Value> > _funcs; | |||
enum ConnectState { NOT, LOCAL, EXTERNAL }; | enum ConnectState { NOT, LOCAL, EXTERNAL }; | |||
ConnectState _connectState; | ConnectState _connectState; | |||
std::map <string, v8::Persistent<v8::String> > _strCache; | ||||
v8::Persistent<v8::FunctionTemplate> lzFunctionTemplate; | v8::Persistent<v8::FunctionTemplate> lzFunctionTemplate; | |||
v8::Persistent<v8::ObjectTemplate> lzObjectTemplate; | v8::Persistent<v8::ObjectTemplate> lzObjectTemplate; | |||
v8::Persistent<v8::ObjectTemplate> roObjectTemplate; | v8::Persistent<v8::ObjectTemplate> roObjectTemplate; | |||
v8::Persistent<v8::ObjectTemplate> lzArrayTemplate; | v8::Persistent<v8::ObjectTemplate> lzArrayTemplate; | |||
v8::Persistent<v8::ObjectTemplate> internalFieldObjects; | v8::Persistent<v8::ObjectTemplate> internalFieldObjects; | |||
v8::Isolate* _isolate; | v8::Isolate* _isolate; | |||
V8CpuProfiler _cpuProfiler; | ||||
mongo::mutex _interruptLock; // protects interruption-related flags | mongo::mutex _interruptLock; // protects interruption-related flags | |||
bool _inNativeExecution; // protected by _interruptLock | bool _inNativeExecution; // protected by _interruptLock | |||
bool _pendingKill; // protected by _interruptLock | bool _pendingKill; // protected by _interruptLock | |||
int _opId; // op id for this scope | int _opId; // op id for this scope | |||
}; | }; | |||
class V8ScriptEngine : public ScriptEngine { | class V8ScriptEngine : public ScriptEngine { | |||
public: | public: | |||
V8ScriptEngine(); | V8ScriptEngine(); | |||
skipping to change at line 361 | skipping to change at line 420 | |||
/** | /** | |||
* Interrupt all v8 contexts (and isolates). @see interrupt(). | * Interrupt all v8 contexts (and isolates). @see interrupt(). | |||
*/ | */ | |||
virtual void interruptAll(); | virtual void interruptAll(); | |||
private: | private: | |||
friend class V8Scope; | friend class V8Scope; | |||
std::string printKnownOps_inlock(); | std::string printKnownOps_inlock(); | |||
/** | ||||
* Get the deadline monitor instance for the v8 ScriptEngine | ||||
*/ | ||||
DeadlineMonitor<V8Scope>* getDeadlineMonitor() { return &_deadlineM | ||||
onitor; } | ||||
typedef map<unsigned, V8Scope*> OpIdToScopeMap; | typedef map<unsigned, V8Scope*> OpIdToScopeMap; | |||
mongo::mutex _globalInterruptLock; // protects map of all operatio n ids -> scope | mongo::mutex _globalInterruptLock; // protects map of all operatio n ids -> scope | |||
OpIdToScopeMap _opToScopeMap; // map of mongo op ids to scope s (protected by | OpIdToScopeMap _opToScopeMap; // map of mongo op ids to scope s (protected by | |||
// _globalInterruptLock). | // _globalInterruptLock). | |||
DeadlineMonitor<V8Scope> _deadlineMonitor; | ||||
}; | ||||
class BSONHolder { | ||||
MONGO_DISALLOW_COPYING(BSONHolder); | ||||
public: | ||||
explicit BSONHolder(BSONObj obj) : | ||||
_scope(NULL), | ||||
_obj(obj.getOwned()), | ||||
_modified(false) { | ||||
// give hint v8's GC | ||||
v8::V8::AdjustAmountOfExternalAllocatedMemory(_obj.objsize()); | ||||
} | ||||
~BSONHolder() { | ||||
if (_scope && _scope->getIsolate()) | ||||
// if v8 is still up, send hint to GC | ||||
v8::V8::AdjustAmountOfExternalAllocatedMemory(-_obj.objsize | ||||
()); | ||||
} | ||||
V8Scope* _scope; | ||||
BSONObj _obj; | ||||
bool _modified; | ||||
list<string> _extra; | ||||
set<string> _removed; | ||||
}; | }; | |||
/** | ||||
* Check for an error condition (e.g. empty handle, JS exception, OOM) | ||||
after executing | ||||
* a v8 operation. | ||||
* @resultHandle handle storing the result of the preceeding v8 | ||||
operation | ||||
* @try_catch the active v8::TryCatch exception handler | ||||
* @param reportError if true, log an error message | ||||
* @param assertOnError if true, throw an exception if an error is det | ||||
ected | ||||
* if false, return value indicates error state | ||||
* @return true if an error was detected and assertOnError is set to fa | ||||
lse | ||||
* false if no error was detected | ||||
*/ | ||||
template <typename _HandleType> | ||||
bool V8Scope::checkV8ErrorState(const _HandleType& resultHandle, | ||||
const v8::TryCatch& try_catch, | ||||
bool reportError, | ||||
bool assertOnError) { | ||||
bool haveError = false; | ||||
if (try_catch.HasCaught() && try_catch.CanContinue()) { | ||||
// normal JS exception | ||||
_error = string("JavaScript execution failed: ") + v8ExceptionT | ||||
oSTLString(&try_catch); | ||||
haveError = true; | ||||
} | ||||
else if (hasOutOfMemoryException()) { | ||||
// out of memory exception (treated as terminal) | ||||
_error = "JavaScript execution failed -- v8 is out of memory"; | ||||
haveError = true; | ||||
} | ||||
else if (resultHandle.IsEmpty() || try_catch.HasCaught()) { | ||||
// terminal exception (due to empty handle, termination, etc.) | ||||
_error = "JavaScript execution failed"; | ||||
haveError = true; | ||||
} | ||||
if (haveError) { | ||||
if (reportError) | ||||
log() << _error << endl; | ||||
if (assertOnError) | ||||
uasserted(16722, _error); | ||||
return true; | ||||
} | ||||
return false; | ||||
} | ||||
extern ScriptEngine* globalScriptEngine; | extern ScriptEngine* globalScriptEngine; | |||
} | } | |||
End of changes. 25 change blocks. | ||||
57 lines changed or deleted | 215 lines changed or added | |||
field_parser-inl.h | field_parser-inl.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
#include "mongo/s/field_parser.h" | #include "mongo/s/field_parser.h" | |||
#include "mongo/util/mongoutils/str.h" | #include "mongo/util/mongoutils/str.h" | |||
namespace mongo { | namespace mongo { | |||
using mongoutils::str::stream; | using mongoutils::str::stream; | |||
// Extracts an array into a vector | // Extracts an array into a vector | |||
template<typename T> | template<typename T> | |||
bool FieldParser::extract(BSONObj doc, | FieldParser::FieldState FieldParser::extract(BSONObj doc, | |||
const BSONField<vector<T> >& field, | const BSONField<vector<T> >& field, | |||
const vector<T>& def, | ||||
vector<T>* out, | vector<T>* out, | |||
string* errMsg) | string* errMsg) | |||
{ | { | |||
BSONElement elem = doc[field.name()]; | BSONElement elem = doc[field.name()]; | |||
if (elem.eoo()) { | if (elem.eoo()) { | |||
*out = def; | if (field.hasDefault()) { | |||
return true; | *out = field.getDefault(); | |||
return FIELD_DEFAULT; | ||||
} | ||||
else { | ||||
return FIELD_NONE; | ||||
} | ||||
} | } | |||
if (elem.type() == Array) { | if (elem.type() == Array) { | |||
BSONArray arr = BSONArray(elem.embeddedObject()); | BSONArray arr = BSONArray(elem.embeddedObject()); | |||
string elErrMsg; | string elErrMsg; | |||
// Append all the new elements to the end of the vector | // Append all the new elements to the end of the vector | |||
size_t initialSize = out->size(); | size_t initialSize = out->size(); | |||
out->resize(initialSize + arr.nFields()); | out->resize(initialSize + arr.nFields()); | |||
int i = 0; | int i = 0; | |||
BSONObjIterator objIt(arr); | BSONObjIterator objIt(arr); | |||
while (objIt.more()) { | while (objIt.more()) { | |||
BSONElement next = objIt.next(); | BSONElement next = objIt.next(); | |||
BSONField<T> fieldFor(next.fieldName()); | BSONField<T> fieldFor(next.fieldName(), out->at(initialSize + i)); | |||
if (!FieldParser::extract(arr, | if (!FieldParser::extract(arr, | |||
fieldFor, | fieldFor, | |||
out->at(initialSize + i), | ||||
&out->at(initialSize + i), | &out->at(initialSize + i), | |||
&elErrMsg)) | &elErrMsg)) | |||
{ | { | |||
if (errMsg) { | if (errMsg) { | |||
*errMsg = stream() << "error parsing element " << i << " of field " | *errMsg = stream() << "error parsing element " << i << " of field " | |||
<< field() << causedBy(elErrMsg) ; | << field() << causedBy(elErrMsg) ; | |||
} | } | |||
return false; | return FIELD_INVALID; | |||
} | } | |||
i++; | i++; | |||
} | } | |||
return true; | return FIELD_SET; | |||
} | } | |||
if (errMsg) { | if (errMsg) { | |||
*errMsg = stream() << "wrong type for '" << field() << "' field , expected " | *errMsg = stream() << "wrong type for '" << field() << "' field , expected " | |||
<< "vector array" << ", found " << doc[field .name()].toString(); | << "vector array" << ", found " << doc[field .name()].toString(); | |||
} | } | |||
return false; | return FIELD_INVALID; | |||
} | } | |||
// Extracts an object into a map | // Extracts an object into a map | |||
template<typename K, typename T> | template<typename K, typename T> | |||
bool FieldParser::extract(BSONObj doc, | FieldParser::FieldState FieldParser::extract(BSONObj doc, | |||
const BSONField<map<K, T> >& field, | const BSONField<map<K, T> >& field, | |||
const map<K, T>& def, | ||||
map<K, T>* out, | map<K, T>* out, | |||
string* errMsg) | string* errMsg) | |||
{ | { | |||
BSONElement elem = doc[field.name()]; | BSONElement elem = doc[field.name()]; | |||
if (elem.eoo()) { | if (elem.eoo()) { | |||
*out = def; | if (field.hasDefault()) { | |||
return true; | *out = field.getDefault(); | |||
return FIELD_DEFAULT; | ||||
} | ||||
else { | ||||
return FIELD_NONE; | ||||
} | ||||
} | } | |||
if (elem.type() == Object) { | if (elem.type() == Object) { | |||
BSONObj obj = elem.embeddedObject(); | BSONObj obj = elem.embeddedObject(); | |||
string elErrMsg; | string elErrMsg; | |||
BSONObjIterator objIt(obj); | BSONObjIterator objIt(obj); | |||
while (objIt.more()) { | while (objIt.more()) { | |||
BSONElement next = objIt.next(); | BSONElement next = objIt.next(); | |||
BSONField<T> fieldFor(next.fieldName()); | ||||
T& value = (*out)[next.fieldName()]; | T& value = (*out)[next.fieldName()]; | |||
if (!FieldParser::extract(obj, fieldFor, value, &value, &el | ||||
ErrMsg)) { | BSONField<T> fieldFor(next.fieldName(), value); | |||
if (!FieldParser::extract(obj, fieldFor, &value, &elErrMsg) | ||||
) { | ||||
if (errMsg) { | if (errMsg) { | |||
*errMsg = stream() << "error parsing map element " << next.fieldName() | *errMsg = stream() << "error parsing map element " << next.fieldName() | |||
<< " of field " << field() << ca usedBy(elErrMsg); | << " of field " << field() << ca usedBy(elErrMsg); | |||
} | } | |||
return false; | return FIELD_INVALID; | |||
} | } | |||
} | } | |||
return true; | return FIELD_SET; | |||
} | } | |||
if (errMsg) { | if (errMsg) { | |||
*errMsg = stream() << "wrong type for '" << field() << "' field , expected " | *errMsg = stream() << "wrong type for '" << field() << "' field , expected " | |||
<< "vector array" << ", found " << doc[field .name()].toString(); | << "vector array" << ", found " << doc[field .name()].toString(); | |||
} | } | |||
return false; | return FIELD_INVALID; | |||
} | } | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 16 change blocks. | ||||
20 lines changed or deleted | 27 lines changed or added | |||
field_parser.h | field_parser.h | |||
---|---|---|---|---|
skipping to change at line 41 | skipping to change at line 41 | |||
* or with the value in 'def', depending on whether the field is pr esent and has the | * or with the value in 'def', depending on whether the field is pr esent and has the | |||
* correct type in 'doc' or not, respectively. Otherwise, if the fi eld exists but has | * correct type in 'doc' or not, respectively. Otherwise, if the fi eld exists but has | |||
* the wrong type, returns false. | * the wrong type, returns false. | |||
* | * | |||
* NOTE ON BSON OWNERSHIP: | * NOTE ON BSON OWNERSHIP: | |||
* | * | |||
* The caller must assume that this class will point to data insi de 'doc' without | * The caller must assume that this class will point to data insi de 'doc' without | |||
* copying it. In practice this means that 'doc' MUST EXIST for a s long as 'out' | * copying it. In practice this means that 'doc' MUST EXIST for a s long as 'out' | |||
* stays in scope. | * stays in scope. | |||
*/ | */ | |||
static bool extract(BSONObj doc, | ||||
enum FieldState { | ||||
// The field is present but has the wrong type | ||||
FIELD_INVALID = 0, | ||||
// The field is present and has the correct type | ||||
FIELD_SET, | ||||
// The field is absent in the BSON object but set from default | ||||
FIELD_DEFAULT, | ||||
// The field is absent and no default was specified | ||||
FIELD_NONE | ||||
}; | ||||
static FieldState extract(BSONObj doc, | ||||
const BSONField<bool>& field, | const BSONField<bool>& field, | |||
bool def, | ||||
bool* out, | bool* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<BSONArray>& field, | const BSONField<BSONArray>& field, | |||
const BSONArray& def, | ||||
BSONArray* out, | BSONArray* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<BSONObj>& field, | const BSONField<BSONObj>& field, | |||
const BSONObj& def, | ||||
BSONObj* out, | BSONObj* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<Date_t>& field, | const BSONField<Date_t>& field, | |||
const Date_t def, | ||||
Date_t* out, | Date_t* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<string>& field, | const BSONField<string>& field, | |||
const string& def, | ||||
string* out, | string* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<OID>& field, | const BSONField<OID>& field, | |||
const OID& def, | ||||
OID* out, | OID* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<int>& field, | const BSONField<int>& field, | |||
const int& def, | ||||
int* out, | int* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<long long>& field, | const BSONField<long long>& field, | |||
const long long& def, | ||||
long long* out, | long long* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
/** | /** | |||
* The following extractNumber methods do implicit conversion betwe en any numeric type and | * The following extractNumber methods do implicit conversion betwe en any numeric type and | |||
* the BSONField type. This can be useful when an exact numeric ty pe is not needed, for | * the BSONField type. This can be useful when an exact numeric ty pe is not needed, for | |||
* example if the field is sometimes modified from the shell which can change the type. | * example if the field is sometimes modified from the shell which can change the type. | |||
*/ | */ | |||
static bool extractNumber(BSONObj doc, | static FieldState extractNumber(BSONObj doc, | |||
const BSONField<int>& field, | const BSONField<int>& field, | |||
const int& def, | ||||
int* out, | int* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
static bool extractNumber(BSONObj doc, | static FieldState extractNumber(BSONObj doc, | |||
const BSONField<long long>& field, | const BSONField<long long>& field, | |||
const long long& def, | ||||
long long* out, | long long* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
/** | /** | |||
* The following extract methods are templatized to handle extracti on of vectors and | * The following extract methods are templatized to handle extracti on of vectors and | |||
* maps of sub-objects. Keys in the map should be StringData compa tible. | * maps of sub-objects. Keys in the map should be StringData compa tible. | |||
* | * | |||
* It's possible to nest extraction of vectors and maps to any dept h, i.e: | * It's possible to nest extraction of vectors and maps to any dept h, i.e: | |||
* | * | |||
* vector<map<string,vector<string> > > val; | * vector<map<string,vector<string> > > val; | |||
* FieldParser::extract(doc, field, val, &val); | * FieldParser::extract(doc, field, val, &val); | |||
*/ | */ | |||
template<typename T> | template<typename T> | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<vector<T> >& field, | const BSONField<vector<T> >& field, | |||
const vector<T>& def, | ||||
vector<T>* out, | vector<T>* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
template<typename K, typename T> | template<typename K, typename T> | |||
static bool extract(BSONObj doc, | static FieldState extract(BSONObj doc, | |||
const BSONField<map<K, T> >& field, | const BSONField<map<K, T> >& field, | |||
const map<K, T>& def, | ||||
map<K, T>* out, | map<K, T>* out, | |||
string* errMsg = NULL); | string* errMsg = NULL); | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
// Inline functions for templating | // Inline functions for templating | |||
#include "field_parser-inl.h" | #include "field_parser-inl.h" | |||
End of changes. 24 change blocks. | ||||
24 lines changed or deleted | 27 lines changed or added | |||
fts_index.h | fts_index.h | |||
---|---|---|---|---|
skipping to change at line 63 | skipping to change at line 63 | |||
}; | }; | |||
class FTSIndexPlugin : public IndexPlugin { | class FTSIndexPlugin : public IndexPlugin { | |||
public: | public: | |||
FTSIndexPlugin(); | FTSIndexPlugin(); | |||
IndexType* generate( const IndexSpec* spec ) const; | IndexType* generate( const IndexSpec* spec ) const; | |||
BSONObj adjustIndexSpec( const BSONObj& spec ) const; | BSONObj adjustIndexSpec( const BSONObj& spec ) const; | |||
void postBuildHook( const IndexSpec& spec ) const; | ||||
}; | }; | |||
} //namespace fts | } //namespace fts | |||
} //namespace mongo | } //namespace mongo | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
geoparser.h | geoparser.h | |||
---|---|---|---|---|
skipping to change at line 24 | skipping to change at line 24 | |||
* 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/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include <vector> | #include <vector> | |||
#include "third_party/s2/s2.h" | #include "third_party/s2/s2.h" | |||
#include "mongo/db/geo/shapes.h" | #include "mongo/db/geo/shapes.h" | |||
class S2Cap; | ||||
class S2Cell; | class S2Cell; | |||
class S2Polyline; | class S2Polyline; | |||
class S2Polygon; | class S2Polygon; | |||
namespace mongo { | namespace mongo { | |||
// TODO: move this to geoparser, perhaps? | // This class parses geographic data. | |||
// This class parses a subset of GeoJSON and creates S2 shapes from it. | // It parses a subset of GeoJSON and creates S2 shapes from it. | |||
// See http://geojson.org/geojson-spec.html for the spec. | // See http://geojson.org/geojson-spec.html for the spec. | |||
// | // | |||
// This class also parses the ad-hoc geo formats that MongoDB introduce d. | // This class also parses the ad-hoc geo formats that MongoDB introduce d. | |||
// | // | |||
// The parseFoo methods that return a bool internally call isFoo and re | ||||
turn true | ||||
// if the foo is parsed correctly. | ||||
// The parseFoo methods that do not return a bool assume isFoo is true. | ||||
// | ||||
// We assume that if you're trying to parse something, you know it's va lid. | // We assume that if you're trying to parse something, you know it's va lid. | |||
// This means don't call parsePoint(x) unless you're sure isPoint(x). | ||||
// Perhaps there should just be parsePoint that returns bool and calls | ||||
isPoint itself? | ||||
class GeoParser { | class GeoParser { | |||
public: | public: | |||
// Try to parse GeoJSON, then try legacy format, return true if eit her succeed. | // Try to parse GeoJSON, then try legacy format, return true if eit her succeed. | |||
// These call the various isPoint and parsePoint methods below. | // These call the various isPoint and parsePoint methods below. | |||
// You can just use these bool parsePoint(...) methods. | // You can just use these bool parsePoint(...) methods. | |||
static bool parsePoint(const BSONObj &obj, S2Point *out); | static bool parsePoint(const BSONObj &obj, S2Point *out); | |||
static bool parsePoint(const BSONObj &obj, S2Cell *out); | static bool parsePoint(const BSONObj &obj, S2Cell *out); | |||
static bool parsePoint(const BSONObj &obj, Point *out); | ||||
// Check to see if it's GeoJSON or if it's legacy geo. | // Check to see if it's GeoJSON or if it's legacy geo. | |||
static bool isPoint(const BSONObj &obj); | static bool isPoint(const BSONObj &obj); | |||
static bool isGeoJSONPoint(const BSONObj &obj); | static bool isGeoJSONPoint(const BSONObj &obj); | |||
static void parseGeoJSONPoint(const BSONObj &obj, S2Point *out); | static void parseGeoJSONPoint(const BSONObj &obj, S2Point *out); | |||
static void parseGeoJSONPoint(const BSONObj &obj, S2Cell *out); | static void parseGeoJSONPoint(const BSONObj &obj, S2Cell *out); | |||
static void parseGeoJSONPoint(const BSONObj &obj, Point *out); | ||||
static bool isLegacyPoint(const BSONObj &obj); | static bool isLegacyPoint(const BSONObj &obj); | |||
// Point is the legacy/planar class (2d), S2Point is the future (2d sphere). | ||||
static void parseLegacyPoint(const BSONObj &obj, S2Point *out); | static void parseLegacyPoint(const BSONObj &obj, S2Point *out); | |||
static void parseLegacyPoint(const BSONObj &obj, Point *out); | static void parseLegacyPoint(const BSONObj &obj, Point *out); | |||
static bool parseLineString(const BSONObj &obj, S2Polyline *out); | static bool parseLineString(const BSONObj &obj, S2Polyline *out); | |||
static bool isLineString(const BSONObj &obj); | static bool isLineString(const BSONObj &obj); | |||
static bool isGeoJSONLineString(const BSONObj &obj); | static bool isGeoJSONLineString(const BSONObj &obj); | |||
static void parseGeoJSONLineString(const BSONObj &obj, S2Polyline * out); | static void parseGeoJSONLineString(const BSONObj &obj, S2Polyline * out); | |||
// There are no legacy lines. | ||||
static bool parsePolygon(const BSONObj &obj, S2Polygon *out); | static bool parsePolygon(const BSONObj &obj, S2Polygon *out); | |||
static bool parsePolygon(const BSONObj &obj, Polygon *out); | ||||
static bool isPolygon(const BSONObj &obj); | static bool isPolygon(const BSONObj &obj); | |||
static bool isGeoJSONPolygon(const BSONObj &obj); | static bool isGeoJSONPolygon(const BSONObj &obj); | |||
static bool isLegacyPolygon(const BSONObj &obj); | static bool isLegacyPolygon(const BSONObj &obj); | |||
static void parseGeoJSONPolygon(const BSONObj &obj, S2Polygon *out) ; | static void parseGeoJSONPolygon(const BSONObj &obj, S2Polygon *out) ; | |||
static void parseLegacyPolygon(const BSONObj &obj, S2Polygon *out); | ||||
static void parseLegacyPolygon(const BSONObj &obj, Polygon *out); | static void parseLegacyPolygon(const BSONObj &obj, Polygon *out); | |||
// TODO(hk): We could do this in 2dsphere with an S2LatLngRect. | ||||
static bool isLegacyBox(const BSONObj &obj); | static bool isLegacyBox(const BSONObj &obj); | |||
static void parseLegacyBox(const BSONObj &obj, Box *out); | static void parseLegacyBox(const BSONObj &obj, Box *out); | |||
static bool isLegacyCenter(const BSONObj &obj); | static bool isLegacyCenter(const BSONObj &obj); | |||
static void parseLegacyCenter(const BSONObj &obj, Point *centerOut, | static void parseLegacyCenter(const BSONObj &obj, Circle *out); | |||
double *radiusOut); | ||||
static bool isLegacyCenterSphere(const BSONObj &obj); | ||||
static void parseLegacyCenterSphere(const BSONObj &obj, S2Cap *out) | ||||
; | ||||
// Return true if the CRS field is 1. missing, or 2. is well-formed and | // Return true if the CRS field is 1. missing, or 2. is well-formed and | |||
// has a datum we accept. Otherwise, return false. | // has a datum we accept. Otherwise, return false. | |||
// TODO(hk): If this is ever used anywhere but internally, consider | // NOTE(hk): If this is ever used anywhere but internally, consider | |||
// returning states: missing, invalid, unknown, ok, etc. -- whateve r | // returning states: missing, invalid, unknown, ok, etc. -- whateve r | |||
// needed. | // needed. | |||
static bool crsIsOK(const BSONObj& obj); | static bool crsIsOK(const BSONObj& obj); | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 14 change blocks. | ||||
12 lines changed or deleted | 19 lines changed or added | |||
gsasl_session.h | gsasl_session.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* limitations under the License. | * limitations under the License. | |||
*/ | */ | |||
#pragma once | #pragma once | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/platform/cstdint.h" // Must be included at all because of SERVER-8086. | #include "mongo/platform/cstdint.h" // Must be included before <gsasl.h> b ecause of SERVER-8086 | |||
#include <gsasl.h> // Must be included here because of SERVER-8086. | #include <gsasl.h> // Must be included after "mongo/platform/cstdint.h" be cause of SERVER-8086. | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* C++ wrapper around Gsasl_session. | * C++ wrapper around Gsasl_session. | |||
*/ | */ | |||
class GsaslSession { | class GsaslSession { | |||
MONGO_DISALLOW_COPYING(GsaslSession); | MONGO_DISALLOW_COPYING(GsaslSession); | |||
public: | public: | |||
GsaslSession(); | GsaslSession(); | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
hashindex.h | hashindex.h | |||
---|---|---|---|---|
skipping to change at line 90 | skipping to change at line 90 | |||
/* The input is "obj" which should have a field corresponding to th e hashedfield. | /* The input is "obj" which should have a field corresponding to th e hashedfield. | |||
* The output is a BSONObj with a single BSONElement whose value is the hash | * The output is a BSONObj with a single BSONElement whose value is the hash | |||
* Eg if this is an index on "a" we have | * Eg if this is an index on "a" we have | |||
* obj is {a : 45} --> key becomes {"" : hash(45) } | * obj is {a : 45} --> key becomes {"" : hash(45) } | |||
* | * | |||
* Limitation: arrays values are not currently supported. This fun ction uasserts | * Limitation: arrays values are not currently supported. This fun ction uasserts | |||
* that the value is not an array, and errors out in that case. | * that the value is not an array, and errors out in that case. | |||
*/ | */ | |||
void getKeys( const BSONObj &obj, BSONObjSet &keys ) const; | void getKeys( const BSONObj &obj, BSONObjSet &keys ) const; | |||
/* A field missing from a document is represented by the hash value | ||||
of a null BSONElement. | ||||
*/ | ||||
BSONElement missingField() const { return _missingKey.firstElement( | ||||
); } | ||||
/* The newCursor method works for suitable queries by generating a BtreeCursor | /* The newCursor method works for suitable queries by generating a BtreeCursor | |||
* using the hash of point-intervals parsed by FieldRangeSet. | * using the hash of point-intervals parsed by FieldRangeSet. | |||
* For unsuitable queries it just instantiates a btree cursor over the whole tree | * For unsuitable queries it just instantiates a btree cursor over the whole tree | |||
*/ | */ | |||
shared_ptr<Cursor> newCursor( const BSONObj& query , | shared_ptr<Cursor> newCursor( const BSONObj& query , | |||
const BSONObj& order , int numWanted ) const; | const BSONObj& order , int numWanted ) const; | |||
/* Takes a BSONElement, seed and hashVersion, and outputs the | /* Takes a BSONElement, seed and hashVersion, and outputs the | |||
* 64-bit hash used for this index | * 64-bit hash used for this index | |||
* E.g. if the element is {a : 3} this outputs v1-hash(3) | * E.g. if the element is {a : 3} this outputs v1-hash(3) | |||
skipping to change at line 118 | skipping to change at line 122 | |||
bool scanAndOrderRequired( const BSONObj& query , const BSONObj& or der ) const { | bool scanAndOrderRequired( const BSONObj& query , const BSONObj& or der ) const { | |||
return ! order.isEmpty(); | return ! order.isEmpty(); | |||
} | } | |||
private: | private: | |||
string _hashedField; | string _hashedField; | |||
KeyPattern _keyPattern; | KeyPattern _keyPattern; | |||
HashSeed _seed; //defaults to zero if not in the IndexSpec | HashSeed _seed; //defaults to zero if not in the IndexSpec | |||
HashVersion _hashVersion; //defaults to zero if not in the IndexSpe c | HashVersion _hashVersion; //defaults to zero if not in the IndexSpe c | |||
bool _isSparse; | bool _isSparse; | |||
BSONObj _missingKey; | ||||
}; | }; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 7 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/bson/util/builder.h" | |||
#include "../../db/cmdline.h" | #include "mongo/db/cmdline.h" | |||
#include "../mongoutils/str.h" | #include "mongo/util/mongoutils/str.h" | |||
#include "mongo/util/net/sock.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 | |||
index_rebuilder.h | index_rebuilder.h | |||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* 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 Lice nse | * You should have received a copy of the GNU Affero General Public Lice nse | |||
* 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/db/namespace_details.h" | #include "mongo/db/namespace_details.h" | |||
#include "mongo/util/background.h" | ||||
namespace mongo { | namespace mongo { | |||
class IndexRebuilder : public BackgroundJob { | class IndexRebuilder { | |||
public: | public: | |||
IndexRebuilder(); | IndexRebuilder(); | |||
std::string name() const; | std::string name() const; | |||
void run(); | void run(); | |||
private: | private: | |||
/** | /** | |||
* Check each collection in a database to see if it has any in-prog ress index builds that | * Check each collection in a database to see if it has any in-prog ress index builds that | |||
* need to be retried. If so, calls retryIndexBuild. | * need to be retried. If so, calls retryIndexBuild. | |||
*/ | */ | |||
void checkDB(const std::string& dbname); | void checkDB(const std::string& dbname, bool* firstTime); | |||
/** | /** | |||
* Actually retry an index build on a given namespace. | * Actually retry an index build on a given namespace. | |||
* @param dbName the name of the database for accessing db.system.i ndexes | * @param dbName the name of the database for accessing db.system.i ndexes | |||
* @param nsd the namespace details of the namespace building the i ndex | * @param nsd the namespace details of the namespace building the i ndex | |||
* @param index the offset into nsd's index array of the partially- built index | * @param index the offset into nsd's index array of the partially- built index | |||
*/ | */ | |||
void retryIndexBuild(const std::string& dbName, NamespaceDetails* n sd, const int index); | void retryIndexBuild(const std::string& dbName, NamespaceDetails* n sd, const int index); | |||
}; | }; | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 2 lines changed or added | |||
indexkey.h | indexkey.h | |||
---|---|---|---|---|
skipping to change at line 53 | skipping to change at line 53 | |||
* done this way so parsing, etc... can be cached | * done this way so parsing, etc... can be cached | |||
* so if there is a FTS IndexPlugin, for each index using FTS | * so if there is a FTS IndexPlugin, for each index using FTS | |||
* there will be 1 of these, and it can have things pre-parsed, etc... | * there will be 1 of these, and it can have things pre-parsed, etc... | |||
*/ | */ | |||
class IndexType : boost::noncopyable { | class IndexType : boost::noncopyable { | |||
public: | public: | |||
IndexType( const IndexPlugin * plugin , const IndexSpec * spec ); | IndexType( const IndexPlugin * plugin , const IndexSpec * spec ); | |||
virtual ~IndexType(); | virtual ~IndexType(); | |||
virtual void getKeys( const BSONObj &obj, BSONObjSet &keys ) const = 0; | virtual void getKeys( const BSONObj &obj, BSONObjSet &keys ) const = 0; | |||
/** | ||||
* Returns the element placed in an index key when indexing a field | ||||
absent from a document. | ||||
* By default this is a null BSONElement. | ||||
*/ | ||||
virtual BSONElement missingField() const; | ||||
/* Full semantics of numWanted: | ||||
* numWanted == 0 : Return any number of results, but try to return | ||||
in batches of 101. | ||||
* numWanted == 1 : Return exactly one result. | ||||
* numWanted > 1 : Return any number of results, but try to return | ||||
in batches of numWanted. | ||||
* | ||||
* In practice, your cursor can ignore numWanted, as enforcement of | ||||
limits is done | ||||
* by the caller. | ||||
*/ | ||||
virtual shared_ptr<Cursor> newCursor( const BSONObj& query , const BSONObj& order , int numWanted ) const = 0; | virtual shared_ptr<Cursor> newCursor( const BSONObj& query , const BSONObj& order , int numWanted ) const = 0; | |||
/** optional op : changes query to match what's in the index */ | /** optional op : changes query to match what's in the index */ | |||
virtual BSONObj fixKey( const BSONObj& in ) { return in; } | virtual BSONObj fixKey( const BSONObj& in ) { return in; } | |||
/** optional op : compare 2 objects with regards to this index */ | /** optional op : compare 2 objects with regards to this index */ | |||
virtual int compare( const BSONObj& l , const BSONObj& r ) const; | virtual int compare( const BSONObj& l , const BSONObj& r ) const; | |||
/** @return plugin */ | /** @return plugin */ | |||
const IndexPlugin * getPlugin() const { return _plugin; } | const IndexPlugin * getPlugin() const { return _plugin; } | |||
skipping to change at line 104 | skipping to change at line 119 | |||
virtual IndexType* generate( const IndexSpec * spec ) const = 0; | virtual IndexType* generate( const IndexSpec * spec ) const = 0; | |||
string getName() const { return _name; } | string getName() const { return _name; } | |||
/** | /** | |||
* @return new keyPattern | * @return new keyPattern | |||
* if nothing changes, should return keyPattern | * if nothing changes, should return keyPattern | |||
*/ | */ | |||
virtual BSONObj adjustIndexSpec( const BSONObj& spec ) const { retu rn spec; } | virtual BSONObj adjustIndexSpec( const BSONObj& spec ) const { retu rn spec; } | |||
/** | ||||
* Hook function to run after an index that uses this plugin is bui | ||||
lt. | ||||
* | ||||
* This will be called with an active write context (and lock) on t | ||||
he database. | ||||
* | ||||
* @param spec The IndexSpec of the newly built index. | ||||
*/ | ||||
virtual void postBuildHook( const IndexSpec& spec ) const { } | ||||
// ------- static below ------- | // ------- static below ------- | |||
static IndexPlugin* get( const string& name ) { | static IndexPlugin* get( const string& name ) { | |||
if ( ! _plugins ) | if ( ! _plugins ) | |||
return 0; | return 0; | |||
map<string,IndexPlugin*>::iterator i = _plugins->find( name ); | map<string,IndexPlugin*>::iterator i = _plugins->find( name ); | |||
if ( i == _plugins->end() ) | if ( i == _plugins->end() ) | |||
return 0; | return 0; | |||
return i->second; | return i->second; | |||
} | } | |||
/** | /** | |||
* @param keyPattern { x : "fts" } | * @param keyPattern { x : "fts" } | |||
* @return "" or the name | * @return "" or the name | |||
*/ | */ | |||
static string findPluginName( const BSONObj& keyPattern ); | static string findPluginName( const BSONObj& keyPattern ); | |||
/** | ||||
* True if is a regular (non-plugin) index or uses a plugin that ex | ||||
isted before 2.4. | ||||
* These plugins are grandfathered in and allowed to exist in DBs w | ||||
ith | ||||
* PDFILE_MINOR_VERSION_22_AND_OLDER | ||||
*/ | ||||
static bool existedBefore24(const string& name) { | ||||
return name.empty() | ||||
|| name == "2d" | ||||
|| name == "geoHaystack" | ||||
|| name == "hashed" | ||||
; | ||||
} | ||||
private: | private: | |||
string _name; | string _name; | |||
static map<string,IndexPlugin*> * _plugins; | static map<string,IndexPlugin*> * _plugins; | |||
}; | }; | |||
/* precomputed details about an index, used for inserting keys on updat es | /* precomputed details about an index, used for inserting keys on updat es | |||
stored/cached in NamespaceDetailsTransient, or can be used standalon e | stored/cached in NamespaceDetailsTransient, or can be used standalon e | |||
*/ | */ | |||
class IndexSpec { | class IndexSpec { | |||
public: | public: | |||
enum PluginRules { | ||||
NoPlugins, | ||||
RulesFor22, // if !IndexPlugin::existedBefore24() treat as asce | ||||
nding | ||||
RulesFor24, // allow new plugins but error if unknown | ||||
}; | ||||
BSONObj keyPattern; // e.g., { name : 1 } | BSONObj keyPattern; // e.g., { name : 1 } | |||
BSONObj info; // this is the same as IndexDetails::info.obj() | BSONObj info; // this is the same as IndexDetails::info.obj() | |||
IndexSpec() | IndexSpec() | |||
: _details(0) , _finishedInit(false) { | : _details(0) , _finishedInit(false) { | |||
} | } | |||
explicit IndexSpec( const BSONObj& k , const BSONObj& m = BSONObj() | explicit IndexSpec(const BSONObj& k, const BSONObj& m=BSONObj(), | |||
) | PluginRules rules=RulesFor24) | |||
: keyPattern(k) , info(m) , _details(0) , _finishedInit(false) { | : keyPattern(k) , info(m) , _details(0) , _finishedInit(false) { | |||
_init(); | _init(rules); | |||
} | } | |||
/** | /** | |||
this is a DiscLoc of an IndexDetails info | this is a DiscLoc of an IndexDetails info | |||
should have a key field | should have a key field | |||
*/ | */ | |||
explicit IndexSpec( const DiskLoc& loc ) { | explicit IndexSpec(const DiskLoc& loc, PluginRules rules=RulesFor24 | |||
reset( loc ); | ) { | |||
reset(loc, rules); | ||||
} | } | |||
void reset( const BSONObj& info ); | void reset(const BSONObj& info, PluginRules rules=RulesFor24); | |||
void reset( const DiskLoc& infoLoc ) { reset(infoLoc.obj()); } | void reset(const IndexDetails * details); // determines rules based | |||
void reset( const IndexDetails * details ); | on pdfile version | |||
void reset(const DiskLoc& infoLoc, PluginRules rules=RulesFor24) { | ||||
reset(infoLoc.obj(), rules); | ||||
} | ||||
void getKeys( const BSONObj &obj, BSONObjSet &keys ) const; | void getKeys( const BSONObj &obj, BSONObjSet &keys ) const; | |||
BSONElement missingField() const { return _nullElt; } | /** | |||
* Returns the element placed in an index key when indexing a field | ||||
absent from a document. | ||||
* By default this is a null BSONElement. | ||||
*/ | ||||
BSONElement missingField() const { | ||||
if ( _indexType.get() ) | ||||
return _indexType->missingField(); | ||||
return _nullElt; | ||||
} | ||||
string getTypeName() const { | string getTypeName() const { | |||
if ( _indexType.get() ) | if ( _indexType.get() ) | |||
return _indexType->getPlugin()->getName(); | return _indexType->getPlugin()->getName(); | |||
return ""; | return ""; | |||
} | } | |||
IndexType* getType() const { | IndexType* getType() const { | |||
return _indexType.get(); | return _indexType.get(); | |||
} | } | |||
skipping to change at line 203 | skipping to change at line 257 | |||
BSONElement _nullElt; // jstNull | BSONElement _nullElt; // jstNull | |||
BSONObj _undefinedObj; // only used for _undefinedElt | BSONObj _undefinedObj; // only used for _undefinedElt | |||
BSONElement _undefinedElt; // undefined | BSONElement _undefinedElt; // undefined | |||
int _nFields; // number of fields in the index | int _nFields; // number of fields in the index | |||
bool _sparse; // if the index is sparse | bool _sparse; // if the index is sparse | |||
shared_ptr<IndexType> _indexType; | shared_ptr<IndexType> _indexType; | |||
const IndexDetails * _details; | const IndexDetails * _details; | |||
void _init(); | void _init(PluginRules rules); | |||
friend class IndexType; | friend class IndexType; | |||
friend class KeyGeneratorV0; | friend class KeyGeneratorV0; | |||
friend class KeyGeneratorV1; | friend class KeyGeneratorV1; | |||
public: | public: | |||
bool _finishedInit; | bool _finishedInit; | |||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 10 change blocks. | ||||
10 lines changed or deleted | 75 lines changed or added | |||
json.h | json.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include "mongo/bson/bsonobj.h" | #include "mongo/bson/bsonobj.h" | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* Create a BSONObj from a JSON <http://www.json.org>, | * Create a BSONObj from a JSON <http://www.json.org>, | |||
* <http://www.ietf.org/rfc/rfc4627.txt> string. In addition to the JS ON | * <http://www.ietf.org/rfc/rfc4627.txt> string. In addition to the JS ON | |||
* extensions extensions described here | * extensions extensions described here | |||
* <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JSON>, | * <http://dochub.mongodb.org/core/mongodbextendedjson>, this function | |||
this | * accepts unquoted field names and allows single quotes to optionally | |||
* function accepts unquoted field names and allows single quotes to | be | |||
* optionally be used when specifying field names and string values ins | * used when specifying field names and string values instead of double | |||
tead | * quotes. JSON unicode escape sequences (of the form \uXXXX) are | |||
* of double quotes. JSON unicode escape sequences (of the form \uXXXX | ||||
) are | ||||
* converted to utf8. | * converted to utf8. | |||
* | * | |||
* @throws MsgAssertionException if parsing fails. The message include d with | * @throws MsgAssertionException if parsing fails. The message include d with | |||
* this assertion includes the character offset where parsing failed. | * this assertion includes the character offset where parsing failed. | |||
*/ | */ | |||
BSONObj fromjson(const std::string& str); | BSONObj fromjson(const std::string& str); | |||
/** @param len will be size of JSON object in text chars. */ | /** @param len will be size of JSON object in text chars. */ | |||
BSONObj fromjson(const char* str, int* len=NULL); | BSONObj fromjson(const char* str, int* len=NULL); | |||
End of changes. 1 change blocks. | ||||
7 lines changed or deleted | 5 lines changed or added | |||
jsregexp.h | jsregexp.h | |||
---|---|---|---|---|
// Copyright 2012 the V8 project authors. All rights reserved. | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- | |||
// Redistribution and use in source and binary forms, with or without | * | |||
// modification, are permitted provided that the following conditions are | * ***** BEGIN LICENSE BLOCK ***** | |||
// met: | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | |||
// | * | |||
// * Redistributions of source code must retain the above copyright | * The contents of this file are subject to the Mozilla Public License Vers | |||
// notice, this list of conditions and the following disclaimer. | ion | |||
// * Redistributions in binary form must reproduce the above | * 1.1 (the "License"); you may not use this file except in compliance with | |||
// copyright notice, this list of conditions and the following | * the License. You may obtain a copy of the License at | |||
// disclaimer in the documentation and/or other materials provided | * http://www.mozilla.org/MPL/ | |||
// with the distribution. | * | |||
// * Neither the name of Google Inc. nor the names of its | * Software distributed under the License is distributed on an "AS IS" basi | |||
// contributors may be used to endorse or promote products derived | s, | |||
// from this software without specific prior written permission. | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
// | * for the specific language governing rights and limitations under the | |||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | * License. | |||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | * | |||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | * The Original Code is Mozilla Communicator client code, released | |||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | * March 31, 1998. | |||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | * | |||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | * The Initial Developer of the Original Code is | |||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * Netscape Communications Corporation. | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * Portions created by the Initial Developer are Copyright (C) 1998 | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * the Initial Developer. All Rights Reserved. | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * Contributor(s): | |||
* | ||||
#ifndef V8_JSREGEXP_H_ | * Alternatively, the contents of this file may be used under the terms of | |||
#define V8_JSREGEXP_H_ | * either of the GNU General Public License Version 2 or later (the "GPL"), | |||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL | ||||
#include "allocation.h" | "), | |||
#include "assembler.h" | * in which case the provisions of the GPL or the LGPL are applicable inste | |||
#include "zone-inl.h" | ad | |||
* of those above. If you wish to allow use of your version of this file on | ||||
namespace v8 { | ly | |||
namespace internal { | * under the terms of either the GPL or the LGPL, and not to allow others t | |||
o | ||||
class NodeVisitor; | * use your version of this file under the terms of the MPL, indicate your | |||
class RegExpCompiler; | * decision by deleting the provisions above and replace them with the noti | |||
class RegExpMacroAssembler; | ce | |||
class RegExpNode; | * and other provisions required by the GPL or the LGPL. If you do not dele | |||
class RegExpTree; | te | |||
class BoyerMooreLookahead; | * the provisions above, a recipient may use your version of this file unde | |||
r | ||||
class RegExpImpl { | * the terms of any one of the MPL, the GPL or the LGPL. | |||
public: | * | |||
// Whether V8 is compiled with native regexp support or not. | * ***** END LICENSE BLOCK ***** */ | |||
static bool UsesNativeRegExp() { | ||||
#ifdef V8_INTERPRETED_REGEXP | #ifndef jsregexp_h___ | |||
return false; | #define jsregexp_h___ | |||
#else | /* | |||
return true; | * JS regular expression interface. | |||
#endif | */ | |||
} | #include <stddef.h> | |||
#include "jspubtd.h" | ||||
// Creates a regular expression literal in the old space. | #include "jsstr.h" | |||
// This function calls the garbage collector if necessary. | ||||
static Handle<Object> CreateRegExpLiteral(Handle<JSFunction> constructor, | ||||
Handle<String> pattern, | ||||
Handle<String> flags, | ||||
bool* has_pending_exception); | ||||
// Returns a string representation of a regular expression. | ||||
// Implements RegExp.prototype.toString, see ECMA-262 section 15.10.6.4. | ||||
// This function calls the garbage collector if necessary. | ||||
static Handle<String> ToString(Handle<Object> value); | ||||
// Parses the RegExp pattern and prepares the JSRegExp object with | ||||
// generic data and choice of implementation - as well as what | ||||
// the implementation wants to store in the data field. | ||||
// Returns false if compilation fails. | ||||
static Handle<Object> Compile(Handle<JSRegExp> re, | ||||
Handle<String> pattern, | ||||
Handle<String> flags, | ||||
Zone* zone); | ||||
// See ECMA-262 section 15.10.6.2. | ||||
// This function calls the garbage collector if necessary. | ||||
static Handle<Object> Exec(Handle<JSRegExp> regexp, | ||||
Handle<String> subject, | ||||
int index, | ||||
Handle<JSArray> lastMatchInfo); | ||||
// Prepares a JSRegExp object with Irregexp-specific data. | ||||
static void IrregexpInitialize(Handle<JSRegExp> re, | ||||
Handle<String> pattern, | ||||
JSRegExp::Flags flags, | ||||
int capture_register_count); | ||||
static void AtomCompile(Handle<JSRegExp> re, | ||||
Handle<String> pattern, | ||||
JSRegExp::Flags flags, | ||||
Handle<String> match_pattern); | ||||
static Handle<Object> AtomExec(Handle<JSRegExp> regexp, | ||||
Handle<String> subject, | ||||
int index, | ||||
Handle<JSArray> lastMatchInfo); | ||||
enum IrregexpResult { RE_FAILURE = 0, RE_SUCCESS = 1, RE_EXCEPTION = -1 } | ||||
; | ||||
// Prepare a RegExp for being executed one or more times (using | ||||
// IrregexpExecOnce) on the subject. | ||||
// This ensures that the regexp is compiled for the subject, and that | ||||
// the subject is flat. | ||||
// Returns the number of integer spaces required by IrregexpExecOnce | ||||
// as its "registers" argument. If the regexp cannot be compiled, | ||||
// an exception is set as pending, and this function returns negative. | ||||
static int IrregexpPrepare(Handle<JSRegExp> regexp, | ||||
Handle<String> subject); | ||||
// Calculate the size of offsets vector for the case of global regexp | ||||
// and the number of matches this vector is able to store. | ||||
static int GlobalOffsetsVectorSize(Handle<JSRegExp> regexp, | ||||
int registers_per_match, | ||||
int* max_matches); | ||||
// Execute a regular expression on the subject, starting from index. | ||||
// If matching succeeds, return the number of matches. This can be large | ||||
r | ||||
// than one in the case of global regular expressions. | ||||
// The captures and subcaptures are stored into the registers vector. | ||||
// If matching fails, returns RE_FAILURE. | ||||
// If execution fails, sets a pending exception and returns RE_EXCEPTION. | ||||
static int IrregexpExecRaw(Handle<JSRegExp> regexp, | ||||
Handle<String> subject, | ||||
int index, | ||||
Vector<int> registers); | ||||
// Execute an Irregexp bytecode pattern. | ||||
// On a successful match, the result is a JSArray containing | ||||
// captured positions. On a failure, the result is the null value. | ||||
// Returns an empty handle in case of an exception. | ||||
static Handle<Object> IrregexpExec(Handle<JSRegExp> regexp, | ||||
Handle<String> subject, | ||||
int index, | ||||
Handle<JSArray> lastMatchInfo); | ||||
// Array index in the lastMatchInfo array. | ||||
static const int kLastCaptureCount = 0; | ||||
static const int kLastSubject = 1; | ||||
static const int kLastInput = 2; | ||||
static const int kFirstCapture = 3; | ||||
static const int kLastMatchOverhead = 3; | ||||
// Direct offset into the lastMatchInfo array. | ||||
static const int kLastCaptureCountOffset = | ||||
FixedArray::kHeaderSize + kLastCaptureCount * kPointerSize; | ||||
static const int kLastSubjectOffset = | ||||
FixedArray::kHeaderSize + kLastSubject * kPointerSize; | ||||
static const int kLastInputOffset = | ||||
FixedArray::kHeaderSize + kLastInput * kPointerSize; | ||||
static const int kFirstCaptureOffset = | ||||
FixedArray::kHeaderSize + kFirstCapture * kPointerSize; | ||||
// Used to access the lastMatchInfo array. | ||||
static int GetCapture(FixedArray* array, int index) { | ||||
return Smi::cast(array->get(index + kFirstCapture))->value(); | ||||
} | ||||
static void SetLastCaptureCount(FixedArray* array, int to) { | ||||
array->set(kLastCaptureCount, Smi::FromInt(to)); | ||||
} | ||||
static void SetLastSubject(FixedArray* array, String* to) { | ||||
array->set(kLastSubject, to); | ||||
} | ||||
static void SetLastInput(FixedArray* array, String* to) { | ||||
array->set(kLastInput, to); | ||||
} | ||||
static void SetCapture(FixedArray* array, int index, int to) { | ||||
array->set(index + kFirstCapture, Smi::FromInt(to)); | ||||
} | ||||
static int GetLastCaptureCount(FixedArray* array) { | ||||
return Smi::cast(array->get(kLastCaptureCount))->value(); | ||||
} | ||||
// For acting on the JSRegExp data FixedArray. | ||||
static int IrregexpMaxRegisterCount(FixedArray* re); | ||||
static void SetIrregexpMaxRegisterCount(FixedArray* re, int value); | ||||
static int IrregexpNumberOfCaptures(FixedArray* re); | ||||
static int IrregexpNumberOfRegisters(FixedArray* re); | ||||
static ByteArray* IrregexpByteCode(FixedArray* re, bool is_ascii); | ||||
static Code* IrregexpNativeCode(FixedArray* re, bool is_ascii); | ||||
// Limit the space regexps take up on the heap. In order to limit this w | ||||
e | ||||
// would like to keep track of the amount of regexp code on the heap. Th | ||||
is | ||||
// is not tracked, however. As a conservative approximation we track the | ||||
// total regexp code compiled including code that has subsequently been f | ||||
reed | ||||
// and the total executable memory at any point. | ||||
static const int kRegExpExecutableMemoryLimit = 16 * MB; | ||||
static const int kRegWxpCompiledLimit = 1 * MB; | ||||
private: | ||||
static String* last_ascii_string_; | ||||
static String* two_byte_cached_string_; | ||||
static bool CompileIrregexp( | ||||
Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii); | ||||
static inline bool EnsureCompiledIrregexp( | ||||
Handle<JSRegExp> re, Handle<String> sample_subject, bool is_ascii); | ||||
// Set the subject cache. The previous string buffer is not deleted, so | ||||
the | ||||
// caller should ensure that it doesn't leak. | ||||
static void SetSubjectCache(String* subject, | ||||
char* utf8_subject, | ||||
int uft8_length, | ||||
int character_position, | ||||
int utf8_position); | ||||
// A one element cache of the last utf8_subject string and its length. T | ||||
he | ||||
// subject JS String object is cached in the heap. We also cache a | ||||
// translation between position and utf8 position. | ||||
static char* utf8_subject_cache_; | ||||
static int utf8_length_cache_; | ||||
static int utf8_position_; | ||||
static int character_position_; | ||||
}; | ||||
// Represents the location of one element relative to the intersection of | ||||
// two sets. Corresponds to the four areas of a Venn diagram. | ||||
enum ElementInSetsRelation { | ||||
kInsideNone = 0, | ||||
kInsideFirst = 1, | ||||
kInsideSecond = 2, | ||||
kInsideBoth = 3 | ||||
}; | ||||
// Represents code units in the range from from_ to to_, both ends are | ||||
// inclusive. | ||||
class CharacterRange { | ||||
public: | ||||
CharacterRange() : from_(0), to_(0) { } | ||||
// For compatibility with the CHECK_OK macro | ||||
CharacterRange(void* null) { ASSERT_EQ(NULL, null); } //NOLINT | ||||
CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { } | ||||
static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges, | ||||
Zone* zone); | ||||
static Vector<const int> GetWordBounds(); | ||||
static inline CharacterRange Singleton(uc16 value) { | ||||
return CharacterRange(value, value); | ||||
} | ||||
static inline CharacterRange Range(uc16 from, uc16 to) { | ||||
ASSERT(from <= to); | ||||
return CharacterRange(from, to); | ||||
} | ||||
static inline CharacterRange Everything() { | ||||
return CharacterRange(0, 0xFFFF); | ||||
} | ||||
bool Contains(uc16 i) { return from_ <= i && i <= to_; } | ||||
uc16 from() const { return from_; } | ||||
void set_from(uc16 value) { from_ = value; } | ||||
uc16 to() const { return to_; } | ||||
void set_to(uc16 value) { to_ = value; } | ||||
bool is_valid() { return from_ <= to_; } | ||||
bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; } | ||||
bool IsSingleton() { return (from_ == to_); } | ||||
void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii, | ||||
Zone* zone); | ||||
static void Split(ZoneList<CharacterRange>* base, | ||||
Vector<const int> overlay, | ||||
ZoneList<CharacterRange>** included, | ||||
ZoneList<CharacterRange>** excluded, | ||||
Zone* zone); | ||||
// Whether a range list is in canonical form: Ranges ordered by from valu | ||||
e, | ||||
// and ranges non-overlapping and non-adjacent. | ||||
static bool IsCanonical(ZoneList<CharacterRange>* ranges); | ||||
// Convert range list to canonical form. The characters covered by the ra | ||||
nges | ||||
// will still be the same, but no character is in more than one range, an | ||||
d | ||||
// adjacent ranges are merged. The resulting list may be shorter than the | ||||
// original, but cannot be longer. | ||||
static void Canonicalize(ZoneList<CharacterRange>* ranges); | ||||
// Negate the contents of a character range in canonical form. | ||||
static void Negate(ZoneList<CharacterRange>* src, | ||||
ZoneList<CharacterRange>* dst, | ||||
Zone* zone); | ||||
static const int kStartMarker = (1 << 24); | ||||
static const int kPayloadMask = (1 << 24) - 1; | ||||
private: | ||||
uc16 from_; | ||||
uc16 to_; | ||||
}; | ||||
// A set of unsigned integers that behaves especially well on small | ||||
// integers (< 32). May do zone-allocation. | ||||
class OutSet: public ZoneObject { | ||||
public: | ||||
OutSet() : first_(0), remaining_(NULL), successors_(NULL) { } | ||||
OutSet* Extend(unsigned value, Zone* zone); | ||||
bool Get(unsigned value); | ||||
static const unsigned kFirstLimit = 32; | ||||
private: | ||||
// Destructively set a value in this set. In most cases you want | ||||
// to use Extend instead to ensure that only one instance exists | ||||
// that contains the same values. | ||||
void Set(unsigned value, Zone* zone); | ||||
// The successors are a list of sets that contain the same values | ||||
// as this set and the one more value that is not present in this | ||||
// set. | ||||
ZoneList<OutSet*>* successors(Zone* zone) { return successors_; } | ||||
OutSet(uint32_t first, ZoneList<unsigned>* remaining) | ||||
: first_(first), remaining_(remaining), successors_(NULL) { } | ||||
uint32_t first_; | ||||
ZoneList<unsigned>* remaining_; | ||||
ZoneList<OutSet*>* successors_; | ||||
friend class Trace; | ||||
}; | ||||
// A mapping from integers, specified as ranges, to a set of integers. | ||||
// Used for mapping character ranges to choices. | ||||
class DispatchTable : public ZoneObject { | ||||
public: | ||||
explicit DispatchTable(Zone* zone) : tree_(zone) { } | ||||
class Entry { | ||||
public: | ||||
Entry() : from_(0), to_(0), out_set_(NULL) { } | ||||
Entry(uc16 from, uc16 to, OutSet* out_set) | ||||
: from_(from), to_(to), out_set_(out_set) { } | ||||
uc16 from() { return from_; } | ||||
uc16 to() { return to_; } | ||||
void set_to(uc16 value) { to_ = value; } | ||||
void AddValue(int value, Zone* zone) { | ||||
out_set_ = out_set_->Extend(value, zone); | ||||
} | ||||
OutSet* out_set() { return out_set_; } | ||||
private: | ||||
uc16 from_; | ||||
uc16 to_; | ||||
OutSet* out_set_; | ||||
}; | ||||
class Config { | ||||
public: | ||||
typedef uc16 Key; | ||||
typedef Entry Value; | ||||
static const uc16 kNoKey; | ||||
static const Entry NoValue() { return Value(); } | ||||
static inline int Compare(uc16 a, uc16 b) { | ||||
if (a == b) | ||||
return 0; | ||||
else if (a < b) | ||||
return -1; | ||||
else | ||||
return 1; | ||||
} | ||||
}; | ||||
void AddRange(CharacterRange range, int value, Zone* zone); | ||||
OutSet* Get(uc16 value); | ||||
void Dump(); | ||||
template <typename Callback> | ||||
void ForEach(Callback* callback) { | ||||
return tree()->ForEach(callback); | ||||
} | ||||
private: | ||||
// There can't be a static empty set since it allocates its | ||||
// successors in a zone and caches them. | ||||
OutSet* empty() { return &empty_; } | ||||
OutSet empty_; | ||||
ZoneSplayTree<Config>* tree() { return &tree_; } | ||||
ZoneSplayTree<Config> tree_; | ||||
}; | ||||
#define FOR_EACH_NODE_TYPE(VISIT) \ | ||||
VISIT(End) \ | ||||
VISIT(Action) \ | ||||
VISIT(Choice) \ | ||||
VISIT(BackReference) \ | ||||
VISIT(Assertion) \ | ||||
VISIT(Text) | ||||
#define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \ | ||||
VISIT(Disjunction) \ | ||||
VISIT(Alternative) \ | ||||
VISIT(Assertion) \ | ||||
VISIT(CharacterClass) \ | ||||
VISIT(Atom) \ | ||||
VISIT(Quantifier) \ | ||||
VISIT(Capture) \ | ||||
VISIT(Lookahead) \ | ||||
VISIT(BackReference) \ | ||||
VISIT(Empty) \ | ||||
VISIT(Text) | ||||
#define FORWARD_DECLARE(Name) class RegExp##Name; | ||||
FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE) | ||||
#undef FORWARD_DECLARE | ||||
class TextElement { | ||||
public: | ||||
enum Type {UNINITIALIZED, ATOM, CHAR_CLASS}; | ||||
TextElement() : type(UNINITIALIZED) { } | ||||
explicit TextElement(Type t) : type(t), cp_offset(-1) { } | ||||
static TextElement Atom(RegExpAtom* atom); | ||||
static TextElement CharClass(RegExpCharacterClass* char_class); | ||||
int length(); | ||||
Type type; | ||||
union { | ||||
RegExpAtom* u_atom; | ||||
RegExpCharacterClass* u_char_class; | ||||
} data; | ||||
int cp_offset; | ||||
}; | ||||
class Trace; | ||||
struct NodeInfo { | ||||
NodeInfo() | ||||
: being_analyzed(false), | ||||
been_analyzed(false), | ||||
follows_word_interest(false), | ||||
follows_newline_interest(false), | ||||
follows_start_interest(false), | ||||
at_end(false), | ||||
visited(false), | ||||
replacement_calculated(false) { } | ||||
// Returns true if the interests and assumptions of this node | ||||
// matches the given one. | ||||
bool Matches(NodeInfo* that) { | ||||
return (at_end == that->at_end) && | ||||
(follows_word_interest == that->follows_word_interest) && | ||||
(follows_newline_interest == that->follows_newline_interest) && | ||||
(follows_start_interest == that->follows_start_interest); | ||||
} | ||||
// Updates the interests of this node given the interests of the | ||||
// node preceding it. | ||||
void AddFromPreceding(NodeInfo* that) { | ||||
at_end |= that->at_end; | ||||
follows_word_interest |= that->follows_word_interest; | ||||
follows_newline_interest |= that->follows_newline_interest; | ||||
follows_start_interest |= that->follows_start_interest; | ||||
} | ||||
bool HasLookbehind() { | ||||
return follows_word_interest || | ||||
follows_newline_interest || | ||||
follows_start_interest; | ||||
} | ||||
// Sets the interests of this node to include the interests of the | ||||
// following node. | ||||
void AddFromFollowing(NodeInfo* that) { | ||||
follows_word_interest |= that->follows_word_interest; | ||||
follows_newline_interest |= that->follows_newline_interest; | ||||
follows_start_interest |= that->follows_start_interest; | ||||
} | ||||
void ResetCompilationState() { | ||||
being_analyzed = false; | ||||
been_analyzed = false; | ||||
} | ||||
bool being_analyzed: 1; | ||||
bool been_analyzed: 1; | ||||
// These bits are set of this node has to know what the preceding | ||||
// character was. | ||||
bool follows_word_interest: 1; | ||||
bool follows_newline_interest: 1; | ||||
bool follows_start_interest: 1; | ||||
bool at_end: 1; | ||||
bool visited: 1; | ||||
bool replacement_calculated: 1; | ||||
}; | ||||
// Details of a quick mask-compare check that can look ahead in the | ||||
// input stream. | ||||
class QuickCheckDetails { | ||||
public: | ||||
QuickCheckDetails() | ||||
: characters_(0), | ||||
mask_(0), | ||||
value_(0), | ||||
cannot_match_(false) { } | ||||
explicit QuickCheckDetails(int characters) | ||||
: characters_(characters), | ||||
mask_(0), | ||||
value_(0), | ||||
cannot_match_(false) { } | ||||
bool Rationalize(bool ascii); | ||||
// Merge in the information from another branch of an alternation. | ||||
void Merge(QuickCheckDetails* other, int from_index); | ||||
// Advance the current position by some amount. | ||||
void Advance(int by, bool ascii); | ||||
void Clear(); | ||||
bool cannot_match() { return cannot_match_; } | ||||
void set_cannot_match() { cannot_match_ = true; } | ||||
struct Position { | ||||
Position() : mask(0), value(0), determines_perfectly(false) { } | ||||
uc16 mask; | ||||
uc16 value; | ||||
bool determines_perfectly; | ||||
}; | ||||
int characters() { return characters_; } | ||||
void set_characters(int characters) { characters_ = characters; } | ||||
Position* positions(int index) { | ||||
ASSERT(index >= 0); | ||||
ASSERT(index < characters_); | ||||
return positions_ + index; | ||||
} | ||||
uint32_t mask() { return mask_; } | ||||
uint32_t value() { return value_; } | ||||
private: | ||||
// How many characters do we have quick check information from. This is | ||||
// the same for all branches of a choice node. | ||||
int characters_; | ||||
Position positions_[4]; | ||||
// These values are the condensate of the above array after Rationalize() | ||||
. | ||||
uint32_t mask_; | ||||
uint32_t value_; | ||||
// If set to true, there is no way this quick check can match at all. | ||||
// E.g., if it requires to be at the start of the input, and isn't. | ||||
bool cannot_match_; | ||||
}; | ||||
extern int kUninitializedRegExpNodePlaceHolder; | ||||
class RegExpNode: public ZoneObject { | #ifdef JS_THREADSAFE | |||
public: | #include "jsdhash.h" | |||
explicit RegExpNode(Zone* zone) | #endif | |||
: replacement_(NULL), trace_count_(0), zone_(zone) { | ||||
bm_info_[0] = bm_info_[1] = NULL; | ||||
} | ||||
virtual ~RegExpNode(); | ||||
virtual void Accept(NodeVisitor* visitor) = 0; | ||||
// Generates a goto to this node or actually generates the code at this p | ||||
oint. | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0; | ||||
// How many characters must this node consume at a minimum in order to | ||||
// succeed. If we have found at least 'still_to_find' characters that | ||||
// must be consumed there is no need to ask any following nodes whether | ||||
// they are sure to eat any more characters. The not_at_start argument i | ||||
s | ||||
// used to indicate that we know we are not at the start of the input. I | ||||
n | ||||
// this case anchored branches will always fail and can be ignored when | ||||
// determining how many characters are consumed on success. | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start) = 0; | ||||
// Emits some quick code that checks whether the preloaded characters mat | ||||
ch. | ||||
// Falls through on certain failure, jumps to the label on possible succe | ||||
ss. | ||||
// If the node cannot make a quick check it does nothing and returns fals | ||||
e. | ||||
bool EmitQuickCheck(RegExpCompiler* compiler, | ||||
Trace* trace, | ||||
bool preload_has_checked_bounds, | ||||
Label* on_possible_success, | ||||
QuickCheckDetails* details_return, | ||||
bool fall_through_on_failure); | ||||
// For a given number of characters this returns a mask and a value. The | ||||
// next n characters are anded with the mask and compared with the value. | ||||
// A comparison failure indicates the node cannot match the next n charac | ||||
ters. | ||||
// A comparison success indicates the node may match. | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start) = 0; | ||||
static const int kNodeIsTooComplexForGreedyLoops = -1; | ||||
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoo | ||||
ps; } | ||||
// Only returns the successor for a text node of length 1 that matches an | ||||
y | ||||
// character and that has no guards on it. | ||||
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( | ||||
RegExpCompiler* compiler) { | ||||
return NULL; | ||||
} | ||||
// Collects information on the possible code units (mod 128) that can mat | ||||
ch if | ||||
// we look forward. This is used for a Boyer-Moore-like string searching | ||||
// implementation. TODO(erikcorry): This should share more code with | ||||
// EatsAtLeast, GetQuickCheckDetails. The budget argument is used to lim | ||||
it | ||||
// the number of nodes we are willing to look at in order to create this | ||||
data. | ||||
static const int kFillInBMBudget = 200; | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start) { | ||||
UNREACHABLE(); | ||||
} | ||||
// If we know that the input is ASCII then there are some nodes that can | ||||
// never match. This method returns a node that can be substituted for | ||||
// itself, or NULL if the node can never match. | ||||
virtual RegExpNode* FilterASCII(int depth) { return this; } | ||||
// Helper for FilterASCII. | ||||
RegExpNode* replacement() { | ||||
ASSERT(info()->replacement_calculated); | ||||
return replacement_; | ||||
} | ||||
RegExpNode* set_replacement(RegExpNode* replacement) { | ||||
info()->replacement_calculated = true; | ||||
replacement_ = replacement; | ||||
return replacement; // For convenience. | ||||
} | ||||
// We want to avoid recalculating the lookahead info, so we store it on t | ||||
he | ||||
// node. Only info that is for this node is stored. We can tell that th | ||||
e | ||||
// info is for this node when offset == 0, so the information is calculat | ||||
ed | ||||
// relative to this node. | ||||
void SaveBMInfo(BoyerMooreLookahead* bm, bool not_at_start, int offset) { | ||||
if (offset == 0) set_bm_info(not_at_start, bm); | ||||
} | ||||
Label* label() { return &label_; } | ||||
// If non-generic code is generated for a node (i.e. the node is not at t | ||||
he | ||||
// start of the trace) then it cannot be reused. This variable sets a li | ||||
mit | ||||
// on how often we allow that to happen before we insist on starting a ne | ||||
w | ||||
// trace and generating generic code for a node that can be reused by flu | ||||
shing | ||||
// the deferred actions in the current trace and generating a goto. | ||||
static const int kMaxCopiesCodeGenerated = 10; | ||||
NodeInfo* info() { return &info_; } | ||||
BoyerMooreLookahead* bm_info(bool not_at_start) { | ||||
return bm_info_[not_at_start ? 1 : 0]; | ||||
} | ||||
Zone* zone() const { return zone_; } | ||||
protected: | ||||
enum LimitResult { DONE, CONTINUE }; | ||||
RegExpNode* replacement_; | ||||
LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace); | ||||
void set_bm_info(bool not_at_start, BoyerMooreLookahead* bm) { | ||||
bm_info_[not_at_start ? 1 : 0] = bm; | ||||
} | ||||
private: | ||||
static const int kFirstCharBudget = 10; | ||||
Label label_; | ||||
NodeInfo info_; | ||||
// This variable keeps track of how many times code has been generated fo | ||||
r | ||||
// this node (in different traces). We don't keep track of where the | ||||
// generated code is located unless the code is generated at the start of | ||||
// a trace, in which case it is generic and can be reused by flushing the | ||||
// deferred operations in the current trace and generating a goto. | ||||
int trace_count_; | ||||
BoyerMooreLookahead* bm_info_[2]; | ||||
Zone* zone_; | ||||
}; | ||||
// A simple closed interval. | ||||
class Interval { | ||||
public: | ||||
Interval() : from_(kNone), to_(kNone) { } | ||||
Interval(int from, int to) : from_(from), to_(to) { } | ||||
Interval Union(Interval that) { | ||||
if (that.from_ == kNone) | ||||
return *this; | ||||
else if (from_ == kNone) | ||||
return that; | ||||
else | ||||
return Interval(Min(from_, that.from_), Max(to_, that.to_)); | ||||
} | ||||
bool Contains(int value) { | ||||
return (from_ <= value) && (value <= to_); | ||||
} | ||||
bool is_empty() { return from_ == kNone; } | ||||
int from() const { return from_; } | ||||
int to() const { return to_; } | ||||
static Interval Empty() { return Interval(); } | ||||
static const int kNone = -1; | ||||
private: | ||||
int from_; | ||||
int to_; | ||||
}; | ||||
class SeqRegExpNode: public RegExpNode { | ||||
public: | ||||
explicit SeqRegExpNode(RegExpNode* on_success) | ||||
: RegExpNode(on_success->zone()), on_success_(on_success) { } | ||||
RegExpNode* on_success() { return on_success_; } | ||||
void set_on_success(RegExpNode* node) { on_success_ = node; } | ||||
virtual RegExpNode* FilterASCII(int depth); | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start) { | ||||
on_success_->FillInBMInfo( | ||||
offset, recursion_depth + 1, budget - 1, bm, not_at_start); | ||||
if (offset == 0) set_bm_info(not_at_start, bm); | ||||
} | ||||
protected: | ||||
RegExpNode* FilterSuccessor(int depth); | ||||
private: | ||||
RegExpNode* on_success_; | ||||
}; | ||||
class ActionNode: public SeqRegExpNode { | ||||
public: | ||||
enum Type { | ||||
SET_REGISTER, | ||||
INCREMENT_REGISTER, | ||||
STORE_POSITION, | ||||
BEGIN_SUBMATCH, | ||||
POSITIVE_SUBMATCH_SUCCESS, | ||||
EMPTY_MATCH_CHECK, | ||||
CLEAR_CAPTURES | ||||
}; | ||||
static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success); | ||||
static ActionNode* IncrementRegister(int reg, RegExpNode* on_success); | ||||
static ActionNode* StorePosition(int reg, | ||||
bool is_capture, | ||||
RegExpNode* on_success); | ||||
static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success); | ||||
static ActionNode* BeginSubmatch(int stack_pointer_reg, | ||||
int position_reg, | ||||
RegExpNode* on_success); | ||||
static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg, | ||||
int restore_reg, | ||||
int clear_capture_count, | ||||
int clear_capture_from, | ||||
RegExpNode* on_success); | ||||
static ActionNode* EmptyMatchCheck(int start_register, | ||||
int repetition_register, | ||||
int repetition_limit, | ||||
RegExpNode* on_success); | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int filled_in, | ||||
bool not_at_start) { | ||||
return on_success()->GetQuickCheckDetails( | ||||
details, compiler, filled_in, not_at_start); | ||||
} | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start); | ||||
Type type() { return type_; } | ||||
// TODO(erikcorry): We should allow some action nodes in greedy loops. | ||||
virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoo | ||||
ps; } | ||||
private: | ||||
union { | ||||
struct { | ||||
int reg; | ||||
int value; | ||||
} u_store_register; | ||||
struct { | ||||
int reg; | ||||
} u_increment_register; | ||||
struct { | ||||
int reg; | ||||
bool is_capture; | ||||
} u_position_register; | ||||
struct { | ||||
int stack_pointer_register; | ||||
int current_position_register; | ||||
int clear_register_count; | ||||
int clear_register_from; | ||||
} u_submatch; | ||||
struct { | ||||
int start_register; | ||||
int repetition_register; | ||||
int repetition_limit; | ||||
} u_empty_match_check; | ||||
struct { | ||||
int range_from; | ||||
int range_to; | ||||
} u_clear_captures; | ||||
} data_; | ||||
ActionNode(Type type, RegExpNode* on_success) | ||||
: SeqRegExpNode(on_success), | ||||
type_(type) { } | ||||
Type type_; | ||||
friend class DotPrinter; | ||||
}; | ||||
class TextNode: public SeqRegExpNode { | ||||
public: | ||||
TextNode(ZoneList<TextElement>* elms, | ||||
RegExpNode* on_success) | ||||
: SeqRegExpNode(on_success), | ||||
elms_(elms) { } | ||||
TextNode(RegExpCharacterClass* that, | ||||
RegExpNode* on_success) | ||||
: SeqRegExpNode(on_success), | ||||
elms_(new(zone()) ZoneList<TextElement>(1, zone())) { | ||||
elms_->Add(TextElement::CharClass(that), zone()); | ||||
} | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start); | ||||
ZoneList<TextElement>* elements() { return elms_; } | ||||
void MakeCaseIndependent(bool is_ascii); | ||||
virtual int GreedyLoopTextLength(); | ||||
virtual RegExpNode* GetSuccessorOfOmnivorousTextNode( | ||||
RegExpCompiler* compiler); | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start); | ||||
void CalculateOffsets(); | ||||
virtual RegExpNode* FilterASCII(int depth); | ||||
private: | ||||
enum TextEmitPassType { | ||||
NON_ASCII_MATCH, // Check for characters that can't match. | ||||
SIMPLE_CHARACTER_MATCH, // Case-dependent single character check. | ||||
NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equi | ||||
vs. | ||||
CASE_CHARACTER_MATCH, // Case-independent single character check | ||||
. | ||||
CHARACTER_CLASS_MATCH // Character class. | ||||
}; | ||||
static bool SkipPass(int pass, bool ignore_case); | ||||
static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH; | ||||
static const int kLastPass = CHARACTER_CLASS_MATCH; | ||||
void TextEmitPass(RegExpCompiler* compiler, | ||||
TextEmitPassType pass, | ||||
bool preloaded, | ||||
Trace* trace, | ||||
bool first_element_checked, | ||||
int* checked_up_to); | ||||
int Length(); | ||||
ZoneList<TextElement>* elms_; | ||||
}; | ||||
class AssertionNode: public SeqRegExpNode { | ||||
public: | ||||
enum AssertionNodeType { | ||||
AT_END, | ||||
AT_START, | ||||
AT_BOUNDARY, | ||||
AT_NON_BOUNDARY, | ||||
AFTER_NEWLINE | ||||
}; | ||||
static AssertionNode* AtEnd(RegExpNode* on_success) { | ||||
return new(on_success->zone()) AssertionNode(AT_END, on_success); | ||||
} | ||||
static AssertionNode* AtStart(RegExpNode* on_success) { | ||||
return new(on_success->zone()) AssertionNode(AT_START, on_success); | ||||
} | ||||
static AssertionNode* AtBoundary(RegExpNode* on_success) { | ||||
return new(on_success->zone()) AssertionNode(AT_BOUNDARY, on_success); | ||||
} | ||||
static AssertionNode* AtNonBoundary(RegExpNode* on_success) { | ||||
return new(on_success->zone()) AssertionNode(AT_NON_BOUNDARY, on_succes | ||||
s); | ||||
} | ||||
static AssertionNode* AfterNewline(RegExpNode* on_success) { | ||||
return new(on_success->zone()) AssertionNode(AFTER_NEWLINE, on_success) | ||||
; | ||||
} | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int filled_in, | ||||
bool not_at_start); | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start); | ||||
AssertionNodeType type() { return type_; } | ||||
void set_type(AssertionNodeType type) { type_ = type; } | ||||
private: | ||||
void EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace); | ||||
enum IfPrevious { kIsNonWord, kIsWord }; | ||||
void BacktrackIfPrevious(RegExpCompiler* compiler, | ||||
Trace* trace, | ||||
IfPrevious backtrack_if_previous); | ||||
AssertionNode(AssertionNodeType t, RegExpNode* on_success) | ||||
: SeqRegExpNode(on_success), type_(t) { } | ||||
AssertionNodeType type_; | ||||
}; | ||||
class BackReferenceNode: public SeqRegExpNode { | ||||
public: | ||||
BackReferenceNode(int start_reg, | ||||
int end_reg, | ||||
RegExpNode* on_success) | ||||
: SeqRegExpNode(on_success), | ||||
start_reg_(start_reg), | ||||
end_reg_(end_reg) { } | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
int start_register() { return start_reg_; } | ||||
int end_register() { return end_reg_; } | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start) { | ||||
return; | ||||
} | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start); | ||||
private: | ||||
int start_reg_; | ||||
int end_reg_; | ||||
}; | ||||
class EndNode: public RegExpNode { | ||||
public: | ||||
enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; | ||||
explicit EndNode(Action action, Zone* zone) | ||||
: RegExpNode(zone), action_(action) { } | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start) { return 0; } | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start) { | ||||
// Returning 0 from EatsAtLeast should ensure we never get here. | ||||
UNREACHABLE(); | ||||
} | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start) { | ||||
// Returning 0 from EatsAtLeast should ensure we never get here. | ||||
UNREACHABLE(); | ||||
} | ||||
private: | ||||
Action action_; | ||||
}; | ||||
class NegativeSubmatchSuccess: public EndNode { | ||||
public: | ||||
NegativeSubmatchSuccess(int stack_pointer_reg, | ||||
int position_reg, | ||||
int clear_capture_count, | ||||
int clear_capture_start, | ||||
Zone* zone) | ||||
: EndNode(NEGATIVE_SUBMATCH_SUCCESS, zone), | ||||
stack_pointer_register_(stack_pointer_reg), | ||||
current_position_register_(position_reg), | ||||
clear_capture_count_(clear_capture_count), | ||||
clear_capture_start_(clear_capture_start) { } | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
private: | ||||
int stack_pointer_register_; | ||||
int current_position_register_; | ||||
int clear_capture_count_; | ||||
int clear_capture_start_; | ||||
}; | ||||
class Guard: public ZoneObject { | ||||
public: | ||||
enum Relation { LT, GEQ }; | ||||
Guard(int reg, Relation op, int value) | ||||
: reg_(reg), | ||||
op_(op), | ||||
value_(value) { } | ||||
int reg() { return reg_; } | ||||
Relation op() { return op_; } | ||||
int value() { return value_; } | ||||
private: | ||||
int reg_; | ||||
Relation op_; | ||||
int value_; | ||||
}; | ||||
class GuardedAlternative { | ||||
public: | ||||
explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL | ||||
) { } | ||||
void AddGuard(Guard* guard, Zone* zone); | ||||
RegExpNode* node() { return node_; } | ||||
void set_node(RegExpNode* node) { node_ = node; } | ||||
ZoneList<Guard*>* guards() { return guards_; } | ||||
private: | ||||
RegExpNode* node_; | ||||
ZoneList<Guard*>* guards_; | ||||
}; | ||||
class AlternativeGeneration; | ||||
class ChoiceNode: public RegExpNode { | ||||
public: | ||||
explicit ChoiceNode(int expected_size, Zone* zone) | ||||
: RegExpNode(zone), | ||||
alternatives_(new(zone) | ||||
ZoneList<GuardedAlternative>(expected_size, zone)), | ||||
table_(NULL), | ||||
not_at_start_(false), | ||||
being_calculated_(false) { } | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
void AddAlternative(GuardedAlternative node) { | ||||
alternatives()->Add(node, zone()); | ||||
} | ||||
ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } | ||||
DispatchTable* GetTable(bool ignore_case); | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
int EatsAtLeastHelper(int still_to_find, | ||||
int recursion_depth, | ||||
RegExpNode* ignore_this_node, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start); | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start); | ||||
bool being_calculated() { return being_calculated_; } | ||||
bool not_at_start() { return not_at_start_; } | ||||
void set_not_at_start() { not_at_start_ = true; } | ||||
void set_being_calculated(bool b) { being_calculated_ = b; } | ||||
virtual bool try_to_emit_quick_check_for_alternative(int i) { return true | ||||
; } | ||||
virtual RegExpNode* FilterASCII(int depth); | ||||
protected: | ||||
int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative); | ||||
ZoneList<GuardedAlternative>* alternatives_; | ||||
private: | ||||
friend class DispatchTableConstructor; | ||||
friend class Analysis; | ||||
void GenerateGuard(RegExpMacroAssembler* macro_assembler, | ||||
Guard* guard, | ||||
Trace* trace); | ||||
int CalculatePreloadCharacters(RegExpCompiler* compiler, int eats_at_leas | ||||
t); | ||||
void EmitOutOfLineContinuation(RegExpCompiler* compiler, | ||||
Trace* trace, | ||||
GuardedAlternative alternative, | ||||
AlternativeGeneration* alt_gen, | ||||
int preload_characters, | ||||
bool next_expects_preload); | ||||
DispatchTable* table_; | ||||
// If true, this node is never checked at the start of the input. | ||||
// Allows a new trace to start with at_start() set to false. | ||||
bool not_at_start_; | ||||
bool being_calculated_; | ||||
}; | ||||
class NegativeLookaheadChoiceNode: public ChoiceNode { | ||||
public: | ||||
explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, | ||||
GuardedAlternative then_do_this, | ||||
Zone* zone) | ||||
: ChoiceNode(2, zone) { | ||||
AddAlternative(this_must_fail); | ||||
AddAlternative(then_do_this); | ||||
} | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start); | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start) { | ||||
alternatives_->at(1).node()->FillInBMInfo( | ||||
offset, recursion_depth + 1, budget - 1, bm, not_at_start); | ||||
if (offset == 0) set_bm_info(not_at_start, bm); | ||||
} | ||||
// For a negative lookahead we don't emit the quick check for the | ||||
// alternative that is expected to fail. This is because quick check cod | ||||
e | ||||
// starts by loading enough characters for the alternative that takes few | ||||
est | ||||
// characters, but on a negative lookahead the negative branch did not ta | ||||
ke | ||||
// part in that calculation (EatsAtLeast) so the assumptions don't hold. | ||||
virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != | ||||
0; } | ||||
virtual RegExpNode* FilterASCII(int depth); | ||||
}; | ||||
class LoopChoiceNode: public ChoiceNode { | ||||
public: | ||||
explicit LoopChoiceNode(bool body_can_be_zero_length, Zone* zone) | ||||
: ChoiceNode(2, zone), | ||||
loop_node_(NULL), | ||||
continue_node_(NULL), | ||||
body_can_be_zero_length_(body_can_be_zero_length) { } | ||||
void AddLoopAlternative(GuardedAlternative alt); | ||||
void AddContinueAlternative(GuardedAlternative alt); | ||||
virtual void Emit(RegExpCompiler* compiler, Trace* trace); | ||||
virtual int EatsAtLeast(int still_to_find, | ||||
int recursion_depth, | ||||
bool not_at_start); | ||||
virtual void GetQuickCheckDetails(QuickCheckDetails* details, | ||||
RegExpCompiler* compiler, | ||||
int characters_filled_in, | ||||
bool not_at_start); | ||||
virtual void FillInBMInfo(int offset, | ||||
int recursion_depth, | ||||
int budget, | ||||
BoyerMooreLookahead* bm, | ||||
bool not_at_start); | ||||
RegExpNode* loop_node() { return loop_node_; } | ||||
RegExpNode* continue_node() { return continue_node_; } | ||||
bool body_can_be_zero_length() { return body_can_be_zero_length_; } | ||||
virtual void Accept(NodeVisitor* visitor); | ||||
virtual RegExpNode* FilterASCII(int depth); | ||||
private: | ||||
// AddAlternative is made private for loop nodes because alternatives | ||||
// should not be added freely, we need to keep track of which node | ||||
// goes back to the node itself. | ||||
void AddAlternative(GuardedAlternative node) { | ||||
ChoiceNode::AddAlternative(node); | ||||
} | ||||
RegExpNode* loop_node_; | ||||
RegExpNode* continue_node_; | ||||
bool body_can_be_zero_length_; | ||||
}; | ||||
// Improve the speed that we scan for an initial point where a non-anchored | ||||
// regexp can match by using a Boyer-Moore-like table. This is done by | ||||
// identifying non-greedy non-capturing loops in the nodes that eat any | ||||
// character one at a time. For example in the middle of the regexp | ||||
// /foo[\s\S]*?bar/ we find such a loop. There is also such a loop implici | ||||
tly | ||||
// inserted at the start of any non-anchored regexp. | ||||
// | ||||
// When we have found such a loop we look ahead in the nodes to find the se | ||||
t of | ||||
// characters that can come at given distances. For example for the regexp | ||||
// /.?foo/ we know that there are at least 3 characters ahead of us, and th | ||||
e | ||||
// sets of characters that can occur are [any, [f, o], [o]]. We find a rang | ||||
e in | ||||
// the lookahead info where the set of characters is reasonably constrained | ||||
. In | ||||
// our example this is from index 1 to 2 (0 is not constrained). We can now | ||||
// look 3 characters ahead and if we don't find one of [f, o] (the union of | ||||
// [f, o] and [o]) then we can skip forwards by the range size (in this cas | ||||
e 2). | ||||
// | ||||
// For Unicode input strings we do the same, but modulo 128. | ||||
// | ||||
// We also look at the first string fed to the regexp and use that to get a | ||||
hint | ||||
// of the character frequencies in the inputs. This affects the assessment | ||||
of | ||||
// whether the set of characters is 'reasonably constrained'. | ||||
// | ||||
// We also have another lookahead mechanism (called quick check in the code | ||||
), | ||||
// which uses a wide load of multiple characters followed by a mask and com | ||||
pare | ||||
// to determine whether a match is possible at this point. | ||||
enum ContainedInLattice { | ||||
kNotYet = 0, | ||||
kLatticeIn = 1, | ||||
kLatticeOut = 2, | ||||
kLatticeUnknown = 3 // Can also mean both in and out. | ||||
}; | ||||
inline ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice | ||||
b) { | ||||
return static_cast<ContainedInLattice>(a | b); | ||||
} | ||||
ContainedInLattice AddRange(ContainedInLattice a, | ||||
const int* ranges, | ||||
int ranges_size, | ||||
Interval new_range); | ||||
class BoyerMoorePositionInfo : public ZoneObject { | ||||
public: | ||||
explicit BoyerMoorePositionInfo(Zone* zone) | ||||
: map_(new(zone) ZoneList<bool>(kMapSize, zone)), | ||||
map_count_(0), | ||||
w_(kNotYet), | ||||
s_(kNotYet), | ||||
d_(kNotYet), | ||||
surrogate_(kNotYet) { | ||||
for (int i = 0; i < kMapSize; i++) { | ||||
map_->Add(false, zone); | ||||
} | ||||
} | ||||
bool& at(int i) { return map_->at(i); } | ||||
static const int kMapSize = 128; | ||||
static const int kMask = kMapSize - 1; | ||||
int map_count() const { return map_count_; } | ||||
void Set(int character); | ||||
void SetInterval(const Interval& interval); | ||||
void SetAll(); | ||||
bool is_non_word() { return w_ == kLatticeOut; } | ||||
bool is_word() { return w_ == kLatticeIn; } | ||||
private: | ||||
ZoneList<bool>* map_; | ||||
int map_count_; // Number of set bits in the map. | ||||
ContainedInLattice w_; // The \w character class. | ||||
ContainedInLattice s_; // The \s character class. | ||||
ContainedInLattice d_; // The \d character class. | ||||
ContainedInLattice surrogate_; // Surrogate UTF-16 code units. | ||||
}; | ||||
class BoyerMooreLookahead : public ZoneObject { | ||||
public: | ||||
BoyerMooreLookahead(int length, RegExpCompiler* compiler, Zone* zone); | ||||
int length() { return length_; } | ||||
int max_char() { return max_char_; } | ||||
RegExpCompiler* compiler() { return compiler_; } | ||||
int Count(int map_number) { | ||||
return bitmaps_->at(map_number)->map_count(); | ||||
} | ||||
BoyerMoorePositionInfo* at(int i) { return bitmaps_->at(i); } | ||||
void Set(int map_number, int character) { | ||||
if (character > max_char_) return; | ||||
BoyerMoorePositionInfo* info = bitmaps_->at(map_number); | ||||
info->Set(character); | ||||
} | ||||
void SetInterval(int map_number, const Interval& interval) { | ||||
if (interval.from() > max_char_) return; | ||||
BoyerMoorePositionInfo* info = bitmaps_->at(map_number); | ||||
if (interval.to() > max_char_) { | ||||
info->SetInterval(Interval(interval.from(), max_char_)); | ||||
} else { | ||||
info->SetInterval(interval); | ||||
} | ||||
} | ||||
void SetAll(int map_number) { | ||||
bitmaps_->at(map_number)->SetAll(); | ||||
} | ||||
void SetRest(int from_map) { | ||||
for (int i = from_map; i < length_; i++) SetAll(i); | ||||
} | ||||
bool EmitSkipInstructions(RegExpMacroAssembler* masm); | ||||
private: | ||||
// This is the value obtained by EatsAtLeast. If we do not have at least | ||||
this | ||||
// many characters left in the sample string then the match is bound to f | ||||
ail. | ||||
// Therefore it is OK to read a character this far ahead of the current m | ||||
atch | ||||
// point. | ||||
int length_; | ||||
RegExpCompiler* compiler_; | ||||
// 0x7f for ASCII, 0xffff for UTF-16. | ||||
int max_char_; | ||||
ZoneList<BoyerMoorePositionInfo*>* bitmaps_; | ||||
int GetSkipTable(int min_lookahead, | ||||
int max_lookahead, | ||||
Handle<ByteArray> boolean_skip_table); | ||||
bool FindWorthwhileInterval(int* from, int* to); | ||||
int FindBestInterval( | ||||
int max_number_of_chars, int old_biggest_points, int* from, int* to); | ||||
}; | ||||
// There are many ways to generate code for a node. This class encapsulate | ||||
s | ||||
// the current way we should be generating. In other words it encapsulates | ||||
// the current state of the code generator. The effect of this is that we | ||||
// generate code for paths that the matcher can take through the regular | ||||
// expression. A given node in the regexp can be code-generated several ti | ||||
mes | ||||
// as it can be part of several traces. For example for the regexp: | ||||
// /foo(bar|ip)baz/ the code to match baz will be generated twice, once as | ||||
part | ||||
// of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The | ||||
code | ||||
// to match foo is generated only once (the traces have a common prefix). | ||||
The | ||||
// code to store the capture is deferred and generated (twice) after the pl | ||||
aces | ||||
// where baz has been matched. | ||||
class Trace { | ||||
public: | ||||
// A value for a property that is either known to be true, know to be fal | ||||
se, | ||||
// or not known. | ||||
enum TriBool { | ||||
UNKNOWN = -1, FALSE = 0, TRUE = 1 | ||||
}; | ||||
class DeferredAction { | ||||
public: | ||||
DeferredAction(ActionNode::Type type, int reg) | ||||
: type_(type), reg_(reg), next_(NULL) { } | ||||
DeferredAction* next() { return next_; } | ||||
bool Mentions(int reg); | ||||
int reg() { return reg_; } | ||||
ActionNode::Type type() { return type_; } | ||||
private: | ||||
ActionNode::Type type_; | ||||
int reg_; | ||||
DeferredAction* next_; | ||||
friend class Trace; | ||||
}; | ||||
class DeferredCapture : public DeferredAction { | ||||
public: | ||||
DeferredCapture(int reg, bool is_capture, Trace* trace) | ||||
: DeferredAction(ActionNode::STORE_POSITION, reg), | ||||
cp_offset_(trace->cp_offset()), | ||||
is_capture_(is_capture) { } | ||||
int cp_offset() { return cp_offset_; } | ||||
bool is_capture() { return is_capture_; } | ||||
private: | ||||
int cp_offset_; | ||||
bool is_capture_; | ||||
void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; } | ||||
}; | ||||
class DeferredSetRegister : public DeferredAction { | ||||
public: | ||||
DeferredSetRegister(int reg, int value) | ||||
: DeferredAction(ActionNode::SET_REGISTER, reg), | ||||
value_(value) { } | ||||
int value() { return value_; } | ||||
private: | ||||
int value_; | ||||
}; | ||||
class DeferredClearCaptures : public DeferredAction { | ||||
public: | ||||
explicit DeferredClearCaptures(Interval range) | ||||
: DeferredAction(ActionNode::CLEAR_CAPTURES, -1), | ||||
range_(range) { } | ||||
Interval range() { return range_; } | ||||
private: | ||||
Interval range_; | ||||
}; | ||||
class DeferredIncrementRegister : public DeferredAction { | ||||
public: | ||||
explicit DeferredIncrementRegister(int reg) | ||||
: DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } | ||||
}; | ||||
Trace() | ||||
: cp_offset_(0), | ||||
actions_(NULL), | ||||
backtrack_(NULL), | ||||
stop_node_(NULL), | ||||
loop_label_(NULL), | ||||
characters_preloaded_(0), | ||||
bound_checked_up_to_(0), | ||||
flush_budget_(100), | ||||
at_start_(UNKNOWN) { } | ||||
// End the trace. This involves flushing the deferred actions in the tra | ||||
ce | ||||
// and pushing a backtrack location onto the backtrack stack. Once this | ||||
is | ||||
// done we can start a new trace or go to one that has already been | ||||
// generated. | ||||
void Flush(RegExpCompiler* compiler, RegExpNode* successor); | ||||
int cp_offset() { return cp_offset_; } | ||||
DeferredAction* actions() { return actions_; } | ||||
// A trivial trace is one that has no deferred actions or other state tha | ||||
t | ||||
// affects the assumptions used when generating code. There is no record | ||||
ed | ||||
// backtrack location in a trivial trace, so with a trivial trace we will | ||||
// generate code that, on a failure to match, gets the backtrack location | ||||
// from the backtrack stack rather than using a direct jump instruction. | ||||
We | ||||
// always start code generation with a trivial trace and non-trivial trac | ||||
es | ||||
// are created as we emit code for nodes or add to the list of deferred | ||||
// actions in the trace. The location of the code generated for a node u | ||||
sing | ||||
// a trivial trace is recorded in a label in the node so that gotos can b | ||||
e | ||||
// generated to that code. | ||||
bool is_trivial() { | ||||
return backtrack_ == NULL && | ||||
actions_ == NULL && | ||||
cp_offset_ == 0 && | ||||
characters_preloaded_ == 0 && | ||||
bound_checked_up_to_ == 0 && | ||||
quick_check_performed_.characters() == 0 && | ||||
at_start_ == UNKNOWN; | ||||
} | ||||
TriBool at_start() { return at_start_; } | ||||
void set_at_start(bool at_start) { at_start_ = at_start ? TRUE : FALSE; } | ||||
Label* backtrack() { return backtrack_; } | ||||
Label* loop_label() { return loop_label_; } | ||||
RegExpNode* stop_node() { return stop_node_; } | ||||
int characters_preloaded() { return characters_preloaded_; } | ||||
int bound_checked_up_to() { return bound_checked_up_to_; } | ||||
int flush_budget() { return flush_budget_; } | ||||
QuickCheckDetails* quick_check_performed() { return &quick_check_performe | ||||
d_; } | ||||
bool mentions_reg(int reg); | ||||
// Returns true if a deferred position store exists to the specified | ||||
// register and stores the offset in the out-parameter. Otherwise | ||||
// returns false. | ||||
bool GetStoredPosition(int reg, int* cp_offset); | ||||
// These set methods and AdvanceCurrentPositionInTrace should be used onl | ||||
y on | ||||
// new traces - the intention is that traces are immutable after creation | ||||
. | ||||
void add_action(DeferredAction* new_action) { | ||||
ASSERT(new_action->next_ == NULL); | ||||
new_action->next_ = actions_; | ||||
actions_ = new_action; | ||||
} | ||||
void set_backtrack(Label* backtrack) { backtrack_ = backtrack; } | ||||
void set_stop_node(RegExpNode* node) { stop_node_ = node; } | ||||
void set_loop_label(Label* label) { loop_label_ = label; } | ||||
void set_characters_preloaded(int count) { characters_preloaded_ = count; | ||||
} | ||||
void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } | ||||
void set_flush_budget(int to) { flush_budget_ = to; } | ||||
void set_quick_check_performed(QuickCheckDetails* d) { | ||||
quick_check_performed_ = *d; | ||||
} | ||||
void InvalidateCurrentCharacter(); | ||||
void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler); | ||||
private: | ||||
int FindAffectedRegisters(OutSet* affected_registers, Zone* zone); | ||||
void PerformDeferredActions(RegExpMacroAssembler* macro, | ||||
int max_register, | ||||
OutSet& affected_registers, | ||||
OutSet* registers_to_pop, | ||||
OutSet* registers_to_clear, | ||||
Zone* zone); | ||||
void RestoreAffectedRegisters(RegExpMacroAssembler* macro, | ||||
int max_register, | ||||
OutSet& registers_to_pop, | ||||
OutSet& registers_to_clear); | ||||
int cp_offset_; | ||||
DeferredAction* actions_; | ||||
Label* backtrack_; | ||||
RegExpNode* stop_node_; | ||||
Label* loop_label_; | ||||
int characters_preloaded_; | ||||
int bound_checked_up_to_; | ||||
QuickCheckDetails quick_check_performed_; | ||||
int flush_budget_; | ||||
TriBool at_start_; | ||||
}; | ||||
class NodeVisitor { | ||||
public: | ||||
virtual ~NodeVisitor() { } | ||||
#define DECLARE_VISIT(Type) \ | ||||
virtual void Visit##Type(Type##Node* that) = 0; | ||||
FOR_EACH_NODE_TYPE(DECLARE_VISIT) | ||||
#undef DECLARE_VISIT | ||||
virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } | ||||
}; | ||||
// Node visitor used to add the start set of the alternatives to the | ||||
// dispatch table of a choice node. | ||||
class DispatchTableConstructor: public NodeVisitor { | ||||
public: | ||||
DispatchTableConstructor(DispatchTable* table, bool ignore_case, | ||||
Zone* zone) | ||||
: table_(table), | ||||
choice_index_(-1), | ||||
ignore_case_(ignore_case), | ||||
zone_(zone) { } | ||||
void BuildTable(ChoiceNode* node); | ||||
void AddRange(CharacterRange range) { | ||||
table()->AddRange(range, choice_index_, zone_); | ||||
} | ||||
void AddInverse(ZoneList<CharacterRange>* ranges); | ||||
#define DECLARE_VISIT(Type) \ | ||||
virtual void Visit##Type(Type##Node* that); | ||||
FOR_EACH_NODE_TYPE(DECLARE_VISIT) | ||||
#undef DECLARE_VISIT | ||||
DispatchTable* table() { return table_; } | ||||
void set_choice_index(int value) { choice_index_ = value; } | ||||
protected: | ||||
DispatchTable* table_; | ||||
int choice_index_; | ||||
bool ignore_case_; | ||||
Zone* zone_; | ||||
}; | ||||
// Assertion propagation moves information about assertions such as | ||||
// \b to the affected nodes. For instance, in /.\b./ information must | ||||
// be propagated to the first '.' that whatever follows needs to know | ||||
// if it matched a word or a non-word, and to the second '.' that it | ||||
// has to check if it succeeds a word or non-word. In this case the | ||||
// result will be something like: | ||||
// | ||||
// +-------+ +------------+ | ||||
// | . | | . | | ||||
// +-------+ ---> +------------+ | ||||
// | word? | | check word | | ||||
// +-------+ +------------+ | ||||
class Analysis: public NodeVisitor { | ||||
public: | ||||
Analysis(bool ignore_case, bool is_ascii) | ||||
: ignore_case_(ignore_case), | ||||
is_ascii_(is_ascii), | ||||
error_message_(NULL) { } | ||||
void EnsureAnalyzed(RegExpNode* node); | ||||
#define DECLARE_VISIT(Type) \ | ||||
virtual void Visit##Type(Type##Node* that); | ||||
FOR_EACH_NODE_TYPE(DECLARE_VISIT) | ||||
#undef DECLARE_VISIT | ||||
virtual void VisitLoopChoice(LoopChoiceNode* that); | ||||
bool has_failed() { return error_message_ != NULL; } | ||||
const char* error_message() { | ||||
ASSERT(error_message_ != NULL); | ||||
return error_message_; | ||||
} | ||||
void fail(const char* error_message) { | ||||
error_message_ = error_message; | ||||
} | ||||
private: | ||||
bool ignore_case_; | ||||
bool is_ascii_; | ||||
const char* error_message_; | ||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis); | ||||
}; | ||||
struct RegExpCompileData { | ||||
RegExpCompileData() | ||||
: tree(NULL), | ||||
node(NULL), | ||||
simple(true), | ||||
contains_anchor(false), | ||||
capture_count(0) { } | ||||
RegExpTree* tree; | ||||
RegExpNode* node; | ||||
bool simple; | ||||
bool contains_anchor; | ||||
Handle<String> error; | ||||
int capture_count; | ||||
}; | ||||
class RegExpEngine: public AllStatic { | ||||
public: | ||||
struct CompilationResult { | ||||
explicit CompilationResult(const char* error_message) | ||||
: error_message(error_message), | ||||
code(HEAP->the_hole_value()), | ||||
num_registers(0) {} | ||||
CompilationResult(Object* code, int registers) | ||||
: error_message(NULL), | ||||
code(code), | ||||
num_registers(registers) {} | ||||
const char* error_message; | ||||
Object* code; | ||||
int num_registers; | ||||
}; | ||||
static CompilationResult Compile(RegExpCompileData* input, | ||||
bool ignore_case, | ||||
bool global, | ||||
bool multiline, | ||||
Handle<String> pattern, | ||||
Handle<String> sample_subject, | ||||
bool is_ascii, Zone* zone); | ||||
static void DotPrint(const char* label, RegExpNode* node, bool ignore_cas | ||||
e); | ||||
}; | ||||
class OffsetsVector { | ||||
public: | ||||
inline OffsetsVector(int num_registers, Isolate* isolate) | ||||
: offsets_vector_length_(num_registers) { | ||||
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) | ||||
{ | ||||
vector_ = NewArray<int>(offsets_vector_length_); | ||||
} else { | ||||
vector_ = isolate->jsregexp_static_offsets_vector(); | ||||
} | ||||
} | ||||
inline ~OffsetsVector() { | ||||
if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) | ||||
{ | ||||
DeleteArray(vector_); | ||||
vector_ = NULL; | ||||
} | ||||
} | ||||
inline int* vector() { return vector_; } | ||||
inline int length() { return offsets_vector_length_; } | ||||
static const int kStaticOffsetsVectorSize = | ||||
Isolate::kJSRegexpStaticOffsetsVectorSize; | ||||
private: | ||||
static Address static_offsets_vector_address(Isolate* isolate) { | ||||
return reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vecto | ||||
r()); | ||||
} | ||||
int* vector_; | ||||
int offsets_vector_length_; | ||||
friend class ExternalReference; | struct JSRegExpStatics { | |||
}; | JSString *input; /* input string to match (perl $_, GC root) | |||
*/ | ||||
JSBool multiline; /* whether input contains newlines (perl $* | ||||
) */ | ||||
uint16 parenCount; /* number of valid elements in parens[] */ | ||||
uint16 moreLength; /* number of allocated elements in morePare | ||||
ns */ | ||||
JSSubString parens[9]; /* last set of parens matched (perl $1, $2) | ||||
*/ | ||||
JSSubString *moreParens; /* null or realloc'd vector for $10, etc. * | ||||
/ | ||||
JSSubString lastMatch; /* last string matched (perl $&) */ | ||||
JSSubString lastParen; /* last paren matched (perl $+) */ | ||||
JSSubString leftContext; /* input to left of last match (perl $`) */ | ||||
JSSubString rightContext; /* input to right of last match (perl $') * | ||||
/ | ||||
}; | ||||
/* | ||||
* This struct holds a bitmap representation of a class from a regexp. | ||||
* There's a list of these referenced by the classList field in the JSRegEx | ||||
p | ||||
* struct below. The initial state has startIndex set to the offset in the | ||||
* original regexp source of the beginning of the class contents. The first | ||||
* use of the class converts the source representation into a bitmap. | ||||
* | ||||
*/ | ||||
typedef struct RECharSet { | ||||
JSPackedBool converted; | ||||
JSPackedBool sense; | ||||
uint16 length; | ||||
union { | ||||
uint8 *bits; | ||||
struct { | ||||
size_t startIndex; | ||||
size_t length; | ||||
} src; | ||||
} u; | ||||
} RECharSet; | ||||
/* | ||||
* This macro is safe because moreParens is guaranteed to be allocated and | ||||
big | ||||
* enough to hold parenCount, or else be null when parenCount is 0. | ||||
*/ | ||||
#define REGEXP_PAREN_SUBSTRING(res, num) | ||||
\ | ||||
(((jsuint)(num) < (jsuint)(res)->parenCount) | ||||
\ | ||||
? ((jsuint)(num) < 9) | ||||
\ | ||||
? &(res)->parens[num] | ||||
\ | ||||
: &(res)->moreParens[(num) - 9] | ||||
\ | ||||
: &js_EmptySubString) | ||||
typedef struct RENode RENode; | ||||
struct JSRegExp { | ||||
jsrefcount nrefs; /* reference count */ | ||||
uint16 flags; /* flags, see jsapi.h's JSREG_* defines */ | ||||
uint16 cloneIndex; /* index in fp->vars or funobj->slots of | ||||
cloned regexp object */ | ||||
size_t parenCount; /* number of parenthesized submatches */ | ||||
size_t classCount; /* count [...] bitmaps */ | ||||
RECharSet *classList; /* list of [...] bitmaps */ | ||||
JSString *source; /* locked source string, sans // */ | ||||
jsbytecode program[1]; /* regular expression bytecode */ | ||||
}; | ||||
extern JSRegExp * | ||||
js_NewRegExp(JSContext *cx, JSTokenStream *ts, | ||||
JSString *str, uintN flags, JSBool flat); | ||||
extern JSRegExp * | ||||
js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, | ||||
JSString *str, JSString *opt, JSBool flat); | ||||
#define HOLD_REGEXP(cx, re) JS_ATOMIC_INCREMENT(&(re)->nrefs) | ||||
#define DROP_REGEXP(cx, re) js_DestroyRegExp(cx, re) | ||||
extern void | ||||
js_DestroyRegExp(JSContext *cx, JSRegExp *re); | ||||
/* | ||||
* Execute re on input str at *indexp, returning null in *rval on mismatch. | ||||
* On match, return true if test is true, otherwise return an array object. | ||||
* Update *indexp and cx->regExpStatics always on match. | ||||
*/ | ||||
extern JSBool | ||||
js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp | ||||
, | ||||
JSBool test, jsval *rval); | ||||
/* | ||||
* These two add and remove GC roots, respectively, so their calls must be | ||||
* well-ordered. | ||||
*/ | ||||
extern JSBool | ||||
js_InitRegExpStatics(JSContext *cx, JSRegExpStatics *res); | ||||
extern void | ||||
js_FreeRegExpStatics(JSContext *cx, JSRegExpStatics *res); | ||||
#define JSVAL_IS_REGEXP(cx, v) | ||||
\ | ||||
(JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) && | ||||
\ | ||||
OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_RegExpClass) | ||||
extern JSClass js_RegExpClass; | ||||
extern JSObject * | ||||
js_InitRegExpClass(JSContext *cx, JSObject *obj); | ||||
/* | ||||
* Export js_regexp_toString to the decompiler. | ||||
*/ | ||||
extern JSBool | ||||
js_regexp_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, | ||||
jsval *rval); | ||||
/* | ||||
* Create, serialize/deserialize, or clone a RegExp object. | ||||
*/ | ||||
extern JSObject * | ||||
js_NewRegExpObject(JSContext *cx, JSTokenStream *ts, | ||||
jschar *chars, size_t length, uintN flags); | ||||
extern JSBool | ||||
js_XDRRegExp(JSXDRState *xdr, JSObject **objp); | ||||
extern JSObject * | ||||
js_CloneRegExpObject(JSContext *cx, JSObject *obj, JSObject *parent); | ||||
/* | ||||
* Get and set the per-object (clone or clone-parent) lastIndex slot. | ||||
*/ | ||||
extern JSBool | ||||
js_GetLastIndex(JSContext *cx, JSObject *obj, jsdouble *lastIndex); | ||||
} } // namespace v8::internal | extern JSBool | |||
js_SetLastIndex(JSContext *cx, JSObject *obj, jsdouble lastIndex); | ||||
#endif // V8_JSREGEXP_H_ | #endif /* jsregexp_h___ */ | |||
End of changes. 5 change blocks. | ||||
1694 lines changed or deleted | 203 lines changed or added | |||
keypattern.h | keypattern.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/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/platform/unordered_set.h" | ||||
#include "mongo/util/mongoutils/str.h" | #include "mongo/util/mongoutils/str.h" | |||
namespace mongo { | namespace mongo { | |||
struct FieldInterval; | struct FieldInterval; | |||
class FieldRangeSet; | class FieldRangeSet; | |||
/** | /** | |||
* 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 | |||
skipping to change at line 50 | skipping to change at line 51 | |||
* document key. Document keys are used to store documents in indices and to target | * document key. Document keys are used to store documents in indices and to target | |||
* sharded queries. | * sharded queries. | |||
* | * | |||
* Examples: | * Examples: | |||
* { a : 1 } | * { a : 1 } | |||
* { a : 1 , b : -1 } | * { a : 1 , b : -1 } | |||
* { a : "hashed" } | * { a : "hashed" } | |||
*/ | */ | |||
class KeyPattern { | class KeyPattern { | |||
public: | public: | |||
KeyPattern( const BSONObj& pattern ): _pattern( pattern ) {} | /* | |||
* We are allowing implicit conversion from BSON | ||||
*/ | ||||
KeyPattern( const BSONObj& pattern ); | ||||
/* | /* | |||
* Returns a BSON representation of this KeyPattern. | * Returns a BSON representation of this KeyPattern. | |||
*/ | */ | |||
BSONObj toBSON() const { return _pattern; } | BSONObj toBSON() const { return _pattern; } | |||
/* | /* | |||
* Returns true if the given fieldname is the name of one element o | * Returns true if the given fieldname is the (dotted prefix of the | |||
f the (potentially) | ) name of one | |||
* compound key described by this KeyPattern. | * element of the (potentially) compound key described by this KeyP | |||
attern. | ||||
*/ | */ | |||
bool hasField( const StringData& fieldname ) const { return _patter | bool hasField( const StringData& fieldname ) const { | |||
n.hasField( fieldname ); } | return _prefixes.find( fieldname ) != _prefixes.end(); | |||
} | ||||
/* | /* | |||
* Gets the element of this pattern corresponding to the given fiel dname. | * Gets the element of this pattern corresponding to the given fiel dname. | |||
* Returns eoo if none exists. | * Returns eoo if none exists. | |||
*/ | */ | |||
BSONElement getField( const char* fieldname ) const { return _patte rn[ fieldname ]; } | BSONElement getField( const char* fieldname ) const { return _patte rn[ fieldname ]; } | |||
/* | /* | |||
* Returns true if the key described by this KeyPattern is a prefix of | * Returns true if the key described by this KeyPattern is a prefix of | |||
* the (potentially) compound key described by 'other' | * the (potentially) compound key described by 'other' | |||
skipping to change at line 162 | skipping to change at line 168 | |||
* | * | |||
* The queryConstraints should be defined for all the fields in thi s keypattern | * The queryConstraints should be defined for all the fields in thi s keypattern | |||
* (i.e. the value of frsp->matchPossibleForSingleKeyFRS(_pattern) should be true, | * (i.e. the value of frsp->matchPossibleForSingleKeyFRS(_pattern) should be true, | |||
* otherwise this function could throw). | * otherwise this function could throw). | |||
* | * | |||
*/ | */ | |||
BoundList keyBounds( const FieldRangeSet& queryConstraints ) const; | BoundList keyBounds( const FieldRangeSet& queryConstraints ) const; | |||
private: | private: | |||
BSONObj _pattern; | BSONObj _pattern; | |||
// Each field in the '_pattern' may be itself a dotted field. We st | ||||
ore all the prefixes | ||||
// of each field here. For instance, if a pattern is { 'a.b.c': 1, | ||||
x: 1 }, we'll store | ||||
// here 'a', 'a.b', 'a.b.c', and 'x'. | ||||
// | ||||
// Since we're indexing into '_pattern's field names, it must stay | ||||
constant after | ||||
// constructed. | ||||
struct PrefixHasher { | ||||
size_t operator()( const StringData& strData ) const { | ||||
size_t result = 0; | ||||
const char* p = strData.rawData(); | ||||
for (size_t len = strData.size(); len > 0; len-- ) { | ||||
result = ( result * 131 ) + *p++; | ||||
} | ||||
return result; | ||||
} | ||||
}; | ||||
unordered_set<StringData, PrefixHasher> _prefixes; | ||||
bool isAscending( const BSONElement& fieldExpression ) const { | bool isAscending( const BSONElement& fieldExpression ) const { | |||
return ( fieldExpression.isNumber() && fieldExpression.numberI nt() == 1 ); | return ( fieldExpression.isNumber() && fieldExpression.numberI nt() == 1 ); | |||
} | } | |||
bool isDescending( const BSONElement& fieldExpression ) const { | bool isDescending( const BSONElement& fieldExpression ) const { | |||
return ( fieldExpression.isNumber() && fieldExpression.numberI nt() == -1 ); | return ( fieldExpression.isNumber() && fieldExpression.numberI nt() == -1 ); | |||
} | } | |||
bool isHashed( const BSONElement& fieldExpression ) const { | bool isHashed( const BSONElement& fieldExpression ) const { | |||
return mongoutils::str::equals( fieldExpression.valuestrsafe() , "hashed" ); | return mongoutils::str::equals( fieldExpression.valuestrsafe() , "hashed" ); | |||
} | } | |||
/* Takes a list of intervals corresponding to constraints on a give n field | /* Takes a list of intervals corresponding to constraints on a give n field | |||
* in this keypattern, and transforms them into a list of bounds | * in this keypattern, and transforms them into a list of bounds | |||
* based on the expression for 'field' | * based on the expression for 'field' | |||
*/ | */ | |||
BoundList _transformFieldBounds( const vector<FieldInterval>& oldIn tervals , | BoundList _transformFieldBounds( const vector<FieldInterval>& oldIn tervals , | |||
const BSONElement& field ) const; | const BSONElement& field ) const; | |||
End of changes. 7 change blocks. | ||||
6 lines changed or deleted | 36 lines changed or added | |||
log.h | log.h | |||
---|---|---|---|---|
skipping to change at line 42 | skipping to change at line 42 | |||
#include "mongo/util/exit_code.h" | #include "mongo/util/exit_code.h" | |||
#ifndef _WIN32 | #ifndef _WIN32 | |||
#include <syslog.h> | #include <syslog.h> | |||
#endif | #endif | |||
namespace mongo { | namespace mongo { | |||
enum ExitCode; | enum ExitCode; | |||
enum LogLevel { LL_DEBUG , LL_INFO , LL_NOTICE , LL_WARNING , LL_ERROR | // using negative numbers so these are always less than ::mongo::loglev | |||
, LL_SEVERE }; | el (see MONGO_LOG) | |||
enum LogLevel { LL_DEBUG=-1000 , LL_INFO , LL_NOTICE , LL_WARNING , LL | ||||
_ERROR , LL_SEVERE }; | ||||
inline const char * logLevelToString( LogLevel l ) { | inline const char * logLevelToString( LogLevel l ) { | |||
switch ( l ) { | switch ( l ) { | |||
case LL_DEBUG: | case LL_DEBUG: | |||
case LL_INFO: | case LL_INFO: | |||
case LL_NOTICE: | case LL_NOTICE: | |||
return ""; | return ""; | |||
case LL_WARNING: | case LL_WARNING: | |||
return "warning" ; | return "warning" ; | |||
case LL_ERROR: | case LL_ERROR: | |||
skipping to change at line 353 | skipping to change at line 354 | |||
void indentInc(){ indent++; } | void indentInc(){ indent++; } | |||
void indentDec(){ indent--; } | void indentDec(){ indent--; } | |||
int getIndent() const { return indent; } | int getIndent() const { return indent; } | |||
// Replace any pre-existing function for appending context informat ion to log lines with | // Replace any pre-existing function for appending context informat ion to log lines with | |||
// "contextFn". Returns Status::OK on first call, and ErrorCodes:: AlreadyInitialized if | // "contextFn". Returns Status::OK on first call, and ErrorCodes:: AlreadyInitialized if | |||
// called more than once. Returns ErrorCodes::BadValue if contextF n is NULL. | // called more than once. Returns ErrorCodes::BadValue if contextF n is NULL. | |||
static Status registerExtraLogContextFn(ExtraLogContextFn contextFn ); | static Status registerExtraLogContextFn(ExtraLogContextFn contextFn ); | |||
private: | private: | |||
static boost::thread_specific_ptr<Logstream> tsp; | ||||
Logstream() { | Logstream() { | |||
indent = 0; | indent = 0; | |||
_init(); | _init(); | |||
} | } | |||
void _init() { | void _init() { | |||
ss.str(""); | ss.str(""); | |||
logLevel = LL_INFO; | logLevel = LL_INFO; | |||
} | } | |||
public: | public: | |||
skipping to change at line 401 | skipping to change at line 401 | |||
set tlogLevel to -1 to suppress tlog() output in a test program. */ | set tlogLevel to -1 to suppress tlog() output in a test program. */ | |||
Nullstream& tlog( int level = 0 ); | Nullstream& tlog( int level = 0 ); | |||
// log if debug build or if at a certain level | // log if debug build or if at a certain level | |||
inline Nullstream& dlog( int level ) { | inline Nullstream& dlog( int level ) { | |||
if ( level <= logLevel || DEBUG_BUILD ) | if ( level <= logLevel || DEBUG_BUILD ) | |||
return Logstream::get().prolog(); | return Logstream::get().prolog(); | |||
return nullstream; | return nullstream; | |||
} | } | |||
#define MONGO_LOG(requiredLevel) \ | #define MONGO_LOG(level) \ | |||
( MONGO_likely( ::mongo::logLevel < (requiredLevel) ) ) \ | ( MONGO_likely( ::mongo::logLevel < (level) ) ) \ | |||
? ::mongo::log() : ::mongo::log() | ? ::mongo::nullstream : ::mongo::logWithLevel(level) | |||
#define LOG MONGO_LOG | #define LOG MONGO_LOG | |||
inline Nullstream& log() { | inline Nullstream& log() { | |||
return Logstream::get().prolog(); | return Logstream::get().prolog(); | |||
} | } | |||
// Use MONGO_LOG() instead of this | ||||
inline Nullstream& logWithLevel( int level ) { | ||||
if ( level > logLevel ) | ||||
return nullstream; | ||||
return Logstream::get().prolog(); | ||||
} | ||||
inline Nullstream& logWithLevel( LogLevel l ) { | ||||
return Logstream::get().prolog().setLogLevel( l ); | ||||
} | ||||
inline Nullstream& logWithLevel( const LabeledLevel& ll ) { | ||||
Nullstream& stream = logWithLevel( ll.getLevel() ); | ||||
if( ll.getLabel() != "" ) | ||||
stream << "[" << ll.getLabel() << "] "; | ||||
return stream; | ||||
} | ||||
inline Nullstream& error() { | inline Nullstream& error() { | |||
return MONGO_LOG( LL_ERROR ); | return logWithLevel( LL_ERROR ); | |||
} | } | |||
inline Nullstream& warning() { | inline Nullstream& warning() { | |||
return MONGO_LOG( LL_WARNING ); | return logWithLevel( LL_WARNING ); | |||
} | } | |||
/* default impl returns "" -- mongod overrides */ | /* default impl returns "" -- mongod overrides */ | |||
extern const char * (*getcurns)(); | extern const char * (*getcurns)(); | |||
inline Nullstream& problem( int level = 0 ) { | inline Nullstream& problem( int level = 0 ) { | |||
if ( level > logLevel ) | if ( level > logLevel ) | |||
return nullstream; | return nullstream; | |||
Logstream& l = Logstream::get().prolog(); | Logstream& l = Logstream::get().prolog(); | |||
l << ' ' << getcurns() << ' '; | l << ' ' << getcurns() << ' '; | |||
End of changes. 6 change blocks. | ||||
8 lines changed or deleted | 27 lines changed or added | |||
macros.h | macros.h | |||
---|---|---|---|---|
skipping to change at line 13 | skipping to change at line 13 | |||
// Various Google-specific macros. | // Various Google-specific macros. | |||
// | // | |||
// This code is compiled directly on many platforms, including client | // This code is compiled directly on many platforms, including client | |||
// platforms like Windows, Mac, and embedded systems. Before making | // platforms like Windows, Mac, and embedded systems. Before making | |||
// any changes here, make sure that you're not breaking any platforms. | // any changes here, make sure that you're not breaking any platforms. | |||
// | // | |||
#ifndef BASE_MACROS_H_ | #ifndef BASE_MACROS_H_ | |||
#define BASE_MACROS_H_ | #define BASE_MACROS_H_ | |||
#include "base/definer.h" // For OS_WINDOWS | ||||
#include <stddef.h> // For size_t | #include <stddef.h> // For size_t | |||
// We use our own local version of type traits while we're waiting | // We use our own local version of type traits while we're waiting | |||
// for TR1 type traits to be standardized. Define some macros so that | // for TR1 type traits to be standardized. Define some macros so that | |||
// most google3 code doesn't have to work with type traits directly. | // most google3 code doesn't have to work with type traits directly. | |||
#include "type_traits.h" | #include "type_traits.h" | |||
// The swigged version of an abstract class must be concrete if any methods | // The swigged version of an abstract class must be concrete if any methods | |||
// return objects of the abstract type. We keep it abstract in C++ and | // return objects of the abstract type. We keep it abstract in C++ and | |||
// concrete for swig. | // concrete for swig. | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 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 "mongo/db/geo/geoparser.h" | #include "mongo/db/geo/geoquery.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 { | |||
skipping to change at line 53 | skipping to change at line 53 | |||
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 { | struct GeoMatcher { | |||
private: | ||||
GeoMatcher(const string& field, bool isNot) : _isBox(false), _isCir | ||||
cle(false), | ||||
_isPolygon(false), _f | ||||
ieldName(field), | ||||
_isNot(isNot) {} | ||||
bool _isBox; | ||||
Box _box; | ||||
bool _isCircle; | ||||
Point _center; | ||||
double _radius; | ||||
bool _isPolygon; | ||||
Polygon _polygon; | ||||
string _fieldName; | ||||
bool _isNot; | ||||
public: | public: | |||
const string& getFieldName() const { return _fieldName; } | GeoMatcher(GeoQuery query, bool negated) : geoQuery(query), isNot(n | |||
egated) {} | ||||
static GeoMatcher makeBoxMatcher(const string& field, const BSONObj | ||||
&obj, bool isNot) { | ||||
GeoMatcher m(field, isNot); | ||||
m._isBox = true; | ||||
GeoParser::parseLegacyBox(obj, &m._box); | ||||
return m; | ||||
} | ||||
static GeoMatcher makeCircleMatcher(const string& field, const BSON | ||||
Obj &obj, bool isNot) { | ||||
GeoMatcher m(field, isNot); | ||||
m._isCircle = true; | ||||
GeoParser::parseLegacyCenter(obj, &m._center, &m._radius); | ||||
return m; | ||||
} | ||||
static GeoMatcher makePolygonMatcher(const string& field, const BSO | string getField() const { return geoQuery.getField(); } | |||
NObj &obj, bool isNot) { | ||||
GeoMatcher m(field, isNot); | ||||
m._isPolygon = true; | ||||
GeoParser::parseLegacyPolygon(obj, &m._polygon); | ||||
return m; | ||||
} | ||||
bool containsPoint(Point p) const { | ||||
bool ret; | ||||
if (_isBox) { | ||||
ret = _box.inside(p, 0); | ||||
} else if (_isCircle) { | ||||
ret = distance(p, _center) <= _radius; | ||||
} else if (_isPolygon) { | ||||
ret = _polygon.contains(p); | ||||
} else { | ||||
ret = false; | ||||
} | ||||
return _isNot ? !ret : ret; | ||||
} | ||||
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) { | bool matches(const GeometryContainer &container) const { | |||
if (!GeoParser::isLegacyPoint(o)) { return false; } | bool satisfied = geoQuery.satisfiesPredicate(container); | |||
GeoParser::parseLegacyPoint(o, p); | if (isNot) { return !satisfied; } | |||
return true; | else { return satisfied; } | |||
} | } | |||
GeoQuery geoQuery; | ||||
bool isNot; | ||||
}; | }; | |||
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 224 | skipping to change at line 165 | |||
bool _elemMatchKeyRequested; | bool _elemMatchKeyRequested; | |||
bool _elemMatchKeyFound; | bool _elemMatchKeyFound; | |||
string _elemMatchKey; | string _elemMatchKey; | |||
}; | }; | |||
/* Match BSON objects against a query pattern. | /* Match BSON objects against a query pattern. | |||
e.g. | e.g. | |||
db.foo.find( { a : 3 } ); | db.foo.find( { a : 3 } ); | |||
{ a : 3 } is the pattern object. See wiki documentation for full in fo. | { a : 3 } is the pattern object. See manual for full info. | |||
GT/LT: | GT/LT: | |||
{ a : { $gt : 3 } } | { a : { $gt : 3 } } | |||
Not equal: | Not equal: | |||
{ a : { $ne : 3 } } | { a : { $ne : 3 } } | |||
TODO: we should rewrite the matcher to be more an AST style. | TODO: we should rewrite the matcher to be more an AST style. | |||
*/ | */ | |||
class Matcher : boost::noncopyable { | class Matcher : boost::noncopyable { | |||
int matchesDotted( | int matchesDotted( | |||
End of changes. 7 change blocks. | ||||
76 lines changed or deleted | 12 lines changed or added | |||
misc.h | misc.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
* 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 <ctime> | #include <ctime> | |||
#include <limits> | #include <limits> | |||
#include <string> | #include <string> | |||
#include "mongo/platform/cstdint.h" | ||||
#include "mongo/util/assert_util.h" | #include "mongo/util/assert_util.h" | |||
namespace mongo { | namespace mongo { | |||
inline void time_t_to_String(time_t t, char *buf) { | inline void time_t_to_String(time_t t, char *buf) { | |||
#if defined(_WIN32) | #if defined(_WIN32) | |||
ctime_s(buf, 32, &t); | ctime_s(buf, 32, &t); | |||
#else | #else | |||
ctime_r(&t, buf); | ctime_r(&t, buf); | |||
#endif | #endif | |||
skipping to change at line 100 | skipping to change at line 101 | |||
char buf[64]; | char buf[64]; | |||
time_t_to_String(toTimeT(), buf); | time_t_to_String(toTimeT(), buf); | |||
return buf; | return buf; | |||
} | } | |||
time_t toTimeT() const { | time_t toTimeT() const { | |||
// cant use uassert from bson/util | // cant use uassert from bson/util | |||
verify((long long)millis >= 0); // TODO when millis is signed, delete | verify((long long)millis >= 0); // TODO when millis is signed, delete | |||
verify(((long long)millis/1000) < (std::numeric_limits<time_t>: :max)()); | verify(((long long)millis/1000) < (std::numeric_limits<time_t>: :max)()); | |||
return millis / 1000; | return millis / 1000; | |||
} | } | |||
int64_t asInt64() { | ||||
return static_cast<int64_t>(millis); | ||||
} | ||||
}; | }; | |||
// Like strlen, but only scans up to n bytes. | // Like strlen, but only scans up to n bytes. | |||
// Returns -1 if no '0' found. | // Returns -1 if no '0' found. | |||
inline int strnlen( const char *s, int n ) { | inline int strnlen( const char *s, int n ) { | |||
for( int i = 0; i < n; ++i ) | for( int i = 0; i < n; ++i ) | |||
if ( !s[ i ] ) | if ( !s[ i ] ) | |||
return i; | return i; | |||
return -1; | return -1; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 4 lines changed or added | |||
mock_dbclient_cursor.h | mock_dbclient_cursor.h | |||
---|---|---|---|---|
skipping to change at line 35 | skipping to change at line 35 | |||
/** | /** | |||
* Simple adapter class for mongo::DBClientMockCursor to mongo::DBClien tCursor. | * Simple adapter class for mongo::DBClientMockCursor to mongo::DBClien tCursor. | |||
* Only supports more and next, the behavior of other operations are un defined. | * Only supports more and next, the behavior of other operations are un defined. | |||
*/ | */ | |||
class MockDBClientCursor: public mongo::DBClientCursor { | class MockDBClientCursor: public mongo::DBClientCursor { | |||
public: | public: | |||
MockDBClientCursor(mongo::DBClientBase* client, | MockDBClientCursor(mongo::DBClientBase* client, | |||
const mongo::BSONArray& mockCollection); | const mongo::BSONArray& mockCollection); | |||
bool more(); | bool more(); | |||
/** | ||||
* Note: has the same contract as DBClientCursor - returned BSONObj | ||||
will | ||||
* become invalid when this cursor is destroyed. | ||||
*/ | ||||
mongo::BSONObj next(); | mongo::BSONObj next(); | |||
private: | private: | |||
boost::scoped_ptr<mongo::DBClientMockCursor> _cursor; | boost::scoped_ptr<mongo::DBClientMockCursor> _cursor; | |||
mongo::BSONObj _resultSet; | mongo::BSONObj _resultSet; | |||
}; | }; | |||
} | } | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 6 lines changed or added | |||
mock_remote_db_server.h | mock_remote_db_server.h | |||
---|---|---|---|---|
skipping to change at line 195 | skipping to change at line 195 | |||
}; | }; | |||
/** | /** | |||
* Checks whether the instance of the server is still up. | * Checks whether the instance of the server is still up. | |||
* | * | |||
* @throws mongo::SocketException if this server is down | * @throws mongo::SocketException if this server is down | |||
*/ | */ | |||
void checkIfUp(InstanceID id) const; | void checkIfUp(InstanceID id) const; | |||
typedef unordered_map<std::string, boost::shared_ptr<CircularBSONIt erator> > CmdToReplyObj; | typedef unordered_map<std::string, boost::shared_ptr<CircularBSONIt erator> > CmdToReplyObj; | |||
typedef unordered_map<std::string, mongo::BSONArrayBuilder*> MockDa taMgr; | typedef unordered_map<std::string, vector<BSONObj> > MockDataMgr; | |||
bool _isRunning; | bool _isRunning; | |||
const std::string _hostAndPort; | const std::string _hostAndPort; | |||
long long _delayMilliSec; | long long _delayMilliSec; | |||
// | // | |||
// Mock replies | // Mock replies | |||
// | // | |||
CmdToReplyObj _cmdMap; | CmdToReplyObj _cmdMap; | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
mr.h | mr.h | |||
---|---|---|---|---|
skipping to change at line 123 | skipping to change at line 123 | |||
public: | public: | |||
JSReducer( const BSONElement& code ) : _func( "_reduce" , code ) {} | JSReducer( const BSONElement& code ) : _func( "_reduce" , code ) {} | |||
virtual void init( State * state ); | virtual void init( State * state ); | |||
virtual BSONObj reduce( const BSONList& tuples ); | virtual BSONObj reduce( const BSONList& tuples ); | |||
virtual BSONObj finalReduce( const BSONList& tuples , Finalizer * finalizer ); | virtual BSONObj finalReduce( const BSONList& tuples , Finalizer * finalizer ); | |||
private: | private: | |||
/** | /** | |||
* result in "return" | * result in "__returnValue" | |||
* @param key OUT | * @param key OUT | |||
* @param endSizeEstimate OUT | * @param endSizeEstimate OUT | |||
*/ | */ | |||
void _reduce( const BSONList& values , BSONObj& key , int& endS izeEstimate ); | void _reduce( const BSONList& values , BSONObj& key , int& endS izeEstimate ); | |||
JSFunction _func; | JSFunction _func; | |||
}; | }; | |||
class JSFinalizer : public Finalizer { | class JSFinalizer : public Finalizer { | |||
public: | public: | |||
skipping to change at line 270 | skipping to change at line 270 | |||
void prepTempCollection(); | void prepTempCollection(); | |||
void finalReduce( BSONList& values ); | void finalReduce( BSONList& values ); | |||
void finalReduce( CurOp * op , ProgressMeterHolder& pm ); | void finalReduce( CurOp * op , ProgressMeterHolder& pm ); | |||
// ------- cleanup/data positioning ---------- | // ------- cleanup/data positioning ---------- | |||
/** | /** | |||
* Clean up the temporary and incremental collections | ||||
*/ | ||||
void dropTempCollections(); | ||||
/** | ||||
@return number objects in collection | @return number objects in collection | |||
*/ | */ | |||
long long postProcessCollection( CurOp* op , ProgressMeterHolde r& pm ); | long long postProcessCollection( CurOp* op , ProgressMeterHolde r& pm ); | |||
long long postProcessCollectionNonAtomic( CurOp* op , ProgressM eterHolder& pm ); | long long postProcessCollectionNonAtomic( CurOp* op , ProgressM eterHolder& pm ); | |||
/** | /** | |||
* if INMEMORY will append | * if INMEMORY will append | |||
* may also append stats or anything else it likes | * may also append stats or anything else it likes | |||
*/ | */ | |||
void appendResults( BSONObjBuilder& b ); | void appendResults( BSONObjBuilder& b ); | |||
skipping to change at line 307 | skipping to change at line 312 | |||
long long numEmits() const { if (_jsMode) return _scope->getNum berLongLong("_emitCt"); return _numEmits; } | long long numEmits() const { if (_jsMode) return _scope->getNum berLongLong("_emitCt"); return _numEmits; } | |||
long long numReduces() const { if (_jsMode) return _scope->getN umberLongLong("_redCt"); return _config.reducer->numReduces; } | long long numReduces() const { if (_jsMode) return _scope->getN umberLongLong("_redCt"); return _config.reducer->numReduces; } | |||
long long numInMemKeys() const { if (_jsMode) return _scope->ge tNumberLongLong("_keyCt"); return _temp->size(); } | long long numInMemKeys() const { if (_jsMode) return _scope->ge tNumberLongLong("_keyCt"); return _temp->size(); } | |||
bool jsMode() {return _jsMode;} | bool jsMode() {return _jsMode;} | |||
void switchMode(bool jsMode); | void switchMode(bool jsMode); | |||
void bailFromJS(); | void bailFromJS(); | |||
const Config& _config; | const Config& _config; | |||
DBDirectClient _db; | DBDirectClient _db; | |||
bool _useIncremental; // use an incremental collection | ||||
protected: | protected: | |||
void _add( InMemory* im , const BSONObj& a , long& size ); | void _add( InMemory* im , const BSONObj& a , long& size ); | |||
scoped_ptr<Scope> _scope; | scoped_ptr<Scope> _scope; | |||
bool _onDisk; // if the end result of this map reduce is disk o r not | bool _onDisk; // if the end result of this map reduce is disk o r not | |||
scoped_ptr<InMemory> _temp; | scoped_ptr<InMemory> _temp; | |||
long _size; // bytes in _temp | long _size; // bytes in _temp | |||
End of changes. 3 change blocks. | ||||
1 lines changed or deleted | 7 lines changed or added | |||
namespace_details-inl.h | namespace_details-inl.h | |||
---|---|---|---|---|
skipping to change at line 95 | skipping to change at line 95 | |||
// @return offset in indexes[] | // @return offset in indexes[] | |||
inline int NamespaceDetails::findIndexByName(const char *name) { | inline int NamespaceDetails::findIndexByName(const char *name) { | |||
IndexIterator i = ii(); | IndexIterator i = ii(); | |||
while( i.more() ) { | while( i.more() ) { | |||
if ( strcmp(i.next().info.obj().getStringField("name"),name) == 0 ) | if ( strcmp(i.next().info.obj().getStringField("name"),name) == 0 ) | |||
return i.pos()-1; | return i.pos()-1; | |||
} | } | |||
return -1; | return -1; | |||
} | } | |||
inline NamespaceDetails::IndexIterator::IndexIterator(NamespaceDetails | inline NamespaceDetails::IndexIterator::IndexIterator(NamespaceDetails | |||
*_d) { | *_d, | |||
bool includeBackg | ||||
roundInProgress) { | ||||
d = _d; | d = _d; | |||
i = 0; | i = 0; | |||
n = d->nIndexes; | n = includeBackgroundInProgress ? d->getTotalIndexCount() : d->nInd exes; | |||
} | } | |||
} | } | |||
End of changes. 2 change blocks. | ||||
3 lines changed or deleted | 5 lines changed or added | |||
namespace_details.h | namespace_details.h | |||
---|---|---|---|---|
skipping to change at line 25 | skipping to change at line 25 | |||
* 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 "mongo/db/d_concurrency.h" | #include "mongo/db/d_concurrency.h" | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/index.h" | #include "mongo/db/index.h" | |||
#include "mongo/db/index_set.h" | ||||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/mongommf.h" | #include "mongo/db/mongommf.h" | |||
#include "mongo/db/namespace.h" | #include "mongo/db/namespace.h" | |||
#include "mongo/db/namespacestring.h" | #include "mongo/db/namespacestring.h" | |||
#include "mongo/db/queryoptimizercursor.h" | #include "mongo/db/queryoptimizercursor.h" | |||
#include "mongo/db/querypattern.h" | #include "mongo/db/querypattern.h" | |||
#include "mongo/platform/unordered_map.h" | #include "mongo/platform/unordered_map.h" | |||
#include "mongo/util/hashtab.h" | #include "mongo/util/hashtab.h" | |||
namespace mongo { | namespace mongo { | |||
skipping to change at line 209 | skipping to change at line 210 | |||
class IndexIterator { | class IndexIterator { | |||
public: | public: | |||
int pos() { return i; } // note this is the next one to come | int pos() { return i; } // note this is the next one to come | |||
bool more() { return i < n; } | bool more() { return i < n; } | |||
IndexDetails& next() { return d->idx(i++); } | IndexDetails& next() { return d->idx(i++); } | |||
private: | private: | |||
friend class NamespaceDetails; | friend class NamespaceDetails; | |||
int i, n; | int i, n; | |||
NamespaceDetails *d; | NamespaceDetails *d; | |||
IndexIterator(NamespaceDetails *_d); | IndexIterator(NamespaceDetails *_d, bool includeBackgroundInPro gress); | |||
}; | }; | |||
IndexIterator ii() { return IndexIterator(this); } | IndexIterator ii( bool includeBackgroundInProgress = false ) { | |||
return IndexIterator(this, includeBackgroundInProgress); | ||||
} | ||||
/* hackish - find our index # in the indexes array */ | /* hackish - find our index # in the indexes array */ | |||
int idxNo(const IndexDetails& idx); | int idxNo(const IndexDetails& idx); | |||
/* multikey indexes are indexes where there are more than one key i n the index | /* multikey indexes are indexes where there are more than one key i n the index | |||
for a single document. see multikey in wiki. | for a single document. see multikey in docs. | |||
for these, we have to do some dedup work on queries. | for these, we have to do some dedup work on queries. | |||
*/ | */ | |||
bool isMultikey(int i) const { return (multiKeyIndexBits & (((unsig ned long long) 1) << i)) != 0; } | bool isMultikey(int i) const { return (multiKeyIndexBits & (((unsig ned long long) 1) << i)) != 0; } | |||
void setIndexIsMultikey(const char *thisns, int i, bool multikey = true); | void setIndexIsMultikey(const char *thisns, int i, bool multikey = true); | |||
/** | /** | |||
* This fetches the IndexDetails for the next empty index slot. The caller must populate | * This fetches the IndexDetails for the next empty index slot. The caller must populate | |||
* returned object. This handles allocating extra index space, if necessary. | * returned object. This handles allocating extra index space, if necessary. | |||
*/ | */ | |||
IndexDetails& getNextIndexDetails(const char* thisns); | IndexDetails& getNextIndexDetails(const char* thisns); | |||
skipping to change at line 533 | skipping to change at line 536 | |||
* It is possible no cursor is returned if the sort is not supporte d by an index. Clients are responsible | * It is possible no cursor is returned if the sort is not supporte d by an index. Clients are responsible | |||
* for checking this if they are not sure an index for a sort exist s, and defaulting to a non-sort if | * for checking this if they are not sure an index for a sort exist s, and defaulting to a non-sort if | |||
* no suitable indices exist. | * no suitable indices exist. | |||
*/ | */ | |||
static shared_ptr<Cursor> bestGuessCursor( const char *ns, const BS ONObj &query, const BSONObj &sort ); | static shared_ptr<Cursor> bestGuessCursor( const char *ns, const BS ONObj &query, const BSONObj &sort ); | |||
/* indexKeys() cache ---------------------------------------------- ------ */ | /* indexKeys() cache ---------------------------------------------- ------ */ | |||
/* assumed to be in write lock for this */ | /* assumed to be in write lock for this */ | |||
private: | private: | |||
bool _keysComputed; | bool _keysComputed; | |||
set<string> _indexKeys; | IndexPathSet _indexedPaths; | |||
void computeIndexKeys(); | void computeIndexKeys(); | |||
public: | public: | |||
/* get set of index keys for this namespace. handy to quickly chec k if a given | /* get set of index keys for this namespace. handy to quickly chec k if a given | |||
field is indexed (Note it might be a secondary component of a co mpound index.) | field is indexed (Note it might be a secondary component of a co mpound index.) | |||
*/ | */ | |||
set<string>& indexKeys() { | const IndexPathSet& indexKeys() { | |||
DEV Lock::assertWriteLocked(_ns); | DEV Lock::assertWriteLocked(_ns); | |||
if ( !_keysComputed ) | if ( !_keysComputed ) | |||
computeIndexKeys(); | computeIndexKeys(); | |||
return _indexKeys; | return _indexedPaths; | |||
} | } | |||
/* IndexSpec caching */ | /* IndexSpec caching */ | |||
private: | private: | |||
map<const IndexDetails*,IndexSpec> _indexSpecs; | map<const IndexDetails*,IndexSpec> _indexSpecs; | |||
static SimpleMutex _isMutex; | static SimpleMutex _isMutex; | |||
public: | public: | |||
const IndexSpec& getIndexSpec( const IndexDetails * details ) { | const IndexSpec& getIndexSpec( const IndexDetails * details ) { | |||
IndexSpec& spec = _indexSpecs[details]; | IndexSpec& spec = _indexSpecs[details]; | |||
if ( ! spec._finishedInit ) { | if ( ! spec._finishedInit ) { | |||
End of changes. 7 change blocks. | ||||
6 lines changed or deleted | 9 lines changed or added | |||
namespacestring.h | namespacestring.h | |||
---|---|---|---|---|
skipping to change at line 72 | skipping to change at line 72 | |||
bool operator!=( const string& nsIn ) const { return nsIn != ns(); } | bool operator!=( const string& nsIn ) const { return nsIn != ns(); } | |||
bool operator!=( const char* nsIn ) const { return (string)nsIn != ns(); } | bool operator!=( const char* nsIn ) const { return (string)nsIn != ns(); } | |||
bool operator!=( const NamespaceString& nsIn ) const { return nsIn. db != db || nsIn.coll != coll; } | bool operator!=( const NamespaceString& nsIn ) const { return nsIn. db != db || nsIn.coll != coll; } | |||
size_t size() const { return ns().size(); } | size_t size() const { return ns().size(); } | |||
string toString() const { return ns(); } | string toString() const { return ns(); } | |||
/** | /** | |||
* @return true if ns is 'normal'. $ used for collections holding | * @return true if ns is 'normal'. A "$" is used for namespaces ho | |||
index data, which do not contain BSON objects in their records. | lding index data, | |||
* special case for the local.oplog.$main ns -- naming it as such w | * which do not contain BSON objects in their records. ("oplog.$mai | |||
as a mistake. | n" is the exception) | |||
*/ | */ | |||
static bool normal(const char* ns) { | static bool normal(const char* ns) { | |||
const char *p = strchr(ns, '$'); | const char *p = strchr(ns, '$'); | |||
if( p == 0 ) | if( p == 0 ) | |||
return true; | return true; | |||
return strcmp( ns, "local.oplog.$main" ) == 0; | return oplog(ns); | |||
} | ||||
/** | ||||
* @return true if the ns is an oplog one, otherwise false. | ||||
*/ | ||||
static bool oplog(const char* ns) { | ||||
return StringData(ns) == StringData("local.oplog.rs") || String | ||||
Data(ns) == StringData("local.oplog.$main"); | ||||
} | } | |||
static bool special(const char *ns) { | static bool special(const char *ns) { | |||
return !normal(ns) || strstr(ns, ".system."); | return !normal(ns) || strstr(ns, ".system."); | |||
} | } | |||
/** | /** | |||
* samples: | * samples: | |||
* good: | * good: | |||
* foo | * foo | |||
End of changes. 2 change blocks. | ||||
5 lines changed or deleted | 13 lines changed or added | |||
oid.h | oid.h | |||
---|---|---|---|---|
skipping to change at line 150 | skipping to change at line 150 | |||
static unsigned ourPid(); | static unsigned ourPid(); | |||
static void foldInPid(MachineAndPid& x); | static void foldInPid(MachineAndPid& x); | |||
static MachineAndPid genMachineAndPid(); | static MachineAndPid genMachineAndPid(); | |||
}; | }; | |||
#pragma pack() | #pragma pack() | |||
std::ostream& operator<<( std::ostream &s, const OID &o ); | std::ostream& operator<<( std::ostream &s, const OID &o ); | |||
inline StringBuilder& operator<< (StringBuilder& s, const OID& o) { ret urn (s << o.str()); } | inline StringBuilder& operator<< (StringBuilder& s, const OID& o) { ret urn (s << o.str()); } | |||
/** Formatting mode for generating JSON from BSON. | /** Formatting mode for generating JSON from BSON. | |||
See <http://mongodb.onconfluence.com/display/DOCS/Mongo+Extended+JS ON> | See <http://dochub.mongodb.org/core/mongodbextendedjson> | |||
for details. | for details. | |||
*/ | */ | |||
enum JsonStringFormat { | enum JsonStringFormat { | |||
/** strict RFC format */ | /** strict RFC format */ | |||
Strict, | Strict, | |||
/** 10gen format, which is close to JS format. This form is unders tandable by | /** 10gen format, which is close to JS format. This form is unders tandable by | |||
javascript running inside the Mongo server via eval() */ | javascript running inside the Mongo server via eval() */ | |||
TenGen, | TenGen, | |||
/** Javascript JSON compatible */ | /** Javascript JSON compatible */ | |||
JS | JS | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
oplogreader.h | oplogreader.h | |||
---|---|---|---|---|
skipping to change at line 108 | skipping to change at line 108 | |||
bool more() { | bool more() { | |||
uassert( 15910, "Doesn't have cursor for reading oplog", cursor .get() ); | uassert( 15910, "Doesn't have cursor for reading oplog", cursor .get() ); | |||
return cursor->more(); | return cursor->more(); | |||
} | } | |||
bool moreInCurrentBatch() { | bool moreInCurrentBatch() { | |||
uassert( 15911, "Doesn't have cursor for reading oplog", cursor .get() ); | uassert( 15911, "Doesn't have cursor for reading oplog", cursor .get() ); | |||
return cursor->moreInCurrentBatch(); | return cursor->moreInCurrentBatch(); | |||
} | } | |||
int currentBatchMessageSize() { | ||||
if( NULL == cursor->getMessage() ) | ||||
return 0; | ||||
return cursor->getMessage()->size(); | ||||
} | ||||
/* old mongod's can't do the await flag... */ | /* old mongod's can't do the await flag... */ | |||
bool awaitCapable() { | bool awaitCapable() { | |||
return cursor->hasResultFlag(ResultFlag_AwaitCapable); | return cursor->hasResultFlag(ResultFlag_AwaitCapable); | |||
} | } | |||
int getTailingQueryOptions() const { return _tailingQueryOptions; } | int getTailingQueryOptions() const { return _tailingQueryOptions; } | |||
void setTailingQueryOptions( int tailingQueryOptions ) { _tailingQu eryOptions = tailingQueryOptions; } | void setTailingQueryOptions( int tailingQueryOptions ) { _tailingQu eryOptions = tailingQueryOptions; } | |||
void peek(vector<BSONObj>& v, int n) { | void peek(vector<BSONObj>& v, int n) { | |||
if( cursor.get() ) | if( cursor.get() ) | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 6 lines changed or added | |||
optime.h | optime.h | |||
---|---|---|---|---|
skipping to change at line 45 | skipping to change at line 45 | |||
*/ | */ | |||
#pragma pack(4) | #pragma pack(4) | |||
class OpTime { | class OpTime { | |||
unsigned i; // ordinal comes first so we can do a single 64 bit com pare on little endian | unsigned i; // ordinal comes first so we can do a single 64 bit com pare on little endian | |||
unsigned secs; | unsigned secs; | |||
static OpTime last; | static OpTime last; | |||
static OpTime skewed(); | static OpTime skewed(); | |||
public: | public: | |||
static void setLast(const Date_t &date) { | static void setLast(const Date_t &date) { | |||
mutex::scoped_lock lk(m); | mutex::scoped_lock lk(m); | |||
notifier.notify_all(); // won't really do anything until write- lock released | ||||
last = OpTime(date); | last = OpTime(date); | |||
notifier.notify_all(); | ||||
} | } | |||
static void setLast(const OpTime &new_last) { | ||||
mutex::scoped_lock lk(m); | ||||
last = new_last; | ||||
notifier.notify_all(); | ||||
} | ||||
unsigned getSecs() const { | unsigned getSecs() const { | |||
return secs; | return secs; | |||
} | } | |||
unsigned getInc() const { | unsigned getInc() const { | |||
return i; | return i; | |||
} | } | |||
OpTime(Date_t date) { | OpTime(Date_t date) { | |||
reinterpret_cast<unsigned long long&>(*this) = date.millis; | reinterpret_cast<unsigned long long&>(*this) = date.millis; | |||
dassert( (int)secs >= 0 ); | dassert( (int)secs >= 0 ); | |||
} | } | |||
End of changes. 3 change blocks. | ||||
1 lines changed or deleted | 7 lines changed or added | |||
pdfile.h | pdfile.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
#pragma once | #pragma once | |||
#include "mongo/db/client.h" | #include "mongo/db/client.h" | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/jsobjmanipulator.h" | #include "mongo/db/jsobjmanipulator.h" | |||
#include "mongo/db/memconcept.h" | #include "mongo/db/memconcept.h" | |||
#include "mongo/db/mongommf.h" | #include "mongo/db/mongommf.h" | |||
#include "mongo/db/namespace-inl.h" | #include "mongo/db/namespace-inl.h" | |||
#include "mongo/db/namespace_details-inl.h" | #include "mongo/db/namespace_details-inl.h" | |||
#include "mongo/db/namespacestring.h" | #include "mongo/db/namespacestring.h" | |||
#include "mongo/db/pdfile_version.h" | ||||
#include "mongo/platform/cstdint.h" | #include "mongo/platform/cstdint.h" | |||
#include "mongo/util/log.h" | #include "mongo/util/log.h" | |||
#include "mongo/util/mmap.h" | #include "mongo/util/mmap.h" | |||
namespace mongo { | namespace mongo { | |||
// pdfile versions | ||||
const int PDFILE_VERSION = 4; | ||||
const int PDFILE_VERSION_MINOR = 5; | ||||
class Cursor; | class Cursor; | |||
class DataFileHeader; | class DataFileHeader; | |||
class Extent; | class Extent; | |||
class OpDebug; | class OpDebug; | |||
class Record; | class Record; | |||
struct SortPhaseOne; | struct SortPhaseOne; | |||
void dropDatabase(const std::string& db); | void dropDatabase(const std::string& db); | |||
bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles OnFailure = false, bool backupOriginalFiles = false); | bool repairDatabase(string db, string &errmsg, bool preserveClonedFiles OnFailure = false, bool backupOriginalFiles = false); | |||
skipping to change at line 466 | skipping to change at line 463 | |||
int versionMinor; | int versionMinor; | |||
int fileLength; | int fileLength; | |||
DiskLoc unused; /* unused is the portion of the file that doesn't b elong to any allocated extents. -1 = no more */ | DiskLoc unused; /* unused is the portion of the file that doesn't b elong to any allocated extents. -1 = no more */ | |||
int unusedLength; | int unusedLength; | |||
char reserved[8192 - 4*4 - 8]; | char reserved[8192 - 4*4 - 8]; | |||
char data[4]; // first extent starts here | char data[4]; // first extent starts here | |||
enum { HeaderSize = 8192 }; | enum { HeaderSize = 8192 }; | |||
bool isCurrentVersion() const { return ( version == PDFILE_VERSION | bool isCurrentVersion() const { | |||
) && ( versionMinor == PDFILE_VERSION_MINOR ); } | return version == PDFILE_VERSION && ( versionMinor == PDFILE_VE | |||
RSION_MINOR_22_AND_OLDER | ||||
|| versionMinor == PDFILE_VE | ||||
RSION_MINOR_24_AND_NEWER | ||||
); | ||||
} | ||||
bool uninitialized() const { return version == 0; } | bool uninitialized() const { return version == 0; } | |||
void init(int fileno, int filelength, const char* filename) { | void init(int fileno, int filelength, const char* filename) { | |||
if ( uninitialized() ) { | if ( uninitialized() ) { | |||
DEV log() << "datafileheader::init initializing " << filena me << " n:" << fileno << endl; | DEV log() << "datafileheader::init initializing " << filena me << " n:" << fileno << endl; | |||
if( !(filelength > 32768 ) ) { | if( !(filelength > 32768 ) ) { | |||
massert(13640, str::stream() << "DataFileHeader looks c orrupt at file open filelength:" << filelength << " fileno:" << fileno, fal se); | massert(13640, str::stream() << "DataFileHeader looks c orrupt at file open filelength:" << filelength << " fileno:" << fileno, fal se); | |||
} | } | |||
skipping to change at line 497 | skipping to change at line 498 | |||
::abort(); | ::abort(); | |||
**/ | **/ | |||
} | } | |||
} | } | |||
getDur().createdFile(filename, filelength); | getDur().createdFile(filename, filelength); | |||
verify( HeaderSize == 8192 ); | verify( HeaderSize == 8192 ); | |||
DataFileHeader *h = getDur().writing(this); | DataFileHeader *h = getDur().writing(this); | |||
h->fileLength = filelength; | h->fileLength = filelength; | |||
h->version = PDFILE_VERSION; | h->version = PDFILE_VERSION; | |||
h->versionMinor = PDFILE_VERSION_MINOR; | h->versionMinor = PDFILE_VERSION_MINOR_22_AND_OLDER; // All dbs start like this | |||
h->unused.set( fileno, HeaderSize ); | h->unused.set( fileno, HeaderSize ); | |||
verify( (data-(char*)this) == HeaderSize ); | verify( (data-(char*)this) == HeaderSize ); | |||
h->unusedLength = fileLength - HeaderSize - 16; | h->unusedLength = fileLength - HeaderSize - 16; | |||
} | } | |||
} | } | |||
bool isEmpty() const { | bool isEmpty() const { | |||
return uninitialized() || ( unusedLength == fileLength - Header Size - 16 ); | return uninitialized() || ( unusedLength == fileLength - Header Size - 16 ); | |||
} | } | |||
}; | }; | |||
End of changes. 4 change blocks. | ||||
7 lines changed or deleted | 9 lines changed or added | |||
query.h | query.h | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
#include "../../s/d_chunk_manager.h" | #include "../../s/d_chunk_manager.h" | |||
// struct QueryOptions, QueryResult, QueryResultFlags in: | // struct QueryOptions, QueryResult, QueryResultFlags in: | |||
namespace mongo { | namespace mongo { | |||
class ParsedQuery; | class ParsedQuery; | |||
class QueryOptimizerCursor; | class QueryOptimizerCursor; | |||
class QueryPlanSummary; | class QueryPlanSummary; | |||
QueryResult* processGetMore(const char *ns, int ntoreturn, long long cu | /** | |||
rsorid , CurOp& op, int pass, bool& exhaust); | * Return a batch of results from a client OP_GET_MORE request. | |||
* 'cursorid' - The id of the cursor producing results. | ||||
* 'isCursorAuthorized' - Set to true after a cursor with id 'cursorid' | ||||
is authorized for use. | ||||
*/ | ||||
QueryResult* processGetMore(const char* ns, | ||||
int ntoreturn, | ||||
long long cursorid, | ||||
CurOp& op, | ||||
int pass, | ||||
bool& exhaust, | ||||
bool* isCursorAuthorized); | ||||
string runQuery(Message& m, QueryMessage& q, CurOp& curop, Message &res ult); | string runQuery(Message& m, QueryMessage& q, CurOp& curop, Message &res ult); | |||
/** Exception indicating that a query should be retried from the beginn ing. */ | /** Exception indicating that a query should be retried from the beginn ing. */ | |||
class QueryRetryException : public DBException { | class QueryRetryException : public DBException { | |||
public: | public: | |||
QueryRetryException() : DBException( "query retry exception" , 1608 3 ) { | QueryRetryException() : DBException( "query retry exception" , 1608 3 ) { | |||
return; | return; | |||
massert( 16083, "reserve 16083", true ); // Reserve 16083. | massert( 16083, "reserve 16083", true ); // Reserve 16083. | |||
} | } | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 13 lines changed or added | |||
queryutil.h | queryutil.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* 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 "jsobj.h" | #include "jsobj.h" | |||
#include "indexkey.h" | #include "indexkey.h" | |||
#include "projection.h" | #include "projection.h" | |||
#include "mongo/client/dbclientinterface.h" | ||||
namespace mongo { | namespace mongo { | |||
extern const int MaxBytesToReturnToClientAtOnce; | extern const int MaxBytesToReturnToClientAtOnce; | |||
//maximum number of intervals produced by $in queries. | //maximum number of intervals produced by $in queries. | |||
static const unsigned MAX_IN_COMBINATIONS = 4000000; | static const unsigned MAX_IN_COMBINATIONS = 4000000; | |||
/* This is for languages whose "objects" are not well ordered (JSON is well ordered). | /* This is for languages whose "objects" are not well ordered (JSON is well ordered). | |||
[ { a : ... } , { b : ... } ] -> { a : ..., b : ... } | [ { a : ... } , { b : ... } ] -> { a : ..., b : ... } | |||
skipping to change at line 158 | skipping to change at line 159 | |||
if ( e.isABSONObj() ) { | if ( e.isABSONObj() ) { | |||
_filter = e.embeddedObject(); | _filter = e.embeddedObject(); | |||
_initTop( q ); | _initTop( q ); | |||
} | } | |||
else { | else { | |||
_filter = q; | _filter = q; | |||
} | } | |||
_filter = _filter.getOwned(); | _filter = _filter.getOwned(); | |||
_hasReadPref = q.hasField("$readPreference"); | _hasReadPref = q.hasField(Query::ReadPrefField.name()); | |||
} | } | |||
void _reset() { | void _reset() { | |||
_wantMore = true; | _wantMore = true; | |||
_explain = false; | _explain = false; | |||
_snapshot = false; | _snapshot = false; | |||
_returnKey = false; | _returnKey = false; | |||
_showDiskLoc = false; | _showDiskLoc = false; | |||
_maxScan = 0; | _maxScan = 0; | |||
} | } | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 2 lines changed or added | |||
queue.h | queue.h | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
#include "mongo/util/timer.h" | #include "mongo/util/timer.h" | |||
namespace mongo { | namespace mongo { | |||
template <typename T> | template <typename T> | |||
size_t _getSizeDefault(const T& t) { | size_t _getSizeDefault(const T& t) { | |||
return 1; | return 1; | |||
} | } | |||
/** | /** | |||
* Simple blocking queue with optional max size. | * Simple blocking queue with optional max size (by count or custom siz | |||
* A custom sizing function can optionally be given. By default, size | ing function). | |||
is calculated as | * A custom sizing function can optionally be given. By default the ge | |||
* _queue.size(). | tSize function | |||
* returns 1 for each item, resulting in size equaling the number of it | ||||
ems queued. | ||||
*/ | */ | |||
template<typename T> | template<typename T> | |||
class BlockingQueue : boost::noncopyable { | class BlockingQueue : boost::noncopyable { | |||
typedef size_t (*getSizeFunc)(const T& t); | typedef size_t (*getSizeFunc)(const T& t); | |||
public: | public: | |||
BlockingQueue() : | BlockingQueue() : | |||
_lock("BlockingQueue"), | _lock("BlockingQueue"), | |||
_maxSize(std::numeric_limits<std::size_t>::max()), | _maxSize(std::numeric_limits<std::size_t>::max()), | |||
_currentSize(0), | _currentSize(0), | |||
_getSize(&_getSizeDefault) {} | _getSize(&_getSizeDefault) {} | |||
skipping to change at line 77 | skipping to change at line 77 | |||
_queue.push( t ); | _queue.push( t ); | |||
_currentSize += tSize; | _currentSize += tSize; | |||
_cvNoLongerEmpty.notify_one(); | _cvNoLongerEmpty.notify_one(); | |||
} | } | |||
bool empty() const { | bool empty() const { | |||
scoped_lock l( _lock ); | scoped_lock l( _lock ); | |||
return _queue.empty(); | return _queue.empty(); | |||
} | } | |||
/** | ||||
* The size as measured by the size function. Default to counting e | ||||
ach item | ||||
*/ | ||||
size_t size() const { | size_t size() const { | |||
scoped_lock l( _lock ); | scoped_lock l( _lock ); | |||
return _currentSize; | return _currentSize; | |||
} | } | |||
/** | ||||
* The max size for this queue | ||||
*/ | ||||
size_t maxSize() const { | ||||
return _maxSize; | ||||
} | ||||
/** | ||||
* The number/count of items in the queue ( _queue.size() ) | ||||
*/ | ||||
int count() const { | ||||
scoped_lock l( _lock ); | ||||
return _queue.size(); | ||||
} | ||||
void clear() { | void clear() { | |||
scoped_lock l(_lock); | scoped_lock l(_lock); | |||
_queue = std::queue<T>(); | _queue = std::queue<T>(); | |||
_currentSize = 0; | _currentSize = 0; | |||
} | } | |||
bool tryPop( T & t ) { | bool tryPop( T & t ) { | |||
scoped_lock l( _lock ); | scoped_lock l( _lock ); | |||
if ( _queue.empty() ) | if ( _queue.empty() ) | |||
return false; | return false; | |||
End of changes. 3 change blocks. | ||||
4 lines changed or deleted | 25 lines changed or added | |||
ramlog.h | ramlog.h | |||
---|---|---|---|---|
skipping to change at line 38 | skipping to change at line 38 | |||
virtual void write(LogLevel ll, const string& str); | virtual void write(LogLevel ll, const string& str); | |||
void get( vector<const char*>& v) const; | void get( vector<const char*>& v) const; | |||
void toHTML(stringstream& s); | void toHTML(stringstream& s); | |||
static RamLog* get( const std::string& name ); | static RamLog* get( const std::string& name ); | |||
static void getNames( vector<string>& names ); | static void getNames( vector<string>& names ); | |||
time_t lastWrite() { return _lastWrite; } // 0 if no writes | time_t lastWrite() { return _lastWrite; } // 0 if no writes | |||
long long getTotalLinesWritten() const { return _totalLinesWritten; } | ||||
protected: | protected: | |||
static int repeats(const vector<const char *>& v, int i); | static int repeats(const vector<const char *>& v, int i); | |||
static string clean(const vector<const char *>& v, int i, string li ne=""); | static string clean(const vector<const char *>& v, int i, string li ne=""); | |||
static string color(const std::string& line); | static string color(const std::string& line); | |||
/* turn http:... into an anchor */ | /* turn http:... into an anchor */ | |||
static string linkify(const char *s); | static string linkify(const char *s); | |||
private: | private: | |||
~RamLog(); // want this private as we want to leak so we can use th em till the very end | ~RamLog(); // want this private as we want to leak so we can use th em till the very end | |||
enum { | enum { | |||
N = 128, // number of links | N = 1024, // number of lines | |||
C = 256 // max size of line | C = 512 // max size of line | |||
}; | }; | |||
char lines[N][C]; | char lines[N][C]; | |||
unsigned h; // current position | unsigned h; // current position | |||
unsigned n; // number of lines stores 0 o N | unsigned n; // number of lines stores 0 o N | |||
string _name; | string _name; | |||
long long _totalLinesWritten; | ||||
typedef map<string,RamLog*> RM; | typedef map<string,RamLog*> RM; | |||
static mongo::mutex* _namedLock; | static mongo::mutex* _namedLock; | |||
static RM* _named; | static RM* _named; | |||
time_t _lastWrite; | time_t _lastWrite; | |||
}; | }; | |||
} | } | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
repl_block.h | repl_block.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
namespace mongo { | namespace mongo { | |||
void updateSlaveLocation( CurOp& curop, const char * oplog_ns , OpTime lastOp ); | void updateSlaveLocation( CurOp& curop, const char * oplog_ns , OpTime lastOp ); | |||
/** @return true if op has made it to w servers */ | /** @return true if op has made it to w servers */ | |||
bool opReplicatedEnough( OpTime op , int w ); | bool opReplicatedEnough( OpTime op , int w ); | |||
bool opReplicatedEnough( OpTime op , BSONElement w ); | bool opReplicatedEnough( OpTime op , BSONElement w ); | |||
bool waitForReplication( OpTime op , int w , int maxSecondsToWait ); | bool waitForReplication( OpTime op , int w , int maxSecondsToWait ); | |||
std::vector<std::string> getHostsReplicatedTo(OpTime& op); | std::vector<BSONObj> getHostsWrittenTo(OpTime& op); | |||
void resetSlaveCache(); | void resetSlaveCache(); | |||
unsigned getSlaveCount(); | unsigned getSlaveCount(); | |||
} | } | |||
End of changes. 1 change blocks. | ||||
1 lines changed or deleted | 1 lines changed or added | |||
rs.h | rs.h | |||
---|---|---|---|---|
skipping to change at line 491 | skipping to change at line 491 | |||
// this is called from within a writelock in logOpRS | // this is called from within a writelock in logOpRS | |||
unsigned selfId() const { return _id; } | unsigned selfId() const { return _id; } | |||
Manager *mgr; | Manager *mgr; | |||
GhostSync *ghost; | GhostSync *ghost; | |||
/** | /** | |||
* This forces a secondary to go into recovering state and stay the re | * This forces a secondary to go into recovering state and stay the re | |||
* until this is called again, passing in "false". Multiple thread s can | * until this is called again, passing in "false". Multiple thread s can | |||
* call this and it will leave maintenance mode once all of the cal lers | * call this and it will leave maintenance mode once all of the cal lers | |||
* have called it again, passing in false. | * have called it again, passing in false. | |||
*/ | */ | |||
void setMaintenanceMode(const bool inc); | bool setMaintenanceMode(const bool inc); | |||
private: | private: | |||
Member* head() const { return _members.head(); } | Member* head() const { return _members.head(); } | |||
public: | public: | |||
const Member* findById(unsigned id) const; | const Member* findById(unsigned id) const; | |||
Member* findByName(const std::string& hostname) const; | Member* findByName(const std::string& hostname) const; | |||
private: | private: | |||
void _getTargets(list<Target>&, int &configVersion); | void _getTargets(list<Target>&, int &configVersion); | |||
void getTargets(list<Target>&, int &configVersion); | void getTargets(list<Target>&, int &configVersion); | |||
void startThreads(); | void startThreads(); | |||
friend class FeedbackThread; | friend class FeedbackThread; | |||
skipping to change at line 546 | skipping to change at line 546 | |||
} | } | |||
IndexPrefetchConfig getIndexPrefetchConfig() { | IndexPrefetchConfig getIndexPrefetchConfig() { | |||
return _indexPrefetchConfig; | return _indexPrefetchConfig; | |||
} | } | |||
static const int replWriterThreadCount; | static const int replWriterThreadCount; | |||
static const int replPrefetcherThreadCount; | static const int replPrefetcherThreadCount; | |||
threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; } | threadpool::ThreadPool& getPrefetchPool() { return _prefetcherPool; } | |||
threadpool::ThreadPool& getWriterPool() { return _writerPool; } | threadpool::ThreadPool& getWriterPool() { return _writerPool; } | |||
static const int maxSyncSourceLagSecs; | ||||
const ReplSetConfig::MemberCfg& myConfig() const { return _config; } | const ReplSetConfig::MemberCfg& myConfig() const { return _config; } | |||
bool tryToGoLiveAsASecondary(OpTime&); // readlocks | bool tryToGoLiveAsASecondary(OpTime&); // readlocks | |||
void syncRollback(OplogReader& r); | void syncRollback(OplogReader& r); | |||
void syncThread(); | void syncThread(); | |||
const OpTime lastOtherOpTime() const; | const OpTime lastOtherOpTime() const; | |||
/** | /** | |||
* When a member reaches its minValid optime it is in a consistent state. Thus, minValid is | * When a member reaches its minValid optime it is in a consistent state. Thus, minValid is | |||
* set as the last step in initial sync (if no minValid is set, thi | * set as the last step in initial sync. At the beginning of initi | |||
s indicates that initial | al sync, _initialSyncFlag | |||
* sync is necessary). It is also used during "normal" sync: the la | * is appended onto minValid to indicate that initial sync was star | |||
st op in each batch is | ted but has not yet | |||
* used to set minValid, to indicate that we are in a consistent st | * completed. | |||
ate when the batch has | * minValid is also used during "normal" sync: the last op in each | |||
* been fully applied. | batch is used to set | |||
* minValid, to indicate that we are in a consistent state when the | ||||
batch has been fully | ||||
* applied. | ||||
*/ | */ | |||
static void setMinValid(BSONObj obj); | static void setMinValid(BSONObj obj); | |||
static OpTime getMinValid(); | static OpTime getMinValid(); | |||
static void clearInitialSyncFlag(); | ||||
static bool getInitialSyncFlag(); | ||||
static void setInitialSyncFlag(); | ||||
int oplogVersion; | int oplogVersion; | |||
private: | private: | |||
IndexPrefetchConfig _indexPrefetchConfig; | IndexPrefetchConfig _indexPrefetchConfig; | |||
static const char* _initialSyncFlagString; | ||||
static const BSONObj _initialSyncFlag; | ||||
}; | }; | |||
class ReplSet : public ReplSetImpl { | class ReplSet : public ReplSetImpl { | |||
public: | public: | |||
static ReplSet* make(ReplSetCmdline& replSetCmdline); | static ReplSet* make(ReplSetCmdline& replSetCmdline); | |||
virtual ~ReplSet() {} | virtual ~ReplSet() {} | |||
// for the replSetStepDown command | // for the replSetStepDown command | |||
bool stepDown(int secs) { return _stepDown(secs); } | bool stepDown(int secs) { return _stepDown(secs); } | |||
End of changes. 5 change blocks. | ||||
8 lines changed or deleted | 19 lines changed or added | |||
s2cellid.h | s2cellid.h | |||
---|---|---|---|---|
skipping to change at line 243 | skipping to change at line 243 | |||
// These methods guarantee that FromToken(ToToken(x)) == x even when | // These methods guarantee that FromToken(ToToken(x)) == x even when | |||
// "x" is an invalid cell id. All tokens are alphanumeric strings. | // "x" is an invalid cell id. All tokens are alphanumeric strings. | |||
// FromToken() returns S2CellId::None() for malformed inputs. | // FromToken() returns S2CellId::None() for malformed inputs. | |||
string ToToken() const; | string ToToken() const; | |||
static S2CellId FromToken(string const& token); | static S2CellId FromToken(string const& token); | |||
// Creates a debug human readable string. Used for << and available for d irect | // Creates a debug human readable string. Used for << and available for d irect | |||
// usage as well. | // usage as well. | |||
string ToString() const; | string ToString() const; | |||
string toString() const { return ToString(); } | string toString() const { return ToString(); } | |||
string slowToString() const; | ||||
static S2CellId FromString(const string& str); | ||||
// Return the four cells that are adjacent across the cell's four edges. | // Return the four cells that are adjacent across the cell's four edges. | |||
// Neighbors are returned in the order defined by S2Cell::GetEdge. All | // Neighbors are returned in the order defined by S2Cell::GetEdge. All | |||
// neighbors are guaranteed to be distinct. | // neighbors are guaranteed to be distinct. | |||
void GetEdgeNeighbors(S2CellId neighbors[4]) const; | void GetEdgeNeighbors(S2CellId neighbors[4]) const; | |||
// Return the neighbors of closest vertex to this cell at the given level , | // Return the neighbors of closest vertex to this cell at the given level , | |||
// by appending them to "output". Normally there are four neighbors, but | // by appending them to "output". Normally there are four neighbors, but | |||
// the closest vertex may only have three neighbors if it is one of the 8 | // the closest vertex may only have three neighbors if it is one of the 8 | |||
// cube vertices. | // cube vertices. | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
s2common.h | s2common.h | |||
---|---|---|---|---|
skipping to change at line 17 | skipping to change at line 17 | |||
* | * | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* 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/>. | |||
*/ | */ | |||
#include "mongo/db/diskloc.h" | ||||
#include "mongo/db/geo/geoparser.h" | #include "mongo/db/geo/geoparser.h" | |||
#include "third_party/s2/s2.h" | #include "third_party/s2/s2.h" | |||
#include "third_party/s2/s2regioncoverer.h" | #include "third_party/s2/s2regioncoverer.h" | |||
#include "third_party/s2/s2cell.h" | #include "third_party/s2/s2cell.h" | |||
#include "third_party/s2/s2polyline.h" | #include "third_party/s2/s2polyline.h" | |||
#include "third_party/s2/s2polygon.h" | #include "third_party/s2/s2polygon.h" | |||
#include "third_party/s2/s2regioncoverer.h" | #include "third_party/s2/s2regioncoverer.h" | |||
#pragma once | #pragma once | |||
namespace mongo { | namespace mongo { | |||
// This is used by both s2cursor and s2nearcursor. | // This is used by both s2cursor and s2nearcursor. | |||
class S2SearchUtil { | class S2SearchUtil { | |||
public: | public: | |||
// Given a coverer, region, and field name, generate a BSONObj that we can pass to a | // Given a coverer, region, and field name, generate a BSONObj that we can pass to a | |||
// FieldRangeSet so that we only examine the keys that the provided region may intersect. | // FieldRangeSet so that we only examine the keys that the provided region may intersect. | |||
static BSONObj coverAsBSON(const vector<S2CellId> &cover, const str ing& field, | static BSONObj coverAsBSON(const vector<S2CellId> &cover, const str ing& field, | |||
const int coarsestIndexedLevel); | const int coarsestIndexedLevel); | |||
}; | static void setCoverLimitsBasedOnArea(double area, S2RegionCoverer | |||
*coverer, int coarsestIndexedLevel); | ||||
// Used for passing geo data from the newCursor entry point to the S2Cu | ||||
rsor class. | ||||
struct QueryGeometry { | ||||
QueryGeometry(const string& f) : field(f), predicate(INTERSECT) {} | ||||
enum Predicate { | ||||
WITHIN, | ||||
INTERSECT, | ||||
}; | ||||
// Name of the field in the query. | ||||
string field; | ||||
// Only one of these should be non-NULL. S2Region is a superclass | ||||
but it only supports | ||||
// testing against S2Cells. We need the most specific class we can | ||||
get. | ||||
// Owned by S2Cursor. | ||||
shared_ptr<S2Cell> cell; | ||||
shared_ptr<S2Polyline> line; | ||||
shared_ptr<S2Polygon> polygon; | ||||
Predicate predicate; | ||||
string toString() const; | ||||
bool satisfiesPredicate(const BSONObj &obj); | ||||
// Does this QueryGeometry intersect the provided data? Sadly ther | ||||
e is no common good way | ||||
// to check this, so we do different things for all query/data pair | ||||
s. | ||||
bool intersects(const S2Cell& otherPoint); | ||||
bool intersects(const S2Polyline& otherLine); | ||||
bool intersects(const S2Polygon& otherPolygon); | ||||
// And, within. | ||||
bool isWithin(const S2Cell& otherPoint); | ||||
bool isWithin(const S2Polyline& otherLine); | ||||
bool isWithin(const S2Polygon& otherPolygon); | ||||
// One region is not NULL and this returns it. | ||||
const S2Region& getRegion() const; | ||||
// Get the centroid, boring if we're a point, interesting if we're | ||||
not. | ||||
S2Point getCentroid() const; | ||||
// Try to parse the provided object into the right place. | ||||
bool parseFrom(const BSONObj &obj); | ||||
}; | }; | |||
struct S2IndexingParams { | struct S2IndexingParams { | |||
static const double kRadiusOfEarthInMeters; | ||||
// Since we take the cartesian product when we generate keys for an insert, | // Since we take the cartesian product when we generate keys for an insert, | |||
// we need a cap. | // we need a cap. | |||
size_t maxKeysPerInsert; | size_t maxKeysPerInsert; | |||
// This is really an advisory parameter that we pass to the cover g enerator. The | // This is really an advisory parameter that we pass to the cover g enerator. The | |||
// finest/coarsest index level determine the required # of cells. | // finest/coarsest index level determine the required # of cells. | |||
int maxCellsInCovering; | int maxCellsInCovering; | |||
// What's the finest grained level that we'll index? When we query for a point | // What's the finest grained level that we'll index? When we query for a point | |||
// we start at that -- we index nothing finer than this. | // we start at that -- we index nothing finer than this. | |||
int finestIndexedLevel; | int finestIndexedLevel; | |||
// And, what's the coarsest? When we search in larger coverings we know we | // And, what's the coarsest? When we search in larger coverings we know we | |||
End of changes. 3 change blocks. | ||||
46 lines changed or deleted | 5 lines changed or added | |||
s2cursor.h | s2cursor.h | |||
---|---|---|---|---|
skipping to change at line 24 | skipping to change at line 24 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | */ | |||
#include <vector> | #include <vector> | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/commands.h" | #include "mongo/db/commands.h" | |||
#include "mongo/db/cursor.h" | #include "mongo/db/cursor.h" | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/matcher.h" | #include "mongo/db/matcher.h" | |||
#include "mongo/db/queryutil.h" | #include "mongo/db/queryutil.h" | |||
#include "mongo/db/geo/geoquery.h" | ||||
#include "mongo/db/geo/s2common.h" | #include "mongo/db/geo/s2common.h" | |||
namespace mongo { | namespace mongo { | |||
class BtreeCursor; | class BtreeCursor; | |||
class S2Cursor : public Cursor { | class S2Cursor : public Cursor { | |||
public: | public: | |||
S2Cursor(const BSONObj &keyPattern, const IndexDetails* details, co nst BSONObj &query, | S2Cursor(const BSONObj &keyPattern, const IndexDetails* details, co nst BSONObj &query, | |||
const vector<QueryGeometry> ®ions, const S2IndexingPara | const vector<GeoQuery> ®ions, const S2IndexingParams &p | |||
ms ¶ms, | arams); | |||
int numWanted); | ||||
virtual ~S2Cursor(); | virtual ~S2Cursor(); | |||
virtual CoveredIndexMatcher *matcher() const; | virtual CoveredIndexMatcher *matcher() const; | |||
virtual bool supportYields() { return true; } | virtual bool supportYields() { return true; } | |||
virtual bool supportGetMore() { return true; } | virtual bool supportGetMore() { return true; } | |||
virtual bool isMultiKey() const { return true; } | virtual bool isMultiKey() const { return true; } | |||
virtual bool autoDedup() const { return false; } | virtual bool autoDedup() const { return false; } | |||
virtual bool modifiedKeys() const { return true; } | virtual bool modifiedKeys() const { return true; } | |||
virtual bool getsetdup(DiskLoc loc) { return false; } | virtual bool getsetdup(DiskLoc loc) { return false; } | |||
virtual string toString() { return "S2Cursor"; } | virtual string toString() { return "S2Cursor"; } | |||
skipping to change at line 68 | skipping to change at line 68 | |||
// It's kind of a monstrous object. Thanks, FieldRangeSet, for doi ng all the work | // It's kind of a monstrous object. Thanks, FieldRangeSet, for doi ng all the work | |||
// for us. | // for us. | |||
// Returns false if the FRS object would be empty. | // Returns false if the FRS object would be empty. | |||
bool makeFRSObject(BSONObj *out); | bool makeFRSObject(BSONObj *out); | |||
// Need this to make a FieldRangeSet. | // Need this to make a FieldRangeSet. | |||
const IndexDetails *_details; | const IndexDetails *_details; | |||
// The query with the geo stuff taken out. We use this with a matc her. | // The query with the geo stuff taken out. We use this with a matc her. | |||
BSONObj _filteredQuery; | BSONObj _filteredQuery; | |||
// What geo regions are we looking for? | // What geo regions are we looking for? | |||
vector<QueryGeometry> _fields; | vector<GeoQuery> _fields; | |||
// We use this for matching non-GEO stuff. | // We use this for matching non-GEO stuff. | |||
shared_ptr<CoveredIndexMatcher> _matcher; | shared_ptr<CoveredIndexMatcher> _matcher; | |||
// How were the keys created? We need this to search for the right stuff. | // How were the keys created? We need this to search for the right stuff. | |||
S2IndexingParams _params; | S2IndexingParams _params; | |||
// How many things did we scan/look at? Not sure exactly how this | ||||
is defined. | ||||
long long _nscanned; | ||||
// We have to pass this to the FieldRangeVector ctor (in modified f orm). | // We have to pass this to the FieldRangeVector ctor (in modified f orm). | |||
BSONObj _keyPattern; | BSONObj _keyPattern; | |||
// How many docs do we want to return? Starts with the # the user | ||||
requests | ||||
// and goes down. | ||||
int _numToReturn; | ||||
// What have we checked so we don't repeat it and waste time? | // What have we checked so we don't repeat it and waste time? | |||
set<DiskLoc> _seen; | set<DiskLoc> _seen; | |||
// This really does all the work/points into the btree. | // This really does all the work/points into the btree. | |||
scoped_ptr<BtreeCursor> _btreeCursor; | scoped_ptr<BtreeCursor> _btreeCursor; | |||
// Stat counters/debug information goes below. | ||||
// How many items did we look at in the btree? | ||||
long long _nscanned; | ||||
// How many did we try to match? | ||||
long long _matchTested; | ||||
// How many did we geo-test? | ||||
long long _geoTested; | ||||
// How many cells were in our cover? | ||||
long long _cellsInCover; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 6 change blocks. | ||||
11 lines changed or deleted | 14 lines changed or added | |||
s2index.h | s2index.h | |||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* 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/>. | |||
*/ | */ | |||
namespace mongo { | namespace mongo { | |||
bool run2DSphereGeoNear(const IndexDetails &id, BSONObj& cmdObj, string | // We need cmdObj and parsedArgs so we can print a useful error msg. | |||
& errmsg, | bool run2DSphereGeoNear(const IndexDetails &id, BSONObj& cmdObj, | |||
const GeoNearArguments &parsedArgs, string& err | ||||
msg, | ||||
BSONObjBuilder& result); | BSONObjBuilder& result); | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 4 lines changed or added | |||
s2nearcursor.h | s2nearcursor.h | |||
---|---|---|---|---|
skipping to change at line 26 | skipping to change at line 26 | |||
#include <vector> | #include <vector> | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/commands.h" | #include "mongo/db/commands.h" | |||
#include "mongo/db/btreecursor.h" | #include "mongo/db/btreecursor.h" | |||
#include "mongo/db/cursor.h" | #include "mongo/db/cursor.h" | |||
#include "mongo/db/diskloc.h" | #include "mongo/db/diskloc.h" | |||
#include "mongo/db/matcher.h" | #include "mongo/db/matcher.h" | |||
#include "mongo/db/queryutil.h" | #include "mongo/db/queryutil.h" | |||
#include "mongo/db/geo/s2common.h" | #include "mongo/db/geo/s2common.h" | |||
#include "mongo/db/geo/geoquery.h" | ||||
#include "mongo/platform/unordered_set.h" | ||||
#include "third_party/s2/s2cap.h" | ||||
#include "third_party/s2/s2regionintersection.h" | ||||
namespace mongo { | namespace mongo { | |||
class S2NearCursor : public Cursor { | class S2NearCursor : public Cursor { | |||
public: | public: | |||
S2NearCursor(const BSONObj &keyPattern, const IndexDetails* details , const BSONObj &query, | S2NearCursor(const BSONObj &keyPattern, const IndexDetails* details , const BSONObj &query, | |||
const vector<QueryGeometry> ®ions, const S2Indexing | const NearQuery &nearQuery, const vector<GeoQuery> &in | |||
Params ¶ms, | dexedGeoRegions, | |||
int numWanted, double maxDistance); | const S2IndexingParams ¶ms); | |||
virtual ~S2NearCursor(); | virtual ~S2NearCursor(); | |||
virtual CoveredIndexMatcher *matcher() const; | virtual CoveredIndexMatcher *matcher() const; | |||
virtual bool supportYields() { return true; } | virtual bool supportYields() { return true; } | |||
virtual bool supportGetMore() { return true; } | virtual bool supportGetMore() { return true; } | |||
virtual bool isMultiKey() const { return true; } | virtual bool isMultiKey() const { return true; } | |||
virtual bool autoDedup() const { return false; } | virtual bool autoDedup() const { return false; } | |||
virtual bool modifiedKeys() const { return true; } | virtual bool modifiedKeys() const { return true; } | |||
virtual bool getsetdup(DiskLoc loc) { return false; } | virtual bool getsetdup(DiskLoc loc) { return false; } | |||
virtual string toString() { return "S2NearCursor"; } | virtual string toString() { return "S2NearCursor"; } | |||
skipping to change at line 81 | skipping to change at line 85 | |||
// Make the object that describes all keys that are within our curr ent search annulus. | // Make the object that describes all keys that are within our curr ent search annulus. | |||
BSONObj makeFRSObject(); | BSONObj makeFRSObject(); | |||
// Fill _results with all of the results in the annulus defined by _innerRadius and | // Fill _results with all of the results in the annulus defined by _innerRadius and | |||
// _outerRadius. If no results are found, grow the annulus and rep eat until success (or | // _outerRadius. If no results are found, grow the annulus and rep eat until success (or | |||
// until the edge of the world). | // until the edge of the world). | |||
void fillResults(); | void fillResults(); | |||
// Grow _innerRadius and _outerRadius by _radiusIncrement, capping _outerRadius at halfway | // Grow _innerRadius and _outerRadius by _radiusIncrement, capping _outerRadius at halfway | |||
// around the world (pi * _params.radius). | // around the world (pi * _params.radius). | |||
void nextAnnulus(); | void nextAnnulus(); | |||
double distanceBetween(const QueryGeometry &field, const BSONObj &o bj); | double distanceTo(const BSONObj &obj); | |||
// Need this to make a FieldRangeSet. | // Need this to make a FieldRangeSet. | |||
const IndexDetails *_details; | const IndexDetails *_details; | |||
// How we need/use the query: | // How we need/use the query: | |||
// Matcher: Can have geo fields in it, but only with $within. | // Matcher: Can have geo fields in it, but only with $within. | |||
// This only really happens (right now) from geoNear comma nd. | // This only really happens (right now) from geoNear comma nd. | |||
// We assume the caller takes care of this in the right wa y. | // We assume the caller takes care of this in the right wa y. | |||
// FRS: No geo fields allowed! | // FRS: No geo fields allowed! | |||
// So, on that note: the query with the geo stuff taken out, used b y makeFRSObject(). | // So, on that note: the query with the geo stuff taken out, used b y makeFRSObject(). | |||
BSONObj _filteredQuery; | BSONObj _filteredQuery; | |||
// The GeoQuery for the point we're doing near searching from. | ||||
NearQuery _nearQuery; | ||||
// What geo regions are we looking for? | // What geo regions are we looking for? | |||
vector<QueryGeometry> _fields; | vector<GeoQuery> _indexedGeoFields; | |||
// We use this for matching non-GEO stuff. | // We use this for matching non-GEO stuff. | |||
shared_ptr<CoveredIndexMatcher> _matcher; | shared_ptr<CoveredIndexMatcher> _matcher; | |||
// How were the keys created? We need this to search for the right stuff. | // How were the keys created? We need this to search for the right stuff. | |||
S2IndexingParams _params; | S2IndexingParams _params; | |||
// How many things did we scan/look at? Not sure exactly how this | ||||
is defined. | ||||
long long _nscanned; | ||||
// We have to pass this to the FieldRangeVector ctor (in modified f orm). | // We have to pass this to the FieldRangeVector ctor (in modified f orm). | |||
BSONObj _keyPattern; | BSONObj _keyPattern; | |||
// We also pass this to the FieldRangeVector ctor. | // We also pass this to the FieldRangeVector ctor. | |||
IndexSpec _specForFRV; | IndexSpec _specForFRV; | |||
// How many docs do we want to return? Starts with the # the user | ||||
requests and goes down. | ||||
int _numToReturn; | ||||
// Geo-related variables. | // Geo-related variables. | |||
// What's the max distance (arc length) we're willing to look for r esults? | // What's the max distance (arc length) we're willing to look for r esults? | |||
double _maxDistance; | double _maxDistance; | |||
// We compute an annulus of results and cache it here. | // We compute an annulus of results and cache it here. | |||
priority_queue<Result> _results; | priority_queue<Result> _results; | |||
// These radii define the annulus. | // These radii define the annulus we're currently looking at. | |||
double _innerRadius; | double _innerRadius; | |||
double _outerRadius; | double _outerRadius; | |||
// When we search the next annulus, what to adjust our radius by? Grows when we search an | // When we search the next annulus, what to adjust our radius by? Grows when we search an | |||
// annulus and find no results. | // annulus and find no results. | |||
double _radiusIncrement; | double _radiusIncrement; | |||
set<DiskLoc> _returned; | // What have we returned already? | |||
unordered_set<DiskLoc, DiskLoc::Hasher> _returned; | ||||
struct Stats { | ||||
Stats() : _nscanned(0), _matchTested(0), _geoMatchTested(0), _n | ||||
umShells(0), | ||||
_keyGeoSkip(0), _returnSkip(0), _btreeDups(0), _inAnn | ||||
ulusTested(0), | ||||
_numReturned(0) {} | ||||
// Stat counters/debug information goes below. | ||||
// How many items did we look at in the btree? | ||||
long long _nscanned; | ||||
// How many did we try to match? | ||||
long long _matchTested; | ||||
// How many did we geo-test? | ||||
long long _geoMatchTested; | ||||
// How many search shells did we use? | ||||
long long _numShells; | ||||
// How many did we skip due to key-geo check? | ||||
long long _keyGeoSkip; | ||||
long long _returnSkip; | ||||
long long _btreeDups; | ||||
long long _inAnnulusTested; | ||||
long long _numReturned; | ||||
}; | ||||
Stats _stats; | ||||
// The S2 machinery that represents the search annulus | ||||
S2Cap _innerCap; | ||||
S2Cap _outerCap; | ||||
S2RegionIntersection _annulus; | ||||
// This is the "array index" of the key field that is the near fiel | ||||
d. We use this to do | ||||
// cheap is-this-doc-in-the-annulus testing. | ||||
int _nearFieldIndex; | ||||
// The max distance we've returned so far. | ||||
double _returnedDistance; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 9 change blocks. | ||||
13 lines changed or deleted | 50 lines changed or added | |||
sasl_client_authenticate.h | sasl_client_authenticate.h | |||
---|---|---|---|---|
skipping to change at line 22 | skipping to change at line 22 | |||
* 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 "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/bson/bsontypes.h" | #include "mongo/bson/bsontypes.h" | |||
#include "mongo/client/dbclientinterface.h" | #include "mongo/client/dbclientinterface.h" | |||
struct Gsasl; | ||||
namespace mongo { | namespace mongo { | |||
class BSONObj; | class BSONObj; | |||
/** | /** | |||
* Attempts to authenticate "client" using the SASL protocol. | * Attempts to authenticate "client" using the SASL protocol. | |||
* | * | |||
* Requires an initialized instance of the "gsasl" library, as the firs | * Do not use directly in client code. Use the DBClientWithCommands::a | |||
t | uth(const BSONObj&) | |||
* parameter. | * method, instead. | |||
* | ||||
* Test against NULL for availability. Client driver must be compiled | ||||
with SASL support _and_ | ||||
* client application must have successfully executed mongo::runGlobalI | ||||
nitializersOrDie() or its | ||||
* ilk to make this functionality available. | ||||
* | * | |||
* The "saslParameters" BSONObj should be initialized with zero or more of the | * The "saslParameters" BSONObj should be initialized with zero or more of the | |||
* fields below. Which fields are required depends on the mechanism. Consult the | * fields below. Which fields are required depends on the mechanism. Consult the | |||
* libgsasl documentation. | * libgsasl documentation. | |||
* | * | |||
* "mechanism": The string name of the sasl mechanism to use. Mand atory. | * "mechanism": The string name of the sasl mechanism to use. Mand atory. | |||
* "autoAuthorize": Truthy values tell the server to automatically acquire privileges on | * "autoAuthorize": Truthy values tell the server to automatically acquire privileges on | |||
* all resources after successful authentication, which is the default. Falsey values | * all resources after successful authentication, which is the default. Falsey values | |||
* instruct the server to await separate privilege-acquisition commands. | * instruct the server to await separate privilege-acquisition commands. | |||
* "user": The string name of the principal to authenticate, GSASL_ AUTHID. | * "user": The string name of the principal to authenticate, GSASL_ AUTHID. | |||
* "userSource": The database target of the auth command, which ide ntifies the location | * "userSource": The database target of the auth command, which ide ntifies the location | |||
* of the credential information for the principal. May be "$s asl" if credential | * of the credential information for the principal. May be "$e xternal" if credential | |||
* information is stored outside of the mongo cluster. | * information is stored outside of the mongo cluster. | |||
* "pwd": The password data, GSASL_PASSWORD. | * "pwd": The password data, GSASL_PASSWORD. | |||
* "serviceName": The GSSAPI service name to use. Defaults to "mon godb". | * "serviceName": The GSSAPI service name to use. Defaults to "mon godb". | |||
* "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote host. | * "serviceHostname": The GSSAPI hostname to use. Defaults to the name of the remote host. | |||
* | * | |||
* Other fields in saslParameters are silently ignored. | * Other fields in saslParameters are silently ignored. | |||
* | * | |||
* "sessionHook" is a pointer to optional data, which may be used by th e gsasl_callback | * "sessionHook" is a pointer to optional data, which may be used by th e gsasl_callback | |||
* previously set on "gsasl". The session hook is set on an underlying Gsasl_session using | * previously set on "gsasl". The session hook is set on an underlying Gsasl_session using | |||
* gsasl_session_hook_set, and may be accessed by callbacks using gsasl _session_hook_get. | * gsasl_session_hook_set, and may be accessed by callbacks using gsasl _session_hook_get. | |||
* See the gsasl documentation. | * See the gsasl documentation. | |||
* | * | |||
* Returns an OK status on success, and ErrorCodes::AuthenticationFaile d if authentication is | * Returns an OK status on success, and ErrorCodes::AuthenticationFaile d if authentication is | |||
* rejected. Other failures, all of which are tantamount to authentica tion failure, may also be | * rejected. Other failures, all of which are tantamount to authentica tion failure, may also be | |||
* returned. | * returned. | |||
*/ | */ | |||
Status saslClientAuthenticate(Gsasl *gsasl, | extern Status (*saslClientAuthenticate)(DBClientWithCommands* client, | |||
DBClientWithCommands* client, | const BSONObj& saslParameters, | |||
const BSONObj& saslParameters, | void* sessionHook); | |||
void* sessionHook); | ||||
/** | /** | |||
* Extracts the payload field from "cmdObj", and store it into "*payloa d". | * Extracts the payload field from "cmdObj", and store it into "*payloa d". | |||
* | * | |||
* Sets "*type" to the BSONType of the payload field in cmdObj. | * Sets "*type" to the BSONType of the payload field in cmdObj. | |||
* | * | |||
* If the type of the payload field is String, the contents base64 deco des and | * If the type of the payload field is String, the contents base64 deco des and | |||
* stores into "*payload". If the type is BinData, the contents are st ored directly | * stores into "*payload". If the type is BinData, the contents are st ored directly | |||
* into "*payload". In all other cases, returns | * into "*payload". In all other cases, returns | |||
*/ | */ | |||
skipping to change at line 120 | skipping to change at line 121 | |||
extern const char* const saslCommandPasswordFieldName; | extern const char* const saslCommandPasswordFieldName; | |||
/// Field containing sasl payloads passed to and from the server. | /// Field containing sasl payloads passed to and from the server. | |||
extern const char* const saslCommandPayloadFieldName; | extern const char* const saslCommandPayloadFieldName; | |||
/// Field containing the string identifier of the principal to authenti cate in | /// Field containing the string identifier of the principal to authenti cate in | |||
/// saslClientAuthenticate(). | /// saslClientAuthenticate(). | |||
extern const char* const saslCommandPrincipalFieldName; | extern const char* const saslCommandPrincipalFieldName; | |||
/// Field containing the string identifier of the database containing c redential information, | /// Field containing the string identifier of the database containing c redential information, | |||
/// or "$sasl" if the credential information is stored outside of the m ongo cluster. | /// or "$external" if the credential information is stored outside of t he mongo cluster. | |||
extern const char* const saslCommandPrincipalSourceFieldName; | extern const char* const saslCommandPrincipalSourceFieldName; | |||
/// Field overriding the FQDN of the hostname hosting the mongodb srevi ce in | /// Field overriding the FQDN of the hostname hosting the mongodb srevi ce in | |||
/// saslClientAuthenticate(). | /// saslClientAuthenticate(). | |||
extern const char* const saslCommandServiceHostnameFieldName; | extern const char* const saslCommandServiceHostnameFieldName; | |||
/// Field overriding the name of the mongodb service saslClientAuthenti cate(). | /// Field overriding the name of the mongodb service saslClientAuthenti cate(). | |||
extern const char* const saslCommandServiceNameFieldName; | extern const char* const saslCommandServiceNameFieldName; | |||
/// Default database against which sasl authentication commands should run. | /// Default database against which sasl authentication commands should run. | |||
extern const char* const saslDefaultDBName; | extern const char* const saslDefaultDBName; | |||
/// Default sasl service name, "mongodb". | /// Default sasl service name, "mongodb". | |||
extern const char* const saslDefaultServiceName; | extern const char* const saslDefaultServiceName; | |||
// Field whose value should be set to true if the field in saslCommandP | ||||
asswordFieldName needs to | ||||
// be digested. | ||||
extern const char* const saslCommandDigestPasswordFieldName; | ||||
} | } | |||
End of changes. 6 change blocks. | ||||
11 lines changed or deleted | 19 lines changed or added | |||
scanandorder.h | scanandorder.h | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
namespace mongo { | namespace mongo { | |||
static const int ScanAndOrderMemoryLimitExceededAssertionCode = 10128; | static const int ScanAndOrderMemoryLimitExceededAssertionCode = 10128; | |||
class KeyType : boost::noncopyable { | class KeyType : boost::noncopyable { | |||
public: | public: | |||
IndexSpec _spec; | IndexSpec _spec; | |||
FieldRangeVector _keyCutter; | FieldRangeVector _keyCutter; | |||
public: | public: | |||
KeyType(const BSONObj &pattern, const FieldRangeSet &frs): | KeyType(const BSONObj &pattern, const FieldRangeSet &frs): | |||
_spec((verify(!pattern.isEmpty()),pattern)), | _spec(pattern, BSONObj(), IndexSpec::NoPlugins), | |||
_keyCutter(frs, _spec, 1) { | _keyCutter(frs, _spec, 1) { | |||
verify(!pattern.isEmpty()); | ||||
} | } | |||
/** | /** | |||
* @return first key of the object that would be encountered while | * @return first key of the object that would be encountered while | |||
* scanning an index with keySpec 'pattern' using constraints 'frs' , or | * scanning an index with keySpec 'pattern' using constraints 'frs' , or | |||
* BSONObj() if no such key. | * BSONObj() if no such key. | |||
*/ | */ | |||
BSONObj getKeyFromObject(const BSONObj &o) const { | BSONObj getKeyFromObject(const BSONObj &o) const { | |||
return _keyCutter.firstMatch(o); | return _keyCutter.firstMatch(o); | |||
} | } | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 2 lines changed or added | |||
server_parameters.h | server_parameters.h | |||
---|---|---|---|---|
skipping to change at line 39 | skipping to change at line 39 | |||
class ServerParameterSet; | class ServerParameterSet; | |||
/** | /** | |||
* Lets you make server level settings easily configurable. | * Lets you make server level settings easily configurable. | |||
* Hooks into (set|get)Paramter, as well as command line processing | * Hooks into (set|get)Paramter, as well as command line processing | |||
*/ | */ | |||
class ServerParameter { | class ServerParameter { | |||
public: | public: | |||
typedef std::map< std::string, ServerParameter* > Map; | typedef std::map< std::string, ServerParameter* > Map; | |||
ServerParameter( ServerParameterSet* sps, const std::string& name, | ||||
bool allowedToChangeAtStartup, bool allowedToChang | ||||
eAtRuntime ); | ||||
ServerParameter( ServerParameterSet* sps, const std::string& name ) ; | ServerParameter( ServerParameterSet* sps, const std::string& name ) ; | |||
virtual ~ServerParameter(); | virtual ~ServerParameter(); | |||
std::string name() const { return _name; } | std::string name() const { return _name; } | |||
/** | /** | |||
* @return if you can set on command line or config file | * @return if you can set on command line or config file | |||
*/ | */ | |||
virtual bool allowedToChangeAtStartup() const { return true; } | bool allowedToChangeAtStartup() const { return _allowedToChangeAtSt artup; } | |||
/** | /** | |||
* @param if you can use (get|set)Parameter | * @param if you can use (get|set)Parameter | |||
*/ | */ | |||
virtual bool allowedToChangeAtRuntime() const { return true; } | bool allowedToChangeAtRuntime() const { return _allowedToChangeAtRu ntime; } | |||
virtual void append( BSONObjBuilder& b, const string& name ) = 0; | virtual void append( BSONObjBuilder& b, const string& name ) = 0; | |||
virtual Status set( const BSONElement& newValueElement ) = 0; | virtual Status set( const BSONElement& newValueElement ) = 0; | |||
virtual Status setFromString( const string& str ) = 0; | virtual Status setFromString( const string& str ) = 0; | |||
private: | private: | |||
string _name; | string _name; | |||
bool _allowedToChangeAtStartup; | ||||
bool _allowedToChangeAtRuntime; | ||||
}; | }; | |||
class ServerParameterSet { | class ServerParameterSet { | |||
public: | public: | |||
typedef std::map< std::string, ServerParameter* > Map; | typedef std::map< std::string, ServerParameter* > Map; | |||
void add( ServerParameter* sp ); | void add( ServerParameter* sp ); | |||
const Map& getMap() const { return _map; } | const Map& getMap() const { return _map; } | |||
static ServerParameterSet* getGlobal(); | static ServerParameterSet* getGlobal(); | |||
private: | private: | |||
Map _map; | Map _map; | |||
}; | }; | |||
/** | ||||
* Implementation of ServerParameter for reading and writing a server p | ||||
arameter with a given | ||||
* name and type into a specific C++ variable. | ||||
*/ | ||||
template<typename T> | template<typename T> | |||
class ExportedServerParameter : public ServerParameter { | class ExportedServerParameter : public ServerParameter { | |||
public: | public: | |||
ExportedServerParameter( ServerParameterSet* sps, const std::string | ||||
& name, T* value ) | /** | |||
: ServerParameter( sps, name ), _value( value ) {} | * Construct an ExportedServerParameter in parameter set "sps", nam | |||
ed "name", whose storage | ||||
* is at "value". | ||||
* | ||||
* If allowedToChangeAtStartup is true, the parameter may be set at | ||||
the command line, | ||||
* e.g. via the --setParameter switch. If allowedToChangeAtRuntime | ||||
is true, the parameter | ||||
* may be set at runtime, e.g. via the setParameter command. | ||||
*/ | ||||
ExportedServerParameter( ServerParameterSet* sps, const std::string | ||||
& name, T* value, | ||||
bool allowedToChangeAtStartup, bool allowe | ||||
dToChangeAtRuntime) | ||||
: ServerParameter( sps, name, allowedToChangeAtStartup, allowed | ||||
ToChangeAtRuntime ), | ||||
_value( value ) {} | ||||
virtual ~ExportedServerParameter() {} | virtual ~ExportedServerParameter() {} | |||
virtual void append( BSONObjBuilder& b, const string& name ) { | virtual void append( BSONObjBuilder& b, const string& name ) { | |||
b.append( name, *_value ); | b.append( name, *_value ); | |||
} | } | |||
virtual Status set( const BSONElement& newValueElement ); | virtual Status set( const BSONElement& newValueElement ); | |||
virtual Status set( const T& newValue ); | virtual Status set( const T& newValue ); | |||
virtual const T& get() const { return *_value; } | virtual const T& get() const { return *_value; } | |||
virtual Status setFromString( const string& str ); | virtual Status setFromString( const string& str ); | |||
protected: | protected: | |||
virtual Status validate( const T& potentialNewValue ){ return Statu s::OK(); } | virtual Status validate( const T& potentialNewValue ){ return Statu s::OK(); } | |||
T* _value; // owned elsewhere | T* _value; // owned elsewhere | |||
}; | }; | |||
} | ||||
#define MONGO_EXPORT_SERVER_PARAMETER_IMPL( NAME, TYPE, INITIAL_VALUE, \ | ||||
CHANGE_AT_STARTUP, CHANGE_AT_RU | ||||
NTIME ) \ | ||||
TYPE NAME = INITIAL_VALUE; \ | ||||
ExportedServerParameter<TYPE> _##NAME(\ | ||||
ServerParameterSet::getGlobal(), #NAME, &NAME, CHANGE_AT_STARTU | ||||
P, CHANGE_AT_RUNTIME ) | ||||
/** | ||||
* Create a global variable of type "TYPE" named "NAME" with the given INIT | ||||
IAL_VALUE. The | ||||
* value may be set at startup or at runtime. | ||||
*/ | ||||
#define MONGO_EXPORT_SERVER_PARAMETER( NAME, TYPE, INITIAL_VALUE ) \ | #define MONGO_EXPORT_SERVER_PARAMETER( NAME, TYPE, INITIAL_VALUE ) \ | |||
TYPE NAME = INITIAL_VALUE; \ | MONGO_EXPORT_SERVER_PARAMETER_IMPL( NAME, TYPE, INITIAL_VALUE, true, tr | |||
ExportedServerParameter<TYPE> _##NAME( ServerParameterSet::getGlobal(), | ue ) | |||
#NAME, &NAME ) | ||||
} | /** | |||
* Like MONGO_EXPORT_SERVER_PARAMETER, but the value may only be set at sta | ||||
rtup. | ||||
*/ | ||||
#define MONGO_EXPORT_STARTUP_SERVER_PARAMETER( NAME, TYPE, INITIAL_VALUE ) | ||||
\ | ||||
MONGO_EXPORT_SERVER_PARAMETER_IMPL( NAME, TYPE, INITIAL_VALUE, true, fa | ||||
lse ) | ||||
/** | ||||
* Like MONGO_EXPORT_SERVER_PARAMETER, but the value may only be set at run | ||||
time. | ||||
*/ | ||||
#define MONGO_EXPORT_RUNTIME_SERVER_PARAMETER( NAME, TYPE, INITIAL_VALUE ) | ||||
\ | ||||
MONGO_EXPORT_SERVER_PARAMETER_IMPL( NAME, TYPE, INITIAL_VALUE, false, t | ||||
rue ) | ||||
#include "server_parameters_inline.h" | #include "server_parameters_inline.h" | |||
End of changes. 10 change blocks. | ||||
9 lines changed or deleted | 64 lines changed or added | |||
shapes.h | shapes.h | |||
---|---|---|---|---|
skipping to change at line 23 | skipping to change at line 23 | |||
* 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 "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
// TODO(hk): move these distance things to something like geomath.h | ||||
struct Point; | struct Point; | |||
double distance(const Point& p1, const Point &p2); | double distance(const Point& p1, const Point &p2); | |||
bool distanceWithin(const Point &p1, const Point &p2, double radius); | bool distanceWithin(const Point &p1, const Point &p2, double radius); | |||
void checkEarthBounds(const Point &p); | void checkEarthBounds(const Point &p); | |||
double spheredist_rad(const Point& p1, const Point& p2); | double spheredist_rad(const Point& p1, const Point& p2); | |||
double spheredist_deg(const Point& p1, const Point& p2); | double spheredist_deg(const Point& p1, const Point& p2); | |||
struct Point { | struct Point { | |||
Point(); | Point(); | |||
Point(double x, double y); | Point(double x, double y); | |||
explicit Point(const BSONElement& e); | explicit Point(const BSONElement& e); | |||
explicit Point(const BSONObj& o); | explicit Point(const BSONObj& o); | |||
string toString() const; | string toString() const; | |||
double x; | double x; | |||
double y; | double y; | |||
}; | }; | |||
struct Circle { | ||||
Circle(); | ||||
Circle(double radius, Point center); | ||||
double radius; | ||||
Point center; | ||||
}; | ||||
class Box { | class Box { | |||
public: | public: | |||
Box(); | Box(); | |||
Box(double x, double y, double size); | Box(double x, double y, double size); | |||
Box(Point min, Point max); | Box(Point min, Point max); | |||
BSONArray toBSON() const; | BSONArray toBSON() const; | |||
string toString() const; | string toString() const; | |||
bool between(double min, double max, double val, double fudge = 0) const; | bool between(double min, double max, double val, double fudge = 0) const; | |||
bool onBoundary(double bound, double val, double fudge = 0) const; | bool onBoundary(double bound, double val, double fudge = 0) const; | |||
// TODO(hk) comment | ||||
bool mid(double amin, double amax, double bmin, double bmax, bool m in, double* res) const; | bool mid(double amin, double amax, double bmin, double bmax, bool m in, double* res) const; | |||
// TODO(hk): What is the return here? comment | ||||
double intersects(const Box& other) const; | double intersects(const Box& other) const; | |||
double area() const; | double area() const; | |||
double maxDim() const; | double maxDim() const; | |||
Point center() const; | Point center() const; | |||
void truncate(double min, double max); | void truncate(double min, double max); | |||
void fudge(double error); | void fudge(double error); | |||
bool onBoundary(Point p, double fudge = 0); | bool onBoundary(Point p, double fudge = 0); | |||
bool inside(Point p, double fudge = 0) const; | bool inside(Point p, double fudge = 0) const; | |||
bool inside(double x, double y, double fudge = 0) const; | bool inside(double x, double y, double fudge = 0) const; | |||
bool contains(const Box& other, double fudge = 0); | bool contains(const Box& other, double fudge = 0); | |||
// TODO(hk): This could be private and Polygon could be our friend, | ||||
or we could | ||||
// have getters/setters (lots of code change). | ||||
Point _min; | Point _min; | |||
Point _max; | Point _max; | |||
}; | }; | |||
class Polygon { | class Polygon { | |||
public: | public: | |||
Polygon(); | Polygon(); | |||
Polygon(vector<Point> points); | Polygon(vector<Point> points); | |||
void add(Point p); | void add(Point p); | |||
End of changes. 5 change blocks. | ||||
7 lines changed or deleted | 8 lines changed or added | |||
shard.h | shard.h | |||
---|---|---|---|---|
skipping to change at line 186 | skipping to change at line 186 | |||
ShardStatus( const Shard& shard , const BSONObj& obj ); | ShardStatus( const Shard& shard , const BSONObj& obj ); | |||
friend ostream& operator << (ostream& out, const ShardStatus& s) { | friend ostream& operator << (ostream& out, const ShardStatus& s) { | |||
out << s.toString(); | out << s.toString(); | |||
return out; | return out; | |||
} | } | |||
string toString() const { | string toString() const { | |||
stringstream ss; | stringstream ss; | |||
ss << "shard: " << _shard << " mapped: " << _mapped << " writeL | ss << "shard: " << _shard | |||
ock: " << _writeLock; | << " mapped: " << _mapped | |||
<< " writeLock: " << _writeLock | ||||
<< " version: " << _mongoVersion; | ||||
return ss.str(); | return ss.str(); | |||
} | } | |||
bool operator<( const ShardStatus& other ) const { | bool operator<( const ShardStatus& other ) const { | |||
return _mapped < other._mapped; | return _mapped < other._mapped; | |||
} | } | |||
Shard shard() const { | Shard shard() const { | |||
return _shard; | return _shard; | |||
} | } | |||
long long mapped() const { | long long mapped() const { | |||
return _mapped; | return _mapped; | |||
} | } | |||
bool hasOpsQueued() const { | bool hasOpsQueued() const { | |||
return _hasOpsQueued; | return _hasOpsQueued; | |||
} | } | |||
string mongoVersion() const { | ||||
return _mongoVersion; | ||||
} | ||||
private: | private: | |||
Shard _shard; | Shard _shard; | |||
long long _mapped; | long long _mapped; | |||
bool _hasOpsQueued; // true if 'writebacks' are pending | bool _hasOpsQueued; // true if 'writebacks' are pending | |||
double _writeLock; | double _writeLock; | |||
string _mongoVersion; | ||||
}; | }; | |||
class ChunkManager; | class ChunkManager; | |||
typedef shared_ptr<const ChunkManager> ChunkManagerPtr; | typedef shared_ptr<const ChunkManager> ChunkManagerPtr; | |||
class ShardConnection : public AScopedConnection { | class ShardConnection : public AScopedConnection { | |||
public: | public: | |||
ShardConnection( const Shard * s , const string& ns, ChunkManagerPt r manager = ChunkManagerPtr() ); | ShardConnection( const Shard * s , const string& ns, ChunkManagerPt r manager = ChunkManagerPtr() ); | |||
ShardConnection( const Shard& s , const string& ns, ChunkManagerPtr manager = ChunkManagerPtr() ); | ShardConnection( const Shard& s , const string& ns, ChunkManagerPtr manager = ChunkManagerPtr() ); | |||
ShardConnection( const string& addr , const string& ns, ChunkManage rPtr manager = ChunkManagerPtr() ); | ShardConnection( const string& addr , const string& ns, ChunkManage rPtr manager = ChunkManagerPtr() ); | |||
End of changes. 3 change blocks. | ||||
2 lines changed or deleted | 9 lines changed or added | |||
ssl_manager.h | ssl_manager.h | |||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
#include <openssl/err.h> | #include <openssl/err.h> | |||
#include <openssl/ssl.h> | #include <openssl/ssl.h> | |||
namespace mongo { | namespace mongo { | |||
class SSLParams { | class SSLParams { | |||
public: | public: | |||
SSLParams(const std::string& pemfile, | SSLParams(const std::string& pemfile, | |||
const std::string& pempwd, | const std::string& pempwd, | |||
const std::string& cafile = "", | const std::string& cafile = "", | |||
const std::string& crlfile = "", | const std::string& crlfile = "", | |||
bool forceCertificateValidation = false) : | bool weakCertificateValidation = false, | |||
bool fipsMode = false) : | ||||
pemfile(pemfile), | pemfile(pemfile), | |||
pempwd(pempwd), | pempwd(pempwd), | |||
cafile(cafile), | cafile(cafile), | |||
crlfile(crlfile), | crlfile(crlfile), | |||
forceCertificateValidation(forceCertificateValidation) {}; | weakCertificateValidation(weakCertificateValidation), | |||
fipsMode(fipsMode) {}; | ||||
std::string pemfile; | std::string pemfile; | |||
std::string pempwd; | std::string pempwd; | |||
std::string cafile; | std::string cafile; | |||
std::string crlfile; | std::string crlfile; | |||
bool forceCertificateValidation; | bool weakCertificateValidation; | |||
bool fipsMode; | ||||
}; | }; | |||
class SSLManager { | class SSLManager { | |||
MONGO_DISALLOW_COPYING(SSLManager); | MONGO_DISALLOW_COPYING(SSLManager); | |||
public: | public: | |||
explicit SSLManager(const SSLParams& params); | explicit SSLManager(const SSLParams& params); | |||
/** | /** | |||
* Initiates a TLS connection. | * Initiates a TLS connection. | |||
* Throws SocketException on failure. | * Throws SocketException on failure. | |||
skipping to change at line 73 | skipping to change at line 76 | |||
*/ | */ | |||
SSL* accept(int fd); | SSL* accept(int fd); | |||
/** | /** | |||
* Fetches a peer certificate and validates it if it exists | * Fetches a peer certificate and validates it if it exists | |||
* Throws SocketException on failure | * Throws SocketException on failure | |||
*/ | */ | |||
void validatePeerCertificate(const SSL* ssl); | void validatePeerCertificate(const SSL* ssl); | |||
/** | /** | |||
* Cleans up SSL thread local memory; use at thread exit | ||||
* to avoid memory leaks | ||||
*/ | ||||
static void cleanupThreadLocals(); | ||||
/** | ||||
* Callbacks for SSL functions | * Callbacks for SSL functions | |||
*/ | */ | |||
static int password_cb( char *buf,int num, int rwflag,void *userdat a ); | static int password_cb( char *buf,int num, int rwflag,void *userdat a ); | |||
static int verify_cb(int ok, X509_STORE_CTX *ctx); | static int verify_cb(int ok, X509_STORE_CTX *ctx); | |||
private: | private: | |||
SSL_CTX* _context; | SSL_CTX* _context; | |||
std::string _password; | std::string _password; | |||
bool _validateCertificates; | bool _validateCertificates; | |||
bool _forceValidation; | bool _weakValidation; | |||
/** | /** | |||
* creates an SSL context to be used for this file descriptor. | * creates an SSL context to be used for this file descriptor. | |||
* caller must SSL_free it. | * caller must SSL_free it. | |||
*/ | */ | |||
SSL* _secure(int fd); | SSL* _secure(int fd); | |||
/** | /** | |||
* Fetches the error text for an error code, in a thread-safe manne r. | * Fetches the error text for an error code, in a thread-safe manne r. | |||
*/ | */ | |||
std::string _getSSLErrorMessage(int code); | std::string _getSSLErrorMessage(int code); | |||
skipping to change at line 113 | skipping to change at line 122 | |||
/* | /* | |||
* Set up SSL for certificate validation by loading a CA | * Set up SSL for certificate validation by loading a CA | |||
*/ | */ | |||
bool _setupCA(const std::string& caFile); | bool _setupCA(const std::string& caFile); | |||
/* | /* | |||
* Import a certificate revocation list into our SSL context | * Import a certificate revocation list into our SSL context | |||
* for use with validating certificates | * for use with validating certificates | |||
*/ | */ | |||
bool _setupCRL(const std::string& crlFile); | bool _setupCRL(const std::string& crlFile); | |||
/* | ||||
* Activate FIPS 140-2 mode, if the server started with a command l | ||||
ine | ||||
* parameter. | ||||
*/ | ||||
void _setupFIPS(); | ||||
/* | ||||
* Wrapper for SSL_Connect() that handles SSL_ERROR_WANT_READ, | ||||
* see SERVER-7940 | ||||
*/ | ||||
int _ssl_connect(SSL* ssl); | ||||
/* | ||||
* Initialize the SSL Library. | ||||
* This function can be called multiple times; it ensures it only | ||||
* does the SSL initialization once per process. | ||||
*/ | ||||
void _initializeSSL(const SSLParams& params); | ||||
}; | }; | |||
} | } | |||
#endif | #endif | |||
End of changes. 6 change blocks. | ||||
4 lines changed or deleted | 33 lines changed or added | |||
string_data-inl.h | string_data-inl.h | |||
---|---|---|---|---|
skipping to change at line 64 | skipping to change at line 64 | |||
return true; | return true; | |||
} | } | |||
inline void StringData::copyTo( char* dest, bool includeEndingNull ) co nst { | inline void StringData::copyTo( char* dest, bool includeEndingNull ) co nst { | |||
memcpy( dest, _data, size() ); | memcpy( dest, _data, size() ); | |||
if ( includeEndingNull ) | if ( includeEndingNull ) | |||
dest[size()] = 0; | dest[size()] = 0; | |||
} | } | |||
inline size_t StringData::find( char c ) const { | inline size_t StringData::find( char c, size_t fromPos ) const { | |||
const void* x = memchr( _data, c, size() ); | if ( fromPos >= size() ) | |||
return string::npos; | ||||
const void* x = memchr( _data + fromPos, c, _size - fromPos ); | ||||
if ( x == 0 ) | if ( x == 0 ) | |||
return string::npos; | return string::npos; | |||
return static_cast<size_t>( static_cast<const char*>(x) - _data ); | return static_cast<size_t>( static_cast<const char*>(x) - _data ); | |||
} | } | |||
inline size_t StringData::find( const StringData& needle ) const { | inline size_t StringData::find( const StringData& needle ) const { | |||
size_t mx = size(); | size_t mx = size(); | |||
size_t needleSize = needle.size(); | size_t needleSize = needle.size(); | |||
if ( needleSize == 0 ) | if ( needleSize == 0 ) | |||
End of changes. 1 change blocks. | ||||
2 lines changed or deleted | 5 lines changed or added | |||
string_data.h | string_data.h | |||
---|---|---|---|---|
skipping to change at line 59 | skipping to change at line 59 | |||
/** | /** | |||
* Constructs a StringData, for the case where the length of string is not known. 'c' | * Constructs a StringData, for the case where the length of string is not known. 'c' | |||
* must be a pointer to a null-terminated string. | * must be a pointer to a null-terminated string. | |||
*/ | */ | |||
StringData( const char* c ) | StringData( const char* c ) | |||
: _data(c), _size((c == NULL) ? 0 : string::npos) {} | : _data(c), _size((c == NULL) ? 0 : string::npos) {} | |||
/** | /** | |||
* Constructs a StringData explicitly, for the case where the lengt h of the string is | * Constructs a StringData explicitly, for the case where the lengt h of the string is | |||
* already known. 'c' must be a pointer to a null-terminated string , and strlenOfc must | * already known. 'c' must be a pointer to a null-terminated string , and len must | |||
* be the length that strlen(c) would return, a.k.a the index of th e terminator in c. | * be the length that strlen(c) would return, a.k.a the index of th e terminator in c. | |||
*/ | */ | |||
StringData( const char* c, size_t len ) | StringData( const char* c, size_t len ) | |||
: _data(c), _size(len) {} | : _data(c), _size(len) {} | |||
/** Constructs a StringData, for the case of a string. */ | /** Constructs a StringData, for the case of a string. */ | |||
StringData( const std::string& s ) | StringData( const std::string& s ) | |||
: _data(s.c_str()), _size(s.size()) {} | : _data(s.c_str()), _size(s.size()) {} | |||
/** | /** | |||
skipping to change at line 99 | skipping to change at line 99 | |||
bool equalCaseInsensitive( const StringData& other ) const; | bool equalCaseInsensitive( const StringData& other ) const; | |||
void copyTo( char* dest, bool includeEndingNull ) const; | void copyTo( char* dest, bool includeEndingNull ) const; | |||
StringData substr( size_t pos, size_t n = std::numeric_limits<size_ t>::max() ) const; | StringData substr( size_t pos, size_t n = std::numeric_limits<size_ t>::max() ) const; | |||
// | // | |||
// finders | // finders | |||
// | // | |||
size_t find( char c ) const; | size_t find( char c , size_t fromPos = 0 ) const; | |||
size_t find( const StringData& needle ) const; | size_t find( const StringData& needle ) const; | |||
/** | /** | |||
* Returns true if 'prefix' is a substring of this instance, anchor ed at position 0. | * Returns true if 'prefix' is a substring of this instance, anchor ed at position 0. | |||
*/ | */ | |||
bool startsWith( const StringData& prefix ) const; | bool startsWith( const StringData& prefix ) const; | |||
/** | /** | |||
* Returns true if 'suffix' is a substring of this instance, anchor ed at the end. | * Returns true if 'suffix' is a substring of this instance, anchor ed at the end. | |||
*/ | */ | |||
bool endsWith( const StringData& suffix ) const; | bool endsWith( const StringData& suffix ) const; | |||
// | // | |||
// accessors | // accessors | |||
// | // | |||
/** | /** | |||
* this is not guaranteed to be null-terminated, | * Get the pointer to the first byte of StringData. This is not gu | |||
* if you use this without all using size(), you are likely doing s | aranteed to be | |||
omething wrong | * null-terminated, so if using this without checking size(), you a | |||
re likely doing | ||||
* something wrong. | ||||
*/ | */ | |||
const char* rawData() const { return _data; } | const char* rawData() const { return _data; } | |||
size_t size() const { fillSize(); return _size; } | size_t size() const { fillSize(); return _size; } | |||
bool empty() const { return size() == 0; } | bool empty() const { return size() == 0; } | |||
string toString() const { return string(_data, size()); } | string toString() const { return string(_data, size()); } | |||
char operator[] ( unsigned pos ) const { return _data[pos]; } | char operator[] ( unsigned pos ) const { return _data[pos]; } | |||
private: | private: | |||
const char* _data; // is not guaranted to be null terminated (see "notes" above) | const char* _data; // is not guaranted to be null terminated (see "notes" above) | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 7 lines changed or added | |||
syncclusterconnection.h | syncclusterconnection.h | |||
---|---|---|---|---|
skipping to change at line 110 | skipping to change at line 110 | |||
int wtimeout=0); | int wtimeout=0); | |||
virtual BSONObj getLastErrorDetailed(bool fsync=false, bool j=false , int w=0, int wtimeout=0); | virtual BSONObj getLastErrorDetailed(bool fsync=false, bool j=false , int w=0, int wtimeout=0); | |||
virtual bool callRead( Message& toSend , Message& response ); | virtual bool callRead( Message& toSend , Message& response ); | |||
virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SYNC; } | virtual ConnectionString::ConnectionType type() const { return Conn ectionString::SYNC; } | |||
void setAllSoTimeouts( double socketTimeout ); | void setAllSoTimeouts( double socketTimeout ); | |||
double getSoTimeout() const { return _socketTimeout; } | double getSoTimeout() const { return _socketTimeout; } | |||
virtual bool auth(const string &dbname, const string &username, con | ||||
st string &password_text, string& errmsg, bool digestPassword, Auth::Level* | ||||
level=NULL); | ||||
virtual bool lazySupported() const { return false; } | virtual bool lazySupported() const { return false; } | |||
protected: | ||||
virtual void _auth(const BSONObj& params); | ||||
private: | private: | |||
SyncClusterConnection( SyncClusterConnection& prev, double socketTi meout = 0 ); | SyncClusterConnection( SyncClusterConnection& prev, double socketTi meout = 0 ); | |||
string _toString() const; | string _toString() const; | |||
bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO NObj &info, int options=0); | bool _commandOnActive(const string &dbname, const BSONObj& cmd, BSO NObj &info, int options=0); | |||
auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que ry, int nToReturn, int nToSkip, | auto_ptr<DBClientCursor> _queryOnActive(const string &ns, Query que ry, int nToReturn, int nToSkip, | |||
const BSONObj *fieldsToRetu rn, int queryOptions, int batchSize ); | const BSONObj *fieldsToRetu rn, int queryOptions, int batchSize ); | |||
int _lockType( const string& name ); | int _lockType( const string& name ); | |||
void _checkLast(); | void _checkLast(); | |||
void _connect( const std::string& host ); | void _connect( const std::string& host ); | |||
End of changes. 2 change blocks. | ||||
4 lines changed or deleted | 4 lines changed or added | |||
targetver.h | targetver.h | |||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
* This program is distributed in the hope that it will be useful, | * This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* 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 | |||
#ifndef _WIN32_WINNT // Allow use of features specific to Window | #ifdef _WIN32 | |||
s Vista or later. | #ifndef _WIN32_WINNT | |||
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to | #if defined _WIN64 | |||
target other versions of Windows. | // For 64 bit Windows we require at least Windows Vista or Windows Server 2 | |||
008. | ||||
#define _WIN32_WINNT 0x0600 | ||||
#else | ||||
// For 32 bit Windows we allow Windows XP as well. See platform/atomic_intr | ||||
insics_win32.h for | ||||
// an example of where this makes a difference. | ||||
#define _WIN32_WINNT 0x0502 | ||||
#endif | ||||
#endif | ||||
#endif | #endif | |||
End of changes. 1 change blocks. | ||||
4 lines changed or deleted | 13 lines changed or added | |||
timer_stats.h | timer_stats.h | |||
---|---|---|---|---|
skipping to change at line 55 | skipping to change at line 55 | |||
long long _num; | long long _num; | |||
long long _totalMillis; | long long _totalMillis; | |||
}; | }; | |||
/** | /** | |||
* Holds an instance of a Timer such that we the time is recorded | * Holds an instance of a Timer such that we the time is recorded | |||
* when the TimerHolder goes out of scope | * when the TimerHolder goes out of scope | |||
*/ | */ | |||
class TimerHolder { | class TimerHolder { | |||
public: | public: | |||
/** Destructor will record to TimerStats */ | ||||
TimerHolder( TimerStats* stats ); | TimerHolder( TimerStats* stats ); | |||
/** Will record stats if recordMillis hasn't (based on _recorded) */ | ||||
~TimerHolder(); | ~TimerHolder(); | |||
/** | /** | |||
* returns elapsed millis from internal timer | * returns elapsed millis from internal timer | |||
*/ | */ | |||
int millis() const { return _t.millis(); } | int millis() const { return _t.millis(); } | |||
/** | /** | |||
* records the time in the TimerStats and marks that we've | * records the time in the TimerStats and marks that we've | |||
* already recorded so the destructor doesn't | * already recorded so the destructor doesn't | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
tool.h | tool.h | |||
---|---|---|---|---|
skipping to change at line 105 | skipping to change at line 105 | |||
virtual void printHelp(ostream &out); | virtual void printHelp(ostream &out); | |||
virtual void printExtraHelp( ostream & out ) {} | virtual void printExtraHelp( ostream & out ) {} | |||
virtual void printExtraHelpAfter( ostream & out ) {} | virtual void printExtraHelpAfter( ostream & out ) {} | |||
virtual void printVersion(ostream &out); | virtual void printVersion(ostream &out); | |||
protected: | protected: | |||
mongo::DBClientBase &conn( bool slaveIfPaired = false ); | mongo::DBClientBase &conn( bool slaveIfPaired = false ); | |||
void auth( string db = "", Auth::Level * level = NULL); | ||||
string _name; | string _name; | |||
string _db; | string _db; | |||
string _coll; | string _coll; | |||
string _fileName; | string _fileName; | |||
string _username; | string _username; | |||
string _password; | string _password; | |||
string _authenticationDatabase; | ||||
string _authenticationMechanism; | ||||
bool _usesstdout; | bool _usesstdout; | |||
bool _noconnection; | bool _noconnection; | |||
bool _autoreconnect; | bool _autoreconnect; | |||
void addFieldOptions(); | void addFieldOptions(); | |||
void needFields(); | void needFields(); | |||
vector<string> _fields; | vector<string> _fields; | |||
BSONObj _fieldsObj; | BSONObj _fieldsObj; | |||
skipping to change at line 140 | skipping to change at line 141 | |||
mongo::DBClientBase * _conn; | mongo::DBClientBase * _conn; | |||
mongo::DBClientBase * _slaveConn; | mongo::DBClientBase * _slaveConn; | |||
bool _paired; | bool _paired; | |||
boost::program_options::options_description * _options; | boost::program_options::options_description * _options; | |||
boost::program_options::options_description * _hidden_options; | boost::program_options::options_description * _hidden_options; | |||
boost::program_options::positional_options_description _positonalOp tions; | boost::program_options::positional_options_description _positonalOp tions; | |||
boost::program_options::variables_map _params; | boost::program_options::variables_map _params; | |||
private: | ||||
void auth(); | ||||
}; | }; | |||
class BSONTool : public Tool { | class BSONTool : public Tool { | |||
bool _objcheck; | bool _objcheck; | |||
auto_ptr<Matcher> _matcher; | auto_ptr<Matcher> _matcher; | |||
public: | public: | |||
BSONTool( const char * name , DBAccess access=ALL, bool objcheck = true ); | BSONTool( const char * name , DBAccess access=ALL, bool objcheck = true ); | |||
virtual int doRun() = 0; | virtual int doRun() = 0; | |||
End of changes. 3 change blocks. | ||||
1 lines changed or deleted | 4 lines changed or added | |||
type_changelog.h | type_changelog.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.changelog collection. All manipulation of documents coming fr om that | * config.changelog collection. All manipulation of documents coming fr om that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* BSONObj query = QUERY(ChangelogType::changeID("host.local-2012-1 | * BSONObj query = QUERY(ChangelogType::exampleField("exampleFieldN | |||
1-21T19:14:10-8")) | ame")); | |||
* logEntryDoc = conn->findOne(ChangelogType::ConfigNS, query); | * exampleDoc = conn->findOne(ChangelogType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* ChangelogType logEntry; | * ChangelogType exampleType; | |||
* logEntry.fromBSON(logEntryDoc); | * string errMsg; | |||
* if (! logEntry.isValid()) { | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* // Can't use 'logEntry'. Take action. | isValid(&errMsg)) { | |||
* // Can't use 'exampleType'. Take action. | ||||
* } | * } | |||
* // use 'logEntry' | * // use 'exampleType' | |||
* | * | |||
*/ | */ | |||
class ChangelogType { | class ChangelogType { | |||
MONGO_DISALLOW_COPYING(ChangelogType); | MONGO_DISALLOW_COPYING(ChangelogType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the collection in the config server. | // Name of the changelog collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the changelog type. | // Field names and types in the changelog collection type. | |||
static BSONField<std::string> changeID; // id for this change " | static const BSONField<std::string> changeID; | |||
<hostname>-<current_time>-<increment>" | static const BSONField<std::string> server; | |||
static BSONField<std::string> server; // hostname of server t | static const BSONField<std::string> clientAddr; | |||
hat we are making the change on. Does not include port. | static const BSONField<Date_t> time; | |||
static BSONField<std::string> clientAddr; // hostname:port of the | static const BSONField<std::string> what; | |||
client that made this change | static const BSONField<std::string> ns; | |||
static BSONField<Date_t> time; // time this change was | static const BSONField<BSONObj> details; | |||
made | ||||
static BSONField<std::string> what; // description of the c | ||||
hange | ||||
static BSONField<std::string> ns; // database or collecti | ||||
on this change applies to | ||||
static BSONField<BSONObj> details; // A BSONObj containing | ||||
extra information about some operations | ||||
// | // | |||
// changelog type methods | // changelog type methods | |||
// | // | |||
ChangelogType(); | ChangelogType(); | |||
~ChangelogType(); | ~ChangelogType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
skipping to change at line 90 | skipping to change at line 90 | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(ChangelogType* other); | void cloneTo(ChangelogType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setChangeID(const StringData& changeID) { _changeID = changeID | // Mandatory Fields | |||
.toString(); } | void setChangeID(const StringData& changeID) { | |||
const std::string& getChangeID() const { return _changeID; } | _changeID = changeID.toString(); | |||
_isChangeIDSet = true; | ||||
} | ||||
void setServer(const StringData& server) { _server = server.toStrin | void unsetChangeID() { _isChangeIDSet = false; } | |||
g(); } | ||||
const std::string& getServer() const { return _server; } | ||||
void setClientAddr(const StringData& clientAddr) { _clientAddr = cl | bool isChangeIDSet() const { return _isChangeIDSet; } | |||
ientAddr.toString(); } | ||||
const std::string& getClientAddr() const { return _clientAddr; } | ||||
void setTime(const Date_t& time) { _time = time; } | // Calling get*() methods when the member is not set results in und | |||
Date_t getTime() const { return _time; } | efined behavior | |||
const std::string& getChangeID() const { | ||||
dassert(_isChangeIDSet); | ||||
return _changeID; | ||||
} | ||||
void setWhat(const StringData& what) { _what = what.toString(); } | void setServer(const StringData& server) { | |||
const std::string& getWhat() const { return _what; } | _server = server.toString(); | |||
_isServerSet = true; | ||||
} | ||||
void setNS(const StringData& ns) { _ns = ns.toString(); } | void unsetServer() { _isServerSet = false; } | |||
const std::string& getNS() const { return _ns; } | ||||
void setDetails(const BSONObj details) { _details = details.getOwne | bool isServerSet() const { return _isServerSet; } | |||
d(); } | ||||
BSONObj getDetails() const { return _details; } | // Calling get*() methods when the member is not set results in und | |||
efined behavior | ||||
const std::string& getServer() const { | ||||
dassert(_isServerSet); | ||||
return _server; | ||||
} | ||||
void setClientAddr(const StringData& clientAddr) { | ||||
_clientAddr = clientAddr.toString(); | ||||
_isClientAddrSet = true; | ||||
} | ||||
void unsetClientAddr() { _isClientAddrSet = false; } | ||||
bool isClientAddrSet() const { return _isClientAddrSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getClientAddr() const { | ||||
dassert(_isClientAddrSet); | ||||
return _clientAddr; | ||||
} | ||||
void setTime(const Date_t time) { | ||||
_time = time; | ||||
_isTimeSet = true; | ||||
} | ||||
void unsetTime() { _isTimeSet = false; } | ||||
bool isTimeSet() const { return _isTimeSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const Date_t getTime() const { | ||||
dassert(_isTimeSet); | ||||
return _time; | ||||
} | ||||
void setWhat(const StringData& what) { | ||||
_what = what.toString(); | ||||
_isWhatSet = true; | ||||
} | ||||
void unsetWhat() { _isWhatSet = false; } | ||||
bool isWhatSet() const { return _isWhatSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getWhat() const { | ||||
dassert(_isWhatSet); | ||||
return _what; | ||||
} | ||||
void setNS(const StringData& ns) { | ||||
_ns = ns.toString(); | ||||
_isNsSet = true; | ||||
} | ||||
void unsetNS() { _isNsSet = false; } | ||||
bool isNSSet() const { return _isNsSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getNS() const { | ||||
dassert(_isNsSet); | ||||
return _ns; | ||||
} | ||||
void setDetails(const BSONObj& details) { | ||||
_details = details.getOwned(); | ||||
_isDetailsSet = true; | ||||
} | ||||
void unsetDetails() { _isDetailsSet = false; } | ||||
bool isDetailsSet() const { return _isDetailsSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const BSONObj getDetails() const { | ||||
dassert(_isDetailsSet); | ||||
return _details; | ||||
} | ||||
// Optional Fields | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
std::string _changeID; // (M) id for this change "<hostname>-<cur | std::string _changeID; // (M) id for this change "<hostname>-< | |||
rent_time>-<increment>" | current_time>-<increment>" | |||
std::string _server; // (M) hostname of server that we are maki | bool _isChangeIDSet; | |||
ng the change on. Does not include port. | std::string _server; // (M) hostname of server that we are mak | |||
std::string _clientAddr; // (M) hostname:port of the client that ma | ing the change on. Does not include port. | |||
de this change | bool _isServerSet; | |||
Date_t _time; // (M) time this change was made | std::string _clientAddr; // (M) hostname:port of the client th | |||
std::string _what; // (M) description of the change | at made this change | |||
std::string _ns; // (M) database or collection this change | bool _isClientAddrSet; | |||
applies to | Date_t _time; // (M) time this change was made | |||
BSONObj _details; // (M) A BSONObj containing extra informat | bool _isTimeSet; | |||
ion about some operations | std::string _what; // (M) description of the change | |||
bool _isWhatSet; | ||||
std::string _ns; // (M) database or collection this change app | ||||
lies to | ||||
bool _isNsSet; | ||||
BSONObj _details; // (M) A BSONObj containing extra informatio | ||||
n about some operations | ||||
bool _isDetailsSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 15 change blocks. | ||||
56 lines changed or deleted | 147 lines changed or added | |||
type_chunk.h | type_chunk.h | |||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.chunks collection. All manipulation of documents coming from that | * config.chunks collection. All manipulation of documents coming from that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* unique_ptr<DbClientCursor> cursor; | * BSONObj query = QUERY(ChunkType::exampleField("exampleFieldName" | |||
* BSONObj query = QUERY(ChunkType::ns("mydb.mycoll")); | )); | |||
* cursor.reset(conn->query(ChunkType::ConfigNS, query, ...)); | * exampleDoc = conn->findOne(ChunkType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* while (cursor->more()) { | * ChunkType exampleType; | |||
* chunkDoc = cursor->next(); | * string errMsg; | |||
* ChunkType chunk; | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* chunk.fromBSON(dbDoc); | isValid(&errMsg)) { | |||
* if (! chunk.isValid()) { | * // Can't use 'exampleType'. Take action. | |||
* // Can't use 'chunk'. Take action. | ||||
* } | ||||
* // use 'chunk' | ||||
* } | * } | |||
* // use 'exampleType' | ||||
* | ||||
*/ | */ | |||
class ChunkType { | class ChunkType { | |||
MONGO_DISALLOW_COPYING(ChunkType); | MONGO_DISALLOW_COPYING(ChunkType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the chunk collection in the config server. | // Name of the chunks collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the chunk collection type. | // Field names and types in the chunks collection type. | |||
static BSONField<std::string> name; // chunk's id | static const BSONField<std::string> name; | |||
static BSONField<std::string> ns; // namespace this chunk is | static const BSONField<std::string> ns; | |||
in | static const BSONField<BSONObj> min; | |||
static BSONField<BSONObj> min; // first key of the chunk, | static const BSONField<BSONObj> max; | |||
including | static const BSONField<BSONArray> version; | |||
static BSONField<BSONObj> max; // last key of the chunk, n | static const BSONField<std::string> shard; | |||
on-including | static const BSONField<bool> jumbo; | |||
static BSONField<BSONArray> version; // [Date_t, OID] | static const BSONField<Date_t> DEPRECATED_lastmod; | |||
static BSONField<std::string> shard; // home of this chunk | static const BSONField<OID> DEPRECATED_epoch; | |||
static BSONField<bool> jumbo; // too big to move? | ||||
// Transition to new format, 2.2 -> 2.4 | ||||
// 2.2 can read both lastmod + lastmodEpoch format and 2.4 [ lastmo | ||||
d, OID ] formats. | ||||
static BSONField<Date_t> DEPRECATED_lastmod; // major | minor vers | ||||
ions | ||||
static BSONField<OID> DEPRECATED_epoch; // OID, to disambigua | ||||
te collection incarnations | ||||
// | // | |||
// chunk type methods | // chunks type methods | |||
// | // | |||
ChunkType(); | ChunkType(); | |||
~ChunkType(); | ~ChunkType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
* representations. Otherwise returns false and fills in the option al 'errMsg' string. | * representations. Otherwise returns false and fills in the option al 'errMsg' string. | |||
*/ | */ | |||
bool isValid(std::string* errMsg) const; | bool isValid(std::string* errMsg) const; | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(ChunkType* other) const; | void cloneTo(ChunkType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
// Mandatory Fields | ||||
void setName(const StringData& name) { | void setName(const StringData& name) { | |||
_name = name.toString(); | _name = name.toString(); | |||
_isNameSet = true; | ||||
} | } | |||
const std::string& getName() const { | void unsetName() { _isNameSet = false; } | |||
bool isNameSet() const { return _isNameSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string getName() const { | ||||
dassert(_isNameSet); | ||||
return _name; | return _name; | |||
} | } | |||
void setNS(const StringData& ns) { | void setNS(const StringData& ns) { | |||
_ns = ns.toString(); | _ns = ns.toString(); | |||
_isNsSet = true; | ||||
} | } | |||
const std::string& getNS() const { | void unsetNS() { _isNsSet = false; } | |||
bool isNSSet() const { return _isNsSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string getNS() const { | ||||
dassert(_isNsSet); | ||||
return _ns; | return _ns; | |||
} | } | |||
void setMin(const BSONObj& min) { | void setMin(const BSONObj& min) { | |||
_min = min.getOwned(); | _min = min.getOwned(); | |||
_isMinSet = true; | ||||
} | } | |||
BSONObj getMin() const { | void unsetMin() { _isMinSet = false; } | |||
bool isMinSet() const { return _isMinSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const BSONObj getMin() const { | ||||
dassert(_isMinSet); | ||||
return _min; | return _min; | |||
} | } | |||
void setMax(const BSONObj& max) { | void setMax(const BSONObj& max) { | |||
_max = max.getOwned(); | _max = max.getOwned(); | |||
_isMaxSet = true; | ||||
} | } | |||
BSONObj getMax() const { | void unsetMax() { _isMaxSet = false; } | |||
bool isMaxSet() const { return _isMaxSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const BSONObj getMax() const { | ||||
dassert(_isMaxSet); | ||||
return _max; | return _max; | |||
} | } | |||
void setVersion(const ChunkVersion& version) { | void setVersion(const ChunkVersion& version) { | |||
_version = version; | _version = version; | |||
_isVersionSet = true; | ||||
} | } | |||
void unsetVersion() { _isVersionSet = false; } | ||||
bool isVersionSet() const { return _isVersionSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const ChunkVersion& getVersion() const { | const ChunkVersion& getVersion() const { | |||
dassert(_isVersionSet); | ||||
return _version; | return _version; | |||
} | } | |||
void setShard(const StringData& shard) { | void setShard(const StringData& shard) { | |||
_shard = shard.toString(); | _shard = shard.toString(); | |||
_isShardSet = true; | ||||
} | } | |||
const std::string& getShard() const { | void unsetShard() { _isShardSet = false; } | |||
bool isShardSet() const { return _isShardSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string getShard() const { | ||||
dassert(_isShardSet); | ||||
return _shard; | return _shard; | |||
} | } | |||
// Optional Fields | ||||
void setJumbo(bool jumbo) { | void setJumbo(bool jumbo) { | |||
_jumbo = jumbo; | _jumbo = jumbo; | |||
_isJumboSet = true; | ||||
} | ||||
void unsetJumbo() { _isJumboSet = false; } | ||||
bool isJumboSet() const { | ||||
return _isJumboSet || jumbo.hasDefault(); | ||||
} | } | |||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getJumbo() const { | bool getJumbo() const { | |||
return _jumbo; | if (_isJumboSet) { | |||
return _jumbo; | ||||
} else { | ||||
dassert(jumbo.hasDefault()); | ||||
return jumbo.getDefault(); | ||||
} | ||||
} | } | |||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
string _name; // (M) chunk's id | std::string _name; // (M) chunk's id | |||
string _ns; // (M) collection this chunk is in | bool _isNameSet; | |||
BSONObj _min; // (M) first key of the range, inclusive | std::string _ns; // (M) collection this chunk is in | |||
BSONObj _max; // (M) last key of the range, non-inclusive | bool _isNsSet; | |||
ChunkVersion _version; // (M) version of this chunk | BSONObj _min; // (M) first key of the range, inclusive | |||
string _shard; // (M) shard this chunk lives in | bool _isMinSet; | |||
bool _jumbo; // (O) too big to move? | BSONObj _max; // (M) last key of the range, non-inclusive | |||
bool _isMaxSet; | ||||
ChunkVersion _version; // (M) version of this chunk | ||||
bool _isVersionSet; | ||||
std::string _shard; // (M) shard this chunk lives in | ||||
bool _isShardSet; | ||||
bool _jumbo; // (O) too big to move? | ||||
bool _isJumboSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 26 change blocks. | ||||
46 lines changed or deleted | 108 lines changed or added | |||
type_collection.h | type_collection.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.collections collection. All manipulation of documents coming from that | * config.collections collection. All manipulation of documents coming from that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* BSONObj query = QUERY(CollectionType::ns("db.coll") << | * BSONObj query = QUERY(CollectionType::exampleField("exampleField | |||
* CollectionType::unique(true)); | Name")); | |||
* collDoc = conn->findOne(CollectionType::ConfigNS, query); | * exampleDoc = conn->findOne(CollectionType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* CollectionType coll; | * CollectionType exampleType; | |||
* coll.fromBSON(collDoc); | * string errMsg; | |||
* if (! coll.isValid()) { | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* // Can't use 'coll'. Take action. | isValid(&errMsg)) { | |||
* // Can't use 'exampleType'. Take action. | ||||
* } | * } | |||
* if (coll.isDropped()) { | * // use 'exampleType' | |||
* // Coll doesn't exist, Take action. | ||||
* } | ||||
* | ||||
* // use 'coll' | ||||
* | * | |||
*/ | */ | |||
class CollectionType { | class CollectionType { | |||
MONGO_DISALLOW_COPYING(CollectionType); | MONGO_DISALLOW_COPYING(CollectionType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the collection in the config server. | // Name of the collections collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the collection type. | // Field names and types in the collections collection type. | |||
static BSONField<std::string> ns; // collection's namespace | static const BSONField<std::string> ns; | |||
static BSONField<std::string> primary; // primary db when not shard | static const BSONField<std::string> primary; | |||
ed | static const BSONField<BSONObj> keyPattern; | |||
static BSONField<BSONObj> keyPattern; // sharding key, if sharded | static const BSONField<bool> unique; | |||
static BSONField<bool> unique; // sharding key unique? | static const BSONField<Date_t> updatedAt; | |||
static BSONField<Date_t> updatedAt; // when collection was creat | static const BSONField<bool> noBalance; | |||
ed | static const BSONField<OID> epoch; | |||
static BSONField<bool> noBalance; // true if balancing is disa | static const BSONField<bool> dropped; | |||
bled | static const BSONField<OID> DEPRECATED_lastmodEpoch; | |||
static BSONField<OID> epoch; // disambiguate ns (drop/rec | static const BSONField<Date_t> DEPRECATED_lastmod; | |||
reate) | ||||
// To-be-deprecated, not yet | ||||
static BSONField<bool> dropped; // true if we should ignore | ||||
this collection entry | ||||
// Deprecated fields should only be used in parseBSON calls. Expose | ||||
d here for testing only. | ||||
static BSONField<OID> DEPRECATED_lastmodEpoch; | ||||
static BSONField<Date_t> DEPRECATED_lastmod; | ||||
// | // | |||
// collection type methods | // collections type methods | |||
// | // | |||
CollectionType(); | CollectionType(); | |||
~CollectionType(); | ~CollectionType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
* representations. Otherwise returns false and fills in the option al 'errMsg' string. | * representations. Otherwise returns false and fills in the option al 'errMsg' string. | |||
*/ | */ | |||
bool isValid(std::string* errMsg) const; | bool isValid(std::string* errMsg) const; | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(CollectionType* other) const; | void cloneTo(CollectionType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setNS(const StringData& ns) { _ns = ns.toString(); } | // Mandatory Fields | |||
const std::string& getNS() const { return _ns; } | void setNS(const StringData& ns) { | |||
_ns = ns.toString(); | ||||
void setPrimary(const StringData& name) { _primary = name.toString( | _isNsSet = true; | |||
); } | } | |||
const std::string& getPrimary() const { return _primary; } | ||||
void unsetNS() { _isNsSet = false; } | ||||
void setKeyPattern(const BSONObj keyPattern) { _keyPattern = keyPat | ||||
tern.getOwned(); } | bool isNSSet() const { return _isNsSet; } | |||
BSONObj getKeyPattern() const { return _keyPattern; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
void setUnique(bool unique) { _unique = unique; } | efined behavior | |||
bool isUnique() const { return _unique; } | const std::string getNS() const { | |||
dassert(_isNsSet); | ||||
void setUpdatedAt(const Date_t& time) { _updatedAt = time; } | return _ns; | |||
Date_t getUpdatedAt() const { return _updatedAt; } | } | |||
void setNoBalance(bool noBalance) { _noBalance = noBalance; } | void setUpdatedAt(const Date_t updatedAt) { | |||
bool getNoBalance() const { return _noBalance; } | _updatedAt = updatedAt; | |||
_isUpdatedAtSet = true; | ||||
void setEpoch(OID oid) { _epoch = oid; } | } | |||
OID getEpoch() const { return _epoch; } | ||||
void unsetUpdatedAt() { _isUpdatedAtSet = false; } | ||||
void setDropped(bool dropped) { _dropped = dropped; } | ||||
bool isDropped() const { return _dropped; } | bool isUpdatedAtSet() const { return _isUpdatedAtSet; } | |||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const Date_t getUpdatedAt() const { | ||||
dassert(_isUpdatedAtSet); | ||||
return _updatedAt; | ||||
} | ||||
void setEpoch(const OID epoch) { | ||||
_epoch = epoch; | ||||
_isEpochSet = true; | ||||
} | ||||
void unsetEpoch() { _isEpochSet = false; } | ||||
bool isEpochSet() const { return _isEpochSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const OID getEpoch() const { | ||||
dassert(_isEpochSet); | ||||
return _epoch; | ||||
} | ||||
// Optional Fields | ||||
void setPrimary(StringData& primary) { | ||||
_primary = primary.toString(); | ||||
_isPrimarySet = true; | ||||
} | ||||
void unsetPrimary() { _isPrimarySet = false; } | ||||
bool isPrimarySet() const { | ||||
return _isPrimarySet || primary.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
std::string getPrimary() const { | ||||
if (_isPrimarySet) { | ||||
return _primary; | ||||
} else { | ||||
dassert(primary.hasDefault()); | ||||
return primary.getDefault(); | ||||
} | ||||
} | ||||
void setKeyPattern(BSONObj& keyPattern) { | ||||
_keyPattern = keyPattern.getOwned(); | ||||
_isKeyPatternSet = true; | ||||
} | ||||
void unsetKeyPattern() { _isKeyPatternSet = false; } | ||||
bool isKeyPatternSet() const { | ||||
return _isKeyPatternSet || keyPattern.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
BSONObj getKeyPattern() const { | ||||
if (_isKeyPatternSet) { | ||||
return _keyPattern; | ||||
} else { | ||||
dassert(keyPattern.hasDefault()); | ||||
return keyPattern.getDefault(); | ||||
} | ||||
} | ||||
void setUnique(bool unique) { | ||||
_unique = unique; | ||||
_isUniqueSet = true; | ||||
} | ||||
void unsetUnique() { _isUniqueSet = false; } | ||||
bool isUniqueSet() const { | ||||
return _isUniqueSet || unique.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getUnique() const { | ||||
if (_isUniqueSet) { | ||||
return _unique; | ||||
} else { | ||||
dassert(unique.hasDefault()); | ||||
return unique.getDefault(); | ||||
} | ||||
} | ||||
void setNoBalance(bool noBalance) { | ||||
_noBalance = noBalance; | ||||
_isNoBalanceSet = true; | ||||
} | ||||
void unsetNoBalance() { _isNoBalanceSet = false; } | ||||
bool isNoBalanceSet() const { | ||||
return _isNoBalanceSet || noBalance.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getNoBalance() const { | ||||
if (_isNoBalanceSet) { | ||||
return _noBalance; | ||||
} else { | ||||
dassert(noBalance.hasDefault()); | ||||
return noBalance.getDefault(); | ||||
} | ||||
} | ||||
void setDropped(bool dropped) { | ||||
_dropped = dropped; | ||||
_isDroppedSet = true; | ||||
} | ||||
void unsetDropped() { _isDroppedSet = false; } | ||||
bool isDroppedSet() const { | ||||
return _isDroppedSet || dropped.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getDropped() const { | ||||
if (_isDroppedSet) { | ||||
return _dropped; | ||||
} else { | ||||
dassert(dropped.hasDefault()); | ||||
return dropped.getDefault(); | ||||
} | ||||
} | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
std::string _ns; // (M) namespace | std::string _ns; // (M) namespace | |||
std::string _primary; // (S) either/or with _keyPattern | bool _isNsSet; | |||
BSONObj _keyPattern; // (S) sharding pattern if sharded | std::string _primary; // (O) either/or with _keyPattern | |||
bool _unique; // (S) mandatory if sharded, index is unique | bool _isPrimarySet; | |||
Date_t _updatedAt; // (M) last updated time | BSONObj _keyPattern; // (O) sharding pattern if sharded | |||
bool _noBalance; // (S) optional if sharded, disable balancin | bool _isKeyPatternSet; | |||
g | bool _unique; // (O) mandatory if sharded, index is unique | |||
OID _epoch; // (M) disambiguates collection incarnations | bool _isUniqueSet; | |||
bool _dropped; // (O) if true, ignore this entry | Date_t _updatedAt; // (M) last updated time | |||
bool _isUpdatedAtSet; | ||||
bool _noBalance; // (O) optional if sharded, disable balancing | ||||
bool _isNoBalanceSet; | ||||
OID _epoch; // (M) disambiguates collection incarnations | ||||
bool _isEpochSet; | ||||
bool _dropped; // (O) if true, ignore this entry | ||||
bool _isDroppedSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 9 change blocks. | ||||
69 lines changed or deleted | 199 lines changed or added | |||
type_config_version.h | type_config_version.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* This class represents the layout and contents of the single document | * This class represents the layout and contents of documents contained | |||
contained in the | in the | |||
* config.version collection. All manipulation of this document should | * config.version collection. All manipulation of documents coming from | |||
be done using this class. | that | |||
* collection should be done with this class. | ||||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | ||||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* BSONObj query = QUERY(); | * BSONObj query = QUERY(VersionType::exampleField("exampleFieldNam | |||
* versionDoc = conn->findOne(VersionType::ConfigNS, query); | e")); | |||
* exampleDoc = conn->findOne(VersionType::ConfigNS, query); | ||||
* | * | |||
* // Process the response. | * // Process the response. | |||
* VersionType versionInfo; | * VersionType exampleType; | |||
* if (!versionInfo.parseBSON(versionDoc)) { | * string errMsg; | |||
* // Can't parse document, take action | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
isValid(&errMsg)) { | ||||
* // Can't use 'exampleType'. Take action. | ||||
* } | * } | |||
* if (!versionInfo.isValid()) { | * // use 'exampleType' | |||
* // Can't use version, take action. | ||||
* } | ||||
* // use 'versionInfo' | ||||
* | * | |||
*/ | */ | |||
class VersionType { | class VersionType { | |||
MONGO_DISALLOW_COPYING(VersionType); | MONGO_DISALLOW_COPYING(VersionType); | |||
public: | public: | |||
// Name of the versions collection in the config schema | // | |||
static const string ConfigNS; | // schema declarations | |||
// | ||||
// Name of the version collection in the config server. | ||||
static const std::string ConfigNS; | ||||
// Field names and types of the version document | // Field names and types in the version collection type. | |||
static const BSONField<int> minCompatibleVersion; | static const BSONField<int> minCompatibleVersion; | |||
static const BSONField<int> currentVersion; | static const BSONField<int> currentVersion; | |||
static const BSONField<BSONArray> excludingMongoVersions; | static const BSONField<BSONArray> excludingMongoVersions; | |||
static const BSONField<OID> clusterId; | static const BSONField<OID> clusterId; | |||
static const BSONField<int> version_DEPRECATED; | ||||
static const BSONField<OID> upgradeId; | static const BSONField<OID> upgradeId; | |||
static const BSONField<BSONObj> upgradeState; | static const BSONField<BSONObj> upgradeState; | |||
// Transition to new format v2.2->v2.4 | // | |||
// We eventually will not use version, minVersion and maxVersion in | // version type methods | |||
stead | // | |||
static const BSONField<int> version_DEPRECATED; | ||||
VersionType(); | VersionType(); | |||
~VersionType(); | ~VersionType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
* representations. Otherwise returns false and fills in the option al 'errMsg' string. | * representations. Otherwise returns false and fills in the option al 'errMsg' string. | |||
*/ | */ | |||
bool isValid(std::string* errMsg) const; | bool isValid(std::string* errMsg) const; | |||
skipping to change at line 88 | skipping to change at line 93 | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(const BSONObj& source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clones to another version entry | * Clears the internal state. | |||
*/ | */ | |||
void cloneTo(VersionType* other) const; | void clear(); | |||
/** | /** | |||
* Clears the internal state. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void clear(); | void cloneTo(VersionType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors and helpers | // individual field accessors | |||
// | ||||
OID getClusterId() const; | ||||
void setClusterId(const OID& clusterId); | ||||
int getMinCompatibleVersion() const; | ||||
void setMinCompatibleVersion(int version); | ||||
int getCurrentVersion() const; | ||||
void setCurrentVersion(int version); | ||||
// | ||||
// Range exclusions | ||||
// | ||||
// The type knows very little about these ranges, mostly because it | ||||
's impossible right now | ||||
// to do generic BSON parsing of more complex types without templat | ||||
e magick. All | ||||
// interpretation of versions happens in the upgrade code. | ||||
// | // | |||
const BSONArray& getExcludedRanges() const { return _excludes; } | // Mandatory Fields | |||
void setExcludedRanges(const BSONArray& excludes) { _excludes = exc | void setMinCompatibleVersion(const int minCompatibleVersion) { | |||
ludes; } | _minCompatibleVersion = minCompatibleVersion; | |||
_isMinCompatibleVersionSet = true; | ||||
OID getUpgradeId() const; | } | |||
void setUpgradeId(const OID& upgradeId); | ||||
void unsetMinCompatibleVersion() { _isMinCompatibleVersionSet = fal | ||||
BSONObj getUpgradeState() const; | se; } | |||
void setUpgradeState(const BSONObj& upgradeState); | ||||
bool isMinCompatibleVersionSet() const { return _isMinCompatibleVer | ||||
sionSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const int getMinCompatibleVersion() const { | ||||
dassert(_isMinCompatibleVersionSet); | ||||
return _minCompatibleVersion; | ||||
} | ||||
void setCurrentVersion(const int currentVersion) { | ||||
_currentVersion = currentVersion; | ||||
_isCurrentVersionSet = true; | ||||
} | ||||
void unsetCurrentVersion() { _isCurrentVersionSet = false; } | ||||
bool isCurrentVersionSet() const { return _isCurrentVersionSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const int getCurrentVersion() const { | ||||
dassert(_isCurrentVersionSet); | ||||
return _currentVersion; | ||||
} | ||||
void setExcludingMongoVersions(const BSONArray& excludingMongoVersi | ||||
ons) { | ||||
_excludingMongoVersions = excludingMongoVersions; | ||||
_isExcludingMongoVersionsSet = true; | ||||
} | ||||
void unsetExcludingMongoVersions() { _isExcludingMongoVersionsSet = | ||||
false; } | ||||
bool isExcludingMongoVersionsSet() const { | ||||
return _isExcludingMongoVersionsSet || excludingMongoVersions.h | ||||
asDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
const BSONArray getExcludingMongoVersions() const { | ||||
if (_isExcludingMongoVersionsSet) { | ||||
return _excludingMongoVersions; | ||||
} else { | ||||
dassert(excludingMongoVersions.hasDefault()); | ||||
return excludingMongoVersions.getDefault(); | ||||
} | ||||
} | ||||
void setClusterId(const OID clusterId) { | ||||
_clusterId = clusterId; | ||||
_isClusterIdSet = true; | ||||
} | ||||
void unsetClusterId() { _isClusterIdSet = false; } | ||||
bool isClusterIdSet() const { return _isClusterIdSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const OID getClusterId() const { | ||||
dassert(_isClusterIdSet); | ||||
return _clusterId; | ||||
} | ||||
// Optional Fields | ||||
void setUpgradeId(OID upgradeId) { | ||||
_upgradeId = upgradeId; | ||||
_isUpgradeIdSet = true; | ||||
} | ||||
void unsetUpgradeId() { _isUpgradeIdSet = false; } | ||||
bool isUpgradeIdSet() const { | ||||
return _isUpgradeIdSet || upgradeId.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
OID getUpgradeId() const { | ||||
if (_isUpgradeIdSet) { | ||||
return _upgradeId; | ||||
} else { | ||||
dassert(upgradeId.hasDefault()); | ||||
return upgradeId.getDefault(); | ||||
} | ||||
} | ||||
void setUpgradeState(const BSONObj& upgradeState) { | ||||
_upgradeState = upgradeState.getOwned(); | ||||
_isUpgradeStateSet = true; | ||||
} | ||||
void unsetUpgradeState() { _isUpgradeStateSet = false; } | ||||
bool isUpgradeStateSet() const { | ||||
return _isUpgradeStateSet || upgradeState.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
BSONObj getUpgradeState() const { | ||||
if (_isUpgradeStateSet) { | ||||
return _upgradeState; | ||||
} else { | ||||
dassert(upgradeState.hasDefault()); | ||||
return upgradeState.getDefault(); | ||||
} | ||||
} | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
int _minVersion; // (M) minimum compatible version | int _minCompatibleVersion; // (M) minimum compatible version | |||
int _currentVersion; // (M) current version | bool _isMinCompatibleVersionSet; | |||
OID _clusterId; // (M) clusterId | int _currentVersion; // (M) current version | |||
BSONArray _excludes; // (O) mongodb versions excluded from the clus | bool _isCurrentVersionSet; | |||
ter | BSONArray _excludingMongoVersions; // (O) range of disallowed | |||
OID _upgradeId; // (O) upgrade id of current or last upgrade | versions to upgrade to | |||
BSONObj _upgradeState; // (S) upgrade state of current or last upgr | bool _isExcludingMongoVersionsSet; | |||
ade | OID _clusterId; // (M) clusterId | |||
bool _isClusterIdSet; | ||||
OID _upgradeId; // (O) upgrade id of current or last upgrade | ||||
bool _isUpgradeIdSet; | ||||
BSONObj _upgradeState; // (O) upgrade state of current or last | ||||
upgrade | ||||
bool _isUpgradeStateSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 17 change blocks. | ||||
62 lines changed or deleted | 167 lines changed or added | |||
type_database.h | type_database.h | |||
---|---|---|---|---|
skipping to change at line 29 | skipping to change at line 29 | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/base/string_data.h" | #include "mongo/base/string_data.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.database collection. All manipulation of documents coming fro m that | * config.databases collection. All manipulation of documents coming fr om that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* BSONObj query = QUERY(DatabaseType::name("mydb")); | * BSONObj query = QUERY(DatabaseType::exampleField("exampleFieldNa | |||
* dbDoc = conn->findOne(DatbaseType::ConfigNS, query); | me")); | |||
* exampleDoc = conn->findOne(DatabaseType::ConfigNS, query); | ||||
* | * | |||
* // Process the response. | * // Process the response. | |||
* DatabaseType db; | * DatabaseType exampleType; | |||
* string errMsg; | * string errMsg; | |||
* if (!db.parseBSON(dbDoc, &errMsg) || !db.isValid(&errMsg)) { | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* // Can't use 'db'. Take action. | isValid(&errMsg)) { | |||
* // Can't use 'exampleType'. Take action. | ||||
* } | * } | |||
* // use 'db' | * // use 'exampleType' | |||
* | * | |||
*/ | */ | |||
class DatabaseType { | class DatabaseType { | |||
MONGO_DISALLOW_COPYING(DatabaseType); | MONGO_DISALLOW_COPYING(DatabaseType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the database collection in the config server. | // Name of the databases collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the database collection type. | // Field names and types in the databases collection type. | |||
static BSONField<std::string> name; // database's name | static const BSONField<std::string> name; | |||
static BSONField<std::string> primary; // primary shard for the da | static const BSONField<std::string> primary; | |||
tabase | static const BSONField<bool> draining; | |||
static BSONField<bool> draining; // is the database being re | static const BSONField<bool> DEPRECATED_partitioned; | |||
moved? | static const BSONField<std::string> DEPRECATED_name; | |||
static const BSONField<bool> DEPRECATED_sharded; | ||||
// This field was last used in 2.2 series (version 3). | ||||
static BSONField<bool> DEPRECATED_partitioned; | ||||
// These fields were last used in 1.4 series (version 2). | ||||
static BSONField<std::string> DEPRECATED_name; | ||||
static BSONField<bool> DEPRECATED_sharded; | ||||
// | // | |||
// database type methods | // databases type methods | |||
// | // | |||
DatabaseType(); | DatabaseType(); | |||
~DatabaseType(); | ~DatabaseType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
* representations. Otherwise returns false and fills in the option al 'errMsg' string. | * representations. Otherwise returns false and fills in the option al 'errMsg' string. | |||
*/ | */ | |||
bool isValid(std::string* errMsg) const; | bool isValid(std::string* errMsg) const; | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(DatabaseType* other) const; | void cloneTo(DatabaseType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setName(const StringData& name) { _name = name.toString(); } | // Mandatory Fields | |||
const std::string& getName() const { return _name; } | void setName(const StringData& name) { | |||
_name = name.toString(); | ||||
void setPrimary(const StringData& shard) { _primary = shard.toStrin | _isNameSet = true; | |||
g(); } | } | |||
const std::string& getPrimary() const { return _primary; } | ||||
void unsetName() { _isNameSet = false; } | ||||
void setDraining(bool draining) { _draining = draining; } | ||||
bool getDraining() const { return _draining; } | bool isNameSet() const { return _isNameSet; } | |||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getName() const { | ||||
dassert(_isNameSet); | ||||
return _name; | ||||
} | ||||
void setPrimary(const StringData& primary) { | ||||
_primary = primary.toString(); | ||||
_isPrimarySet = true; | ||||
} | ||||
void unsetPrimary() { _isPrimarySet = false; } | ||||
bool isPrimarySet() const { return _isPrimarySet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getPrimary() const { | ||||
dassert(_isPrimarySet); | ||||
return _primary; | ||||
} | ||||
// Optional Fields | ||||
void setDraining(bool draining) { | ||||
_draining = draining; | ||||
_isDrainingSet = true; | ||||
} | ||||
void unsetDraining() { _isDrainingSet = false; } | ||||
bool isDrainingSet() const { | ||||
return _isDrainingSet || draining.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getDraining() const { | ||||
if (_isDrainingSet) { | ||||
return _draining; | ||||
} else { | ||||
dassert(draining.hasDefault()); | ||||
return draining.getDefault(); | ||||
} | ||||
} | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
string _name; // (M) database name | std::string _name; // (M) database name | |||
string _primary; // (M) primary shard for the database | bool _isNameSet; | |||
bool _draining; // (O) is this database about to be deleted? | std::string _primary; // (M) primary shard for the database | |||
bool _isPrimarySet; | ||||
bool _draining; // (O) is this database about to be deleted? | ||||
bool _isDrainingSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 11 change blocks. | ||||
35 lines changed or deleted | 81 lines changed or added | |||
type_lockpings.h | type_lockpings.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.lockpings collection. All manipulation of documents coming fr om that | * config.lockpings collection. All manipulation of documents coming fr om that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* unique_ptr<DbClientCursor> cursor; | * BSONObj query = QUERY(LockpingsType::exampleField("exampleFieldN | |||
* BSONObj query = QUERY(LockpingsType::name("localhost:27017")); | ame")); | |||
* cursor.reset(conn->query(LockpingsType::ConfigNS, query, ...)); | * exampleDoc = conn->findOne(LockpingsType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* while (cursor->more()) { | * LockpingsType exampleType; | |||
* lockPingDoc = cursor->next(); | * string errMsg; | |||
* LockpingsType lockPing; | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* lockPing.fromBSON(lockPingDoc); | isValid(&errMsg)) { | |||
* if (! lockPing.isValid()) { | * // Can't use 'exampleType'. Take action. | |||
* // Can't use 'lockPing'. Take action. | ||||
* } | ||||
* // use 'lockPing' | ||||
* } | * } | |||
* // use 'exampleType' | ||||
* | ||||
*/ | */ | |||
class LockpingsType { | class LockpingsType { | |||
MONGO_DISALLOW_COPYING(LockpingsType); | MONGO_DISALLOW_COPYING(LockpingsType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the lockpings collection in the config server. | // Name of the lockpings collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the lockpings collection type. | // Field names and types in the lockpings collection type. | |||
static BSONField<string> process; // string describing the process | static const BSONField<std::string> process; | |||
holding the lock | static const BSONField<Date_t> ping; | |||
static BSONField<Date_t> ping; // last time the holding process | ||||
updated this document | ||||
// | // | |||
// lockpings type methods | // lockpings type methods | |||
// | // | |||
LockpingsType(); | LockpingsType(); | |||
~LockpingsType(); | ~LockpingsType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
skipping to change at line 89 | skipping to change at line 85 | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(LockpingsType* other); | void cloneTo(LockpingsType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setProcess(const StringData& process) { _process = process.toS | // Mandatory Fields | |||
tring(); } | void setProcess(const StringData& process) { | |||
const std::string& getProcess() const { return _process; } | _process = process.toString(); | |||
_isProcessSet = true; | ||||
} | ||||
void unsetProcess() { _isProcessSet = false; } | ||||
bool isProcessSet() const { return _isProcessSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getProcess() const { | ||||
dassert(_isProcessSet); | ||||
return _process; | ||||
} | ||||
void setPing(const Date_t ping) { | ||||
_ping = ping; | ||||
_isPingSet = true; | ||||
} | ||||
void unsetPing() { _isPingSet = false; } | ||||
bool isPingSet() const { return _isPingSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const Date_t getPing() const { | ||||
dassert(_isPingSet); | ||||
return _ping; | ||||
} | ||||
void setPing(const Date_t& time) { _ping = time; } | // Optional Fields | |||
Date_t getPing() const { return _ping; } | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
std::string _process; // (M) string describing the process holding | std::string _process; // (M) string describing the process hol | |||
the lock | ding the lock | |||
Date_t _ping; // (M) last time the holding process updated | bool _isProcessSet; | |||
this document | Date_t _ping; // (M) last time the holding process updated thi | |||
s document | ||||
bool _isPingSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 11 change blocks. | ||||
27 lines changed or deleted | 53 lines changed or added | |||
type_locks.h | type_locks.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.locks collection. All manipulation of documents coming from t hat | * config.locks collection. All manipulation of documents coming from t hat | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* BSONObj query = QUERY(LocksType::name("balancer")); | * BSONObj query = QUERY(LocksType::exampleField("exampleFieldName" | |||
* lockDoc = conn->findOne(LocksType::ConfigNS, query); | )); | |||
* exampleDoc = conn->findOne(LocksType::ConfigNS, query); | ||||
* | * | |||
* // Process the response. | * // Process the response. | |||
* LocksType lock; | * LocksType exampleType; | |||
* lock.fromBSON(lockDoc); | * string errMsg; | |||
* if (! lock.isValid()) { | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* // Can't use 'lock'. Take action. | isValid(&errMsg)) { | |||
* // Can't use 'exampleType'. Take action. | ||||
* } | * } | |||
* // use 'lock' | * // use 'exampleType' | |||
* | * | |||
*/ | */ | |||
class LocksType { | class LocksType { | |||
MONGO_DISALLOW_COPYING(LocksType); | MONGO_DISALLOW_COPYING(LocksType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the collection in the config server. | // Name of the locks collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
static BSONField<std::string> name; // name of the lock | // Field names and types in the locks collection type. | |||
static BSONField<int> state; // 0: Unlocked | static const BSONField<std::string> name; | |||
// 1: Locks in contention | static const BSONField<int> state; | |||
// 2: Lock held | static const BSONField<std::string> process; | |||
static BSONField<std::string> process; // the process field cont | static const BSONField<OID> lockID; | |||
ains the (unique) | static const BSONField<std::string> who; | |||
// identifier for the ins | static const BSONField<std::string> why; | |||
tance of mongod/mongos | ||||
// which has requested th | ||||
e lock | ||||
static BSONField<OID> lockID; // a unique identifier fo | ||||
r the instance of the | ||||
// lock itself. Allows fo | ||||
r safe cleanup after | ||||
// network partitioning | ||||
static BSONField<std::string> who; // a note about why the l | ||||
ock is held, or which | ||||
// subcomponent is holdin | ||||
g it | ||||
static BSONField<std::string> why; // a human readable descr | ||||
iption of the purpose of | ||||
// the lock | ||||
// | // | |||
// collection type methods | // locks type methods | |||
// | // | |||
LocksType(); | LocksType(); | |||
~LocksType(); | ~LocksType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
* representations. Otherwise returns false and fills in the option al 'errMsg' string. | * representations. Otherwise returns false and fills in the option al 'errMsg' string. | |||
*/ | */ | |||
bool isValid(std::string* errMsg) const; | bool isValid(std::string* errMsg) const; | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(LocksType* other); | void cloneTo(LocksType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setName(const StringData& name) { _name = name.toString(); } | // Mandatory Fields | |||
const std::string& getName() const { return _name; } | void setName(const StringData& name) { | |||
_name = name.toString(); | ||||
_isNameSet = true; | ||||
} | ||||
void unsetName() { _isNameSet = false; } | ||||
bool isNameSet() const { return _isNameSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string getName() const { | ||||
dassert(_isNameSet); | ||||
return _name; | ||||
} | ||||
void setState(const int state) { | ||||
_state = state; | ||||
_isStateSet = true; | ||||
} | ||||
void unsetState() { _isStateSet = false; } | ||||
void setState(int state) { _state = state; } | bool isStateSet() const { return _isStateSet; } | |||
int getState() const { return _state; } | ||||
void setProcess(const StringData& process) { | // Calling get*() methods when the member is not set results in und | |||
efined behavior | ||||
const int getState() const { | ||||
dassert(_isStateSet); | ||||
return _state; | ||||
} | ||||
// Optional Fields | ||||
void setProcess(StringData& process) { | ||||
_process = process.toString(); | _process = process.toString(); | |||
_isProcessSet = true; | ||||
} | ||||
void unsetProcess() { _isProcessSet = false; } | ||||
bool isProcessSet() const { | ||||
return _isProcessSet || process.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
std::string getProcess() const { | ||||
if (_isProcessSet) { | ||||
return _process; | ||||
} else { | ||||
dassert(process.hasDefault()); | ||||
return process.getDefault(); | ||||
} | ||||
} | ||||
void setLockID(OID lockID) { | ||||
_lockID = lockID; | ||||
_isLockIDSet = true; | ||||
} | ||||
void unsetLockID() { _isLockIDSet = false; } | ||||
bool isLockIDSet() const { | ||||
return _isLockIDSet || lockID.hasDefault(); | ||||
} | } | |||
const std::string& getProcess() const { return _process; } | ||||
void setLockID(OID lockID) { _lockID = lockID; } | // Calling get*() methods when the member is not set and has no def | |||
OID getLockID() const { return _lockID; } | ault results in undefined | |||
// behavior | ||||
OID getLockID() const { | ||||
if (_isLockIDSet) { | ||||
return _lockID; | ||||
} else { | ||||
dassert(lockID.hasDefault()); | ||||
return lockID.getDefault(); | ||||
} | ||||
} | ||||
void setWho(StringData& who) { | ||||
_who = who.toString(); | ||||
_isWhoSet = true; | ||||
} | ||||
void setWho(const StringData& who) { _who = who.toString(); } | void unsetWho() { _isWhoSet = false; } | |||
const std::string& getWho() const { return _who; } | ||||
bool isWhoSet() const { | ||||
return _isWhoSet || who.hasDefault(); | ||||
} | ||||
void setWhy(const StringData& why) { _why = why.toString(); } | // Calling get*() methods when the member is not set and has no def | |||
const std::string& getWhy() const { return _why; } | ault results in undefined | |||
// behavior | ||||
std::string getWho() const { | ||||
if (_isWhoSet) { | ||||
return _who; | ||||
} else { | ||||
dassert(who.hasDefault()); | ||||
return who.getDefault(); | ||||
} | ||||
} | ||||
void setWhy(StringData& why) { | ||||
_why = why.toString(); | ||||
_isWhySet = true; | ||||
} | ||||
void unsetWhy() { _isWhySet = false; } | ||||
bool isWhySet() const { | ||||
return _isWhySet || why.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
std::string getWhy() const { | ||||
if (_isWhySet) { | ||||
return _why; | ||||
} else { | ||||
dassert(why.hasDefault()); | ||||
return why.getDefault(); | ||||
} | ||||
} | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
std::string _name; // (M) name of the lock | std::string _name; // (M) name of the lock | |||
int _state; // (M) 0: Unlocked | 1: Locks in contention | | bool _isNameSet; | |||
2: Lock held | int _state; // (M) 0: Unlocked | 1: Locks in contention | 2: L | |||
std::string _process; // (S) optional if unlocked. contains the (u | ock held | |||
nique) identifier | bool _isStateSet; | |||
// for the instance of mongod/mongos which ha | std::string _process; // (O) optional if unlocked. contains t | |||
s requested the lock | he (unique) identifier | |||
OID _lockID; // (S) optional if unlocked. a unique identi | bool _isProcessSet; | |||
fier for the instance | OID _lockID; // (O) optional if unlocked. a unique identifier | |||
// of the lock itself. Allows for safe cleanu | for the instance | |||
p after network | bool _isLockIDSet; | |||
// partitioning | std::string _who; // (O) optional if unlocked. a note about w | |||
std::string _who; // (S) optional if unlocked. a note about wh | hy the lock is held, | |||
y the lock is held, | bool _isWhoSet; | |||
// or which subcomponent is holding it | std::string _why; // (O) optional if unlocked. a human readab | |||
std::string _why; // (S) optional if unlocked. a human readabl | le description of the | |||
e description of the | bool _isWhySet; | |||
// purpose of the lock | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 17 change blocks. | ||||
63 lines changed or deleted | 152 lines changed or added | |||
type_mongos.h | type_mongos.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.mongos collection. All manipulation of documents coming from that | * config.mongos collection. All manipulation of documents coming from that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* unique_ptr<DbClientCursor> cursor; | * BSONObj query = QUERY(MongosType::exampleField("exampleFieldName | |||
* BSONObj query = QUERY(MongosType::name("localhost:27017")); | ")); | |||
* cursor.reset(conn->query(MongosType::ConfigNS, query, ...)); | * exampleDoc = conn->findOne(MongosType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* while (cursor->more()) { | * MongosType exampleType; | |||
* mongosDoc = cursor->next(); | * string errMsg; | |||
* MongosType mongos; | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* mongos.fromBSON(mongosDoc); | isValid(&errMsg)) { | |||
* if (! mongos.isValid()) { | * // Can't use 'exampleType'. Take action. | |||
* // Can't use 'mongos'. Take action. | ||||
* } | ||||
* // use 'mongos' | ||||
* } | * } | |||
* // use 'exampleType' | ||||
* | ||||
*/ | */ | |||
class MongosType { | class MongosType { | |||
MONGO_DISALLOW_COPYING(MongosType); | MONGO_DISALLOW_COPYING(MongosType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the mongos collection in the config server. | // Name of the mongos collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the mongos collection type. | // Field names and types in the mongos collection type. | |||
static BSONField<string> name; // "host:port" for this mongos | static const BSONField<std::string> name; | |||
static BSONField<Date_t> ping; // last time it was seen alive | static const BSONField<Date_t> ping; | |||
static BSONField<int> up; // uptime at the last ping | static const BSONField<int> up; | |||
static BSONField<bool> waiting; // for testing purposes | static const BSONField<bool> waiting; | |||
static BSONField<string> mongoVersion; // version of mongos | static const BSONField<std::string> mongoVersion; | |||
static BSONField<int> configVersion; // config version of mongos | static const BSONField<int> configVersion; | |||
// | // | |||
// mongos type methods | // mongos type methods | |||
// | // | |||
MongosType(); | MongosType(); | |||
~MongosType(); | ~MongosType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
skipping to change at line 93 | skipping to change at line 89 | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(MongosType* other) const; | void cloneTo(MongosType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setName(const StringData& name) { _name = name.toString(); } | // Mandatory Fields | |||
const std::string& getName() const { return _name; } | void setName(const StringData& name) { | |||
_name = name.toString(); | ||||
void setPing(const Date_t& time) { _ping = time; } | _isNameSet = true; | |||
Date_t getPing() const { return _ping; } | } | |||
void setUp(int up) { _up = up; } | void unsetName() { _isNameSet = false; } | |||
int getUp() const { return _up; } | ||||
bool isNameSet() const { return _isNameSet; } | ||||
void setWaiting(bool waiting) { _waiting = waiting; } | ||||
bool getWaiting() const { return _waiting; } | // Calling get*() methods when the member is not set results in und | |||
efined behavior | ||||
void setMongoVersion(const std::string& mongoVersion) { _mongoVersi | const std::string& getName() const { | |||
on = mongoVersion; } | dassert(_isNameSet); | |||
const std::string getMongoVersion() const { return _mongoVersion; } | return _name; | |||
} | ||||
void setConfigVersion(int configVersion) { _configVersion = configV | ||||
ersion; } | void setPing(const Date_t ping) { | |||
int getConfigVersion() const { return _configVersion; } | _ping = ping; | |||
_isPingSet = true; | ||||
} | ||||
void unsetPing() { _isPingSet = false; } | ||||
bool isPingSet() const { return _isPingSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const Date_t getPing() const { | ||||
dassert(_isPingSet); | ||||
return _ping; | ||||
} | ||||
void setUp(const int up) { | ||||
_up = up; | ||||
_isUpSet = true; | ||||
} | ||||
void unsetUp() { _isUpSet = false; } | ||||
bool isUpSet() const { return _isUpSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const int getUp() const { | ||||
dassert(_isUpSet); | ||||
return _up; | ||||
} | ||||
void setWaiting(const bool waiting) { | ||||
_waiting = waiting; | ||||
_isWaitingSet = true; | ||||
} | ||||
void unsetWaiting() { _isWaitingSet = false; } | ||||
bool isWaitingSet() const { return _isWaitingSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const bool getWaiting() const { | ||||
dassert(_isWaitingSet); | ||||
return _waiting; | ||||
} | ||||
// Optional Fields | ||||
void setMongoVersion(const StringData& mongoVersion) { | ||||
_mongoVersion = mongoVersion.toString(); | ||||
_isMongoVersionSet = true; | ||||
} | ||||
void unsetMongoVersion() { _isMongoVersionSet = false; } | ||||
bool isMongoVersionSet() const { | ||||
return _isMongoVersionSet || mongoVersion.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
std::string getMongoVersion() const { | ||||
if (_isMongoVersionSet) { | ||||
return _mongoVersion; | ||||
} else { | ||||
dassert(mongoVersion.hasDefault()); | ||||
return mongoVersion.getDefault(); | ||||
} | ||||
} | ||||
void setConfigVersion(const int configVersion) { | ||||
_configVersion = configVersion; | ||||
_isConfigVersionSet = true; | ||||
} | ||||
void unsetConfigVersion() { _isConfigVersionSet = false; } | ||||
bool isConfigVersionSet() const { | ||||
return _isConfigVersionSet || configVersion.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
int getConfigVersion() const { | ||||
if (_isConfigVersionSet) { | ||||
return _configVersion; | ||||
} else { | ||||
dassert(configVersion.hasDefault()); | ||||
return configVersion.getDefault(); | ||||
} | ||||
} | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
string _name; // (M) "host:port" for this mongos | std::string _name; // (M) "host:port" for this mongos | |||
Date_t _ping; // (M) last time it was seen alive | bool _isNameSet; | |||
int _up; // (M) uptime at the last ping | Date_t _ping; // (M) last time it was seen alive | |||
bool _waiting; // (M) for testing purposes | bool _isPingSet; | |||
string _mongoVersion; // (M) the mongodb version of the ping | int _up; // (M) uptime at the last ping | |||
ing mongos | bool _isUpSet; | |||
int _configVersion; // (M) the config version of the pingi | bool _waiting; // (M) for testing purposes | |||
ng mongos | bool _isWaitingSet; | |||
std::string _mongoVersion; // (O) the mongodb version of the p | ||||
inging mongos | ||||
bool _isMongoVersionSet; | ||||
int _configVersion; // (O) the config version of the pinging m | ||||
ongos | ||||
bool _isConfigVersionSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 9 change blocks. | ||||
46 lines changed or deleted | 141 lines changed or added | |||
type_settings.h | type_settings.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.settings collection. All manipulation of documents coming fro m that | * config.settings collection. All manipulation of documents coming fro m that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* unique_ptr<DbClientCursor> cursor; | * BSONObj query = QUERY(SettingsType::exampleField("exampleFieldNa | |||
* BSONObj query = QUERY(SettingsType::key("balancer")); | me")); | |||
* cursor.reset(conn->query(SettingsType::ConfigNS, query, ...)); | * exampleDoc = conn->findOne(SettingsType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* while (cursor->more()) { | * SettingsType exampleType; | |||
* settingsDoc = cursor->next(); | * string errMsg; | |||
* SettingsType settings; | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* settings.fromBSON(settingsDoc); | isValid(&errMsg)) { | |||
* if (! settings.isValid()) { | * // Can't use 'exampleType'. Take action. | |||
* // Can't use 'settings'. Take action. | ||||
* } | ||||
* // use 'settings' | ||||
* } | * } | |||
* // use 'exampleType' | ||||
* | ||||
*/ | */ | |||
class SettingsType { | class SettingsType { | |||
MONGO_DISALLOW_COPYING(SettingsType); | MONGO_DISALLOW_COPYING(SettingsType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the settings collection in the config server. | // Name of the settings collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the settings collection type. | // Field names and types in the settings collection type. | |||
static BSONField<string> key; // key determinin | static const BSONField<std::string> key; | |||
g the type of setting | static const BSONField<int> chunksize; | |||
// document this | static const BSONField<bool> balancerStopped; | |||
is | static const BSONField<BSONObj> balancerActiveWindow; | |||
// === chunksize options === | static const BSONField<bool> shortBalancerSleep; | |||
static BSONField<int> chunksize; // size of the ch | static const BSONField<bool> secondaryThrottle; | |||
unks in our cluster | ||||
// === balancer options === | ||||
static BSONField<bool> balancerStopped; // balancer enabl | ||||
ed/disabled | ||||
static BSONField<BSONObj> balancerActiveWindow; // if present, ac | ||||
tiveWindow is an interval | ||||
// during the day | ||||
when the balancer should | ||||
// be active. | ||||
// Format: { star | ||||
t: "08:00" , stop: | ||||
// "19:30" }, str | ||||
ftime format is %H:%M | ||||
static BSONField<bool> shortBalancerSleep; // controls how l | ||||
ong the balancer sleeps | ||||
// in some situat | ||||
ions | ||||
static BSONField<bool> secondaryThrottle; // only migrate c | ||||
hunks as fast as at least | ||||
// one secondary | ||||
can keep up with | ||||
// | // | |||
// settings type methods | // settings type methods | |||
// | // | |||
SettingsType(); | SettingsType(); | |||
~SettingsType(); | ~SettingsType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
skipping to change at line 102 | skipping to change at line 89 | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(SettingsType* other); | void cloneTo(SettingsType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setKey(const StringData& key) { _key = key.toString(); } | // Mandatory Fields | |||
const std::string& getKey() const { return _key; } | void setKey(const StringData& key) { | |||
_key = key.toString(); | ||||
_isKeySet = true; | ||||
} | ||||
void unsetKey() { _isKeySet = false; } | ||||
bool isKeySet() const { return _isKeySet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string getKey() const { | ||||
dassert(_isKeySet); | ||||
return _key; | ||||
} | ||||
// Optional Fields | ||||
void setChunksize(int chunksize) { | ||||
_chunksize = chunksize; | ||||
_isChunksizeSet = true; | ||||
} | ||||
void unsetChunksize() { _isChunksizeSet = false; } | ||||
bool isChunksizeSet() const { | ||||
return _isChunksizeSet || chunksize.hasDefault(); | ||||
} | ||||
void setChunksize(int chunksize) { _chunksize = chunksize; } | // Calling get*() methods when the member is not set and has no def | |||
int getChunksize() const { return _chunksize; } | ault results in undefined | |||
// behavior | ||||
int getChunksize() const { | ||||
if (_isChunksizeSet) { | ||||
return _chunksize; | ||||
} else { | ||||
dassert(chunksize.hasDefault()); | ||||
return chunksize.getDefault(); | ||||
} | ||||
} | ||||
void setBalancerStopped(bool balancerStopped) { | ||||
_balancerStopped = balancerStopped; | ||||
_isBalancerStoppedSet = true; | ||||
} | ||||
void setBalancerStopped(bool balancerStopped) { _balancerStopped = | void unsetBalancerStopped() { _isBalancerStoppedSet = false; } | |||
balancerStopped; } | ||||
bool getBalancerStopped() const { return _balancerStopped; } | bool isBalancerStoppedSet() const { | |||
return _isBalancerStoppedSet || balancerStopped.hasDefault(); | ||||
} | ||||
void setBalancerActiveWindow(const BSONObj balancerActiveWindow) { | // Calling get*() methods when the member is not set and has no def | |||
ault results in undefined | ||||
// behavior | ||||
bool getBalancerStopped() const { | ||||
if (_isBalancerStoppedSet) { | ||||
return _balancerStopped; | ||||
} else { | ||||
dassert(balancerStopped.hasDefault()); | ||||
return balancerStopped.getDefault(); | ||||
} | ||||
} | ||||
void setBalancerActiveWindow(BSONObj& balancerActiveWindow) { | ||||
_balancerActiveWindow = balancerActiveWindow.getOwned(); | _balancerActiveWindow = balancerActiveWindow.getOwned(); | |||
_isBalancerActiveWindowSet = true; | ||||
} | ||||
void unsetBalancerActiveWindow() { _isBalancerActiveWindowSet = fal | ||||
se; } | ||||
bool isBalancerActiveWindowSet() const { | ||||
return _isBalancerActiveWindowSet || balancerActiveWindow.hasDe | ||||
fault(); | ||||
} | } | |||
BSONObj getBalancerActiveWindow() const { return _balancerActiveWin dow; } | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
BSONObj getBalancerActiveWindow() const { | ||||
if (_isBalancerActiveWindowSet) { | ||||
return _balancerActiveWindow; | ||||
} else { | ||||
dassert(balancerActiveWindow.hasDefault()); | ||||
return balancerActiveWindow.getDefault(); | ||||
} | ||||
} | ||||
void setShortBalancerSleep(bool shortBalancerSleep) { | void setShortBalancerSleep(bool shortBalancerSleep) { | |||
_shortBalancerSleep = shortBalancerSleep; | _shortBalancerSleep = shortBalancerSleep; | |||
_isShortBalancerSleepSet = true; | ||||
} | ||||
void unsetShortBalancerSleep() { _isShortBalancerSleepSet = false; | ||||
} | ||||
bool isShortBalancerSleepSet() const { | ||||
return _isShortBalancerSleepSet || shortBalancerSleep.hasDefaul | ||||
t(); | ||||
} | } | |||
bool getShortBalancerSleep() const { return _shortBalancerSleep; } | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getShortBalancerSleep() const { | ||||
if (_isShortBalancerSleepSet) { | ||||
return _shortBalancerSleep; | ||||
} else { | ||||
dassert(shortBalancerSleep.hasDefault()); | ||||
return shortBalancerSleep.getDefault(); | ||||
} | ||||
} | ||||
void setSecondaryThrottle(bool secondaryThrottle) { | void setSecondaryThrottle(bool secondaryThrottle) { | |||
_secondaryThrottle = secondaryThrottle; | _secondaryThrottle = secondaryThrottle; | |||
_isSecondaryThrottleSet = true; | ||||
} | ||||
void unsetSecondaryThrottle() { _isSecondaryThrottleSet = false; } | ||||
bool isSecondaryThrottleSet() const { | ||||
return _isSecondaryThrottleSet || secondaryThrottle.hasDefault( | ||||
); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getSecondaryThrottle() const { | ||||
if (_isSecondaryThrottleSet) { | ||||
return _secondaryThrottle; | ||||
} else { | ||||
dassert(secondaryThrottle.hasDefault()); | ||||
return secondaryThrottle.getDefault(); | ||||
} | ||||
} | } | |||
bool getSecondaryThrottle() const { return _secondaryThrottle; } | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
std::string _key; // (M) key determining the type of o | std::string _key; // (M) key determining the type o | |||
ptions to use | f options to use | |||
// === chunksize options === | bool _isKeySet; | |||
int _chunksize; // (S) size of the chunks in our clu | // === chunksize options === | |||
ster | int _chunksize; // (O) size of the chunks in our | |||
// === balancer options === | cluster | |||
bool _balancerStopped; // (O) balancer enabled/disabled | bool _isChunksizeSet; | |||
BSONObj _balancerActiveWindow; // (O) if present, activeWindow is a | // === balancer options === | |||
n interval | bool _balancerStopped; // (O) balancer enabled/disabled | |||
// during the day when the balancer | bool _isBalancerStoppedSet; | |||
should | ||||
// be active. | BSONObj _balancerActiveWindow; // (O) if present, activeWindow i | |||
// Format: { start: "08:00" , stop: | s an interval | |||
// "19:30" }, strftime format is %H: | bool _isBalancerActiveWindowSet; // during the day when the balance | |||
%M | r should | |||
bool _shortBalancerSleep; // (O) controls how long the balance | // be active. | |||
r sleeps | // Format: { start: "08:00" , stop | |||
// in some situations | : | |||
bool _secondaryThrottle; // (O) only migrate chunks as fast a | // "19:30" }, strftime format is % | |||
s at least | H:%M | |||
// one secondary can keep up with | ||||
bool _shortBalancerSleep; // (O) controls how long the bala | ||||
ncer sleeps | ||||
bool _isShortBalancerSleepSet; // in some situations | ||||
bool _secondaryThrottle; // (O) only migrate chunks as fas | ||||
t as at least | ||||
bool _isSecondaryThrottleSet; // one secondary can keep up with | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 21 change blocks. | ||||
73 lines changed or deleted | 166 lines changed or added | |||
type_shard.h | type_shard.h | |||
---|---|---|---|---|
skipping to change at line 34 | skipping to change at line 34 | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.shards collection. All manipulation of documents coming from that | * config.shards collection. All manipulation of documents coming from that | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | ||||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* BSONObj query = QUERY(ShardType::name("shard0000")); | * BSONObj query = QUERY(ShardType::exampleField("exampleFieldName" | |||
* shardDoc = conn->findOne(ShardType::ConfigNS, query); | )); | |||
* exampleDoc = conn->findOne(ShardType::ConfigNS, query); | ||||
* | * | |||
* // Process the response. | * // Process the response. | |||
* ShardType shard; | * ShardType exampleType; | |||
* shard.fromBSON(shardDoc); | * string errMsg; | |||
* if (! shard.isValid()) { | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* // Can't use 'shard'. Take action. | isValid(&errMsg)) { | |||
* // Can't use 'exampleType'. Take action. | ||||
* } | * } | |||
* // use 'shard' | * // use 'exampleType' | |||
* | * | |||
*/ | */ | |||
class ShardType { | class ShardType { | |||
MONGO_DISALLOW_COPYING(ShardType); | MONGO_DISALLOW_COPYING(ShardType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the shard collection in the config server. | // Name of the shards collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the shard collection type. | // Field names and types in the shards collection type. | |||
static BSONField<std::string> name; // shard's id | static const BSONField<std::string> name; | |||
static BSONField<std::string> host; // connection string for th | static const BSONField<std::string> host; | |||
e host(s) | static const BSONField<bool> draining; | |||
static BSONField<bool> draining; // is it draining chunks? | static const BSONField<long long> maxSize; | |||
static BSONField<long long> maxSize; // max allowed disk space u | static const BSONField<BSONArray> tags; | |||
sage | ||||
static BSONField<BSONArray> tags; // shard tags | ||||
// | // | |||
// shard type methods | // shards type methods | |||
// | // | |||
ShardType(); | ShardType(); | |||
~ShardType(); | ~ShardType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
* representations. Otherwise returns false and fills in the option al 'errMsg' string. | * representations. Otherwise returns false and fills in the option al 'errMsg' string. | |||
*/ | */ | |||
bool isValid(std::string* errMsg) const; | bool isValid(std::string* errMsg) const; | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(ShardType* other) const; | void cloneTo(ShardType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setName(const StringData& name) { _name = name.toString(); } | // Mandatory Fields | |||
const std::string& getName() const { return _name; } | void setName(const StringData& name) { | |||
_name = name.toString(); | ||||
void setHost(const StringData& host) { _host = host.toString(); } | _isNameSet = true; | |||
const std::string& getHost() const { return _host; } | } | |||
void setDraining(bool draining) { _draining = draining; } | void unsetName() { _isNameSet = false; } | |||
bool getDraining() const { return _draining; } | ||||
bool isNameSet() const { return _isNameSet; } | ||||
void setMaxSize(uint64_t maxSize) { _maxSize = maxSize; } | ||||
uint64_t getMaxSize() const { return _maxSize; } | // Calling get*() methods when the member is not set results in und | |||
efined behavior | ||||
void setTags(const BSONArray& tags) { _tags = tags; } | const std::string getName() const { | |||
BSONArray getTags() const { return _tags; } | dassert(_isNameSet); | |||
return _name; | ||||
} | ||||
void setHost(const StringData& host) { | ||||
_host = host.toString(); | ||||
_isHostSet = true; | ||||
} | ||||
void unsetHost() { _isHostSet = false; } | ||||
bool isHostSet() const { return _isHostSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string getHost() const { | ||||
dassert(_isHostSet); | ||||
return _host; | ||||
} | ||||
// Optional Fields | ||||
void setDraining(bool draining) { | ||||
_draining = draining; | ||||
_isDrainingSet = true; | ||||
} | ||||
void unsetDraining() { _isDrainingSet = false; } | ||||
bool isDrainingSet() const { | ||||
return _isDrainingSet || draining.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
bool getDraining() const { | ||||
if (_isDrainingSet) { | ||||
return _draining; | ||||
} else { | ||||
dassert(draining.hasDefault()); | ||||
return draining.getDefault(); | ||||
} | ||||
} | ||||
void setMaxSize(long long maxSize) { | ||||
_maxSize = maxSize; | ||||
_isMaxSizeSet = true; | ||||
} | ||||
void unsetMaxSize() { _isMaxSizeSet = false; } | ||||
bool isMaxSizeSet() const { | ||||
return _isMaxSizeSet || maxSize.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
long long getMaxSize() const { | ||||
if (_isMaxSizeSet) { | ||||
return _maxSize; | ||||
} else { | ||||
dassert(maxSize.hasDefault()); | ||||
return maxSize.getDefault(); | ||||
} | ||||
} | ||||
void setTags(BSONArray tags) { | ||||
_tags = tags; | ||||
_isTagsSet = true; | ||||
} | ||||
void unsetTags() { _isTagsSet = false; } | ||||
bool isTagsSet() const { | ||||
return _isTagsSet || tags.hasDefault(); | ||||
} | ||||
// Calling get*() methods when the member is not set and has no def | ||||
ault results in undefined | ||||
// behavior | ||||
BSONArray getTags() const { | ||||
if (_isTagsSet) { | ||||
return _tags; | ||||
} else { | ||||
dassert(tags.hasDefault()); | ||||
return tags.getDefault(); | ||||
} | ||||
} | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
std::string _name; // (M) shard's id | std::string _name; // (M) shard's id | |||
std::string _host; // (M) connection string for the host(s) | bool _isNameSet; | |||
bool _draining; // (O) is it draining chunks? | std::string _host; // (M) connection string for the host(s) | |||
long long _maxSize; // (O) maximum allowed disk space in MB | bool _isHostSet; | |||
BSONArray _tags; // (O) shard tags | bool _draining; // (O) is it draining chunks? | |||
bool _isDrainingSet; | ||||
long long _maxSize; // (O) maximum allowed disk space in MB | ||||
bool _isMaxSizeSet; | ||||
BSONArray _tags; // (O) shard tags | ||||
bool _isTagsSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 11 change blocks. | ||||
37 lines changed or deleted | 129 lines changed or added | |||
type_tags.h | type_tags.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
/** | /** | |||
* This class represents the layout and contents of documents contained in the | * This class represents the layout and contents of documents contained in the | |||
* config.tags collection. All manipulation of documents coming from th at | * config.tags collection. All manipulation of documents coming from th at | |||
* collection should be done with this class. | * collection should be done with this class. | |||
* | * | |||
* Usage Example: | * Usage Example: | |||
* | * | |||
* // Contact the config. 'conn' has been obtained before. | * // Contact the config. 'conn' has been obtained before. | |||
* DBClientBase* conn; | * DBClientBase* conn; | |||
* unique_ptr<DbClientCursor> cursor; | * BSONObj query = QUERY(TagsType::exampleField("exampleFieldName") | |||
* BSONObj query = QUERY(TagsType::ns("mydb.mycoll")); | ); | |||
* cursor.reset(conn->query(TagsType::ConfigNS, query, ...)); | * exampleDoc = conn->findOne(TagsType::ConfigNS, query); | |||
* | * | |||
* // Process the response. | * // Process the response. | |||
* while (cursor->more()) { | * TagsType exampleType; | |||
* tagDoc = cursor->next(); | * string errMsg; | |||
* TagsType tag; | * if (!exampleType.parseBSON(exampleDoc, &errMsg) || !exampleType. | |||
* tag.fromBSON(dbDoc); | isValid(&errMsg)) { | |||
* if (! tag.isValid()) { | * // Can't use 'exampleType'. Take action. | |||
* // Can't use 'tag'. Take action. | ||||
* } | ||||
* // use 'tag' | ||||
* } | * } | |||
* // use 'exampleType' | ||||
* | ||||
*/ | */ | |||
class TagsType { | class TagsType { | |||
MONGO_DISALLOW_COPYING(TagsType); | MONGO_DISALLOW_COPYING(TagsType); | |||
public: | public: | |||
// | // | |||
// schema declarations | // schema declarations | |||
// | // | |||
// Name of the tags collection in the config server. | // Name of the tags collection in the config server. | |||
static const std::string ConfigNS; | static const std::string ConfigNS; | |||
// Field names and types in the tags collection type. | // Field names and types in the tags collection type. | |||
static BSONField<std::string> ns; // namespace this tag is for | static const BSONField<std::string> ns; | |||
static BSONField<std::string> tag; // tag name | static const BSONField<std::string> tag; | |||
static BSONField<BSONObj> min; // first key of the tag, includi | static const BSONField<BSONObj> min; | |||
ng | static const BSONField<BSONObj> max; | |||
static BSONField<BSONObj> max; // last key of the tag, non-incl | ||||
uding | ||||
// | // | |||
// tags type methods | // tags type methods | |||
// | // | |||
TagsType(); | TagsType(); | |||
~TagsType(); | ~TagsType(); | |||
/** | /** | |||
* Returns true if all the mandatory fields are present and have va lid | * Returns true if all the mandatory fields are present and have va lid | |||
skipping to change at line 90 | skipping to change at line 87 | |||
/** | /** | |||
* Returns the BSON representation of the entry. | * Returns the BSON representation of the entry. | |||
*/ | */ | |||
BSONObj toBSON() const; | BSONObj toBSON() const; | |||
/** | /** | |||
* Clears and populates the internal state using the 'source' BSON object if the | * Clears and populates the internal state using the 'source' BSON object if the | |||
* latter contains valid values. Otherwise sets errMsg and returns false. | * latter contains valid values. Otherwise sets errMsg and returns false. | |||
*/ | */ | |||
bool parseBSON(BSONObj source, std::string* errMsg); | bool parseBSON(const BSONObj& source, std::string* errMsg); | |||
/** | /** | |||
* Clears the internal state. | * Clears the internal state. | |||
*/ | */ | |||
void clear(); | void clear(); | |||
/** | /** | |||
* Copies all the fields present in 'this' to 'other'. | * Copies all the fields present in 'this' to 'other'. | |||
*/ | */ | |||
void cloneTo(TagsType* other); | void cloneTo(TagsType* other) const; | |||
/** | /** | |||
* Returns a string representation of the current internal state. | * Returns a string representation of the current internal state. | |||
*/ | */ | |||
std::string toString() const; | std::string toString() const; | |||
// | // | |||
// individual field accessors | // individual field accessors | |||
// | // | |||
void setNS(const StringData& ns) { _ns = ns.toString(); } | // Mandatory Fields | |||
const std::string& getNS() const { return _ns; } | void setNS(const StringData& ns) { | |||
_ns = ns.toString(); | ||||
_isNsSet = true; | ||||
} | ||||
void unsetNS() { _isNsSet = false; } | ||||
bool isNSSet() const { return _isNsSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getNS() const { | ||||
dassert(_isNsSet); | ||||
return _ns; | ||||
} | ||||
void setTag(const StringData& tag) { | ||||
_tag = tag.toString(); | ||||
_isTagSet = true; | ||||
} | ||||
void unsetTag() { _isTagSet = false; } | ||||
bool isTagSet() const { return _isTagSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const std::string& getTag() const { | ||||
dassert(_isTagSet); | ||||
return _tag; | ||||
} | ||||
void setMin(const BSONObj& min) { | ||||
_min = min.getOwned(); | ||||
_isMinSet = true; | ||||
} | ||||
void unsetMin() { _isMinSet = false; } | ||||
bool isMinSet() const { return _isMinSet; } | ||||
// Calling get*() methods when the member is not set results in und | ||||
efined behavior | ||||
const BSONObj getMin() const { | ||||
dassert(_isMinSet); | ||||
return _min; | ||||
} | ||||
void setMax(const BSONObj& max) { | ||||
_max = max.getOwned(); | ||||
_isMaxSet = true; | ||||
} | ||||
void unsetMax() { _isMaxSet = false; } | ||||
void setTag(const StringData& tag) { _tag = tag.toString(); } | bool isMaxSet() const { return _isMaxSet; } | |||
const std::string& getTag() const { return _tag; } | ||||
void setMin(const BSONObj& min) { _min = min.getOwned(); } | // Calling get*() methods when the member is not set results in und | |||
BSONObj getMin() const { return _min; } | efined behavior | |||
const BSONObj getMax() const { | ||||
dassert(_isMaxSet); | ||||
return _max; | ||||
} | ||||
void setMax(const BSONObj& max) { _max = max.getOwned(); } | // Optional Fields | |||
BSONObj getMax() const { return _max; } | ||||
private: | private: | |||
// Convention: (M)andatory, (O)ptional, (S)pecial rule. | // Convention: (M)andatory, (O)ptional, (S)pecial rule. | |||
string _ns; // (M) namespace this tag is for | std::string _ns; // (M) namespace this tag is for | |||
string _tag; // (M) tag name | bool _isNsSet; | |||
BSONObj _min; // (M) first key of the tag, including | std::string _tag; // (M) tag name | |||
BSONObj _max; // (M) last key of the tag, non-including | bool _isTagSet; | |||
BSONObj _min; // (M) first key of the tag, including | ||||
bool _isMinSet; | ||||
BSONObj _max; // (M) last key of the tag, non-including | ||||
bool _isMaxSet; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 12 change blocks. | ||||
31 lines changed or deleted | 87 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 StringData& 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 14 | // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |||
enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO, SET_ON_INSERT } op; | enum Op { INC, SET, PUSH, PUSH_ALL, PULL, PULL_ALL , POP, UNSET, BI TAND, BITOR , BIT , ADDTOSET, RENAME_FROM, RENAME_TO, SET_ON_INSERT } op; | |||
static const char* modNames[]; | static const char* modNames[]; | |||
static unsigned modNamesNum; | static unsigned modNamesNum; | |||
const char* fieldName; | const char* fieldName; | |||
const char* shortFieldName; | const char* shortFieldName; | |||
// Determines if this mod must absoluetly be applied. In some repli cation scenarios, a | // Determines if this mod must absoluetly be applied. In some repli cation scenarios, a | |||
// failed apply of a mod does not constitute an error. In those cas es, setting strict | // failed apply of a mod does not constitute an error. In those cas es, setting strict | |||
// to off would not throw errors. | // to off would not throw errors. | |||
bool strictApply; | bool strictApply; | |||
// Determines if an index is going to be updated as part of the app | ||||
lication of this | ||||
// mod. | ||||
bool isIndexed; | ||||
BSONElement elt; // x:5 note: this is the actual element from the u pdateobj | BSONElement elt; // x:5 note: this is the actual element from the u pdateobj | |||
boost::shared_ptr<Matcher> matcher; | boost::shared_ptr<Matcher> matcher; | |||
bool matcherOnPrimitive; | bool matcherOnPrimitive; | |||
void init( Op o , BSONElement& e , bool forReplication ) { | void init( Op o , BSONElement& e , bool forReplication ) { | |||
op = o; | op = o; | |||
elt = e; | elt = e; | |||
strictApply = !forReplication; | strictApply = !forReplication; | |||
isIndexed = false; | ||||
if ( op == PULL && e.type() == Object ) { | if ( op == PULL && e.type() == Object ) { | |||
BSONObj t = e.embeddedObject(); | BSONObj t = e.embeddedObject(); | |||
if ( t.firstElement().getGtLtOp() == 0 ) { | if ( t.firstElement().getGtLtOp() == 0 ) { | |||
matcher.reset( new Matcher( t ) ); | matcher.reset( new Matcher( t ) ); | |||
matcherOnPrimitive = false; | matcherOnPrimitive = false; | |||
} | } | |||
else { | else { | |||
matcher.reset( new Matcher( BSON( "" << t ) ) ); | matcher.reset( new Matcher( BSON( "" << t ) ) ); | |||
matcherOnPrimitive = true; | matcherOnPrimitive = true; | |||
} | } | |||
skipping to change at line 142 | skipping to change at line 141 | |||
switch (op) { | switch (op) { | |||
case PUSH: | case PUSH: | |||
case PUSH_ALL: | case PUSH_ALL: | |||
case POP: | case POP: | |||
return true; | return true; | |||
default: | default: | |||
return false; | return false; | |||
} | } | |||
} | } | |||
static bool isIndexed( const string& fullName , const set<string>& | ||||
idxKeys ) { | ||||
const char * fieldName = fullName.c_str(); | ||||
// 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, '.' ) ) | ||||
if ( idxKeys.count( string( fieldName, dot - fieldName ) ) | ||||
) | ||||
return true; | ||||
// check if there is an index key equal to mod | ||||
if ( idxKeys.count(fullName) ) | ||||
return true; | ||||
// check if there is an index key that is a child of mod | ||||
set< string >::const_iterator j = idxKeys.upper_bound( fullName | ||||
); | ||||
if ( j != idxKeys.end() && j->find( fullName ) == 0 && (*j)[ful | ||||
lName.size()] == '.' ) | ||||
return true; | ||||
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 { | ||||
// first, check if full name is in idxKeys | ||||
if ( isIndexed( fieldName , idxKeys ) ) | ||||
return true; | ||||
string x; | ||||
if ( getCanonicalIndexField( fieldName, &x ) ) { | ||||
if ( isIndexed( x, idxKeys ) ) | ||||
return true; | ||||
} | ||||
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 | |||
*/ | */ | |||
bool _pullElementMatch( BSONElement& toMatch ) const; | bool _pullElementMatch( BSONElement& toMatch ) const; | |||
void _checkForAppending( const BSONElement& e ) const { | void _checkForAppending( const BSONElement& e ) const { | |||
if ( e.type() == Object ) { | if ( e.type() == Object ) { | |||
// this is a tiny bit slow, but rare and important | // this is a tiny bit slow, but rare and important | |||
skipping to change at line 232 | skipping to change at line 191 | |||
BSONObj obj = elt.embeddedObject(); | BSONObj obj = elt.embeddedObject(); | |||
if ( obj.nFields() != 2 ) | if ( obj.nFields() != 2 ) | |||
return false; | return false; | |||
BSONObjIterator i( obj ); | BSONObjIterator i( obj ); | |||
i.next(); | i.next(); | |||
BSONElement elemSlice = i.next(); | BSONElement elemSlice = i.next(); | |||
return strcmp( elemSlice.fieldName(), "$slice" ) == 0; | return strcmp( elemSlice.fieldName(), "$slice" ) == 0; | |||
} | } | |||
long long getSlice() const { | long long getSlice() const { | |||
// The $slice may be the second or the third elemen in the fiel d object. | // The $slice may be the second or the third element in the fie ld object. | |||
// { <field name>: { $each: [<each array>], $slice: -N, $sort: <pattern> } } | // { <field name>: { $each: [<each array>], $slice: -N, $sort: <pattern> } } | |||
// 'elt' here is the BSONElement above. | // 'elt' here is the BSONElement above. | |||
BSONObj obj = elt.embeddedObject(); | BSONObj obj = elt.embeddedObject(); | |||
BSONObjIterator i( obj ); | BSONObjIterator i( obj ); | |||
i.next(); | i.next(); | |||
BSONElement elem = i.next(); | BSONElement elem = i.next(); | |||
if ( ! str::equals( elem.fieldName(), "$slice" ) ) { | if ( ! str::equals( elem.fieldName(), "$slice" ) ) { | |||
elem = i.next(); | elem = i.next(); | |||
} | } | |||
dassert( elem.isNumber() ); | dassert( elem.isNumber() ); | |||
skipping to change at line 310 | skipping to change at line 269 | |||
} | } | |||
}; | }; | |||
/** | /** | |||
* stores a set of Mods | * stores a set of Mods | |||
* once created, should never be changed | * once created, should never be changed | |||
*/ | */ | |||
class ModSet : boost::noncopyable { | class ModSet : boost::noncopyable { | |||
typedef map<string,Mod> ModHolder; | typedef map<string,Mod> ModHolder; | |||
ModHolder _mods; | ModHolder _mods; | |||
int _isIndexed; | int _numIndexMaybeUpdated; | |||
int _numIndexAlwaysUpdated; | ||||
bool _hasDynamicArray; | bool _hasDynamicArray; | |||
static Mod::Op opFromStr( const char* fn ) { | static Mod::Op opFromStr( const char* fn ) { | |||
verify( fn[0] == '$' ); | verify( fn[0] == '$' ); | |||
switch( fn[1] ) { | switch( fn[1] ) { | |||
case 'i': { | case 'i': { | |||
if ( fn[2] == 'n' && fn[3] == 'c' && fn[4] == 0 ) | if ( fn[2] == 'n' && fn[3] == 'c' && fn[4] == 0 ) | |||
return Mod::INC; | return Mod::INC; | |||
break; | break; | |||
} | } | |||
skipping to change at line 392 | skipping to change at line 352 | |||
break; | break; | |||
} | } | |||
default: break; | default: break; | |||
} | } | |||
uassert( 10161 , "Invalid modifier specified " + string( fn ), false ); | uassert( 10161 , "Invalid modifier specified " + string( fn ), false ); | |||
return Mod::INC; | return Mod::INC; | |||
} | } | |||
ModSet() {} | ModSet() {} | |||
void updateIsIndexed( const Mod& m, const set<string>& idxKeys, con | /** | |||
st set<string>* backgroundKeys ) { | * if if applying this mod would require updating an index, set suc | |||
if ( m.isIndexed( idxKeys ) || | h condition in 'm', | |||
(backgroundKeys && m.isIndexed(*backgroundKeys)) ) { | * and update the number of indices touched in 'this' ModSet. | |||
_isIndexed++; | */ | |||
} | void setIndexedStatus( Mod& m, const IndexPathSet& idxKeys ); | |||
} | ||||
public: | public: | |||
ModSet( const BSONObj& from, | ModSet( const BSONObj& from, | |||
const set<string>& idxKeys = set<string>(), | const IndexPathSet& idxKeys = IndexPathSet(), | |||
const set<string>* backgroundKeys = 0, | ||||
bool forReplication = false ); | bool forReplication = false ); | |||
/** | /** | |||
* re-check if this mod is impacted by indexes | * re-check if this mod is impacted by indexes | |||
*/ | */ | |||
void updateIsIndexed( const set<string>& idxKeys, const set<string> * backgroundKeys ); | void setIndexedStatus( const IndexPathSet& idxKeys ); | |||
// TODO: this is inefficient - should probably just handle when ite rating | // TODO: this is inefficient - should probably just handle when ite rating | |||
ModSet * fixDynamicArray( const string& elemMatchKey ) const; | ModSet * fixDynamicArray( const string& elemMatchKey ) const; | |||
bool hasDynamicArray() const { return _hasDynamicArray; } | bool hasDynamicArray() const { return _hasDynamicArray; } | |||
/** | /** | |||
* creates a ModSetState suitable for operation on obj | * creates a ModSetState suitable for operation on obj | |||
* doesn't change or modify this ModSet or any underlying Mod | * doesn't change or modify this ModSet or any underlying Mod | |||
* | ||||
* flag 'insertion' differentiates between obj existing prior to th | ||||
is update. | ||||
*/ | */ | |||
auto_ptr<ModSetState> prepare( const BSONObj& obj ) const; | auto_ptr<ModSetState> prepare( const BSONObj& obj, bool insertion = false ) const; | |||
/** | /** | |||
* given a query pattern, builds an object suitable for an upsert | * given a query pattern, builds an object suitable for an upsert | |||
* will take the query spec and combine all $ operators | * will take the query spec and combine all $ operators | |||
*/ | */ | |||
BSONObj createNewFromQuery( const BSONObj& query ); | BSONObj createNewFromQuery( const BSONObj& query ); | |||
int isIndexed() const { return _isIndexed; } | int maxNumIndexUpdated() const { return _numIndexMaybeUpdated + _nu mIndexAlwaysUpdated; } | |||
unsigned size() const { return _mods.size(); } | unsigned size() const { return _mods.size(); } | |||
bool haveModForField( const char* fieldName ) const { | bool haveModForField( const char* fieldName ) const { | |||
return _mods.find( fieldName ) != _mods.end(); | return _mods.find( fieldName ) != _mods.end(); | |||
} | } | |||
bool haveConflictingMod( const string& fieldName ) { | bool haveConflictingMod( const string& fieldName ) { | |||
size_t idx = fieldName.find( '.' ); | size_t idx = fieldName.find( '.' ); | |||
if ( idx == string::npos ) | if ( idx == string::npos ) | |||
skipping to change at line 464 | skipping to change at line 424 | |||
} | } | |||
}; | }; | |||
/** | /** | |||
* Comparator between two BSONObjects that takes in consideration only the keys and | * Comparator between two BSONObjects that takes in consideration only the keys and | |||
* direction described in the sort pattern. | * direction described in the sort pattern. | |||
*/ | */ | |||
struct ProjectKeyCmp { | struct ProjectKeyCmp { | |||
BSONObj sortPattern; | BSONObj sortPattern; | |||
BSONObj projectionPattern; | ||||
ProjectKeyCmp( BSONObj pattern ) : sortPattern( pattern ) { | ||||
BSONObjBuilder projectBuilder; | ||||
BSONObjIterator i( sortPattern ); | ||||
while ( i.more() ) { | ||||
BSONElement elem = i.next(); | ||||
uassert( 16645, "sort pattern must be numeric", elem.isNumb | ||||
er() ); | ||||
double val = elem.Number(); | ProjectKeyCmp( BSONObj pattern ) : sortPattern( pattern) {} | |||
uassert( 16646, "sort pattern must contain 1 or -1", val*va | ||||
l == 1.0); | ||||
// | ||||
// If there are dots in the field name, check that they for | ||||
m a proper | ||||
// field path (e.g., no empty field parts). | ||||
// | ||||
StringData field( elem.fieldName() ); | ||||
uassert( 16651, "sort pattern field name cannot be empty" , | ||||
field.size() ); | ||||
size_t pos = field.find('.'); | ||||
while ( pos != string::npos ) { | ||||
uassert( 16639, | ||||
"empty field in dotted sort pattern", | ||||
(pos > 0) && (pos != field.size() - 1) ); | ||||
field = field.substr( pos+1 ); | ||||
pos = field.find('.'); | ||||
} | ||||
projectBuilder.append( elem.fieldName(), 1 ); | int operator()( const BSONObj& left, const BSONObj& right ) const { | |||
BSONObj keyLeft = left.extractFields( sortPattern, true ); | ||||
} | BSONObj keyRight = right.extractFields( sortPattern, true ); | |||
projectionPattern = projectBuilder.obj(); | ||||
} | ||||
int operator()( const BSONObj& left, const BSONObj& right ) { | ||||
BSONObj keyLeft = left.extractFields( projectionPattern, true ) | ||||
; | ||||
BSONObj keyRight = right.extractFields( projectionPattern, true | ||||
); | ||||
return keyLeft.woCompare( keyRight, sortPattern ) < 0; | return keyLeft.woCompare( keyRight, sortPattern ) < 0; | |||
} | } | |||
}; | }; | |||
/** | /** | |||
* stores any information about a single Mod operating on a single Obje ct | * stores any information about a single Mod operating on a single Obje ct | |||
*/ | */ | |||
class ModState : boost::noncopyable { | class ModState : boost::noncopyable { | |||
public: | public: | |||
const Mod* m; | const Mod* m; | |||
skipping to change at line 572 | skipping to change at line 498 | |||
return true; | return true; | |||
case Mod::BIT: | case Mod::BIT: | |||
case Mod::BITAND: | case Mod::BITAND: | |||
case Mod::BITOR: | case Mod::BITOR: | |||
return true; | return true; | |||
default: | default: | |||
return false; | return false; | |||
} | } | |||
} | } | |||
const char* getOpLogName() const; | ||||
void appendForOpLog( BSONObjBuilder& b ) const; | void appendForOpLog( BSONObjBuilder& b ) const; | |||
void apply( BSONBuilderBase& b , BSONElement in ) { | void apply( BSONBuilderBase& b , BSONElement in ) { | |||
m->apply( b , in , *this ); | m->apply( b , in , *this ); | |||
} | } | |||
void appendIncValue( BSONBuilderBase& b , bool useFullName ) const { | void appendIncValue( BSONBuilderBase& b , bool useFullName ) const { | |||
const char* n = useFullName ? m->fieldName : m->shortFieldName; | const char* n = useFullName ? m->fieldName : m->shortFieldName; | |||
switch ( incType ) { | switch ( incType ) { | |||
skipping to change at line 609 | skipping to change at line 536 | |||
* this is used to hold state, meta data while applying a ModSet to a B SONObj | * this is used to hold state, meta data while applying a ModSet to a B SONObj | |||
* the goal is to make ModSet const so its re-usable | * the goal is to make ModSet const so its re-usable | |||
*/ | */ | |||
class ModSetState : boost::noncopyable { | class ModSetState : boost::noncopyable { | |||
typedef map<string,shared_ptr<ModState>,LexNumCmp> ModStateHolder; | typedef map<string,shared_ptr<ModState>,LexNumCmp> ModStateHolder; | |||
typedef pair<const ModStateHolder::iterator,const ModStateHolder::i terator> ModStateRange; | typedef pair<const ModStateHolder::iterator,const ModStateHolder::i terator> ModStateRange; | |||
const BSONObj& _obj; | const BSONObj& _obj; | |||
ModStateHolder _mods; | ModStateHolder _mods; | |||
bool _inPlacePossible; | bool _inPlacePossible; | |||
BSONObj _newFromMods; // keep this data alive, as oplog generation may depend on it | BSONObj _newFromMods; // keep this data alive, as oplog generation may depend on it | |||
int _numIndexAlwaysUpdated; | ||||
int _numIndexMaybeUpdated; | ||||
ModSetState( const BSONObj& obj ) | ModSetState( const BSONObj& obj , int numIndexAlwaysUpdated , int n | |||
: _obj( obj ) , _mods( LexNumCmp( true ) ) , _inPlacePossible(t | umIndexMaybeUpdated ) | |||
rue) { | : _obj( obj ) | |||
, _mods( LexNumCmp( true ) ) | ||||
, _inPlacePossible(true) | ||||
, _numIndexAlwaysUpdated( numIndexAlwaysUpdated ) | ||||
, _numIndexMaybeUpdated( numIndexMaybeUpdated ) { | ||||
} | } | |||
/** | /** | |||
* @return if in place is still possible | * @return if in place is still possible | |||
*/ | */ | |||
bool amIInPlacePossible( bool inPlacePossible ) { | bool amIInPlacePossible( bool inPlacePossible ) { | |||
if ( ! inPlacePossible ) | if ( ! inPlacePossible ) | |||
_inPlacePossible = false; | _inPlacePossible = false; | |||
return _inPlacePossible; | return _inPlacePossible; | |||
} | } | |||
skipping to change at line 677 | skipping to change at line 610 | |||
continue; | continue; | |||
} | } | |||
arrBuilder.append( j.next() ); | arrBuilder.append( j.next() ); | |||
} | } | |||
ms.forceEmptyArray = true; | ms.forceEmptyArray = true; | |||
ms.fixedArray = BSONArray( arrBuilder.done().getOwn ed() ); | ms.fixedArray = BSONArray( arrBuilder.done().getOwn ed() ); | |||
} | } | |||
else if ( m.isSliceAndSort() ) { | else if ( m.isSliceAndSort() ) { | |||
long long slice = m.getSlice(); | long long slice = m.getSlice(); | |||
BSONObj sortPattern = m.getSort(); | ||||
// Sort the $each array over sortPattern. | // Sort the $each array over sortPattern. | |||
vector<BSONObj> workArea; | vector<BSONObj> workArea; | |||
BSONObjIterator j( arr ); | BSONObjIterator j( arr ); | |||
while ( j.more() ) { | while ( j.more() ) { | |||
workArea.push_back( j.next().Obj() ); | workArea.push_back( j.next().Obj() ); | |||
} | } | |||
sort( workArea.begin(), workArea.end(), ProjectKeyC | ProjectKeyCmp cmp( m.getSort() ); | |||
mp( sortPattern) ); | sort( workArea.begin(), workArea.end(), cmp ); | |||
// Slice to the appropriate size. If slice is zero, that's equivalent | // Slice to the appropriate size. If slice is zero, that's equivalent | |||
// to resetting the array, ie, a no-op. | // to resetting the array, ie, a no-op. | |||
BSONArrayBuilder arrBuilder( b.subarrayStart( m.sho rtFieldName ) ); | BSONArrayBuilder arrBuilder( b.subarrayStart( m.sho rtFieldName ) ); | |||
if (slice > 0) { | if (slice > 0) { | |||
long long skip = std::max( 0LL, | long long skip = std::max( 0LL, | |||
(long long)workArea. size() - slice ); | (long long)workArea. size() - slice ); | |||
for (vector<BSONObj>::iterator it = workArea.be gin(); | for (vector<BSONObj>::iterator it = workArea.be gin(); | |||
it != workArea.end(); | it != workArea.end(); | |||
++it ) { | ++it ) { | |||
skipping to change at line 794 | skipping to change at line 727 | |||
/** @return true iff the elements aren't eoo(), are distinct, and s hare a field name. */ | /** @return true iff the elements aren't eoo(), are distinct, and s hare a field name. */ | |||
static bool duplicateFieldName( const BSONElement& a, const BSONEle ment& b ); | static bool duplicateFieldName( const BSONElement& a, const BSONEle ment& b ); | |||
public: | public: | |||
bool canApplyInPlace() const { | bool canApplyInPlace() const { | |||
return _inPlacePossible; | return _inPlacePossible; | |||
} | } | |||
bool isUpdateIndexed() const { | ||||
if ( _numIndexAlwaysUpdated != 0 ) { | ||||
return true; | ||||
} | ||||
return isUpdateIndexedSlow(); | ||||
} | ||||
bool isUpdateIndexedSlow() const; | ||||
/** | /** | |||
* modified underlying _obj | * modified underlying _obj | |||
* @param isOnDisk - true means this is an on disk object, and this update needs to be made durable | * @param isOnDisk - true means this is an on disk object, and this update needs to be made durable | |||
*/ | */ | |||
void applyModsInPlace( bool isOnDisk ); | void applyModsInPlace( bool isOnDisk ); | |||
BSONObj createNewFromMods(); | BSONObj createNewFromMods(); | |||
// re-writing for oplog | // re-writing for oplog | |||
bool DEPRECATED_needOpLogRewrite() const { | bool DEPRECATED_needOpLogRewrite() const { | |||
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) | |||
if ( i->second->DEPRECATED_needOpLogRewrite() ) | if ( i->second->DEPRECATED_needOpLogRewrite() ) | |||
return true; | return true; | |||
return false; | return false; | |||
} | } | |||
BSONObj getOpLogRewrite() const { | BSONObj getOpLogRewrite() const; | |||
BSONObjBuilder b; | ||||
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m | ||||
ods.end(); i++ ) | ||||
i->second->appendForOpLog( b ); | ||||
return b.obj(); | ||||
} | ||||
bool DEPRECATED_haveArrayDepMod() const { | bool DEPRECATED_haveArrayDepMod() const { | |||
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) | |||
if ( i->second->m->arrayDep() ) | if ( i->second->m->arrayDep() ) | |||
return true; | return true; | |||
return false; | return false; | |||
} | } | |||
void DEPRECATED_appendSizeSpecForArrayDepMods( BSONObjBuilder& b ) const { | void DEPRECATED_appendSizeSpecForArrayDepMods( BSONObjBuilder& b ) const { | |||
for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) { | for ( ModStateHolder::const_iterator i = _mods.begin(); i != _m ods.end(); i++ ) { | |||
End of changes. 22 change blocks. | ||||
123 lines changed or deleted | 49 lines changed or added | |||
v8_db.h | v8_db.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#include <boost/function.hpp> | #include <boost/function.hpp> | |||
#include <v8.h> | #include <v8.h> | |||
#include "mongo/scripting/engine_v8.h" | #include "mongo/scripting/engine_v8.h" | |||
namespace mongo { | namespace mongo { | |||
class DBClientBase; | class DBClientBase; | |||
/** | /** | |||
* install the db related functions and objects in the given scope | * install database access functions | |||
*/ | */ | |||
void installDBTypes(V8Scope* scope, v8::Handle<v8::Object>& global); | void installDBAccess(V8Scope* scope); | |||
/** | ||||
* install BSON types and helpers | ||||
*/ | ||||
void installBSONTypes(V8Scope* scope); | ||||
/** | /** | |||
* get the DBClientBase connection from JS args | * get the DBClientBase connection from JS args | |||
*/ | */ | |||
mongo::DBClientBase* getConnection(const v8::Arguments& args); | mongo::DBClientBase* getConnection(const v8::Arguments& args); | |||
// Mongo constructors | // Mongo constructors | |||
v8::Handle<v8::Value> mongoConsLocal(V8Scope* scope, const v8::Argument s& args); | v8::Handle<v8::Value> mongoConsLocal(V8Scope* scope, const v8::Argument s& args); | |||
v8::Handle<v8::Value> mongoConsExternal(V8Scope* scope, const v8::Argum ents& args); | v8::Handle<v8::Value> mongoConsExternal(V8Scope* scope, const v8::Argum ents& args); | |||
v8::Handle<v8::FunctionTemplate> getMongoFunctionTemplate(V8Scope* scop e, bool local); | v8::Handle<v8::FunctionTemplate> getMongoFunctionTemplate(V8Scope* scop e, bool local); | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 7 lines changed or added | |||
v8_utils.h | v8_utils.h | |||
---|---|---|---|---|
skipping to change at line 28 | skipping to change at line 28 | |||
#pragma once | #pragma once | |||
#include <cstdio> | #include <cstdio> | |||
#include <cstdlib> | #include <cstdlib> | |||
#include <iostream> | #include <iostream> | |||
#include <string> | #include <string> | |||
#include <v8.h> | #include <v8.h> | |||
namespace mongo { | namespace mongo { | |||
void ReportException(v8::TryCatch* handler); | #define jsassert(x,msg) uassert(16664, (msg), (x)) | |||
#define jsassert(x,msg) uassert(16664, msg, x) | #define argumentCheck(mustBeTrue, errorMessage) \ | |||
if (!(mustBeTrue)) { \ | ||||
return v8AssertionException((errorMessage)); \ | ||||
} | ||||
std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::Value>& o); | std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::Value>& o); | |||
std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::TryCatch >* try_catch); | std::ostream& operator<<(std::ostream& s, const v8::Handle<v8::TryCatch >* try_catch); | |||
/** Simple v8 object to string conversion helper */ | ||||
std::string toSTLString(const v8::Handle<v8::Value>& o); | std::string toSTLString(const v8::Handle<v8::Value>& o); | |||
std::string toSTLString(const v8::TryCatch* try_catch); | ||||
/** Get the properties of an object (and it's prototype) as a comma-del | ||||
imited string */ | ||||
std::string v8ObjectToString(const v8::Handle<v8::Object>& o); | ||||
class V8Scope; | class V8Scope; | |||
void installFork(V8Scope* scope, | void installFork(V8Scope* scope, | |||
v8::Handle<v8::Object>& global, | v8::Handle<v8::Object>& global, | |||
v8::Handle<v8::Context>& context); | v8::Handle<v8::Context>& context); | |||
/** Throw a V8 exception from Mongo callback code; message text will be | ||||
preceded by "Error: ". | ||||
* Note: this function should be used for text that did not originate | ||||
from the JavaScript | ||||
* engine. Errors from the JavaScript engine will already have | ||||
a prefix such as | ||||
* ReferenceError, TypeError or SyntaxError. | ||||
* Note: call only from a native function called from JavaScript (a c | ||||
allback). | ||||
* The V8 ThrowException routine will note a JavaScript excepti | ||||
on that will be | ||||
* "thrown" in JavaScript when we return from the native functi | ||||
on. | ||||
* Note: it's required to return immediately to V8's execution contro | ||||
l without calling any | ||||
* V8 API functions. In this state, an empty handle may (will) | ||||
be returned. | ||||
* @param errorMessage Error message text. | ||||
* @return Empty handle to be returned from callback function. | ||||
*/ | ||||
v8::Handle<v8::Value> v8AssertionException(const char* errorMessage); | ||||
v8::Handle<v8::Value> v8AssertionException(const std::string& errorMess | ||||
age); | ||||
} | } | |||
End of changes. 5 change blocks. | ||||
3 lines changed or deleted | 34 lines changed or added | |||
value_internal.h | value_internal.h | |||
---|---|---|---|---|
skipping to change at line 121 | skipping to change at line 121 | |||
if (refCounter) | if (refCounter) | |||
intrusive_ptr_add_ref(genericRCPtr); | intrusive_ptr_add_ref(genericRCPtr); | |||
} | } | |||
/// These are only to be called during Value construction on an emp ty Value | /// These are only to be called during Value construction on an emp ty Value | |||
void putString(const StringData& s); | void putString(const StringData& s); | |||
void putVector(const RCVector* v); | void putVector(const RCVector* v); | |||
void putDocument(const Document& d); | void putDocument(const Document& d); | |||
void putRegEx(const BSONRegEx& re); | void putRegEx(const BSONRegEx& re); | |||
void putBinData(const BSONBinData& bd) { | void putBinData(const BSONBinData& bd) { | |||
putString(StringData(static_cast<const char*>(bd.data), bd.leng | putRefCountable( | |||
th)); | RCString::create( | |||
StringData(static_cast<const char*>(bd.data), bd.length | ||||
))); | ||||
binSubType = bd.type; | binSubType = bd.type; | |||
} | } | |||
void putDBRef(const BSONDBRef& dbref) { | void putDBRef(const BSONDBRef& dbref) { | |||
putRefCountable(new RCDBRef(dbref.ns.toString(), dbref.oid)); | putRefCountable(new RCDBRef(dbref.ns.toString(), dbref.oid)); | |||
} | } | |||
void putCodeWScope(const BSONCodeWScope& cws) { | void putCodeWScope(const BSONCodeWScope& cws) { | |||
putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope )); | putRefCountable(new RCCodeWScope(cws.code.toString(), cws.scope )); | |||
} | } | |||
skipping to change at line 213 | skipping to change at line 215 | |||
// bytes 3-16; | // bytes 3-16; | |||
union { | union { | |||
unsigned char oid[12]; | unsigned char oid[12]; | |||
struct { | struct { | |||
char shortStrSize; // TODO Consider moving into fla gs union (4 bits) | char shortStrSize; // TODO Consider moving into fla gs union (4 bits) | |||
char shortStrStorage[16/*total bytes*/ - 3/*offset* / - 1/*NUL byte*/]; | char shortStrStorage[16/*total bytes*/ - 3/*offset* / - 1/*NUL byte*/]; | |||
union { | union { | |||
char nulTerminator; | char nulTerminator; | |||
unsigned char binSubType; // type always goes h ere even if !shortStr | ||||
}; | }; | |||
}; | }; | |||
struct { | struct { | |||
union { | union { | |||
unsigned char binSubType; | ||||
char pad[6]; | char pad[6]; | |||
char stringCache[6]; // TODO copy first few byt es of strings in here | char stringCache[6]; // TODO copy first few byt es of strings in here | |||
}; | }; | |||
union { // 8 bytes long and 8-byte aligned | union { // 8 bytes long and 8-byte aligned | |||
// There should be no pointers to non-const dat a | // There should be no pointers to non-const dat a | |||
const RefCountable* genericRCPtr; | const RefCountable* genericRCPtr; | |||
double doubleValue; | double doubleValue; | |||
bool boolValue; | bool boolValue; | |||
int intValue; | int intValue; | |||
End of changes. 3 change blocks. | ||||
3 lines changed or deleted | 5 lines changed or added | |||
version.h | version.h | |||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
#include "mongo/bson/bsonobjbuilder.h" | #include "mongo/bson/bsonobjbuilder.h" | |||
namespace mongo { | namespace mongo { | |||
struct BSONArray; | struct BSONArray; | |||
// mongo version | // mongo version | |||
extern const char versionString[]; | extern const char versionString[]; | |||
extern const BSONArray versionArray; | extern const BSONArray versionArray; | |||
std::string mongodVersion(); | std::string mongodVersion(); | |||
// Convert a version string into a numeric array | ||||
BSONArray toVersionArray(const char* version); | ||||
// Checks whether another version is the same major version as us | ||||
bool isSameMajorVersion(const char* version); | ||||
void appendBuildInfo(BSONObjBuilder& result); | void appendBuildInfo(BSONObjBuilder& result); | |||
const char * gitVersion(); | const char * gitVersion(); | |||
const char * compiledJSEngine(); | const char * compiledJSEngine(); | |||
const char * allocator(); | const char * allocator(); | |||
const char * loaderFlags(); | const char * loaderFlags(); | |||
const char * compilerFlags(); | const char * compilerFlags(); | |||
void printGitVersion(); | void printGitVersion(); | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 6 lines changed or added | |||
windows_basic.h | windows_basic.h | |||
---|---|---|---|---|
skipping to change at line 30 | skipping to change at line 30 | |||
#if defined(_WIN32) | #if defined(_WIN32) | |||
// for rand_s() usage: | // for rand_s() usage: | |||
# define _CRT_RAND_S | # define _CRT_RAND_S | |||
# ifndef NOMINMAX | # ifndef NOMINMAX | |||
# define NOMINMAX | # define NOMINMAX | |||
# endif | # endif | |||
// tell windows.h not to include a bunch of headers we don't need: | // tell windows.h not to include a bunch of headers we don't need: | |||
# define WIN32_LEAN_AND_MEAN | # define WIN32_LEAN_AND_MEAN | |||
# include "mongo/targetver.h" | # include "mongo/targetver.h" | |||
# include <winsock2.h> //this must be included before the first windows.h i nclude | # include <winsock2.h> //this must be included before the first windows.h i nclude | |||
# include <ws2tcpip.h> | # include <ws2tcpip.h> | |||
# include <wspiapi.h> | # include <wspiapi.h> | |||
# include <windows.h> | # include <windows.h> | |||
#endif | #endif | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added | |||
writeback_listener.h | writeback_listener.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 "mongo/platform/unordered_map.h" | ||||
#include "mongo/platform/unordered_set.h" | ||||
#include "../client/connpool.h" | #include "../client/connpool.h" | |||
#include "../util/background.h" | #include "../util/background.h" | |||
#include "../db/client.h" | #include "../db/client.h" | |||
namespace mongo { | namespace mongo { | |||
/* | /* | |||
* The writeback listener takes back write attempts that were made agai nst a wrong shard. | * The writeback listener takes back write attempts that were made agai nst a wrong shard. | |||
* (Wrong here in the sense that the target chunk moved before this mon gos had a chance to | * (Wrong here in the sense that the target chunk moved before this mon gos had a chance to | |||
* learn so.) It is responsible for reapplying these writes to the corr ect shard. | * learn so.) It is responsible for reapplying these writes to the corr ect shard. | |||
skipping to change at line 75 | skipping to change at line 77 | |||
WriteBackListener( const string& addr ); | WriteBackListener( const string& addr ); | |||
string name() const { return _name; } | string name() const { return _name; } | |||
void run(); | void run(); | |||
private: | private: | |||
string _addr; | string _addr; | |||
string _name; | string _name; | |||
static mongo::mutex _cacheLock; // protects _cache | static mongo::mutex _cacheLock; // protects _cache | |||
static map<string,WriteBackListener*> _cache; // server to listener | static unordered_map<string,WriteBackListener*> _cache; // server t | |||
static set<string> _seenSets; // cache of set urls we've seen - not | o listener | |||
e this is ever expanding for order, case, changes | static unordered_set<string> _seenSets; // cache of set urls we've | |||
seen - note this is ever expanding for order, case, changes | ||||
struct WBStatus { | struct WBStatus { | |||
OID id; | OID id; | |||
BSONObj gle; | BSONObj gle; | |||
}; | }; | |||
static mongo::mutex _seenWritebacksLock; // protects _seenWritback s | static mongo::mutex _seenWritebacksLock; // protects _seenWritback s | |||
static map<ConnectionIdent,WBStatus> _seenWritebacks; // connection Id -> last write back GLE | static map<ConnectionIdent,WBStatus> _seenWritebacks; // connection Id -> last write back GLE | |||
}; | }; | |||
End of changes. 2 change blocks. | ||||
3 lines changed or deleted | 6 lines changed or added | |||