| and_common-inl.h | | and_common-inl.h | |
| | | | |
| skipping to change at line 41 | | skipping to change at line 41 | |
| class AndCommon { | | class AndCommon { | |
| public: | | public: | |
| /** | | /** | |
| * If src has any data dest doesn't, add that data to dest. | | * If src has any data dest doesn't, add that data to dest. | |
| */ | | */ | |
| static void mergeFrom(WorkingSetMember* dest, const WorkingSetMembe
r& src) { | | static void mergeFrom(WorkingSetMember* dest, const WorkingSetMembe
r& src) { | |
| verify(dest->hasLoc()); | | verify(dest->hasLoc()); | |
| verify(src.hasLoc()); | | verify(src.hasLoc()); | |
| verify(dest->loc == src.loc); | | verify(dest->loc == src.loc); | |
| | | | |
|
| | | // Merge computed data. | |
| | | typedef WorkingSetComputedDataType WSCD; | |
| | | for (WSCD i = WSCD(0); i < WSM_COMPUTED_NUM_TYPES; i = WSCD(i + | |
| | | 1)) { | |
| | | if (!dest->hasComputed(i) && src.hasComputed(i)) { | |
| | | dest->addComputed(src.getComputed(i)->clone()); | |
| | | } | |
| | | } | |
| | | | |
| | | if (dest->hasObj()) { | |
| | | // The merged WSM that we're creating already has the full | |
| | | document, so there's | |
| | | // nothing left to do. | |
| | | return; | |
| | | } | |
| | | | |
| | | if (src.hasObj()) { | |
| | | // 'src' has the full document but 'dest' doesn't so we nee | |
| | | d to copy it over. | |
| | | // | |
| | | // The source diskloc must be in the "diskloc and unowned o | |
| | | bject" state rather than | |
| | | // the "owned object" state. This is because we've just int | |
| | | ersected according to | |
| | | // diskloc. Since we merge based on finding working set mem | |
| | | bers with matching | |
| | | // disklocs, we shouldn't have a WSM that is missing the di | |
| | | skloc. | |
| | | invariant(WorkingSetMember::LOC_AND_UNOWNED_OBJ == src.stat | |
| | | e); | |
| | | | |
| | | // Copy the object to 'dest'. | |
| | | dest->obj = src.obj; | |
| | | | |
| | | // We have an object so we don't need key data. | |
| | | dest->keyData.clear(); | |
| | | | |
| | | // 'dest' should be LOC_AND_UNOWNED_OBJ | |
| | | dest->state = src.state; | |
| | | | |
| | | // Now 'dest' has the full object. No more work to do. | |
| | | return; | |
| | | } | |
| | | | |
| | | // If we're here, then both WSMs getting merged contain index k | |
| | | eys. We need | |
| | | // to merge the key data. | |
| | | // | |
| // This is N^2 but N is probably pretty small. Easy enough to
revisit. | | // This is N^2 but N is probably pretty small. Easy enough to
revisit. | |
|
| // Merge key data. | | | |
| for (size_t i = 0; i < src.keyData.size(); ++i) { | | for (size_t i = 0; i < src.keyData.size(); ++i) { | |
| bool found = false; | | bool found = false; | |
| for (size_t j = 0; j < dest->keyData.size(); ++j) { | | for (size_t j = 0; j < dest->keyData.size(); ++j) { | |
| if (dest->keyData[j].indexKeyPattern == src.keyData[i].
indexKeyPattern) { | | if (dest->keyData[j].indexKeyPattern == src.keyData[i].
indexKeyPattern) { | |
| found = true; | | found = true; | |
| break; | | break; | |
| } | | } | |
| } | | } | |
| if (!found) { dest->keyData.push_back(src.keyData[i]); } | | if (!found) { dest->keyData.push_back(src.keyData[i]); } | |
| } | | } | |
|
| | | | |
| // Merge computed data. | | | |
| typedef WorkingSetComputedDataType WSCD; | | | |
| for (WSCD i = WSCD(0); i < WSM_COMPUTED_NUM_TYPES; i = WSCD(i + | | | |
| 1)) { | | | |
| if (!dest->hasComputed(i) && src.hasComputed(i)) { | | | |
| dest->addComputed(src.getComputed(i)->clone()); | | | |
| } | | | |
| } | | | |
| } | | } | |
| }; | | }; | |
| | | | |
| } // namespace mongo | | } // namespace mongo | |
| | | | |
End of changes. 3 change blocks. |
| 10 lines changed or deleted | | 48 lines changed or added | |
|
| audit.h | | audit.h | |
| | | | |
| skipping to change at line 353 | | skipping to change at line 353 | |
| | | | |
| /** | | /** | |
| * Logs the result of a shardCollection command. | | * Logs the result of a shardCollection command. | |
| */ | | */ | |
| void logShardCollection(ClientBasic* client, | | void logShardCollection(ClientBasic* client, | |
| const StringData& ns, | | const StringData& ns, | |
| const BSONObj& keyPattern, | | const BSONObj& keyPattern, | |
| bool unique); | | bool unique); | |
| | | | |
| /* | | /* | |
|
| * Appends an array of user/db pairs to the provided Document. | | * Appends an array of user/db pairs and an array of role/db pairs | |
| * The users are extracted from the current client. They are to be the | | * to the provided Document. The users and roles are extracted from the | |
| * impersonated users for a Command run by an internal user. | | current client. | |
| | | * They are to be the impersonated users and roles for a Command run by | |
| | | an internal user. | |
| */ | | */ | |
| void appendImpersonatedUsers(BSONObjBuilder* cmd); | | void appendImpersonatedUsers(BSONObjBuilder* cmd); | |
| const char cmdOptionImpersonatedUsers[] = "impersonatedUsers"; | | const char cmdOptionImpersonatedUsers[] = "impersonatedUsers"; | |
|
| | | const char cmdOptionImpersonatedRoles[] = "impersonatedRoles"; | |
| | | | |
| /* | | /* | |
| * Looks for an 'impersonatedUsers' field. This field is used by mongo
s to | | * Looks for an 'impersonatedUsers' field. This field is used by mongo
s to | |
| * transmit the usernames of the currently authenticated user when it r
uns commands | | * transmit the usernames of the currently authenticated user when it r
uns commands | |
| * on a shard using internal user authentication. Auditing uses this i
nformation | | * on a shard using internal user authentication. Auditing uses this i
nformation | |
| * to properly ascribe users to actions. This is necessary only for im
plicit actions that | | * to properly ascribe users to actions. This is necessary only for im
plicit actions that | |
| * mongos cannot properly audit itself; examples are implicit collectio
n and database creation. | | * mongos cannot properly audit itself; examples are implicit collectio
n and database creation. | |
| * This function requires that the field is the last field in the bson
object; it edits the | | * This function requires that the field is the last field in the bson
object; it edits the | |
| * command BSON to efficiently remove the field before returning. | | * command BSON to efficiently remove the field before returning. | |
| * | | * | |
| * cmdObj [in, out]: If any impersonated users field exists, it will be
parsed and removed. | | * cmdObj [in, out]: If any impersonated users field exists, it will be
parsed and removed. | |
| * authSession [in]: current authorization session | | * authSession [in]: current authorization session | |
| * parsedUserNames [out]: populated with parsed usernames | | * parsedUserNames [out]: populated with parsed usernames | |
| * fieldIsPresent [out]: true if impersonatedUsers field was present in
the object | | * fieldIsPresent [out]: true if impersonatedUsers field was present in
the object | |
| */ | | */ | |
|
| void parseAndRemoveImpersonatedUserField(BSONObj cmdObj, | | void parseAndRemoveImpersonatedUsersField( | |
| AuthorizationSession* authSess | | BSONObj cmdObj, | |
| ion, | | AuthorizationSession* authSession, | |
| std::vector<UserName>* parsedU | | std::vector<UserName>* parsedUserNames, | |
| serNames, | | bool* fieldIsPresent); | |
| bool* fieldIsPresent); | | | |
| | | /* | |
| | | * Looks for an 'impersonatedRoles' field. This field is used by mongo | |
| | | s to | |
| | | * transmit the roles of the currently authenticated user when it runs | |
| | | commands | |
| | | * on a shard using internal user authentication. Auditing uses this i | |
| | | nformation | |
| | | * to properly ascribe user roles to actions. This is necessary only f | |
| | | or implicit actions that | |
| | | * mongos cannot properly audit itself; examples are implicit collectio | |
| | | n and database creation. | |
| | | * This function requires that the field is the last field in the bson | |
| | | object; it edits the | |
| | | * command BSON to efficiently remove the field before returning. | |
| | | * | |
| | | * cmdObj [in, out]: If any impersonated roles field exists, it will be | |
| | | parsed and removed. | |
| | | * authSession [in]: current authorization session | |
| | | * parsedRoleNames [out]: populated with parsed user rolenames | |
| | | * fieldIsPresent [out]: true if impersonatedRoles field was present in | |
| | | the object | |
| | | */ | |
| | | void parseAndRemoveImpersonatedRolesField( | |
| | | BSONObj cmdObj, | |
| | | AuthorizationSession* authSession, | |
| | | std::vector<RoleName>* parsedRoleNames, | |
| | | bool* fieldIsPresent); | |
| | | | |
| } // namespace audit | | } // namespace audit | |
| } // namespace mongo | | } // namespace mongo | |
| | | | |
End of changes. 3 change blocks. |
| 9 lines changed or deleted | | 39 lines changed or added | |
|
| authorization_session.h | | authorization_session.h | |
| | | | |
| skipping to change at line 91 | | skipping to change at line 91 | |
| | | | |
| // Returns the authenticated user with the given name. Returns NUL
L | | // Returns the authenticated user with the given name. Returns NUL
L | |
| // if no such user is found. | | // if no such user is found. | |
| // The user remains in the _authenticatedUsers set for this Authori
zationSession, | | // The user remains in the _authenticatedUsers set for this Authori
zationSession, | |
| // and ownership of the user stays with the AuthorizationManager | | // and ownership of the user stays with the AuthorizationManager | |
| User* lookupUser(const UserName& name); | | User* lookupUser(const UserName& name); | |
| | | | |
| // Gets an iterator over the names of all authenticated users store
d in this manager. | | // Gets an iterator over the names of all authenticated users store
d in this manager. | |
| UserNameIterator getAuthenticatedUserNames(); | | UserNameIterator getAuthenticatedUserNames(); | |
| | | | |
|
| // Returns a string representing all logged-in users on the current | | // Gets an iterator over the roles of all authenticated users store | |
| session. | | d in this manager. | |
| // WARNING: this string will contain NUL bytes so don't call c_str( | | RoleNameIterator getAuthenticatedRoleNames(); | |
| )! | | | |
| | | // Returns a std::string representing all logged-in users on the cu | |
| | | rrent session. | |
| | | // WARNING: this std::string will contain NUL bytes so don't call c | |
| | | _str()! | |
| std::string getAuthenticatedUserNamesToken(); | | std::string getAuthenticatedUserNamesToken(); | |
| | | | |
| // Removes any authenticated principals whose authorization credent
ials came from the given | | // Removes any authenticated principals whose authorization credent
ials came from the given | |
| // database, and revokes any privileges that were granted via that
principal. | | // database, and revokes any privileges that were granted via that
principal. | |
| void logoutDatabase(const std::string& dbname); | | void logoutDatabase(const std::string& dbname); | |
| | | | |
| // Adds the internalSecurity user to the set of authenticated users
. | | // Adds the internalSecurity user to the set of authenticated users
. | |
| // Used to grant internal threads full access. | | // Used to grant internal threads full access. | |
| void grantInternalAuthorization(); | | void grantInternalAuthorization(); | |
| | | | |
| | | | |
| skipping to change at line 180 | | skipping to change at line 183 | |
| const ActionSet& actions); | | const ActionSet& actions); | |
| | | | |
| // Utility function for | | // Utility function for | |
| // isAuthorizedForActionsOnResource(ResourcePattern::forExactNamesp
ace(ns), action). | | // isAuthorizedForActionsOnResource(ResourcePattern::forExactNamesp
ace(ns), action). | |
| bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, A
ctionType action); | | bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, A
ctionType action); | |
| | | | |
| // Utility function for | | // Utility function for | |
| // isAuthorizedForActionsOnResource(ResourcePattern::forExactNamesp
ace(ns), actions). | | // isAuthorizedForActionsOnResource(ResourcePattern::forExactNamesp
ace(ns), actions). | |
| bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, c
onst ActionSet& actions); | | bool isAuthorizedForActionsOnNamespace(const NamespaceString& ns, c
onst ActionSet& actions); | |
| | | | |
|
| // Replaces the vector of UserNames that a system user is impersona | | // Replaces the data for users that a system user is impersonating | |
| ting with a new vector. | | with new data. | |
| // The auditing system adds these to each audit record in the log. | | // The auditing system adds these users and their roles to each aud | |
| void setImpersonatedUserNames(const std::vector<UserName>& names); | | it record in the log. | |
| | | void setImpersonatedUserData(std::vector<UserName> usernames, std:: | |
| | | vector<RoleName> roles); | |
| | | | |
| | | // Gets an iterator over the names of all users that the system use | |
| | | r is impersonating. | |
| | | UserNameIterator getImpersonatedUserNames(); | |
| | | | |
|
| // Returns an iterator to a vector of impersonated usernames. | | // Gets an iterator over the roles of all users that the system use | |
| UserNameIterator getImpersonatedUserNames() const; | | r is impersonating. | |
| | | RoleNameIterator getImpersonatedRoleNames(); | |
| | | | |
|
| // Clears the vector of impersonated UserNames. | | // Clears the data for impersonated users. | |
| void clearImpersonatedUserNames(); | | void clearImpersonatedUserData(); | |
| | | | |
| // Tells whether impersonation is active or not. This state is set
when | | // Tells whether impersonation is active or not. This state is set
when | |
|
| // setImpersonatedUserNames is called and cleared when clearImperso
natedUserNames is | | // setImpersonatedUserData is called and cleared when clearImperson
atedUserData is | |
| // called. | | // called. | |
| bool isImpersonating() const; | | bool isImpersonating() const; | |
| | | | |
| private: | | private: | |
| | | | |
| // If any users authenticated on this session are marked as invalid
this updates them with | | // If any users authenticated on this session are marked as invalid
this updates them with | |
| // up-to-date information. May require a read lock on the "admin" d
b to read the user data. | | // up-to-date information. May require a read lock on the "admin" d
b to read the user data. | |
| void _refreshUserInfoAsNeeded(); | | void _refreshUserInfoAsNeeded(); | |
| | | | |
|
| | | // Builds a vector of all roles held by users who are authenticated | |
| | | on this connection. The | |
| | | // vector is stored in _authenticatedRoleNames. This function is ca | |
| | | lled when users are | |
| | | // logged in or logged out, as well as when the user cache is deter | |
| | | mined to be out of date. | |
| | | void _buildAuthenticatedRolesVector(); | |
| | | | |
| // Checks if this connection is authorized for the given Privilege,
ignoring whether or not | | // Checks if this connection is authorized for the given Privilege,
ignoring whether or not | |
| // we should even be doing authorization checks in general. Note:
this may acquire a read | | // we should even be doing authorization checks in general. Note:
this may acquire a read | |
| // lock on the admin database (to update out-of-date user privilege
information). | | // lock on the admin database (to update out-of-date user privilege
information). | |
| bool _isAuthorizedForPrivilege(const Privilege& privilege); | | bool _isAuthorizedForPrivilege(const Privilege& privilege); | |
| | | | |
| scoped_ptr<AuthzSessionExternalState> _externalState; | | scoped_ptr<AuthzSessionExternalState> _externalState; | |
| | | | |
|
| // All Users who have been authenticated on this connection | | // All Users who have been authenticated on this connection. | |
| UserSet _authenticatedUsers; | | UserSet _authenticatedUsers; | |
|
| | | // The roles of the authenticated users. This vector is generated w | |
| | | hen the authenticated | |
| | | // users set is changed. | |
| | | std::vector<RoleName> _authenticatedRoleNames; | |
| | | | |
|
| // A vector of impersonated UserNames. These are used in the audit | | // A vector of impersonated UserNames and a vector of those users' | |
| ing system. | | RoleNames. | |
| // They are not used for authz checks. | | // These are used in the auditing system. They are not used for aut | |
| | | hz checks. | |
| std::vector<UserName> _impersonatedUserNames; | | std::vector<UserName> _impersonatedUserNames; | |
|
| | | std::vector<RoleName> _impersonatedRoleNames; | |
| bool _impersonationFlag; | | bool _impersonationFlag; | |
| }; | | }; | |
| | | | |
| } // namespace mongo | | } // namespace mongo | |
| | | | |
End of changes. 10 change blocks. |
| 17 lines changed or deleted | | 42 lines changed or added | |
|
| collection_info_cache.h | | collection_info_cache.h | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| * file(s), but you are not obligated to do so. If you do not wish to do
so, | | * file(s), but you are not obligated to do so. If you do not wish to do
so, | |
| * delete this exception statement from your version. If you delete this | | * delete this exception statement from your version. If you delete this | |
| * exception statement from all source files in the program, then also de
lete | | * exception statement from all source files in the program, then also de
lete | |
| * it in the license file. | | * it in the license file. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include <boost/scoped_ptr.hpp> | | #include <boost/scoped_ptr.hpp> | |
| | | | |
|
| #include "mongo/db/index_set.h" | | | |
| #include "mongo/db/query/query_settings.h" | | | |
| #include "mongo/db/query/plan_cache.h" | | #include "mongo/db/query/plan_cache.h" | |
|
| | | #include "mongo/db/query/query_settings.h" | |
| | | #include "mongo/db/update_index_data.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class Collection; | | class Collection; | |
| | | | |
| /** | | /** | |
| * this is for storing things that you want to cache about a single col
lection | | * this is for storing things that you want to cache about a single col
lection | |
| * life cycle is managed for you from inside Collection | | * life cycle is managed for you from inside Collection | |
| */ | | */ | |
| class CollectionInfoCache { | | class CollectionInfoCache { | |
| | | | |
| skipping to change at line 76 | | skipping to change at line 76 | |
| /** | | /** | |
| * Get the QuerySettings for this collection. | | * Get the QuerySettings for this collection. | |
| */ | | */ | |
| QuerySettings* getQuerySettings() const; | | QuerySettings* getQuerySettings() const; | |
| | | | |
| // ------------------- | | // ------------------- | |
| | | | |
| /* 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.) | |
| */ | | */ | |
|
| const IndexPathSet& indexKeys() { | | const UpdateIndexData& indexKeys() { | |
| if ( !_keysComputed ) | | if ( !_keysComputed ) | |
| computeIndexKeys(); | | computeIndexKeys(); | |
| return _indexedPaths; | | return _indexedPaths; | |
| } | | } | |
| | | | |
| // --------------------- | | // --------------------- | |
| | | | |
| /** | | /** | |
| * Called when an index is added to this collection. | | * Called when an index is added to this collection. | |
| */ | | */ | |
| | | | |
| skipping to change at line 100 | | skipping to change at line 100 | |
| | | | |
| /* you must notify the cache if you are doing writes, as query plan
utility will change */ | | /* you must notify the cache if you are doing writes, as query plan
utility will change */ | |
| void notifyOfWriteOp(); | | void notifyOfWriteOp(); | |
| | | | |
| private: | | private: | |
| | | | |
| Collection* _collection; // not owned | | Collection* _collection; // not owned | |
| | | | |
| // --- index keys cache | | // --- index keys cache | |
| bool _keysComputed; | | bool _keysComputed; | |
|
| IndexPathSet _indexedPaths; | | UpdateIndexData _indexedPaths; | |
| | | | |
| // A cache for query plans. | | // A cache for query plans. | |
| boost::scoped_ptr<PlanCache> _planCache; | | boost::scoped_ptr<PlanCache> _planCache; | |
| | | | |
| // Query settings. | | // Query settings. | |
| // Includes index filters. | | // Includes index filters. | |
| boost::scoped_ptr<QuerySettings> _querySettings; | | boost::scoped_ptr<QuerySettings> _querySettings; | |
| | | | |
| void computeIndexKeys(); | | void computeIndexKeys(); | |
| }; | | }; | |
| | | | |
End of changes. 4 change blocks. |
| 4 lines changed or deleted | | 4 lines changed or added | |
|
| database.h | | database.h | |
| | | | |
| skipping to change at line 193 | | skipping to change at line 193 | |
| /** | | /** | |
| * @return name of an existing database with same text name but dif
ferent | | * @return name of an existing database with same text name but dif
ferent | |
| * casing, if one exists. Otherwise the empty string is returned.
If | | * casing, if one exists. Otherwise the empty string is returned.
If | |
| * 'duplicates' is specified, it is filled with all duplicate names
. | | * 'duplicates' is specified, it is filled with all duplicate names
. | |
| */ | | */ | |
| static string duplicateUncasedName( bool inholderlockalready, const
string &name, const string &path, set< string > *duplicates = 0 ); | | static string duplicateUncasedName( bool inholderlockalready, const
string &name, const string &path, set< string > *duplicates = 0 ); | |
| | | | |
| static Status validateDBName( const StringData& dbname ); | | static Status validateDBName( const StringData& dbname ); | |
| | | | |
| const string& getSystemIndexesName() const { return _indexesName; } | | const string& getSystemIndexesName() const { return _indexesName; } | |
|
| | | | |
| | | /** | |
| | | * Search system.namespaces for indexes on collection "system" that | |
| | | don't exist in the index | |
| | | * catalog, and clean up any that are found. These would exist due | |
| | | to a bug in 2.4 | |
| | | * (SERVER-13975). | |
| | | */ | |
| | | void cleanUpOrphanIndexesOnSystemCollection(); | |
| private: | | private: | |
| | | | |
| void _clearCollectionCache( const StringData& fullns ); | | void _clearCollectionCache( const StringData& fullns ); | |
| | | | |
| void _clearCollectionCache_inlock( const StringData& fullns ); | | void _clearCollectionCache_inlock( const StringData& fullns ); | |
| | | | |
| ~Database(); // closes files and other cleanup see below. | | ~Database(); // closes files and other cleanup see below. | |
| | | | |
| void _addNamespaceToCatalog( const StringData& ns, const BSONObj* o
ptions ); | | void _addNamespaceToCatalog( const StringData& ns, const BSONObj* o
ptions ); | |
| | | | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 9 lines changed or added | |
|
| dbclient_rs.h | | dbclient_rs.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 <boost/shared_ptr.hpp> | | #include <boost/shared_ptr.hpp> | |
| #include <utility> | | #include <utility> | |
| | | | |
| #include "mongo/client/dbclientinterface.h" | | #include "mongo/client/dbclientinterface.h" | |
| #include "mongo/client/export_macros.h" | | #include "mongo/client/export_macros.h" | |
|
| | | #include "mongo/platform/random.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; | | struct ReadPreferenceSetting; | |
| typedef shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr; | | typedef shared_ptr<ReplicaSetMonitor> ReplicaSetMonitorPtr; | |
| | | | |
| /** Use this class to connect to a replica set of servers. The class w
ill manage | | /** Use this class to connect to a replica set of servers. The class w
ill manage | |
| | | | |
| skipping to change at line 48 | | skipping to change at line 49 | |
| | | | |
| On a failover situation, expect at least one operation to return an
error (throw | | On a failover situation, expect at least one operation to return an
error (throw | |
| an exception) before the failover is complete. Operations are not r
etried. | | an exception) before the failover is complete. Operations are not r
etried. | |
| */ | | */ | |
| class MONGO_CLIENT_API DBClientReplicaSet : public DBClientBase { | | class MONGO_CLIENT_API DBClientReplicaSet : public DBClientBase { | |
| public: | | public: | |
| using DBClientBase::query; | | using DBClientBase::query; | |
| using DBClientBase::update; | | using DBClientBase::update; | |
| using DBClientBase::remove; | | using DBClientBase::remove; | |
| | | | |
|
| | | // For internal use only. The desired probability for reevaluating | |
| | | node | |
| | | // selection given a read preference, expressed in percentage. Any | |
| | | value | |
| | | // less than 0 will be treated as 0% and any value greater than 100 | |
| | | will | |
| | | // be treated as 100%. | |
| | | static int reevaluatePercentage; | |
| | | | |
| /** Call connect() after constructing. autoReconnect is always on f
or DBClientReplicaSet connections. */ | | /** Call connect() after constructing. autoReconnect is always on f
or DBClientReplicaSet connections. */ | |
| 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(); | |
| | | | |
| skipping to change at line 215 | | skipping to change at line 222 | |
| | | | |
| /** | | /** | |
| * 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 | |
| * operation. | | * operation. | |
| */ | | */ | |
| static const size_t MAX_RETRY; | | static const size_t MAX_RETRY; | |
| | | | |
| // Throws a DBException if the monitor doesn't exist and there isn'
t a cached seed to use. | | // Throws a DBException if the monitor doesn't exist and there isn'
t a cached seed to use. | |
| ReplicaSetMonitorPtr _getMonitor() const; | | ReplicaSetMonitorPtr _getMonitor() const; | |
| | | | |
|
| | | /** | |
| | | * Returns true if this connection should re-evaluate the node sele | |
| | | ction for | |
| | | * a given read preference, regardless of it's compatibility with t | |
| | | he currently | |
| | | * cached connection. | |
| | | */ | |
| | | bool shouldReevaluate(); | |
| | | | |
| string _setName; | | string _setName; | |
| | | | |
| HostAndPort _masterHost; | | HostAndPort _masterHost; | |
| // Note: reason why this is a shared_ptr is because we want _lastSl
aveOkConn to | | // Note: reason why this is a shared_ptr is because we want _lastSl
aveOkConn to | |
| // keep a reference of the _master connection when it selected a pr
imary node. | | // keep a reference of the _master connection when it selected a pr
imary node. | |
| // 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; | |
| | | | |
| skipping to change at line 240 | | skipping to change at line 254 | |
| boost::shared_ptr<ReadPreferenceSetting> _lastReadPref; | | boost::shared_ptr<ReadPreferenceSetting> _lastReadPref; | |
| | | | |
| double _so_timeout; | | double _so_timeout; | |
| | | | |
| // 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, BSONObj> _auths; // dbName -> auth parameters | | std::map<string, BSONObj> _auths; // dbName -> auth parameters | |
| | | | |
|
| | | // For v2.6 only. | |
| | | // Random generator to be used to determine whether this connection | |
| | | object | |
| | | // should re-evaluate node selection from scratch. | |
| | | PseudoRandom _nodeSelectOracle; | |
| | | | |
| 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() : | | LazyState() : | |
| _lastClient( NULL ), _lastOp( -1 ), _secondaryQueryOk( fals
e ), _retries( 0 ) {} | | _lastClient( NULL ), _lastOp( -1 ), _secondaryQueryOk( fals
e ), _retries( 0 ) {} | |
| DBClientConnection* _lastClient; | | DBClientConnection* _lastClient; | |
| | | | |
End of changes. 4 change blocks. |
| 0 lines changed or deleted | | 25 lines changed or added | |
|
| dbmessage.h | | dbmessage.h | |
| | | | |
| skipping to change at line 123 | | skipping to change at line 123 | |
| }; | | }; | |
| | | | |
| #pragma pack() | | #pragma pack() | |
| | | | |
| /* For the database/server protocol, these objects and functions encaps
ulate | | /* For the database/server protocol, these objects and functions encaps
ulate | |
| the various messages transmitted over the connection. | | the various messages transmitted over the connection. | |
| | | | |
| See http://dochub.mongodb.org/core/mongowireprotocol | | See http://dochub.mongodb.org/core/mongowireprotocol | |
| */ | | */ | |
| class DbMessage { | | class DbMessage { | |
|
| | | // Assume sizeof(int) == 4 bytes | |
| | | BOOST_STATIC_ASSERT(sizeof(int) == 4); | |
| | | | |
| public: | | public: | |
|
| DbMessage(const Message& _m) : m(_m) , mark(0) { | | // Note: DbMessage constructor reads the first 4 bytes and stores i | |
| // for received messages, Message has only one buffer | | t in reserved | |
| theEnd = _m.singleData()->_data + _m.header()->dataLen(); | | DbMessage(const Message& msg); | |
| char *r = _m.singleData()->_data; | | | |
| reserved = (int *) r; | | // Indicates whether this message is expected to have a ns | |
| data = r + 4; | | // or in the case of dbMsg, a string in the same place as ns | |
| nextjsobj = data; | | bool messageShouldHaveNs() const { | |
| | | return (_msg.operation() >= dbMsg) & (_msg.operation() <= dbDel | |
| | | ete); | |
| } | | } | |
| | | | |
| /** the 32 bit field before the ns | | /** the 32 bit field before the ns | |
| * track all bit usage here as its cross op | | * track all bit usage here as its cross op | |
| * 0: InsertOption_ContinueOnError | | * 0: InsertOption_ContinueOnError | |
| * 1: fromWriteback | | * 1: fromWriteback | |
| */ | | */ | |
|
| int& reservedField() { return *reserved; } | | int reservedField() const { return _reserved; } | |
| | | | |
|
| const char * getns() const { | | const char * getns() const; | |
| return data; | | int getQueryNToReturn() const; | |
| } | | | |
| | | | |
|
| const char * afterNS() const { | | int pullInt(); | |
| return data + strlen( data ) + 1; | | long long pullInt64(); | |
| } | | const long long* getArray(size_t count) const; | |
| | | | |
|
| int getInt( int num ) const { | | /* for insert and update msgs */ | |
| const int * foo = (const int*)afterNS(); | | bool moreJSObjs() const { | |
| return foo[num]; | | return _nextjsobj != 0; | |
| } | | } | |
| | | | |
|
| int getQueryNToReturn() const { | | BSONObj nextJsObj(); | |
| return getInt( 1 ); | | | |
| } | | | |
| | | | |
|
| /** | | const Message& msg() const { return _msg; } | |
| * get an int64 at specified offsetBytes after ns | | | |
| */ | | | |
| long long getInt64( int offsetBytes ) const { | | | |
| const char * x = afterNS(); | | | |
| x += offsetBytes; | | | |
| const long long * ll = (const long long*)x; | | | |
| return ll[0]; | | | |
| } | | | |
| | | | |
|
| void resetPull() { nextjsobj = data; } | | const char * markGet() const { | |
| int pullInt() const { return pullInt(); } | | return _nextjsobj; | |
| int& pullInt() { | | | |
| if ( nextjsobj == data ) | | | |
| nextjsobj += strlen(data) + 1; // skip namespace | | | |
| int& i = *((int *)nextjsobj); | | | |
| nextjsobj += 4; | | | |
| return i; | | | |
| } | | | |
| long long pullInt64() const { | | | |
| return pullInt64(); | | | |
| } | | | |
| long long &pullInt64() { | | | |
| if ( nextjsobj == data ) | | | |
| nextjsobj += strlen(data) + 1; // skip namespace | | | |
| long long &i = *((long long *)nextjsobj); | | | |
| nextjsobj += 8; | | | |
| return i; | | | |
| } | | } | |
| | | | |
|
| OID* getOID() const { | | void markSet() { | |
| return (OID *) (data + strlen(data) + 1); // skip namespace | | _mark = _nextjsobj; | |
| } | | } | |
| | | | |
|
| void getQueryStuff(const char *&query, int& ntoreturn) { | | void markReset(const char * toMark); | |
| int *i = (int *) (data + strlen(data) + 1); | | | |
| ntoreturn = *i; | | | |
| i++; | | | |
| query = (const char *) i; | | | |
| } | | | |
| | | | |
|
| /* for insert and update msgs */ | | private: | |
| bool moreJSObjs() const { | | // Check if we have enough data to read | |
| return nextjsobj != 0; | | template<typename T> | |
| } | | void checkRead(const char* start, size_t count = 0) const; | |
| BSONObj nextJsObj() { | | | |
| if ( nextjsobj == data ) { | | | |
| nextjsobj += strlen(data) + 1; // skip namespace | | | |
| massert( 13066 , "Message contains no documents", theEnd > | | | |
| nextjsobj ); | | | |
| } | | | |
| massert( 10304, | | | |
| "Client Error: Remaining data too small for BSON objec | | | |
| t", | | | |
| theEnd - nextjsobj >= 5 ); | | | |
| | | | |
| if (serverGlobalParams.objcheck) { | | | |
| Status status = validateBSON( nextjsobj, theEnd - nextjsobj | | | |
| ); | | | |
| massert( 10307, | | | |
| str::stream() << "Client Error: bad object in mess | | | |
| age: " << status.reason(), | | | |
| status.isOK() ); | | | |
| } | | | |
| | | | |
| BSONObj js(nextjsobj); | | | |
| verify( js.objsize() >= 5 ); | | | |
| verify( js.objsize() < ( theEnd - data ) ); | | | |
| | | | |
| nextjsobj += js.objsize(); | | | |
| if ( nextjsobj >= theEnd ) | | | |
| nextjsobj = 0; | | | |
| return js; | | | |
| } | | | |
| | | | |
|
| const Message& msg() const { return m; } | | // Read some type without advancing our position | |
| | | template<typename T> | |
| | | T read() const; | |
| | | | |
|
| const char * markGet() { | | // Read some type, and advance our position | |
| return nextjsobj; | | template<typename T> T readAndAdvance(); | |
| } | | | |
| | | | |
|
| void markSet() { | | const Message& _msg; | |
| mark = nextjsobj; | | int _reserved; // flags or zero depending on packet, starts the pac | |
| } | | ket | |
| | | | |
|
| void markReset( const char * toMark = 0) { | | const char* _nsStart; // start of namespace string, +4 from message | |
| if( toMark == 0 ) toMark = mark; | | start | |
| verify( toMark ); | | const char* _nextjsobj; // current position reading packet | |
| nextjsobj = toMark; | | const char* _theEnd; // end of packet | |
| } | | | |
| | | | |
|
| private: | | const char* _mark; | |
| const Message& m; | | | |
| int* reserved; | | | |
| const char *data; | | | |
| const char *nextjsobj; | | | |
| const char *theEnd; | | | |
| | | | |
|
| const char * mark; | | unsigned int _nsLen; | |
| }; | | }; | |
| | | | |
| /* a request to run a query, received from the database */ | | /* a request to run a query, received from the database */ | |
| class QueryMessage { | | class QueryMessage { | |
| public: | | public: | |
| const char *ns; | | const char *ns; | |
| int ntoskip; | | int ntoskip; | |
| int ntoreturn; | | int ntoreturn; | |
| int queryOptions; | | int queryOptions; | |
| BSONObj query; | | BSONObj query; | |
| | | | |
End of changes. 18 change blocks. |
| 107 lines changed or deleted | | 46 lines changed or added | |
|
| engine_v8.h | | engine_v8.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 <boost/shared_ptr.hpp> | |
| #include <v8.h> | | #include <v8.h> | |
| #include <vector> | | #include <vector> | |
| | | | |
| #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/client/dbclientinterface.h" | | #include "mongo/client/dbclientinterface.h" | |
| #include "mongo/client/dbclientcursor.h" | | #include "mongo/client/dbclientcursor.h" | |
| #include "mongo/platform/unordered_map.h" | | #include "mongo/platform/unordered_map.h" | |
| #include "mongo/scripting/engine.h" | | #include "mongo/scripting/engine.h" | |
| #include "mongo/scripting/v8_deadline_monitor.h" | | #include "mongo/scripting/v8_deadline_monitor.h" | |
| | | | |
| skipping to change at line 63 | | skipping to change at line 64 | |
| * required because v8 does not invoke the WeakReferenceCallback when s
hutting down | | * 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 | | * 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 | | * 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 | | * of calling v8::Persistent::MakeWeak() directly, simply invoke track(
) with the | |
| * persistent handle and the pointer to be freed. | | * persistent handle and the pointer to be freed. | |
| */ | | */ | |
| template <typename _ObjType> | | template <typename _ObjType> | |
| class ObjTracker { | | class ObjTracker { | |
| public: | | public: | |
| /** Track an object to be freed when it is no longer referenced in
JavaScript. | | /** Track an object to be freed when it is no longer referenced in
JavaScript. | |
|
| | | * Return handle to object instance shared pointer. | |
| * @param instanceHandle persistent handle to the weakly referenc
ed object | | * @param instanceHandle persistent handle to the weakly referenc
ed object | |
| * @param rawData pointer to the object instance | | * @param rawData pointer to the object instance | |
| */ | | */ | |
|
| void track(v8::Persistent<v8::Value> instanceHandle, _ObjType* inst | | v8::Local<v8::External> track(v8::Persistent<v8::Value> instanceHan | |
| ance) { | | dle, | |
| | | _ObjType* instance) { | |
| TrackedPtr* collectionHandle = new TrackedPtr(instance, this); | | TrackedPtr* collectionHandle = new TrackedPtr(instance, this); | |
| _container.insert(collectionHandle); | | _container.insert(collectionHandle); | |
| instanceHandle.MakeWeak(collectionHandle, deleteOnCollect); | | instanceHandle.MakeWeak(collectionHandle, deleteOnCollect); | |
|
| | | return v8::External::New(&(collectionHandle->_objPtr)); | |
| } | | } | |
| /** | | /** | |
| * Free any remaining objects and their TrackedPtrs. Invoked when
the | | * Free any remaining objects and their TrackedPtrs. Invoked when
the | |
| * V8Scope is destructed. | | * V8Scope is destructed. | |
| */ | | */ | |
| ~ObjTracker() { | | ~ObjTracker() { | |
| if (!_container.empty()) { | | if (!_container.empty()) { | |
| LOG(1) << "freeing " << _container.size() << " uncollected
" | | LOG(1) << "freeing " << _container.size() << " uncollected
" | |
| << typeid(_ObjType).name() << " objects" << endl; | | << typeid(_ObjType).name() << " objects" << endl; | |
| } | | } | |
| | | | |
| skipping to change at line 97 | | skipping to change at line 101 | |
| /** | | /** | |
| * Simple struct which contains a pointer to the tracked object, an
d a pointer | | * Simple struct which contains a pointer to the tracked object, an
d a pointer | |
| * to the ObjTracker which owns it. This is the argument supplied
to v8's | | * to the ObjTracker which owns it. This is the argument supplied
to v8's | |
| * WeakReferenceCallback and MakeWeak(). | | * WeakReferenceCallback and MakeWeak(). | |
| */ | | */ | |
| struct TrackedPtr { | | struct TrackedPtr { | |
| public: | | public: | |
| TrackedPtr(_ObjType* instance, ObjTracker<_ObjType>* tracker) : | | TrackedPtr(_ObjType* instance, ObjTracker<_ObjType>* tracker) : | |
| _objPtr(instance), | | _objPtr(instance), | |
| _tracker(tracker) { } | | _tracker(tracker) { } | |
|
| scoped_ptr<_ObjType> _objPtr; | | boost::shared_ptr<_ObjType> _objPtr; | |
| ObjTracker<_ObjType>* _tracker; | | ObjTracker<_ObjType>* _tracker; | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * v8 callback for weak persistent handles that have been marked fo
r removal by the | | * v8 callback for weak persistent handles that have been marked fo
r removal by the | |
| * garbage collector. Signature conforms to v8's WeakReferenceCall
back. | | * garbage collector. Signature conforms to v8's WeakReferenceCall
back. | |
| * @param instanceHandle persistent handle to the weakly referenc
ed object | | * @param instanceHandle persistent handle to the weakly referenc
ed object | |
| * @param rawData pointer to the TrackedPtr instance | | * @param rawData pointer to the TrackedPtr instance | |
| */ | | */ | |
| static void deleteOnCollect(v8::Persistent<v8::Value> instanceHandl
e, void* rawData) { | | static void deleteOnCollect(v8::Persistent<v8::Value> instanceHandl
e, void* rawData) { | |
| | | | |
| skipping to change at line 297 | | skipping to change at line 301 | |
| * 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; } | |
| | | | |
| /** | | /** | |
| * Get the global JS object | | * Get the global JS object | |
| */ | | */ | |
| v8::Persistent<v8::Object> getGlobal() { return _global; } | | v8::Persistent<v8::Object> getGlobal() { return _global; } | |
| | | | |
| ObjTracker<BSONHolder> bsonHolderTracker; | | ObjTracker<BSONHolder> bsonHolderTracker; | |
|
| ObjTracker<DBClientWithCommands> dbClientWithCommandsTracker; | | | |
| ObjTracker<DBClientBase> dbClientBaseTracker; | | ObjTracker<DBClientBase> dbClientBaseTracker; | |
|
| ObjTracker<DBClientCursor> dbClientCursorTracker; | | // Track both cursor and connection. | |
| | | // This ensures the connection outlives the cursor. | |
| | | struct DBConnectionAndCursor { | |
| | | boost::shared_ptr<DBClientBase> conn; | |
| | | boost::shared_ptr<DBClientCursor> cursor; | |
| | | DBConnectionAndCursor(boost::shared_ptr<DBClientBase> conn, | |
| | | boost::shared_ptr<DBClientCursor> cursor) | |
| | | : conn(conn), cursor(cursor) { } | |
| | | }; | |
| | | ObjTracker<DBConnectionAndCursor> dbConnectionAndCursor; | |
| | | | |
| // These are all named after the JS constructor name + FT | | // These are all named after the JS constructor name + FT | |
| v8::Handle<v8::FunctionTemplate> ObjectIdFT() const { return
_ObjectIdFT; } | | v8::Handle<v8::FunctionTemplate> ObjectIdFT() const { return
_ObjectIdFT; } | |
| v8::Handle<v8::FunctionTemplate> DBRefFT() const { return
_DBRefFT; } | | v8::Handle<v8::FunctionTemplate> DBRefFT() const { return
_DBRefFT; } | |
| v8::Handle<v8::FunctionTemplate> DBPointerFT() const { return
_DBPointerFT; } | | v8::Handle<v8::FunctionTemplate> DBPointerFT() const { return
_DBPointerFT; } | |
| v8::Handle<v8::FunctionTemplate> BinDataFT() const { return
_BinDataFT; } | | v8::Handle<v8::FunctionTemplate> BinDataFT() const { return
_BinDataFT; } | |
| v8::Handle<v8::FunctionTemplate> NumberLongFT() const { return
_NumberLongFT; } | | v8::Handle<v8::FunctionTemplate> NumberLongFT() const { return
_NumberLongFT; } | |
| v8::Handle<v8::FunctionTemplate> NumberIntFT() const { return
_NumberIntFT; } | | v8::Handle<v8::FunctionTemplate> NumberIntFT() const { return
_NumberIntFT; } | |
| v8::Handle<v8::FunctionTemplate> TimestampFT() const { return
_TimestampFT; } | | v8::Handle<v8::FunctionTemplate> TimestampFT() const { return
_TimestampFT; } | |
| v8::Handle<v8::FunctionTemplate> MinKeyFT() const { return
_MinKeyFT; } | | v8::Handle<v8::FunctionTemplate> MinKeyFT() const { return
_MinKeyFT; } | |
| | | | |
End of changes. 7 change blocks. |
| 5 lines changed or deleted | | 17 lines changed or added | |
|
| index_scan.h | | index_scan.h | |
| | | | |
| skipping to change at line 105 | | skipping to change at line 105 | |
| | | | |
| private: | | private: | |
| /** | | /** | |
| * Initialize the underlying IndexCursor, grab information from the
catalog for stats. | | * Initialize the underlying IndexCursor, grab information from the
catalog for stats. | |
| */ | | */ | |
| void initIndexScan(); | | void initIndexScan(); | |
| | | | |
| /** See if the cursor is pointing at or past _endKey, if _endKey is
non-empty. */ | | /** See if the cursor is pointing at or past _endKey, if _endKey is
non-empty. */ | |
| void checkEnd(); | | void checkEnd(); | |
| | | | |
|
| | | // The number of keys examined during a call to checkEnd() that hav | |
| | | e not yet been | |
| | | // accounted for by returning a NEED_TIME. | |
| | | // | |
| | | // Good plan ranking requires that the index scan uses one work cyc | |
| | | le per index key | |
| | | // examined. Since checkEnd() may examine multiple keys, we keep tr | |
| | | ack of them here | |
| | | // and make up for it later by returning NEED_TIME. | |
| | | // | |
| | | // Example of how this is useful for plan ranking: | |
| | | // Say you have indices {a: 1, b: 1} and {a: 1, x: 1, b: 1}, with | |
| | | predicates over | |
| | | // fields 'a' and 'b'. It's cheaper to use index {a: 1, b: 1}. Wh | |
| | | y? Because for | |
| | | // index {a: 1, x: 1, b: 1} you have to skip lots of keys due to | |
| | | the interceding | |
| | | // 'x' field. This skipping is done inside checkEnd(), and we use | |
| | | '_checkEndKeys' | |
| | | // to account for it. | |
| | | size_t _checkEndKeys; | |
| | | | |
| // The WorkingSet we annotate with results. Not owned by us. | | // The WorkingSet we annotate with results. Not owned by us. | |
| WorkingSet* _workingSet; | | WorkingSet* _workingSet; | |
| | | | |
| // Index access. | | // Index access. | |
| const IndexAccessMethod* _iam; // owned by Collection -> IndexCatal
og | | const IndexAccessMethod* _iam; // owned by Collection -> IndexCatal
og | |
| scoped_ptr<IndexCursor> _indexCursor; | | scoped_ptr<IndexCursor> _indexCursor; | |
| BSONObj _keyPattern; | | BSONObj _keyPattern; | |
| | | | |
| // Have we hit the end of the index scan? | | // Have we hit the end of the index scan? | |
| bool _hitEnd; | | bool _hitEnd; | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 22 lines changed or added | |
|
| message.h | | message.h | |
| | | | |
| skipping to change at line 109 | | skipping to change at line 109 | |
| int messageLength; // total message size, including this | | int messageLength; // total message size, including this | |
| int requestID; // identifier for this message | | int requestID; // identifier for this message | |
| int responseTo; // requestID from the original request | | int responseTo; // requestID from the original request | |
| // (used in responses from db) | | // (used in responses from db) | |
| int opCode; | | int opCode; | |
| }; | | }; | |
| #pragma pack() | | #pragma pack() | |
| | | | |
| #pragma pack(1) | | #pragma pack(1) | |
| /* todo merge this with MSGHEADER (or inherit from it). */ | | /* todo merge this with MSGHEADER (or inherit from it). */ | |
|
| struct MsgData { | | class MsgData { | |
| | | friend class Message; | |
| | | friend class DbMessage; | |
| | | friend class MessagingPort; | |
| | | public: | |
| int len; /* len of the msg, including this field */ | | int len; /* len of the msg, including this field */ | |
| MSGID id; /* request/reply id's match... */ | | MSGID id; /* request/reply id's match... */ | |
| MSGID responseTo; /* id of the message we are responding to */ | | MSGID responseTo; /* id of the message we are responding to */ | |
| short _operation; | | short _operation; | |
| char _flags; | | char _flags; | |
| char _version; | | char _version; | |
|
| | | | |
| int operation() const { | | int operation() const { | |
| return _operation; | | return _operation; | |
| } | | } | |
| void setOperation(int o) { | | void setOperation(int o) { | |
| _flags = 0; | | _flags = 0; | |
| _version = 0; | | _version = 0; | |
| _operation = o; | | _operation = o; | |
| } | | } | |
|
| char _data[4]; | | | |
| | | | |
| int& dataAsInt() { | | int& dataAsInt() { | |
| return *((int *) _data); | | return *((int *) _data); | |
| } | | } | |
| | | | |
| bool valid() { | | bool valid() { | |
| if ( len <= 0 || len > ( 4 * BSONObjMaxInternalSize ) ) | | if ( len <= 0 || len > ( 4 * BSONObjMaxInternalSize ) ) | |
| return false; | | return false; | |
| if ( _operation < 0 || _operation > 30000 ) | | if ( _operation < 0 || _operation > 30000 ) | |
| return false; | | return false; | |
| | | | |
| skipping to change at line 146 | | skipping to change at line 150 | |
| } | | } | |
| | | | |
| long long getCursor() { | | long long getCursor() { | |
| verify( responseTo > 0 ); | | verify( responseTo > 0 ); | |
| verify( _operation == opReply ); | | verify( _operation == opReply ); | |
| long long * l = (long long *)(_data + 4); | | long long * l = (long long *)(_data + 4); | |
| return l[0]; | | return l[0]; | |
| } | | } | |
| | | | |
| int dataLen(); // len without header | | int dataLen(); // len without header | |
|
| | | private: | |
| | | char _data[4]; //must be last member | |
| }; | | }; | |
| const int MsgDataHeaderSize = sizeof(MsgData) - 4; | | const int MsgDataHeaderSize = sizeof(MsgData) - 4; | |
| inline int MsgData::dataLen() { | | inline int MsgData::dataLen() { | |
| return len - MsgDataHeaderSize; | | return len - MsgDataHeaderSize; | |
| } | | } | |
| #pragma pack() | | #pragma pack() | |
| | | | |
| class Message { | | class Message { | |
| public: | | public: | |
| // we assume here that a vector with initial size 0 does no allocat
ion (0 is the default, but wanted to make it explicit). | | // we assume here that a vector with initial size 0 does no allocat
ion (0 is the default, but wanted to make it explicit). | |
| | | | |
End of changes. 4 change blocks. |
| 2 lines changed or deleted | | 8 lines changed or added | |
|
| shardkey.h | | shardkey.h | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| * version of the file(s), but you are not obligated to do so. If you do
not | | * version of the file(s), but you are not obligated to do so. If you do
not | |
| * wish to do so, delete this exception statement from your version. If y
ou | | * wish to do so, delete this exception statement from your version. If y
ou | |
| * delete this exception statement from all source files in the program, | | * delete this exception statement from all source files in the program, | |
| * then also delete it in the license file. | | * then also delete it in the license file. | |
| */ | | */ | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include "mongo/base/string_data.h" | | #include "mongo/base/string_data.h" | |
| #include "mongo/db/keypattern.h" | | #include "mongo/db/keypattern.h" | |
|
| | | #include "mongo/s/shard_key_pattern.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| /** | | /** | |
| * THIS FUNCTIONALITY IS DEPRECATED | | * THIS FUNCTIONALITY IS DEPRECATED | |
| * Everything BSON related in this file should migrate gradually to s/s
hard_key_pattern.h, new | | * Everything BSON related in this file should migrate gradually to s/s
hard_key_pattern.h, new | |
| * functionality should not go here. | | * functionality should not go here. | |
| */ | | */ | |
| | | | |
| class Chunk; | | class Chunk; | |
| | | | |
| skipping to change at line 171 | | skipping to change at line 172 | |
| KeyPattern pattern; | | KeyPattern pattern; | |
| BSONObj gMin; | | BSONObj gMin; | |
| BSONObj gMax; | | BSONObj gMax; | |
| | | | |
| /* question: better to have patternfields precomputed or not? depe
nds on if we use copy constructor often. */ | | /* question: better to have patternfields precomputed or not? depe
nds on if we use copy constructor often. */ | |
| set<string> patternfields; | | set<string> patternfields; | |
| }; | | }; | |
| | | | |
| inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const { | | inline BSONObj ShardKeyPattern::extractKey(const BSONObj& from) const { | |
| BSONObj k = pattern.extractSingleKey( from ); | | BSONObj k = pattern.extractSingleKey( from ); | |
|
| uassert(13334, "Shard Key must be less than 512 bytes", k.objsize()
< 512); | | uassert(13334, "Shard Key must be less than 512 bytes", k.objsize()
< kMaxShardKeySize); | |
| return k; | | return k; | |
| } | | } | |
| | | | |
| } | | } | |
| | | | |
End of changes. 2 change blocks. |
| 1 lines changed or deleted | | 2 lines changed or added | |
|
| ssl_options.h | | ssl_options.h | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| AtomicInt32 sslMode; // --sslMode - the SSL operation mode,
see enum SSLModes | | AtomicInt32 sslMode; // --sslMode - the SSL operation mode,
see enum SSLModes | |
| bool sslOnNormalPorts; // --sslOnNormalPorts (deprecated) | | bool sslOnNormalPorts; // --sslOnNormalPorts (deprecated) | |
| std::string sslPEMKeyFile; // --sslPEMKeyFile | | std::string sslPEMKeyFile; // --sslPEMKeyFile | |
| std::string sslPEMKeyPassword; // --sslPEMKeyPassword | | std::string sslPEMKeyPassword; // --sslPEMKeyPassword | |
| std::string sslClusterFile; // --sslInternalKeyFile | | std::string sslClusterFile; // --sslInternalKeyFile | |
| std::string sslClusterPassword; // --sslInternalKeyPassword | | std::string sslClusterPassword; // --sslInternalKeyPassword | |
| std::string sslCAFile; // --sslCAFile | | std::string sslCAFile; // --sslCAFile | |
| std::string sslCRLFile; // --sslCRLFile | | std::string sslCRLFile; // --sslCRLFile | |
| bool sslWeakCertificateValidation; // --sslWeakCertificateValidatio
n | | bool sslWeakCertificateValidation; // --sslWeakCertificateValidatio
n | |
| bool sslFIPSMode; // --sslFIPSMode | | bool sslFIPSMode; // --sslFIPSMode | |
|
| bool sslAllowInvalidCertificates; // --sslIgnoreCertificateValidati | | bool sslAllowInvalidCertificates; // --sslAllowInvalidCertificates | |
| on | | bool sslAllowInvalidHostnames; // --sslAllowInvalidHostnames | |
| | | | |
| SSLGlobalParams() { | | SSLGlobalParams() { | |
| sslMode.store(SSLMode_disabled); | | sslMode.store(SSLMode_disabled); | |
| } | | } | |
| | | | |
| enum SSLModes { | | enum SSLModes { | |
| /** | | /** | |
| * Make unencrypted outgoing connections and do not accept incom
ing SSL-connections | | * Make unencrypted outgoing connections and do not accept incom
ing SSL-connections | |
| */ | | */ | |
| SSLMode_disabled, | | SSLMode_disabled, | |
| | | | |
End of changes. 1 change blocks. |
| 2 lines changed or deleted | | 2 lines changed or added | |
|
| storage_options.h | | storage_options.h | |
| | | | |
| skipping to change at line 45 | | skipping to change at line 45 | |
| * persistence. Many executables that can access data files directly such
as mongod and certain | | * persistence. Many executables that can access data files directly such
as mongod and certain | |
| * tools use these variables, but each executable may have a different set
of command line flags | | * tools use these variables, but each executable may have a different set
of command line flags | |
| * that allow the user to change a different subset of these options. | | * that allow the user to change a different subset of these options. | |
| */ | | */ | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| struct StorageGlobalParams { | | struct StorageGlobalParams { | |
| | | | |
| StorageGlobalParams() : | | StorageGlobalParams() : | |
|
| #ifdef _WIN32 | | dbpath(kDefaultDbPath), | |
| dbpath("\\data\\db\\"), | | | |
| #else | | | |
| dbpath("/data/db/"), | | | |
| #endif | | | |
| directoryperdb(false), | | directoryperdb(false), | |
| lenForNewNsFiles(16 * 1024 * 1024), | | lenForNewNsFiles(16 * 1024 * 1024), | |
| preallocj(true), | | preallocj(true), | |
| journalCommitInterval(0), // 0 means use default | | journalCommitInterval(0), // 0 means use default | |
| quota(false), quotaFiles(8), | | quota(false), quotaFiles(8), | |
| syncdelay(60), | | syncdelay(60), | |
| useHints(true) | | useHints(true) | |
| { | | { | |
| repairpath = dbpath; | | repairpath = dbpath; | |
| dur = false; | | dur = false; | |
| | | | |
| skipping to change at line 71 | | skipping to change at line 67 | |
| dur = true; | | dur = true; | |
| #endif | | #endif | |
| if (sizeof(void*) == 8) | | if (sizeof(void*) == 8) | |
| dur = true; | | dur = true; | |
| #if defined(_DURABLEDEFAULTOFF) | | #if defined(_DURABLEDEFAULTOFF) | |
| dur = false; | | dur = false; | |
| #endif | | #endif | |
| } | | } | |
| | | | |
| std::string dbpath; | | std::string dbpath; | |
|
| | | static const char* kDefaultDbPath; | |
| | | static const char* kDefaultConfigDbPath; | |
| | | | |
| bool directoryperdb; | | bool directoryperdb; | |
| std::string repairpath; | | std::string repairpath; | |
| unsigned lenForNewNsFiles; | | unsigned lenForNewNsFiles; | |
| | | | |
| bool preallocj; // --nopreallocj no preallocation of journal
files | | bool preallocj; // --nopreallocj no preallocation of journal
files | |
| bool prealloc; // --noprealloc no preallocation of data fil
es | | bool prealloc; // --noprealloc no preallocation of data fil
es | |
| bool smallfiles; // --smallfiles allocate smaller data files | | bool smallfiles; // --smallfiles allocate smaller data files | |
| bool noTableScan; // --notablescan no table scans allowed | | bool noTableScan; // --notablescan no table scans allowed | |
| | | | |
| bool dur; // --dur durability (now --journal) | | bool dur; // --dur durability (now --journal) | |
| | | | |
End of changes. 2 change blocks. |
| 5 lines changed or deleted | | 4 lines changed or added | |
|
| update_driver.h | | update_driver.h | |
| | | | |
| skipping to change at line 38 | | skipping to change at line 38 | |
| | | | |
| #pragma once | | #pragma once | |
| | | | |
| #include <string> | | #include <string> | |
| #include <vector> | | #include <vector> | |
| | | | |
| #include "mongo/base/owned_pointer_vector.h" | | #include "mongo/base/owned_pointer_vector.h" | |
| #include "mongo/base/status.h" | | #include "mongo/base/status.h" | |
| #include "mongo/bson/mutable/document.h" | | #include "mongo/bson/mutable/document.h" | |
| #include "mongo/db/field_ref_set.h" | | #include "mongo/db/field_ref_set.h" | |
|
| #include "mongo/db/index_set.h" | | | |
| #include "mongo/db/jsobj.h" | | #include "mongo/db/jsobj.h" | |
| #include "mongo/db/ops/modifier_interface.h" | | #include "mongo/db/ops/modifier_interface.h" | |
| #include "mongo/db/ops/modifier_table.h" | | #include "mongo/db/ops/modifier_table.h" | |
| #include "mongo/db/query/canonical_query.h" | | #include "mongo/db/query/canonical_query.h" | |
|
| | | #include "mongo/db/update_index_data.h" | |
| | | | |
| namespace mongo { | | namespace mongo { | |
| | | | |
| class UpdateDriver { | | class UpdateDriver { | |
| public: | | public: | |
| | | | |
| struct Options; | | struct Options; | |
| UpdateDriver(const Options& opts); | | UpdateDriver(const Options& opts); | |
| | | | |
| ~UpdateDriver(); | | ~UpdateDriver(); | |
| | | | |
| skipping to change at line 110 | | skipping to change at line 110 | |
| | | | |
| // | | // | |
| // Accessors | | // Accessors | |
| // | | // | |
| | | | |
| size_t numMods() const; | | size_t numMods() const; | |
| | | | |
| bool isDocReplacement() const; | | bool isDocReplacement() const; | |
| | | | |
| bool modsAffectIndices() const; | | bool modsAffectIndices() const; | |
|
| void refreshIndexKeys(const IndexPathSet* indexedFields); | | void refreshIndexKeys(const UpdateIndexData* indexedFields); | |
| | | | |
| bool logOp() const; | | bool logOp() const; | |
| void setLogOp(bool logOp); | | void setLogOp(bool logOp); | |
| | | | |
| ModifierInterface::Options modOptions() const; | | ModifierInterface::Options modOptions() const; | |
| void setModOptions(ModifierInterface::Options modOpts); | | void setModOptions(ModifierInterface::Options modOpts); | |
| | | | |
| ModifierInterface::ExecInfo::UpdateContext context() const; | | ModifierInterface::ExecInfo::UpdateContext context() const; | |
| void setContext(ModifierInterface::ExecInfo::UpdateContext context)
; | | void setContext(ModifierInterface::ExecInfo::UpdateContext context)
; | |
| | | | |
| | | | |
| skipping to change at line 156 | | skipping to change at line 156 | |
| // Is there a list of $mod's on '_mods' or is it just full object r
eplacement? | | // Is there a list of $mod's on '_mods' or is it just full object r
eplacement? | |
| bool _replacementMode; | | bool _replacementMode; | |
| | | | |
| // Collection of update mod instances. Owned here. | | // Collection of update mod instances. Owned here. | |
| vector<ModifierInterface*> _mods; | | vector<ModifierInterface*> _mods; | |
| | | | |
| // What are the list of fields in the collection over which the upd
ate is going to be | | // What are the list of fields in the collection over which the upd
ate is going to be | |
| // applied that participate in indices? | | // applied that participate in indices? | |
| // | | // | |
| // NOTE: Owned by the collection's info cache!. | | // NOTE: Owned by the collection's info cache!. | |
|
| const IndexPathSet* _indexedFields; | | const UpdateIndexData* _indexedFields; | |
| | | | |
| // | | // | |
| // mutable properties after parsing | | // mutable properties after parsing | |
| // | | // | |
| | | | |
| // Should this driver generate an oplog record when it applies the
update? | | // Should this driver generate an oplog record when it applies the
update? | |
| bool _logOp; | | bool _logOp; | |
| | | | |
| // The options to initiate the mods with | | // The options to initiate the mods with | |
| ModifierInterface::Options _modOptions; | | ModifierInterface::Options _modOptions; | |
| | | | |
End of changes. 4 change blocks. |
| 3 lines changed or deleted | | 3 lines changed or added | |
|
| user.h | | user.h | |
| | | | |
| skipping to change at line 70 | | skipping to change at line 70 | |
| * Returns the user name for this user. | | * Returns the user name for this user. | |
| */ | | */ | |
| const UserName& getName() const; | | const UserName& getName() const; | |
| | | | |
| /** | | /** | |
| * Returns an iterator over the names of the user's direct roles | | * Returns an iterator over the names of the user's direct roles | |
| */ | | */ | |
| RoleNameIterator getRoles() const; | | RoleNameIterator getRoles() const; | |
| | | | |
| /** | | /** | |
|
| | | * Returns an iterator over the names of the user's indirect roles | |
| | | */ | |
| | | RoleNameIterator getIndirectRoles() const; | |
| | | | |
| | | /** | |
| * Returns true if this user is a member of the given role. | | * Returns true if this user is a member of the given role. | |
| */ | | */ | |
| bool hasRole(const RoleName& roleName) const; | | bool hasRole(const RoleName& roleName) const; | |
| | | | |
| /** | | /** | |
| * Returns a reference to the information about the user's privileg
es. | | * Returns a reference to the information about the user's privileg
es. | |
| */ | | */ | |
| const ResourcePrivilegeMap& getPrivileges() const { return _privile
ges; } | | const ResourcePrivilegeMap& getPrivileges() const { return _privile
ges; } | |
| | | | |
| /** | | /** | |
| | | | |
| skipping to change at line 133 | | skipping to change at line 138 | |
| * Sets this user's authentication credentials. | | * Sets this user's authentication credentials. | |
| */ | | */ | |
| void setCredentials(const CredentialData& credentials); | | void setCredentials(const CredentialData& credentials); | |
| | | | |
| /** | | /** | |
| * Replaces any existing user role membership information with the
roles from "roles". | | * Replaces any existing user role membership information with the
roles from "roles". | |
| */ | | */ | |
| void setRoles(RoleNameIterator roles); | | void setRoles(RoleNameIterator roles); | |
| | | | |
| /** | | /** | |
|
| | | * Replaces any existing indirect user role membership information | |
| | | with the roles from | |
| | | * "indirectRoles". | |
| | | */ | |
| | | void setIndirectRoles(RoleNameIterator indirectRoles); | |
| | | | |
| | | /** | |
| * Replaces any existing user privilege information with "privilege
s". | | * Replaces any existing user privilege information with "privilege
s". | |
| */ | | */ | |
| void setPrivileges(const PrivilegeVector& privileges); | | void setPrivileges(const PrivilegeVector& privileges); | |
| | | | |
| /** | | /** | |
| * Adds the given role name to the list of roles of which this user
is a member. | | * Adds the given role name to the list of roles of which this user
is a member. | |
| */ | | */ | |
| void addRole(const RoleName& role); | | void addRole(const RoleName& role); | |
| | | | |
| /** | | /** | |
| | | | |
| skipping to change at line 209 | | skipping to change at line 220 | |
| // Maps resource name to privilege on that resource | | // Maps resource name to privilege on that resource | |
| ResourcePrivilegeMap _privileges; | | ResourcePrivilegeMap _privileges; | |
| | | | |
| // Roles the user has privileges from | | // Roles the user has privileges from | |
| unordered_set<RoleName> _roles; | | unordered_set<RoleName> _roles; | |
| | | | |
| // List of databases already probed for privilege information for t
his user. Only | | // List of databases already probed for privilege information for t
his user. Only | |
| // meaningful for V2.4-schema users. | | // meaningful for V2.4-schema users. | |
| std::vector<std::string> _probedDatabases; | | std::vector<std::string> _probedDatabases; | |
| | | | |
|
| | | // Roles that the user indirectly has privileges from, due to role | |
| | | inheritance. | |
| | | std::vector<RoleName> _indirectRoles; | |
| | | | |
| // Credential information. | | // Credential information. | |
| CredentialData _credentials; | | CredentialData _credentials; | |
| | | | |
| // Schema version of user documents used to build this user. Valid
values are | | // Schema version of user documents used to build this user. Valid
values are | |
| // AuthorizationManager::schemaVersion24 and schemaVersion26Final. | | // AuthorizationManager::schemaVersion24 and schemaVersion26Final. | |
| int _schemaVersion; | | int _schemaVersion; | |
| | | | |
| // _refCount and _isInvalidated are modified exclusively by the Aut
horizationManager | | // _refCount and _isInvalidated are modified exclusively by the Aut
horizationManager | |
| // _isInvalidated can be read by any consumer of User, but _refCoun
t can only be | | // _isInvalidated can be read by any consumer of User, but _refCoun
t can only be | |
| // meaningfully read by the AuthorizationManager, as _refCount is g
uarded by the AM's _lock | | // meaningfully read by the AuthorizationManager, as _refCount is g
uarded by the AM's _lock | |
| | | | |
End of changes. 3 change blocks. |
| 0 lines changed or deleted | | 16 lines changed or added | |
|
| user_management_commands_parser.h | | user_management_commands_parser.h | |
| | | | |
| skipping to change at line 222 | | skipping to change at line 222 | |
| * output param parsedUserNames) a list of the usernames in the input a
rray. | | * output param parsedUserNames) a list of the usernames in the input a
rray. | |
| * Performs syntactic validation of "usersArray", only. | | * Performs syntactic validation of "usersArray", only. | |
| */ | | */ | |
| Status parseUserNamesFromBSONArray(const BSONArray& usersArray, | | Status parseUserNamesFromBSONArray(const BSONArray& usersArray, | |
| const StringData& dbname, | | const StringData& dbname, | |
| std::vector<UserName>* parsedUserNam
es); | | std::vector<UserName>* parsedUserNam
es); | |
| | | | |
| struct MergeAuthzCollectionsArgs { | | struct MergeAuthzCollectionsArgs { | |
| std::string usersCollName; | | std::string usersCollName; | |
| std::string rolesCollName; | | std::string rolesCollName; | |
|
| | | std::string db; | |
| bool drop; | | bool drop; | |
| BSONObj writeConcern; | | BSONObj writeConcern; | |
| MergeAuthzCollectionsArgs() : drop(false) {} | | MergeAuthzCollectionsArgs() : drop(false) {} | |
| }; | | }; | |
| | | | |
| /** | | /** | |
| * Takes a command object describing an invocation of the "_mergeAuthzC
ollections" command and | | * Takes a command object describing an invocation of the "_mergeAuthzC
ollections" command and | |
| * parses out the name of the temporary collections to use for user and
role data, whether or | | * parses out the name of the temporary collections to use for user and
role data, whether or | |
|
| * not to drop the existing users/roles, and the writeConcern. | | * not to drop the existing users/roles, the database if this is a for | |
| | | a db-specific restore, | |
| | | * and the writeConcern. | |
| | | * Returns ErrorCodes::OutdatedClient if the "db" field is missing, as | |
| | | that likely indicates | |
| | | * the command was sent by an outdated (pre 2.6.4) version of mongorest | |
| | | ore. | |
| | | * Returns other codes indicating missing or incorrectly typed fields. | |
| */ | | */ | |
| Status parseMergeAuthzCollectionsCommand(const BSONObj& cmdObj, | | Status parseMergeAuthzCollectionsCommand(const BSONObj& cmdObj, | |
| MergeAuthzCollectionsArgs* par
sedArgs); | | MergeAuthzCollectionsArgs* par
sedArgs); | |
| | | | |
| } // namespace auth | | } // namespace auth | |
| } // namespace mongo | | } // namespace mongo | |
| | | | |
End of changes. 2 change blocks. |
| 1 lines changed or deleted | | 9 lines changed or added | |
|