| config.h | | config.h | |
| | | | |
| skipping to change at line 144 | | skipping to change at line 144 | |
| /** | | /** | |
| @return true if there was sharding info to remove | | @return true if there was sharding info to remove | |
| */ | | */ | |
| bool removeSharding( const string& ns ); | | bool removeSharding( const string& ns ); | |
| | | | |
| /** | | /** | |
| * @return whether or not the 'ns' collection is partitioned | | * @return whether or not the 'ns' collection is partitioned | |
| */ | | */ | |
| bool isSharded( const string& ns ); | | bool isSharded( const string& ns ); | |
| | | | |
|
| ChunkManagerPtr getChunkManager( const string& ns , bool reload = f | | ChunkManagerPtr getChunkManager( const string& ns , bool reload = f | |
| alse ); | | alse, bool forceReload = false ); | |
| ChunkManagerPtr getChunkManagerIfExists( const string& ns , bool re | | ChunkManagerPtr getChunkManagerIfExists( const string& ns , bool re | |
| load = false ); | | load = false, bool forceReload = false ); | |
| | | | |
| /** | | /** | |
| * @return the correct for shard for the ns | | * @return the correct for shard for the ns | |
| * if the namespace is sharded, will return NULL | | * if the namespace is sharded, will return NULL | |
| */ | | */ | |
| const Shard& getShard( const string& ns ); | | const Shard& getShard( const string& ns ); | |
| | | | |
| const Shard& getPrimary() const { | | const Shard& getPrimary() const { | |
| uassert( 8041 , (string)"no primary shard configured for db: "
+ _name , _primary.ok() ); | | uassert( 8041 , (string)"no primary shard configured for db: "
+ _name , _primary.ok() ); | |
| return _primary; | | return _primary; | |
| | | | |
End of changes. 1 change blocks. |
| 4 lines changed or deleted | | 4 lines changed or added | |
|
| distlock.h | | distlock.h | |
| | | | |
| skipping to change at line 74 | | skipping to change at line 74 | |
| * collection with that name. | | * collection with that name. | |
| * | | * | |
| * To be maintained, each taken lock needs to be revalidaded ("pinged")
within a pre-established amount of time. This | | * To be maintained, each taken lock needs to be revalidaded ("pinged")
within a pre-established amount of time. This | |
| * class does this maintenance automatically once a DistributedLock obj
ect was constructed. | | * class does this maintenance automatically once a DistributedLock obj
ect was constructed. | |
| */ | | */ | |
| class DistributedLock { | | class DistributedLock { | |
| public: | | public: | |
| | | | |
| static LabeledLevel logLvl; | | static LabeledLevel logLvl; | |
| | | | |
|
| | | typedef boost::tuple<string, Date_t, Date_t, OID> PingData; | |
| | | | |
| | | class LastPings { | |
| | | public: | |
| | | LastPings() : _mutex( "DistributedLock::LastPings" ) {} | |
| | | ~LastPings(){} | |
| | | | |
| | | PingData getLastPing( const ConnectionString& conn, const string | |
| | | & lockName ); | |
| | | void setLastPing( const ConnectionString& conn, const string& lo | |
| | | ckName, const PingData& pd ); | |
| | | | |
| | | mongo::mutex _mutex; | |
| | | map< std::pair<string, string>, PingData > _lastPings; | |
| | | }; | |
| | | | |
| | | static LastPings lastPings; | |
| | | | |
| /** | | /** | |
| * The constructor does not connect to the configdb yet and constru
cting does not mean the lock was acquired. | | * The constructor does not connect to the configdb yet and constru
cting does not mean the lock was acquired. | |
| * Construction does trigger a lock "pinging" mechanism, though. | | * Construction does trigger a lock "pinging" mechanism, though. | |
| * | | * | |
| * @param conn address of config(s) server(s) | | * @param conn address of config(s) server(s) | |
| * @param name identifier for the lock | | * @param name identifier for the lock | |
| * @param lockTimeout how long can the log go "unpinged" before a n
ew attempt to lock steals it (in minutes). | | * @param lockTimeout how long can the log go "unpinged" before a n
ew attempt to lock steals it (in minutes). | |
| * @param lockPing how long to wait between lock pings | | * @param lockPing how long to wait between lock pings | |
| * @param legacy use legacy logic | | * @param legacy use legacy logic | |
| * | | * | |
| | | | |
| skipping to change at line 148 | | skipping to change at line 164 | |
| const string _processId; | | const string _processId; | |
| | | | |
| // Timeout for lock, usually LOCK_TIMEOUT | | // Timeout for lock, usually LOCK_TIMEOUT | |
| const unsigned long long _lockTimeout; | | const unsigned long long _lockTimeout; | |
| const unsigned long long _maxClockSkew; | | const unsigned long long _maxClockSkew; | |
| const unsigned long long _maxNetSkew; | | const unsigned long long _maxNetSkew; | |
| const unsigned long long _lockPing; | | const unsigned long long _lockPing; | |
| | | | |
| private: | | private: | |
| | | | |
|
| void resetLastPing(){ | | void resetLastPing(){ lastPings.setLastPing( _conn, _name, PingData | |
| scoped_lock lk( _mutex ); | | () ); } | |
| _lastPingCheck = boost::tuple<string, Date_t, Date_t, OID>(); | | void setLastPing( const PingData& pd ){ lastPings.setLastPing( _con | |
| } | | n, _name, pd ); } | |
| | | PingData getLastPing(){ return lastPings.getLastPing( _conn, _name | |
| mongo::mutex _mutex; | | ); } | |
| | | | |
|
| // Data from last check of process with ping time | | | |
| boost::tuple<string, Date_t, Date_t, OID> _lastPingCheck; | | | |
| // May or may not exist, depending on startup | | // May or may not exist, depending on startup | |
|
| | | mongo::mutex _mutex; | |
| string _threadId; | | string _threadId; | |
| | | | |
| }; | | }; | |
| | | | |
| class dist_lock_try { | | class dist_lock_try { | |
| public: | | public: | |
| | | | |
| dist_lock_try() : _lock(NULL), _got(false) {} | | dist_lock_try() : _lock(NULL), _got(false) {} | |
| | | | |
| dist_lock_try( const dist_lock_try& that ) : _lock(that._lock), _got
(that._got), _other(that._other) { | | dist_lock_try( const dist_lock_try& that ) : _lock(that._lock), _got
(that._got), _other(that._other) { | |
| | | | |
End of changes. 4 change blocks. |
| 8 lines changed or deleted | | 25 lines changed or added | |
|
| oplog.h | | oplog.h | |
| | | | |
| skipping to change at line 133 | | skipping to change at line 133 | |
| }; | | }; | |
| | | | |
| void pretouchOperation(const BSONObj& op); | | void pretouchOperation(const BSONObj& op); | |
| void pretouchN(vector<BSONObj>&, unsigned a, unsigned b); | | void pretouchN(vector<BSONObj>&, unsigned a, unsigned b); | |
| | | | |
| /** | | /** | |
| * take an op and apply locally | | * take an op and apply locally | |
| * used for applying from an oplog | | * used for applying from an oplog | |
| * @param fromRepl really from replication or for testing/internal/comm
and/etc... | | * @param fromRepl really from replication or for testing/internal/comm
and/etc... | |
| */ | | */ | |
|
| void applyOperation_inlock(const BSONObj& op , bool fromRepl = true ); | | bool applyOperation_inlock(const BSONObj& op , bool fromRepl = true ); | |
| } | | } | |
| | | | |
End of changes. 1 change blocks. |
| 1 lines changed or deleted | | 1 lines changed or added | |
|
| queryutil.h | | queryutil.h | |
| | | | |
| skipping to change at line 331 | | skipping to change at line 331 | |
| * @return first key of 'obj' that would be encountered by a forwar
d | | * @return first key of 'obj' that would be encountered by a forwar
d | |
| * index scan using this FieldRangeVector, BSONObj() if no such key
. | | * index scan using this FieldRangeVector, BSONObj() if no such key
. | |
| */ | | */ | |
| BSONObj firstMatch( const BSONObj &obj ) const; | | BSONObj firstMatch( const BSONObj &obj ) const; | |
| | | | |
| private: | | private: | |
| int matchingLowElement( const BSONElement &e, int i, bool direction
, bool &lowEquality ) const; | | int matchingLowElement( const BSONElement &e, int i, bool direction
, bool &lowEquality ) const; | |
| bool matchesElement( const BSONElement &e, int i, bool direction )
const; | | bool matchesElement( const BSONElement &e, int i, bool direction )
const; | |
| bool matchesKey( const BSONObj &key ) const; | | bool matchesKey( const BSONObj &key ) const; | |
| vector<FieldRange> _ranges; | | vector<FieldRange> _ranges; | |
|
| const IndexSpec &_indexSpec; | | IndexSpec _indexSpec; | |
| int _direction; | | int _direction; | |
| vector<BSONObj> _queries; // make sure mem owned | | vector<BSONObj> _queries; // make sure mem owned | |
| friend class FieldRangeVectorIterator; | | friend class FieldRangeVectorIterator; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Helper class for iterating through an ordered representation of keys | | * Helper class for iterating through an ordered representation of keys | |
| * to find those keys that match a specified FieldRangeVector. | | * to find those keys that match a specified FieldRangeVector. | |
| */ | | */ | |
| class FieldRangeVectorIterator { | | class FieldRangeVectorIterator { | |
| | | | |
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 494 | | skipping to change at line 494 | |
| friend class Consensus; | | friend class Consensus; | |
| | | | |
| private: | | private: | |
| /* pulling data from primary related - see rs_sync.cpp */ | | /* pulling data from primary related - see rs_sync.cpp */ | |
| bool initialSyncOplogApplication(const Member *primary, OpTime appl
yGTE, OpTime minValid); | | bool initialSyncOplogApplication(const Member *primary, OpTime appl
yGTE, OpTime minValid); | |
| void _syncDoInitialSync(); | | void _syncDoInitialSync(); | |
| void syncDoInitialSync(); | | void syncDoInitialSync(); | |
| void _syncThread(); | | void _syncThread(); | |
| bool tryToGoLiveAsASecondary(OpTime&); // readlocks | | bool tryToGoLiveAsASecondary(OpTime&); // readlocks | |
| void syncTail(); | | void syncTail(); | |
|
| void syncApply(const BSONObj &o); | | bool syncApply(const BSONObj &o); | |
| unsigned _syncRollback(OplogReader& r); | | unsigned _syncRollback(OplogReader& r); | |
| void syncRollback(OplogReader& r); | | void syncRollback(OplogReader& r); | |
| void syncFixUp(HowToFixUp& h, OplogReader& r); | | void syncFixUp(HowToFixUp& h, OplogReader& r); | |
| bool _getOplogReader(OplogReader& r, string& hn); | | bool _getOplogReader(OplogReader& r, string& hn); | |
| bool _isStale(OplogReader& r, const string& hn); | | bool _isStale(OplogReader& r, const string& hn); | |
| public: | | public: | |
| void syncThread(); | | void syncThread(); | |
| const OpTime lastOtherOpTime() const; | | const OpTime lastOtherOpTime() const; | |
| }; | | }; | |
| | | | |
| | | | |
End of changes. 1 change blocks. |
| 1 lines changed or deleted | | 1 lines changed or added | |
|
| rs_config.h | | rs_config.h | |
| | | | |
| skipping to change at line 83 | | skipping to change at line 83 | |
| } | | } | |
| void check() const; /* check validity, assert if not. */ | | void check() const; /* check validity, assert if not. */ | |
| BSONObj asBson() const; | | BSONObj asBson() const; | |
| bool potentiallyHot() const { return !arbiterOnly && priority >
0; } | | bool potentiallyHot() const { return !arbiterOnly && priority >
0; } | |
| void updateGroups(const OpTime& last) { | | void updateGroups(const OpTime& last) { | |
| for (set<TagSubgroup*>::iterator it = _groups.begin(); it !
= _groups.end(); it++) { | | for (set<TagSubgroup*>::iterator it = _groups.begin(); it !
= _groups.end(); it++) { | |
| ((TagSubgroup*)(*it))->updateLast(last); | | ((TagSubgroup*)(*it))->updateLast(last); | |
| } | | } | |
| } | | } | |
| bool operator==(const MemberCfg& r) const { | | bool operator==(const MemberCfg& r) const { | |
|
| | | if (!tags.empty() || !r.tags.empty()) { | |
| | | if (tags.size() != r.tags.size()) { | |
| | | return false; | |
| | | } | |
| | | | |
| | | // if they are the same size and not equal, at least on | |
| | | e | |
| | | // element in A must be different in B | |
| | | for (map<string,string>::const_iterator lit = tags.begi | |
| | | n(); lit != tags.end(); lit++) { | |
| | | map<string,string>::const_iterator rit = r.tags.fin | |
| | | d((*lit).first); | |
| | | | |
| | | if (rit == r.tags.end() || (*lit).second != (*rit). | |
| | | second) { | |
| | | return false; | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| return _id==r._id && votes == r.votes && h == r.h && priori
ty == r.priority && | | return _id==r._id && votes == r.votes && h == r.h && priori
ty == r.priority && | |
| arbiterOnly == r.arbiterOnly && slaveDelay == r.slav
eDelay && hidden == r.hidden && | | arbiterOnly == r.arbiterOnly && slaveDelay == r.slav
eDelay && hidden == r.hidden && | |
| buildIndexes == buildIndexes; | | buildIndexes == buildIndexes; | |
| } | | } | |
| bool operator!=(const MemberCfg& r) const { return !(*this == r
); } | | bool operator!=(const MemberCfg& r) const { return !(*this == r
); } | |
| }; | | }; | |
| | | | |
| vector<MemberCfg> members; | | vector<MemberCfg> members; | |
| string _id; | | string _id; | |
| int version; | | int version; | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 20 lines changed or added | |
|
| rwlock.h | | rwlock.h | |
| | | | |
| skipping to change at line 206 | | skipping to change at line 206 | |
| | | | |
| const char * implType() const { return "posix"; } | | const char * implType() const { return "posix"; } | |
| | | | |
| int lowPriorityWaitMS() const { return _lowPriorityWaitMS; } | | int lowPriorityWaitMS() const { return _lowPriorityWaitMS; } | |
| | | | |
| void lock() { | | void lock() { | |
| check( pthread_rwlock_wrlock( &_lock ) ); | | check( pthread_rwlock_wrlock( &_lock ) ); | |
| DEV mutexDebugger.entering(_name); | | DEV mutexDebugger.entering(_name); | |
| } | | } | |
| void unlock() { | | void unlock() { | |
|
| mutexDebugger.leaving(_name); | | DEV mutexDebugger.leaving(_name); | |
| check( pthread_rwlock_unlock( &_lock ) ); | | check( pthread_rwlock_unlock( &_lock ) ); | |
| } | | } | |
| | | | |
| void lock_shared() { | | void lock_shared() { | |
| check( pthread_rwlock_rdlock( &_lock ) ); | | check( pthread_rwlock_rdlock( &_lock ) ); | |
| } | | } | |
| | | | |
| void unlock_shared() { | | void unlock_shared() { | |
| check( pthread_rwlock_unlock( &_lock ) ); | | check( pthread_rwlock_unlock( &_lock ) ); | |
| } | | } | |
| | | | |
End of changes. 1 change blocks. |
| 1 lines changed or deleted | | 1 lines changed or added | |
|
| value.h | | value.h | |
| | | | |
| skipping to change at line 24 | | skipping to change at line 24 | |
| * 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 | |
| | | | |
| #include "mutex.h" | | #include "mutex.h" | |
|
| | | #include "spin_lock.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| /** declare that a variable that is "guarded" by a mutex. | | /** declare that a variable that is "guarded" by a mutex. | |
| | | | |
| The decl documents the rule. For example "counta and countb are gu
arded by xyzMutex": | | The decl documents the rule. For example "counta and countb are gu
arded by xyzMutex": | |
| | | | |
| Guarded<int, xyzMutex> counta; | | Guarded<int, xyzMutex> counta; | |
| Guarded<int, xyzMutex> countb; | | Guarded<int, xyzMutex> countb; | |
| | | | |
| Upon use, specify the scoped_lock object. This makes it hard for s
omeone | | Upon use, specify the scoped_lock object. This makes it hard for s
omeone | |
| later to forget to be in the lock. Check is made that it is the ri
ght lock in _DEBUG | | later to forget to be in the lock. Check is made that it is the ri
ght lock in _DEBUG | |
| builds at runtime. | | builds at runtime. | |
| */ | | */ | |
| template <typename T, mutex& BY> | | template <typename T, mutex& BY> | |
|
| class Guarded { | | class Guarded : boost::noncopyable { | |
| T _val; | | T _val; | |
| public: | | public: | |
| T& ref(const scoped_lock& lk) { | | T& ref(const scoped_lock& lk) { | |
| dassert( lk._mut == &BY ); | | dassert( lk._mut == &BY ); | |
| return _val; | | return _val; | |
| } | | } | |
| }; | | }; | |
| | | | |
| class DiagStr { | | class DiagStr { | |
| string _s; | | string _s; | |
|
| static mutex m; | | mutable SpinLock m; | |
| public: | | public: | |
| DiagStr(const DiagStr& r) : _s(r.get()) { } | | DiagStr(const DiagStr& r) : _s(r.get()) { } | |
| DiagStr() { } | | DiagStr() { } | |
| bool empty() const { | | bool empty() const { | |
|
| mutex::scoped_lock lk(m); | | scoped_spinlock lk(m); | |
| return _s.empty(); | | return _s.empty(); | |
| } | | } | |
| string get() const { | | string get() const { | |
|
| mutex::scoped_lock lk(m); | | scoped_spinlock lk(m); | |
| return _s; | | return _s; | |
| } | | } | |
| | | | |
| void set(const char *s) { | | void set(const char *s) { | |
|
| mutex::scoped_lock lk(m); | | scoped_spinlock lk(m); | |
| _s = s; | | _s = s; | |
| } | | } | |
| void set(const string& s) { | | void set(const string& s) { | |
|
| mutex::scoped_lock lk(m); | | scoped_spinlock lk(m); | |
| _s = s; | | _s = s; | |
| } | | } | |
| operator string() const { return get(); } | | operator string() const { return get(); } | |
| void operator=(const string& s) { set(s); } | | void operator=(const string& s) { set(s); } | |
|
| | | void operator=(const DiagStr& rhs) { | |
| | | scoped_spinlock lk(m); | |
| | | _s = rhs.get(); | |
| | | } | |
| }; | | }; | |
| | | | |
|
| | | #if 0 // not including in 2.0 | |
| | | | |
| | | /** Thread safe map. | |
| | | Be careful not to use this too much or it could make things slow; | |
| | | if not a hot code path no problem. | |
| | | | |
| | | Examples: | |
| | | | |
| | | mapsf<int,int> mp; | |
| | | | |
| | | int x = mp.get(); | |
| | | | |
| | | map<int,int> two; | |
| | | mp.swap(two); | |
| | | | |
| | | { | |
| | | mapsf<int,int>::ref r(mp); | |
| | | r[9] = 1; | |
| | | map<int,int>::iterator i = r.r.begin(); | |
| | | } | |
| | | | |
| | | */ | |
| | | template< class K, class V > | |
| | | struct mapsf : boost::noncopyable { | |
| | | SimpleMutex m; | |
| | | map<K,V> val; | |
| | | friend struct ref; | |
| | | public: | |
| | | mapsf() : m("mapsf") { } | |
| | | void swap(map<K,V>& rhs) { | |
| | | SimpleMutex::scoped_lock lk(m); | |
| | | val.swap(rhs); | |
| | | } | |
| | | // safe as we pass by value: | |
| | | V get(K k) { | |
| | | SimpleMutex::scoped_lock lk(m); | |
| | | map<K,V>::iterator i = val.find(k); | |
| | | if( i == val.end() ) | |
| | | return K(); | |
| | | return i->second; | |
| | | } | |
| | | // think about deadlocks when using ref. the other methods | |
| | | // above will always be safe as they are "leaf" operations. | |
| | | struct ref { | |
| | | SimpleMutex::scoped_lock lk; | |
| | | public: | |
| | | map<K,V> const &r; | |
| | | ref(mapsf<K,V> &m) : lk(m.m), r(m.val) { } | |
| | | V& operator[](const K& k) { return r[k]; } | |
| | | }; | |
| | | }; | |
| | | #endif | |
| } | | } | |
| | | | |
End of changes. 9 change blocks. |
| 6 lines changed or deleted | | 63 lines changed or added | |
|