authorization_manager.h | authorization_manager.h | |||
---|---|---|---|---|
skipping to change at line 41 | skipping to change at line 41 | |||
#include <boost/function.hpp> | #include <boost/function.hpp> | |||
#include <boost/scoped_ptr.hpp> | #include <boost/scoped_ptr.hpp> | |||
#include <boost/thread/condition_variable.hpp> | #include <boost/thread/condition_variable.hpp> | |||
#include <boost/thread/mutex.hpp> | #include <boost/thread/mutex.hpp> | |||
#include <memory> | #include <memory> | |||
#include <string> | #include <string> | |||
#include "mongo/base/disallow_copying.h" | #include "mongo/base/disallow_copying.h" | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/bson/mutable/element.h" | #include "mongo/bson/mutable/element.h" | |||
#include "mongo/bson/oid.h" | ||||
#include "mongo/db/auth/action_set.h" | #include "mongo/db/auth/action_set.h" | |||
#include "mongo/db/auth/resource_pattern.h" | #include "mongo/db/auth/resource_pattern.h" | |||
#include "mongo/db/auth/role_graph.h" | #include "mongo/db/auth/role_graph.h" | |||
#include "mongo/db/auth/user.h" | #include "mongo/db/auth/user.h" | |||
#include "mongo/db/auth/user_name.h" | #include "mongo/db/auth/user_name.h" | |||
#include "mongo/db/auth/user_name_hash.h" | #include "mongo/db/auth/user_name_hash.h" | |||
#include "mongo/db/jsobj.h" | #include "mongo/db/jsobj.h" | |||
#include "mongo/db/namespace_string.h" | #include "mongo/db/namespace_string.h" | |||
#include "mongo/platform/unordered_map.h" | #include "mongo/platform/unordered_map.h" | |||
skipping to change at line 178 | skipping to change at line 179 | |||
/** | /** | |||
* Returns via the output parameter "version" the version number of the authorization | * Returns via the output parameter "version" the version number of the authorization | |||
* system. Returns Status::OK() if it was able to successfully fet ch the current | * system. Returns Status::OK() if it was able to successfully fet ch the current | |||
* authorization version. If it has problems fetching the most up to date version it | * authorization version. If it has problems fetching the most up to date version it | |||
* returns a non-OK status. When returning a non-OK status, *versi on will be set to | * returns a non-OK status. When returning a non-OK status, *versi on will be set to | |||
* schemaVersionInvalid (0). | * schemaVersionInvalid (0). | |||
*/ | */ | |||
Status getAuthorizationVersion(int* version); | Status getAuthorizationVersion(int* version); | |||
/** | ||||
* Returns the user cache generation identifier. | ||||
*/ | ||||
OID getCacheGeneration(); | ||||
// Returns true if there exists at least one privilege document in the system. | // Returns true if there exists at least one privilege document in the system. | |||
bool hasAnyPrivilegeDocuments() const; | bool hasAnyPrivilegeDocuments() const; | |||
/** | /** | |||
* Updates the auth schema version document to reflect that the sys tem is upgraded to | * Updates the auth schema version document to reflect that the sys tem is upgraded to | |||
* schemaVersion26Final. | * schemaVersion26Final. | |||
* | * | |||
* Do not call if getAuthorizationVersion() reports a value other t han schemaVersion26Final. | * Do not call if getAuthorizationVersion() reports a value other t han schemaVersion26Final. | |||
*/ | */ | |||
Status writeAuthSchemaVersionIfNeeded(); | Status writeAuthSchemaVersionIfNeeded(); | |||
skipping to change at line 447 | skipping to change at line 453 | |||
class CacheGuard; | class CacheGuard; | |||
friend class AuthorizationManager::CacheGuard; | friend class AuthorizationManager::CacheGuard; | |||
/** | /** | |||
* Invalidates all User objects in the cache and removes them from the cache. | * Invalidates all User objects in the cache and removes them from the cache. | |||
* Should only be called when already holding _cacheMutex. | * Should only be called when already holding _cacheMutex. | |||
*/ | */ | |||
void _invalidateUserCache_inlock(); | void _invalidateUserCache_inlock(); | |||
/** | /** | |||
* Updates _cacheGeneration to a new OID | ||||
*/ | ||||
void _updateCacheGeneration_inlock(); | ||||
/** | ||||
* Fetches user information from a v2-schema user document for the named user, | * Fetches user information from a v2-schema user document for the named user, | |||
* and stores a pointer to a new user object into *acquiredUser on success. | * and stores a pointer to a new user object into *acquiredUser on success. | |||
*/ | */ | |||
Status _fetchUserV2(const UserName& userName, std::auto_ptr<User>* acquiredUser); | Status _fetchUserV2(const UserName& userName, std::auto_ptr<User>* acquiredUser); | |||
/** | /** | |||
* Fetches user information from a v1-schema user document for the named user, possibly | * Fetches user information from a v1-schema user document for the named user, possibly | |||
* examining system.users collections from userName.getDB() and adm in.system.users in the | * examining system.users collections from userName.getDB() and adm in.system.users in the | |||
* process. Stores a pointer to a new user object into *acquiredUs er on success. | * process. Stores a pointer to a new user object into *acquiredUs er on success. | |||
*/ | */ | |||
skipping to change at line 490 | skipping to change at line 501 | |||
/** | /** | |||
* Caches User objects with information about user privileges, to a void the need to | * Caches User objects with information about user privileges, to a void the need to | |||
* go to disk to read user privilege documents whenever possible. Every User object | * go to disk to read user privilege documents whenever possible. Every User object | |||
* has a reference count - the AuthorizationManager must not delete a User object in the | * has a reference count - the AuthorizationManager must not delete a User object in the | |||
* cache unless its reference count is zero. | * cache unless its reference count is zero. | |||
*/ | */ | |||
unordered_map<UserName, User*> _userCache; | unordered_map<UserName, User*> _userCache; | |||
/** | /** | |||
* Current generation of cached data. Bumped every time part of th | * Current generation of cached data. Updated every time part of t | |||
e cache gets | he cache gets | |||
* invalidated. | * invalidated. Protected by CacheGuard. | |||
*/ | */ | |||
uint64_t _cacheGeneration; | OID _cacheGeneration; | |||
/** | /** | |||
* True if there is an update to the _userCache in progress, and th at update is currently in | * True if there is an update to the _userCache in progress, and th at update is currently in | |||
* the "fetch phase", during which it does not hold the _cacheMutex . | * the "fetch phase", during which it does not hold the _cacheMutex . | |||
* | * | |||
* Manipulated via CacheGuard. | * Manipulated via CacheGuard. | |||
*/ | */ | |||
bool _isFetchPhaseBusy; | bool _isFetchPhaseBusy; | |||
/** | /** | |||
End of changes. 5 change blocks. | ||||
4 lines changed or deleted | 15 lines changed or added | |||
btree_index_cursor.h | btree_index_cursor.h | |||
---|---|---|---|---|
skipping to change at line 49 | skipping to change at line 49 | |||
namespace mongo { | namespace mongo { | |||
class BtreeIndexCursor : public IndexCursor { | class BtreeIndexCursor : public IndexCursor { | |||
public: | public: | |||
virtual ~BtreeIndexCursor(); | virtual ~BtreeIndexCursor(); | |||
bool isEOF() const; | bool isEOF() const; | |||
/** | /** | |||
* Called from btree.cpp when we're about to delete a Btree bucket. | * Called from btree.cpp when we're about to delete a Btree bucket. | |||
The index descriptor | ||||
* is needed as just the DiskLoc of the bucket is not unique across | ||||
databases, which might | ||||
* result in incorrect invalidation of cursors in other unlocked da | ||||
tabases. | ||||
*/ | */ | |||
static void aboutToDeleteBucket(const DiskLoc& bucket); | static void aboutToDeleteBucket(const IndexCatalogEntry* index, | |||
const DiskLoc& bucket); | ||||
virtual Status setOptions(const CursorOptions& options); | virtual Status setOptions(const CursorOptions& options); | |||
virtual Status seek(const BSONObj& position); | virtual Status seek(const BSONObj& position); | |||
// Btree-specific seeking functions. | // Btree-specific seeking functions. | |||
Status seek(const vector<const BSONElement*>& position, | Status seek(const vector<const BSONElement*>& position, | |||
const vector<bool>& inclusive); | const vector<bool>& inclusive); | |||
/** | /** | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 8 lines changed or added | |||
client.h | client.h | |||
---|---|---|---|---|
skipping to change at line 139 | skipping to change at line 139 | |||
/** | /** | |||
* Call this to allow PageFaultExceptions even if writes happened b efore this was called. | * Call this to allow PageFaultExceptions even if writes happened b efore this was called. | |||
* Writes after this is called still prevent PFEs from being thrown . | * Writes after this is called still prevent PFEs from being thrown . | |||
*/ | */ | |||
void clearHasWrittenThisOperation() { _hasWrittenThisOperation = fa lse; } | void clearHasWrittenThisOperation() { _hasWrittenThisOperation = fa lse; } | |||
bool allowedToThrowPageFaultException() const; | bool allowedToThrowPageFaultException() const; | |||
LockState& lockState() { return _ls; } | LockState& lockState() { return _ls; } | |||
void setIsWriteCmd(bool newSetting); | ||||
bool isWriteCmd() const; | ||||
private: | private: | |||
Client(const std::string& desc, AbstractMessagingPort *p = 0); | Client(const std::string& desc, AbstractMessagingPort *p = 0); | |||
friend class CurOp; | friend class CurOp; | |||
ConnectionId _connectionId; // > 0 for things "conn", 0 otherwise | ConnectionId _connectionId; // > 0 for things "conn", 0 otherwise | |||
string _threadId; // "" on non support systems | string _threadId; // "" on non support systems | |||
CurOp * _curOp; | CurOp * _curOp; | |||
Context * _context; | Context * _context; | |||
bool _shutdown; // to track if Client::shutdown() gets called | bool _shutdown; // to track if Client::shutdown() gets called | |||
std::string _desc; | std::string _desc; | |||
bool _god; | bool _god; | |||
skipping to change at line 161 | skipping to change at line 164 | |||
BSONObj _remoteId; | BSONObj _remoteId; | |||
bool _hasWrittenThisOperation; | bool _hasWrittenThisOperation; | |||
bool _hasWrittenSinceCheckpoint; | bool _hasWrittenSinceCheckpoint; | |||
PageFaultRetryableSection *_pageFaultRetryableSection; | PageFaultRetryableSection *_pageFaultRetryableSection; | |||
LockState _ls; | LockState _ls; | |||
friend class PageFaultRetryableSection; // TEMP | friend class PageFaultRetryableSection; // TEMP | |||
friend class NoPageFaultsAllowed; // TEMP | friend class NoPageFaultsAllowed; // TEMP | |||
bool _isWriteCmd; | ||||
public: | public: | |||
/** "read lock, and set my context, all in one operation" | /** "read lock, and set my context, all in one operation" | |||
* This handles (if not recursively locked) opening an unopened da tabase. | * This handles (if not recursively locked) opening an unopened da tabase. | |||
*/ | */ | |||
class ReadContext : boost::noncopyable { | class ReadContext : boost::noncopyable { | |||
public: | public: | |||
ReadContext(const std::string& ns, const std::string& path=stor ageGlobalParams.dbpath); | ReadContext(const std::string& ns, const std::string& path=stor ageGlobalParams.dbpath); | |||
Context& ctx() { return *c.get(); } | Context& ctx() { return *c.get(); } | |||
private: | private: | |||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 6 lines changed or added | |||
compiler.h | compiler.h | |||
---|---|---|---|---|
// Copyright 2012 the V8 project authors. All rights reserved. | /* | |||
// Redistribution and use in source and binary forms, with or without | * Copyright 2012 10gen Inc. | |||
// modification, are permitted provided that the following conditions are | * | |||
// met: | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
// | * you may not use this file except in compliance with the License. | |||
// * Redistributions of source code must retain the above copyright | * You may obtain a copy of the License at | |||
// notice, this list of conditions and the following disclaimer. | * | |||
// * Redistributions in binary form must reproduce the above | * http://www.apache.org/licenses/LICENSE-2.0 | |||
// copyright notice, this list of conditions and the following | * | |||
// disclaimer in the documentation and/or other materials provided | * Unless required by applicable law or agreed to in writing, software | |||
// with the distribution. | * distributed under the License is distributed on an "AS IS" BASIS, | |||
// * Neither the name of Google Inc. nor the names of its | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
// contributors may be used to endorse or promote products derived | * See the License for the specific language governing permissions and | |||
// from this software without specific prior written permission. | * limitations under the License. | |||
// | */ | |||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | #pragma once | |||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | /** | |||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | * Include "mongo/platform/compiler.h" to get compiler-targeted macro defin | |||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | itions and utilities. | |||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * The following macros are provided in all compiler environments: | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * MONGO_COMPILER_NORETURN | |||
* | ||||
#ifndef V8_COMPILER_H_ | * Instructs the compiler that the decorated function will not return thr | |||
#define V8_COMPILER_H_ | ough the normal return | |||
* path. | ||||
#include "allocation.h" | * | |||
#include "ast.h" | * Correct: MONGO_COMPILER_NORETURN void myAbortFunction(); | |||
#include "zone.h" | * | |||
* | ||||
namespace v8 { | * MONGO_COMPILER_VARIABLE_UNUSED | |||
namespace internal { | * | |||
* Instructs the compiler not to warn if it detects no use of the decorat | ||||
class ScriptDataImpl; | ed variable. | |||
* Typically only useful for variables that are always declared but only | ||||
// CompilationInfo encapsulates some information known at compile time. It | used in | |||
// is constructed based on the resources available at compile-time. | * conditionally-compiled code. | |||
class CompilationInfo { | * | |||
public: | * Correct: MONGO_COMPILER_VARIABLE_UNUSED int ignored; | |||
CompilationInfo(Handle<Script> script, Zone* zone); | * | |||
CompilationInfo(Handle<SharedFunctionInfo> shared_info, Zone* zone); | * | |||
CompilationInfo(Handle<JSFunction> closure, Zone* zone); | * MONGO_COMPILER_ALIGN_TYPE(ALIGNMENT) | |||
* | ||||
virtual ~CompilationInfo(); | * Instructs the compiler to use the given minimum alignment for the deco | |||
rated type. | ||||
Isolate* isolate() { | * | |||
ASSERT(Isolate::Current() == isolate_); | * Alignments should probably always be powers of two. Also, note that m | |||
return isolate_; | ost allocators will not | |||
} | * be able to guarantee better than 16- or 32-byte alignment. | |||
Zone* zone() { | * | |||
return zone_; | * Correct: | |||
} | * class MONGO_COMPILER_ALIGN_TYPE(16) MyClass {...}; | |||
bool is_lazy() const { return IsLazy::decode(flags_); } | * | |||
bool is_eval() const { return IsEval::decode(flags_); } | * Incorrect: | |||
bool is_global() const { return IsGlobal::decode(flags_); } | * MONGO_COMPILER_ALIGN_TYPE(16) class MyClass {...}; | |||
bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; } | * class MyClass{...} MONGO_COMPILER_ALIGN_TYPE(16); | |||
bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; | * | |||
} | * | |||
LanguageMode language_mode() const { | * MONGO_COMPILER_ALIGN_VARIABLE(ALIGNMENT) | |||
return LanguageModeField::decode(flags_); | * | |||
} | * Instructs the compiler to use the given minimum alignment for the deco | |||
bool is_in_loop() const { return IsInLoop::decode(flags_); } | rated variable. | |||
FunctionLiteral* function() const { return function_; } | * | |||
Scope* scope() const { return scope_; } | * Note that most allocators will not allow heap allocated alignments tha | |||
Scope* global_scope() const { return global_scope_; } | t are better than 16- or | |||
Handle<Code> code() const { return code_; } | * 32-byte aligned. Stack allocators may only guarantee up to the natura | |||
Handle<JSFunction> closure() const { return closure_; } | l word length worth of | |||
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } | * alignment. | |||
Handle<Script> script() const { return script_; } | * | |||
v8::Extension* extension() const { return extension_; } | * Correct: | |||
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; } | * class MyClass { | |||
Handle<Context> calling_context() const { return calling_context_; } | * MONGO_COMPILER_ALIGN_VARIABLE(8) char a; | |||
int osr_ast_id() const { return osr_ast_id_; } | * }; | |||
* | ||||
void MarkAsEval() { | * MONGO_COMPILER_ALIGN_VARIABLE(8) class MyClass {...} singletonInstan | |||
ASSERT(!is_lazy()); | ce; | |||
flags_ |= IsEval::encode(true); | * | |||
} | * Incorrect: | |||
void MarkAsGlobal() { | * int MONGO_COMPILER_ALIGN_VARIABLE(16) a, b; | |||
ASSERT(!is_lazy()); | * | |||
flags_ |= IsGlobal::encode(true); | * | |||
} | * MONGO_COMPILER_API_EXPORT | |||
void SetLanguageMode(LanguageMode language_mode) { | * | |||
ASSERT(this->language_mode() == CLASSIC_MODE || | * Instructs the compiler to label the given type, variable or function a | |||
this->language_mode() == language_mode || | s part of the | |||
language_mode == EXTENDED_MODE); | * exported interface of the library object under construction. | |||
flags_ = LanguageModeField::update(flags_, language_mode); | * | |||
} | * Correct: | |||
void MarkAsInLoop() { | * MONGO_COMPILER_API_EXPORT int globalSwitch; | |||
ASSERT(is_lazy()); | * class MONGO_COMPILER_API_EXPORT ExportedType { ... }; | |||
flags_ |= IsInLoop::encode(true); | * MONGO_COMPILER_API_EXPORT SomeType exportedFunction(...); | |||
} | * | |||
void MarkAsNative() { | * NOTE: Rather than using this macro directly, one typically declares an | |||
flags_ |= IsNative::encode(true); | other macro named for the | |||
} | * library, which is conditionally defined to either MONGO_COMIPLER_API_E | |||
bool is_native() const { | XPORT or | |||
return IsNative::decode(flags_); | * MONGO_COMPILER_API_IMPORT based on whether the compiler is currently b | |||
} | uilding the library or | |||
void SetFunction(FunctionLiteral* literal) { | * building an object that depends on the library, respectively. For exa | |||
ASSERT(function_ == NULL); | mple, MONGO_CLIENT_API | |||
function_ = literal; | * might be defined to MONGO_COMPILER_API_EXPORT when building the MongoD | |||
} | B shared library, and to | |||
void SetScope(Scope* scope) { | * MONGO_COMPILER_API_IMPORT when building an application that links agai | |||
ASSERT(scope_ == NULL); | nst the shared library. | |||
scope_ = scope; | * | |||
} | * | |||
void SetGlobalScope(Scope* global_scope) { | * MONGO_COMPILER_API_IMPORT | |||
ASSERT(global_scope_ == NULL); | * | |||
global_scope_ = global_scope; | * Instructs the compiler to label the given type, variable or function a | |||
} | s imported | |||
void SetCode(Handle<Code> code) { code_ = code; } | * from another library, and not part of the library object under constru | |||
void SetExtension(v8::Extension* extension) { | ction. | |||
ASSERT(!is_lazy()); | * | |||
extension_ = extension; | * Same correct/incorrect usage as for MONGO_COMPILER_API_EXPORT. | |||
} | * | |||
void SetPreParseData(ScriptDataImpl* pre_parse_data) { | * | |||
ASSERT(!is_lazy()); | * MONGO_COMPILER_API_CALLING_CONVENTION | |||
pre_parse_data_ = pre_parse_data; | * | |||
} | * Explicitly decorates a function declaration the api calling conventio | |||
void SetCallingContext(Handle<Context> context) { | n used for | |||
ASSERT(is_eval()); | * shared libraries. | |||
calling_context_ = context; | * | |||
} | * Same correct/incorrect usage as for MONGO_COMPILER_API_EXPORT. | |||
void SetOsrAstId(int osr_ast_id) { | */ | |||
ASSERT(IsOptimizing()); | ||||
osr_ast_id_ = osr_ast_id; | #if defined(_MSC_VER) | |||
} | #include "mongo/platform/compiler_msvc.h" | |||
void MarkCompilingForDebugging(Handle<Code> current_code) { | #elif defined(__GNUC__) | |||
ASSERT(mode_ != OPTIMIZE); | #include "mongo/platform/compiler_gcc.h" | |||
ASSERT(current_code->kind() == Code::FUNCTION); | #else | |||
flags_ |= IsCompilingForDebugging::encode(true); | #error "Unsupported compiler family" | |||
if (current_code->is_compiled_optimizable()) { | ||||
EnableDeoptimizationSupport(); | ||||
} else { | ||||
mode_ = CompilationInfo::NONOPT; | ||||
} | ||||
} | ||||
bool IsCompilingForDebugging() { | ||||
return IsCompilingForDebugging::decode(flags_); | ||||
} | ||||
bool has_global_object() const { | ||||
return !closure().is_null() && (closure()->context()->global() != NULL) | ||||
; | ||||
} | ||||
GlobalObject* global_object() const { | ||||
return has_global_object() ? closure()->context()->global() : NULL; | ||||
} | ||||
// Accessors for the different compilation modes. | ||||
bool IsOptimizing() const { return mode_ == OPTIMIZE; } | ||||
bool IsOptimizable() const { return mode_ == BASE; } | ||||
void SetOptimizing(int osr_ast_id) { | ||||
SetMode(OPTIMIZE); | ||||
osr_ast_id_ = osr_ast_id; | ||||
} | ||||
void DisableOptimization(); | ||||
// Deoptimization support. | ||||
bool HasDeoptimizationSupport() const { | ||||
return SupportsDeoptimization::decode(flags_); | ||||
} | ||||
void EnableDeoptimizationSupport() { | ||||
ASSERT(IsOptimizable()); | ||||
flags_ |= SupportsDeoptimization::encode(true); | ||||
} | ||||
// Determines whether or not to insert a self-optimization header. | ||||
bool ShouldSelfOptimize(); | ||||
// Disable all optimization attempts of this info for the rest of the | ||||
// current compilation pipeline. | ||||
void AbortOptimization(); | ||||
void set_deferred_handles(DeferredHandles* deferred_handles) { | ||||
ASSERT(deferred_handles_ == NULL); | ||||
deferred_handles_ = deferred_handles; | ||||
} | ||||
void SaveHandles() { | ||||
SaveHandle(&closure_); | ||||
SaveHandle(&shared_info_); | ||||
SaveHandle(&calling_context_); | ||||
SaveHandle(&script_); | ||||
} | ||||
private: | ||||
Isolate* isolate_; | ||||
// Compilation mode. | ||||
// BASE is generated by the full codegen, optionally prepared for bailout | ||||
s. | ||||
// OPTIMIZE is optimized code generated by the Hydrogen-based backend. | ||||
// NONOPT is generated by the full codegen and is not prepared for | ||||
// recompilation/bailouts. These functions are never recompiled. | ||||
enum Mode { | ||||
BASE, | ||||
OPTIMIZE, | ||||
NONOPT | ||||
}; | ||||
void Initialize(Mode mode) { | ||||
mode_ = V8::UseCrankshaft() ? mode : NONOPT; | ||||
ASSERT(!script_.is_null()); | ||||
if (script_->type()->value() == Script::TYPE_NATIVE) { | ||||
MarkAsNative(); | ||||
} | ||||
if (!shared_info_.is_null()) { | ||||
ASSERT(language_mode() == CLASSIC_MODE); | ||||
SetLanguageMode(shared_info_->language_mode()); | ||||
} | ||||
} | ||||
void SetMode(Mode mode) { | ||||
ASSERT(V8::UseCrankshaft()); | ||||
mode_ = mode; | ||||
} | ||||
// Flags using template class BitField<type, start, length>. All are | ||||
// false by default. | ||||
// | ||||
// Compilation is either eager or lazy. | ||||
class IsLazy: public BitField<bool, 0, 1> {}; | ||||
// Flags that can be set for eager compilation. | ||||
class IsEval: public BitField<bool, 1, 1> {}; | ||||
class IsGlobal: public BitField<bool, 2, 1> {}; | ||||
// Flags that can be set for lazy compilation. | ||||
class IsInLoop: public BitField<bool, 3, 1> {}; | ||||
// Strict mode - used in eager compilation. | ||||
class LanguageModeField: public BitField<LanguageMode, 4, 2> {}; | ||||
// Is this a function from our natives. | ||||
class IsNative: public BitField<bool, 6, 1> {}; | ||||
// Is this code being compiled with support for deoptimization.. | ||||
class SupportsDeoptimization: public BitField<bool, 7, 1> {}; | ||||
// If compiling for debugging produce just full code matching the | ||||
// initial mode setting. | ||||
class IsCompilingForDebugging: public BitField<bool, 8, 1> {}; | ||||
unsigned flags_; | ||||
// Fields filled in by the compilation pipeline. | ||||
// AST filled in by the parser. | ||||
FunctionLiteral* function_; | ||||
// The scope of the function literal as a convenience. Set to indicate | ||||
// that scopes have been analyzed. | ||||
Scope* scope_; | ||||
// The global scope provided as a convenience. | ||||
Scope* global_scope_; | ||||
// The compiled code. | ||||
Handle<Code> code_; | ||||
// Possible initial inputs to the compilation process. | ||||
Handle<JSFunction> closure_; | ||||
Handle<SharedFunctionInfo> shared_info_; | ||||
Handle<Script> script_; | ||||
// Fields possibly needed for eager compilation, NULL by default. | ||||
v8::Extension* extension_; | ||||
ScriptDataImpl* pre_parse_data_; | ||||
// The context of the caller is needed for eval code, and will be a null | ||||
// handle otherwise. | ||||
Handle<Context> calling_context_; | ||||
// Compilation mode flag and whether deoptimization is allowed. | ||||
Mode mode_; | ||||
int osr_ast_id_; | ||||
// The zone from which the compilation pipeline working on this | ||||
// CompilationInfo allocates. | ||||
Zone* zone_; | ||||
DeferredHandles* deferred_handles_; | ||||
template<typename T> | ||||
void SaveHandle(Handle<T> *object) { | ||||
if (!object->is_null()) { | ||||
Handle<T> handle(*(*object)); | ||||
*object = handle; | ||||
} | ||||
} | ||||
DISALLOW_COPY_AND_ASSIGN(CompilationInfo); | ||||
}; | ||||
// Exactly like a CompilationInfo, except also creates and enters a | ||||
// Zone on construction and deallocates it on exit. | ||||
class CompilationInfoWithZone: public CompilationInfo { | ||||
public: | ||||
explicit CompilationInfoWithZone(Handle<Script> script) | ||||
: CompilationInfo(script, &zone_), | ||||
zone_(script->GetIsolate()), | ||||
zone_scope_(&zone_, DELETE_ON_EXIT) {} | ||||
explicit CompilationInfoWithZone(Handle<SharedFunctionInfo> shared_info) | ||||
: CompilationInfo(shared_info, &zone_), | ||||
zone_(shared_info->GetIsolate()), | ||||
zone_scope_(&zone_, DELETE_ON_EXIT) {} | ||||
explicit CompilationInfoWithZone(Handle<JSFunction> closure) | ||||
: CompilationInfo(closure, &zone_), | ||||
zone_(closure->GetIsolate()), | ||||
zone_scope_(&zone_, DELETE_ON_EXIT) {} | ||||
private: | ||||
Zone zone_; | ||||
ZoneScope zone_scope_; | ||||
}; | ||||
// A wrapper around a CompilationInfo that detaches the Handles from | ||||
// the underlying DeferredHandleScope and stores them in info_ on | ||||
// destruction. | ||||
class CompilationHandleScope BASE_EMBEDDED { | ||||
public: | ||||
explicit CompilationHandleScope(CompilationInfo* info) | ||||
: deferred_(info->isolate()), info_(info) {} | ||||
~CompilationHandleScope() { | ||||
info_->set_deferred_handles(deferred_.Detach()); | ||||
} | ||||
private: | ||||
DeferredHandleScope deferred_; | ||||
CompilationInfo* info_; | ||||
}; | ||||
class HGraph; | ||||
class HGraphBuilder; | ||||
class LChunk; | ||||
// A helper class that calls the three compilation phases in | ||||
// Crankshaft and keeps track of its state. The three phases | ||||
// CreateGraph, OptimizeGraph and GenerateAndInstallCode can either | ||||
// fail, bail-out to the full code generator or succeed. Apart from | ||||
// their return value, the status of the phase last run can be checked | ||||
// using last_status(). | ||||
class OptimizingCompiler: public ZoneObject { | ||||
public: | ||||
explicit OptimizingCompiler(CompilationInfo* info) | ||||
: info_(info), | ||||
oracle_(NULL), | ||||
graph_builder_(NULL), | ||||
graph_(NULL), | ||||
chunk_(NULL), | ||||
time_taken_to_create_graph_(0), | ||||
time_taken_to_optimize_(0), | ||||
time_taken_to_codegen_(0), | ||||
last_status_(FAILED) { } | ||||
enum Status { | ||||
FAILED, BAILED_OUT, SUCCEEDED | ||||
}; | ||||
MUST_USE_RESULT Status CreateGraph(); | ||||
MUST_USE_RESULT Status OptimizeGraph(); | ||||
MUST_USE_RESULT Status GenerateAndInstallCode(); | ||||
Status last_status() const { return last_status_; } | ||||
CompilationInfo* info() const { return info_; } | ||||
MUST_USE_RESULT Status AbortOptimization() { | ||||
info_->AbortOptimization(); | ||||
info_->shared_info()->DisableOptimization(); | ||||
return SetLastStatus(BAILED_OUT); | ||||
} | ||||
private: | ||||
CompilationInfo* info_; | ||||
TypeFeedbackOracle* oracle_; | ||||
HGraphBuilder* graph_builder_; | ||||
HGraph* graph_; | ||||
LChunk* chunk_; | ||||
int64_t time_taken_to_create_graph_; | ||||
int64_t time_taken_to_optimize_; | ||||
int64_t time_taken_to_codegen_; | ||||
Status last_status_; | ||||
MUST_USE_RESULT Status SetLastStatus(Status status) { | ||||
last_status_ = status; | ||||
return last_status_; | ||||
} | ||||
void RecordOptimizationStats(); | ||||
struct Timer { | ||||
Timer(OptimizingCompiler* compiler, int64_t* location) | ||||
: compiler_(compiler), | ||||
start_(OS::Ticks()), | ||||
location_(location) { } | ||||
~Timer() { | ||||
*location_ += (OS::Ticks() - start_); | ||||
} | ||||
OptimizingCompiler* compiler_; | ||||
int64_t start_; | ||||
int64_t* location_; | ||||
}; | ||||
}; | ||||
// The V8 compiler | ||||
// | ||||
// General strategy: Source code is translated into an anonymous function w | ||||
/o | ||||
// parameters which then can be executed. If the source code contains other | ||||
// functions, they will be compiled and allocated as part of the compilatio | ||||
n | ||||
// of the source code. | ||||
// Please note this interface returns shared function infos. This means yo | ||||
u | ||||
// need to call Factory::NewFunctionFromSharedFunctionInfo before you have | ||||
a | ||||
// real function with a context. | ||||
class Compiler : public AllStatic { | ||||
public: | ||||
// Default maximum number of function optimization attempts before we | ||||
// give up. | ||||
static const int kDefaultMaxOptCount = 10; | ||||
static const int kMaxInliningLevels = 3; | ||||
// Call count before primitive functions trigger their own optimization. | ||||
static const int kCallsUntilPrimitiveOpt = 200; | ||||
// All routines return a SharedFunctionInfo. | ||||
// If an error occurs an exception is raised and the return handle | ||||
// contains NULL. | ||||
// Compile a String source within a context. | ||||
static Handle<SharedFunctionInfo> Compile(Handle<String> source, | ||||
Handle<Object> script_name, | ||||
int line_offset, | ||||
int column_offset, | ||||
v8::Extension* extension, | ||||
ScriptDataImpl* pre_data, | ||||
Handle<Object> script_data, | ||||
NativesFlag is_natives_code); | ||||
// Compile a String source within a context for Eval. | ||||
static Handle<SharedFunctionInfo> CompileEval(Handle<String> source, | ||||
Handle<Context> context, | ||||
bool is_global, | ||||
LanguageMode language_mode, | ||||
int scope_position); | ||||
// Compile from function info (used for lazy compilation). Returns true o | ||||
n | ||||
// success and false if the compilation resulted in a stack overflow. | ||||
static bool CompileLazy(CompilationInfo* info); | ||||
static void RecompileParallel(Handle<JSFunction> function); | ||||
// Compile a shared function info object (the function is possibly lazily | ||||
// compiled). | ||||
static Handle<SharedFunctionInfo> BuildFunctionInfo(FunctionLiteral* node | ||||
, | ||||
Handle<Script> script | ||||
); | ||||
// Set the function info for a newly compiled function. | ||||
static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info, | ||||
FunctionLiteral* lit, | ||||
bool is_toplevel, | ||||
Handle<Script> script); | ||||
static void InstallOptimizedCode(OptimizingCompiler* info); | ||||
#ifdef ENABLE_DEBUGGER_SUPPORT | ||||
static bool MakeCodeForLiveEdit(CompilationInfo* info); | ||||
#endif | #endif | |||
static void RecordFunctionCompilation(Logger::LogEventsAndTags tag, | ||||
CompilationInfo* info, | ||||
Handle<SharedFunctionInfo> shared); | ||||
}; | ||||
} } // namespace v8::internal | ||||
#endif // V8_COMPILER_H_ | ||||
End of changes. 2 change blocks. | ||||
472 lines changed or deleted | 135 lines changed or added | |||
d_logic.h | d_logic.h | |||
---|---|---|---|---|
skipping to change at line 378 | skipping to change at line 378 | |||
* if it's relevant. The entries saved here are later transferred to th e receiving side of | * if it's relevant. The entries saved here are later transferred to th e receiving side of | |||
* the migration. A relevant entry is an insertion, a deletion, or an u pdate. | * the migration. A relevant entry is an insertion, a deletion, or an u pdate. | |||
*/ | */ | |||
void logOpForSharding( const char * opstr, | void logOpForSharding( const char * opstr, | |||
const char * ns, | const char * ns, | |||
const BSONObj& obj, | const BSONObj& obj, | |||
BSONObj * patt, | BSONObj * patt, | |||
const BSONObj* fullObj, | const BSONObj* fullObj, | |||
bool forMigrateCleanup ); | bool forMigrateCleanup ); | |||
void ensureShardVersionOKOrThrow(const std::string& ns); | ||||
} | } | |||
End of changes. 1 change blocks. | ||||
0 lines changed or deleted | 2 lines changed or added | |||
dbwebserver.h | dbwebserver.h | |||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
* 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. | |||
*/ | */ | |||
#include <string> | #include <string> | |||
#include <vector> | #include <vector> | |||
#include "mongo/util/admin_access.h" | #include "mongo/util/admin_access.h" | |||
#include "mongo/util/net/miniwebserver.h" | ||||
#include "mongo/util/net/sock.h" | #include "mongo/util/net/sock.h" | |||
namespace mongo { | namespace mongo { | |||
class Prioritizable { | class Prioritizable { | |||
public: | public: | |||
Prioritizable( double p ) : _priority(p) {} | Prioritizable( double p ) : _priority(p) {} | |||
double priority() const { return _priority; } | double priority() const { return _priority; } | |||
private: | private: | |||
double _priority; | double _priority; | |||
skipping to change at line 98 | skipping to change at line 99 | |||
static void initAll(); | static void initAll(); | |||
static void runAll( stringstream& ss ); | static void runAll( stringstream& ss ); | |||
private: | private: | |||
string _name; | string _name; | |||
string _subHeading; | string _subHeading; | |||
static vector<WebStatusPlugin*> * _plugins; | static vector<WebStatusPlugin*> * _plugins; | |||
}; | }; | |||
void webServerThread( const AdminAccess* admins ); | class DbWebServer : public MiniWebServer { | |||
public: | ||||
DbWebServer(const std::string& ip, int port, const AdminAccess* web | ||||
Users); | ||||
private: | ||||
virtual void doRequest(const char *rq, | ||||
std::string url, | ||||
std::string& responseMsg, | ||||
int& responseCode, | ||||
std::vector<std::string>& headers, | ||||
const SockAddr &from); | ||||
bool _allowed(const char* rq, std::vector<std::string>& headers, co | ||||
nst SockAddr& from); | ||||
void _rejectREST(std::string& responseMsg, | ||||
int& responseCode, | ||||
std::vector<std::string>& headers); | ||||
// not owned here | ||||
const AdminAccess* _webUsers; | ||||
}; | ||||
void webServerListenThread(boost::shared_ptr<DbWebServer> dbWebServer); | ||||
string prettyHostName(); | string prettyHostName(); | |||
}; | }; | |||
End of changes. 2 change blocks. | ||||
1 lines changed or deleted | 25 lines changed or added | |||
expression.h | expression.h | |||
---|---|---|---|---|
skipping to change at line 50 | skipping to change at line 50 | |||
namespace mongo { | namespace mongo { | |||
class TreeMatchExpression; | class TreeMatchExpression; | |||
class MatchExpression { | class MatchExpression { | |||
MONGO_DISALLOW_COPYING( MatchExpression ); | MONGO_DISALLOW_COPYING( MatchExpression ); | |||
public: | public: | |||
enum MatchType { | enum MatchType { | |||
// tree types | // tree types | |||
AND, OR, NOR, NOT, | AND, OR, | |||
// array types | // array types | |||
ALL, ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE, | ELEM_MATCH_OBJECT, ELEM_MATCH_VALUE, SIZE, | |||
// leaf types | // leaf types | |||
LTE, LT, EQ, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, NIN, | EQ, LTE, LT, GT, GTE, REGEX, MOD, EXISTS, MATCH_IN, | |||
// Negations. | ||||
NOT, NIN, NOR, | ||||
// special types | // special types | |||
TYPE_OPERATOR, GEO, WHERE, | TYPE_OPERATOR, GEO, WHERE, | |||
// things that maybe shouldn't even be nodes | // things that maybe shouldn't even be nodes | |||
ATOMIC, ALWAYS_FALSE, | ATOMIC, ALWAYS_FALSE, | |||
// Things that we parse but cannot be answered without an index . | // Things that we parse but cannot be answered without an index . | |||
GEO_NEAR, TEXT, | GEO_NEAR, TEXT, | |||
skipping to change at line 127 | skipping to change at line 130 | |||
* AND, OR, NOT, NOR. | * AND, OR, NOT, NOR. | |||
*/ | */ | |||
bool isLogical() const { | bool isLogical() const { | |||
return AND == _matchType || OR == _matchType || NOT == _matchTy pe || NOR == _matchType; | return AND == _matchType || OR == _matchType || NOT == _matchTy pe || NOR == _matchType; | |||
} | } | |||
/** | /** | |||
* Is this node an array operator? Array operators have multiple c lauses but operate on one | * Is this node an array operator? Array operators have multiple c lauses but operate on one | |||
* field. | * field. | |||
* | * | |||
* ALL (AllElemMatchOp) | ||||
* ELEM_MATCH_VALUE, ELEM_MATCH_OBJECT, SIZE (ArrayMatchingMatchExp ression) | * ELEM_MATCH_VALUE, ELEM_MATCH_OBJECT, SIZE (ArrayMatchingMatchExp ression) | |||
*/ | */ | |||
bool isArray() const { | bool isArray() const { | |||
return SIZE == _matchType || ALL == _matchType || ELEM_MATCH_VA | return SIZE == _matchType | |||
LUE == _matchType | || ELEM_MATCH_VALUE == _matchType | |||
|| ELEM_MATCH_OBJECT == _matchType; | || ELEM_MATCH_OBJECT == _matchType; | |||
} | } | |||
/** | /** | |||
* Not-internal nodes, predicates over one field. Almost all of th ese inherit from | * Not-internal nodes, predicates over one field. Almost all of th ese inherit from | |||
* LeafMatchExpression. | * LeafMatchExpression. | |||
* | * | |||
* Exceptions: WHERE, which doesn't have a field. | * Exceptions: WHERE, which doesn't have a field. | |||
* TYPE_OPERATOR, which inherits from MatchExpression d ue to unique array | * TYPE_OPERATOR, which inherits from MatchExpression d ue to unique array | |||
* semantics. | * semantics. | |||
End of changes. 5 change blocks. | ||||
6 lines changed or deleted | 8 lines changed or added | |||
expression_array.h | expression_array.h | |||
---|---|---|---|---|
skipping to change at line 43 | skipping to change at line 43 | |||
#include <vector> | #include <vector> | |||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/bson/bsonobj.h" | #include "mongo/bson/bsonobj.h" | |||
#include "mongo/bson/bsonmisc.h" | #include "mongo/bson/bsonmisc.h" | |||
#include "mongo/db/matcher/expression.h" | #include "mongo/db/matcher/expression.h" | |||
#include "mongo/db/matcher/expression_leaf.h" | #include "mongo/db/matcher/expression_leaf.h" | |||
namespace mongo { | namespace mongo { | |||
/** | ||||
* ALL and ELEM_MATCH inherit from this. | ||||
*/ | ||||
class ArrayMatchingMatchExpression : public MatchExpression { | class ArrayMatchingMatchExpression : public MatchExpression { | |||
public: | public: | |||
ArrayMatchingMatchExpression( MatchType matchType ) : MatchExpressi on( matchType ){} | ArrayMatchingMatchExpression( MatchType matchType ) : MatchExpressi on( matchType ){} | |||
virtual ~ArrayMatchingMatchExpression(){} | virtual ~ArrayMatchingMatchExpression(){} | |||
Status initPath( const StringData& path ); | Status initPath( const StringData& path ); | |||
virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails ) const; | virtual bool matches( const MatchableDocument* doc, MatchDetails* d etails ) const; | |||
/** | /** | |||
skipping to change at line 158 | skipping to change at line 155 | |||
virtual void debugString( StringBuilder& debug, int level ) const; | virtual void debugString( StringBuilder& debug, int level ) const; | |||
virtual bool equivalent( const MatchExpression* other ) const; | virtual bool equivalent( const MatchExpression* other ) const; | |||
int getData() const { return _size; } | int getData() const { return _size; } | |||
private: | private: | |||
int _size; // >= 0 real, < 0, nothing will match | int _size; // >= 0 real, < 0, nothing will match | |||
}; | }; | |||
/** | ||||
* i'm suprised this isn't a regular AllMatchExpression | ||||
*/ | ||||
class AllElemMatchOp : public MatchExpression { | ||||
public: | ||||
AllElemMatchOp() : MatchExpression( ALL ){} | ||||
virtual ~AllElemMatchOp(); | ||||
Status init( const StringData& path ); | ||||
void add( ArrayMatchingMatchExpression* expr ); | ||||
virtual MatchExpression* shallowClone() const { | ||||
AllElemMatchOp* e = new AllElemMatchOp(); | ||||
e->init(path()); | ||||
for (size_t i = 0; i < _list.size(); ++i) { | ||||
e->add(reinterpret_cast<ArrayMatchingMatchExpression*>( | ||||
_list[i]->shallowClone())); | ||||
} | ||||
if ( getTag() ) { | ||||
e->setTag(getTag()->clone()); | ||||
} | ||||
return e; | ||||
} | ||||
virtual bool matches( const MatchableDocument* doc, MatchDetails* d | ||||
etails ) const; | ||||
/** | ||||
* @param e has to be an array | ||||
*/ | ||||
virtual bool matchesSingleElement( const BSONElement& e ) const; | ||||
virtual void debugString( StringBuilder& debug, int level ) const; | ||||
virtual bool equivalent( const MatchExpression* other ) const; | ||||
virtual size_t numChildren() const { return _list.size(); } | ||||
virtual MatchExpression* getChild( size_t i ) const { return _list[ | ||||
i]; } | ||||
virtual std::vector<MatchExpression*>* getChildVector() { return &_ | ||||
list; } | ||||
const StringData path() const { return _path; } | ||||
private: | ||||
bool _allMatch( const BSONObj& anArray ) const; | ||||
StringData _path; | ||||
ElementPath _elementPath; | ||||
std::vector<MatchExpression*> _list; | ||||
}; | ||||
} | } | |||
End of changes. 2 change blocks. | ||||
57 lines changed or deleted | 0 lines changed or added | |||
indexability.h | indexability.h | |||
---|---|---|---|---|
skipping to change at line 89 | skipping to change at line 89 | |||
return true; | return true; | |||
} | } | |||
/** | /** | |||
* Certain array operators require that the field for that operator is prepended | * Certain array operators require that the field for that operator is prepended | |||
* to all fields in that operator's children. | * to all fields in that operator's children. | |||
* | * | |||
* Example: a: {$elemMatch: {b:1, c:1}}. | * Example: a: {$elemMatch: {b:1, c:1}}. | |||
*/ | */ | |||
static bool arrayUsesIndexOnChildren(const MatchExpression* me) { | static bool arrayUsesIndexOnChildren(const MatchExpression* me) { | |||
return me->isArray() && (MatchExpression::ELEM_MATCH_OBJECT == | return me->isArray() && MatchExpression::ELEM_MATCH_OBJECT == m | |||
me->matchType() | e->matchType(); | |||
|| MatchExpression::ALL == me->matchTy | ||||
pe()); | ||||
} | } | |||
/** | /** | |||
* Returns true if 'me' is a NOT, and the child of the NOT can use | * Returns true if 'me' is a NOT, and the child of the NOT can use | |||
* an index on its own field. | * an index on its own field. | |||
*/ | */ | |||
static bool isBoundsGeneratingNot(const MatchExpression* me) { | static bool isBoundsGeneratingNot(const MatchExpression* me) { | |||
return MatchExpression::NOT == me->matchType() && | return MatchExpression::NOT == me->matchType() && | |||
nodeCanUseIndexOnOwnField(me->getChild(0)); | nodeCanUseIndexOnOwnField(me->getChild(0)); | |||
} | } | |||
End of changes. 1 change blocks. | ||||
4 lines changed or deleted | 2 lines changed or added | |||
insert.h | insert.h | |||
---|---|---|---|---|
skipping to change at line 43 | skipping to change at line 43 | |||
namespace mongo { | namespace mongo { | |||
/** | /** | |||
* if doc is ok, then return is BSONObj() | * if doc is ok, then return is BSONObj() | |||
* otherwise, BSONObj is what should be inserted instead | * otherwise, BSONObj is what should be inserted instead | |||
*/ | */ | |||
StatusWith<BSONObj> fixDocumentForInsert( const BSONObj& doc ); | StatusWith<BSONObj> fixDocumentForInsert( const BSONObj& doc ); | |||
/** | /** | |||
* check if this is a collection _any_ user can write to | * Returns Status::OK() if this namespace is valid for user write opera | |||
* does NOT to permission checking, that is elsewhere | tions. If not, returns | |||
* for example, can't write to foo.system.bar | * an error Status. | |||
*/ | */ | |||
Status userAllowedWriteNS( const StringData& db, const StringData& coll ); | Status userAllowedWriteNS( const StringData& db, const StringData& coll ); | |||
Status userAllowedWriteNS( const StringData& ns ); | Status userAllowedWriteNS( const StringData& ns ); | |||
Status userAllowedWriteNS( const NamespaceString& ns ); | Status userAllowedWriteNS( const NamespaceString& ns ); | |||
/** | ||||
* Returns Status::OK() if the namespace described by (db, coll) is val | ||||
id for user create | ||||
* operations. If not, returns an error Status. | ||||
*/ | ||||
Status userAllowedCreateNS( const StringData& db, const StringData& col | ||||
l ); | ||||
} | } | |||
End of changes. 2 change blocks. | ||||
3 lines changed or deleted | 11 lines changed or added | |||
pcre.h | pcre.h | |||
---|---|---|---|---|
skipping to change at line 45 | skipping to change at line 45 | |||
POSSIBILITY OF SUCH DAMAGE. | POSSIBILITY OF SUCH DAMAGE. | |||
--------------------------------------------------------------------------- -- | --------------------------------------------------------------------------- -- | |||
*/ | */ | |||
#ifndef _PCRE_H | #ifndef _PCRE_H | |||
#define _PCRE_H | #define _PCRE_H | |||
/* The current PCRE version information. */ | /* The current PCRE version information. */ | |||
#define PCRE_MAJOR 8 | #define PCRE_MAJOR 8 | |||
#define PCRE_MINOR 36 | #define PCRE_MINOR 37 | |||
#define PCRE_PRERELEASE | #define PCRE_PRERELEASE | |||
#define PCRE_DATE 2014-09-26 | #define PCRE_DATE 2015-04-28 | |||
/* When an application links to a PCRE DLL in Windows, the symbols that are | /* When an application links to a PCRE DLL in Windows, the symbols that are | |||
imported have to be identified as such. When building PCRE, the appropriate | imported have to be identified as such. When building PCRE, the appropriate | |||
export setting is defined in pcre_internal.h, which includes this file. So we | export setting is defined in pcre_internal.h, which includes this file. So we | |||
don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ | don't change existing definitions of PCRE_EXP_DECL and PCRECPP_EXP_DECL. */ | |||
#if defined(_WIN32) && !defined(PCRE_STATIC) | #if defined(_WIN32) && !defined(PCRE_STATIC) | |||
# ifndef PCRE_EXP_DECL | # ifndef PCRE_EXP_DECL | |||
# define PCRE_EXP_DECL extern __declspec(dllimport) | # define PCRE_EXP_DECL extern __declspec(dllimport) | |||
# endif | # endif | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
pcre_stringpiece.h | pcre_stringpiece.h | |||
---|---|---|---|---|
skipping to change at line 177 | skipping to change at line 177 | |||
template<> struct __type_traits<pcrecpp::StringPiece> { | template<> struct __type_traits<pcrecpp::StringPiece> { | |||
typedef __true_type has_trivial_default_constructor; | typedef __true_type has_trivial_default_constructor; | |||
typedef __true_type has_trivial_copy_constructor; | typedef __true_type has_trivial_copy_constructor; | |||
typedef __true_type has_trivial_assignment_operator; | typedef __true_type has_trivial_assignment_operator; | |||
typedef __true_type has_trivial_destructor; | typedef __true_type has_trivial_destructor; | |||
typedef __true_type is_POD_type; | typedef __true_type is_POD_type; | |||
}; | }; | |||
#endif | #endif | |||
// allow StringPiece to be logged | // allow StringPiece to be logged | |||
PCRECPP_EXP_DECL std::ostream& operator<<(std::ostream& o, | std::ostream& operator<<(std::ostream& o, const pcrecpp::StringPiece& piece | |||
const pcrecpp::StringPiece& piece | ); | |||
); | ||||
#endif /* _PCRE_STRINGPIECE_H */ | #endif /* _PCRE_STRINGPIECE_H */ | |||
End of changes. 1 change blocks. | ||||
3 lines changed or deleted | 2 lines changed or added | |||
planner_access.h | planner_access.h | |||
---|---|---|---|---|
skipping to change at line 214 | skipping to change at line 214 | |||
*/ | */ | |||
static QuerySolutionNode* makeIndexScan(const IndexEntry& index, | static QuerySolutionNode* makeIndexScan(const IndexEntry& index, | |||
const CanonicalQuery& query , | const CanonicalQuery& query , | |||
const QueryPlannerParams& p arams, | const QueryPlannerParams& p arams, | |||
const BSONObj& startKey, | const BSONObj& startKey, | |||
const BSONObj& endKey); | const BSONObj& endKey); | |||
// | // | |||
// Indexed Data Access methods. | // Indexed Data Access methods. | |||
// | // | |||
// The inArrayOperator flag deserves some attention. It is set whe | // The inArrayOperator flag deserves some attention. It is set whe | |||
n we're processing a child of | n we're processing a | |||
// a MatchExpression::ALL or MatchExpression::ELEM_MATCH_OBJECT. | // child of an MatchExpression::ELEM_MATCH_OBJECT. | |||
// | // | |||
// When true, the following behavior changes for all methods below that take it as an argument: | // When true, the following behavior changes for all methods below that take it as an argument: | |||
// 0. No deletion of MatchExpression(s). In fact, | // 0. No deletion of MatchExpression(s). In fact, | |||
// 1. No mutation of the MatchExpression at all. We need the tree as-is in order to perform | // 1. No mutation of the MatchExpression at all. We need the tree as-is in order to perform | |||
// a filter on the entire tree. | // a filter on the entire tree. | |||
// 2. No fetches performed. There will be a final fetch by the cal ler of buildIndexedDataAccess | // 2. No fetches performed. There will be a final fetch by the cal ler of buildIndexedDataAccess | |||
// who set the value of inArrayOperator to true. | // who set the value of inArrayOperator to true. | |||
// 3. No compound indices are used and no bounds are combined. The se are incorrect in the context | // 3. No compound indices are used and no bounds are combined. The se are incorrect in the context | |||
// of these operators. | // of these operators. | |||
// | // | |||
skipping to change at line 256 | skipping to change at line 256 | |||
static QuerySolutionNode* buildIndexedOr(const CanonicalQuery& quer y, | static QuerySolutionNode* buildIndexedOr(const CanonicalQuery& quer y, | |||
MatchExpression* root, | MatchExpression* root, | |||
bool inArrayOperator, | bool inArrayOperator, | |||
const vector<IndexEntry>& indices); | const vector<IndexEntry>& indices); | |||
/** | /** | |||
* Traverses the tree rooted at the $elemMatch expression 'node', | * Traverses the tree rooted at the $elemMatch expression 'node', | |||
* finding all predicates that can use an index directly and return ing | * finding all predicates that can use an index directly and return ing | |||
* them in the out-parameter vector 'out'. | * them in the out-parameter vector 'out'. | |||
* | * | |||
* Traverses only through $and and array nodes like $all. | * Traverses only through AND and ELEM_MATCH_OBJECT nodes. | |||
* | * | |||
* Other nodes (i.e. nodes which cannot use an index directly, and which are | * Other nodes (i.e. nodes which cannot use an index directly, and which are | |||
* neither $and nor array nodes) are returned in 'subnodesOut' if t hey are | * neither AND nor ELEM_MATCH_OBJECT) are returned in 'subnodesOut' if they are | |||
* tagged to use an index. | * tagged to use an index. | |||
*/ | */ | |||
static void findElemMatchChildren(const MatchExpression* node, | static void findElemMatchChildren(const MatchExpression* node, | |||
vector<MatchExpression*>* out, | vector<MatchExpression*>* out, | |||
vector<MatchExpression*>* subnode sOut); | vector<MatchExpression*>* subnode sOut); | |||
/** | /** | |||
* Helper used by buildIndexedAnd and buildIndexedOr. | * Helper used by buildIndexedAnd and buildIndexedOr. | |||
* | * | |||
* The children of AND and OR nodes are sorted by the index that th e subtree rooted at | * The children of AND and OR nodes are sorted by the index that th e subtree rooted at | |||
End of changes. 3 change blocks. | ||||
5 lines changed or deleted | 5 lines changed or added | |||
ssl_options.h | ssl_options.h | |||
---|---|---|---|---|
skipping to change at line 18 | skipping to change at line 18 | |||
* | * | |||
* 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 implied. | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* 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 <vector> | ||||
#include "mongo/base/status.h" | #include "mongo/base/status.h" | |||
#include "mongo/client/export_macros.h" | #include "mongo/client/export_macros.h" | |||
#include "mongo/util/net/ssl_manager.h" | #include "mongo/util/net/ssl_manager.h" | |||
namespace mongo { | namespace mongo { | |||
namespace optionenvironment { | namespace optionenvironment { | |||
class OptionSection; | class OptionSection; | |||
class Environment; | class Environment; | |||
} // namespace optionenvironment | } // namespace optionenvironment | |||
namespace moe = mongo::optionenvironment; | namespace moe = mongo::optionenvironment; | |||
struct MONGO_CLIENT_API SSLGlobalParams { | struct MONGO_CLIENT_API SSLGlobalParams { | |||
enum Protocols { | ||||
TLS1_0, | ||||
TLS1_1, | ||||
TLS1_2 | ||||
}; | ||||
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 | |||
std::string sslCipherConfig; // --sslCipherConfig | std::string sslCipherConfig; // --sslCipherConfig | |||
std::vector<Protocols> sslDisabledProtocols; // --sslDisabledProtoc ols | ||||
bool sslWeakCertificateValidation; // --sslWeakCertificateValidatio n | bool sslWeakCertificateValidation; // --sslWeakCertificateValidatio n | |||
bool sslFIPSMode; // --sslFIPSMode | bool sslFIPSMode; // --sslFIPSMode | |||
bool sslAllowInvalidCertificates; // --sslAllowInvalidCertificates | bool sslAllowInvalidCertificates; // --sslAllowInvalidCertificates | |||
bool sslAllowInvalidHostnames; // --sslAllowInvalidHostnames | bool sslAllowInvalidHostnames; // --sslAllowInvalidHostnames | |||
SSLGlobalParams() { | SSLGlobalParams() { | |||
sslMode.store(SSLMode_disabled); | sslMode.store(SSLMode_disabled); | |||
} | } | |||
enum SSLModes { | enum SSLModes { | |||
End of changes. 3 change blocks. | ||||
0 lines changed or deleted | 8 lines changed or added | |||
sync_source_feedback.h | sync_source_feedback.h | |||
---|---|---|---|---|
skipping to change at line 61 | skipping to change at line 61 | |||
/// Adds an entry to _members for a secondary that has connected to us. | /// Adds an entry to _members for a secondary that has connected to us. | |||
void associateMember(const BSONObj& id, Member* member); | void associateMember(const BSONObj& id, Member* member); | |||
/// Ensures local.me is populated and populates it if not. | /// Ensures local.me is populated and populates it if not. | |||
void ensureMe(); | void ensureMe(); | |||
/// Passes handshake up the replication chain, upon receiving a han dshake. | /// Passes handshake up the replication chain, upon receiving a han dshake. | |||
void forwardSlaveHandshake(); | void forwardSlaveHandshake(); | |||
void updateSelfInMap(const OpTime& ot) { | void updateSelfInMap(const OpTime& ot) { | |||
updateMap(_me["_id"].OID(), ot); | updateMap(_me["_id"].OID(), ot, true); | |||
} | } | |||
/// Connect to sync target and create OplogReader if needed. | /// Connect to sync target and create OplogReader if needed. | |||
bool connect(const Member* target); | bool connect(const Member* target); | |||
void resetConnection() { | void resetConnection() { | |||
LOG(1) << "resetting connection in sync source feedback"; | LOG(1) << "resetting connection in sync source feedback"; | |||
_connection.reset(); | _connection.reset(); | |||
} | } | |||
skipping to change at line 87 | skipping to change at line 87 | |||
bool supportsUpdater() const { | bool supportsUpdater() const { | |||
// oplogReader will be NULL if new updater is supported | // oplogReader will be NULL if new updater is supported | |||
//boost::unique_lock<boost::mutex> lock(_mtx); | //boost::unique_lock<boost::mutex> lock(_mtx); | |||
return _supportsUpdater; | return _supportsUpdater; | |||
} | } | |||
/// Transfers information about a chained node's oplog position fro m downstream to upstream | /// Transfers information about a chained node's oplog position fro m downstream to upstream | |||
void percolate(const mongo::OID& rid, const OpTime& ot); | void percolate(const mongo::OID& rid, const OpTime& ot); | |||
/// Updates the _slaveMap to be forwarded to the sync target. | /// Updates the _slaveMap to be forwarded to the sync target. | |||
void updateMap(const mongo::OID& rid, const OpTime& ot); | void updateMap(const mongo::OID& rid, const OpTime& ot, bool self=f alse); | |||
std::string name() const { return "SyncSourceFeedbackThread"; } | std::string name() const { return "SyncSourceFeedbackThread"; } | |||
/// Loops forever, passing updates when they are present. | /// Loops forever, passing updates when they are present. | |||
void run(); | void run(); | |||
/* The below methods just fall through to OplogReader and are only used when our sync target | /* The below methods just fall through to OplogReader and are only used when our sync target | |||
* does not support the update command. | * does not support the update command. | |||
*/ | */ | |||
bool connectOplogReader(const std::string& hostName) { | bool connectOplogReader(const std::string& hostName) { | |||
End of changes. 2 change blocks. | ||||
2 lines changed or deleted | 2 lines changed or added | |||
ucp.h | ucp.h | |||
---|---|---|---|---|
/************************************************* | /************************************************* | |||
* Unicode Property Table handler * | * Unicode Property Table handler * | |||
*************************************************/ | *************************************************/ | |||
#ifndef _UCP_H | #ifndef _UCP_H | |||
#define _UCP_H | #define _UCP_H | |||
/* This file contains definitions of the property values that are returned by | /* This file contains definitions of the property values that are returned by | |||
the UCD access macros. New values that are added for new releases of Unicod e | the UCD access macros. New values that are added for new releases of Unicod e | |||
should always be at the end of each enum, for backwards compatibility. | should always be at the end of each enum, for backwards compatibility. */ | |||
IMPORTANT: Note also that the specific numeric values of the enums have to | ||||
be | ||||
the same as the values that are generated by the maint/MultiStage2.py scrip | ||||
t, | ||||
where the equivalent property descriptive names are listed in vectors. | ||||
ALSO: The specific values of the first two enums are assumed for the table | ||||
called catposstab in pcre_compile.c. */ | ||||
/* These are the general character categories. */ | /* These are the general character categories. */ | |||
enum { | enum { | |||
ucp_C, /* Other */ | ucp_C, /* Other */ | |||
ucp_L, /* Letter */ | ucp_L, /* Letter */ | |||
ucp_M, /* Mark */ | ucp_M, /* Mark */ | |||
ucp_N, /* Number */ | ucp_N, /* Number */ | |||
ucp_P, /* Punctuation */ | ucp_P, /* Punctuation */ | |||
ucp_S, /* Symbol */ | ucp_S, /* Symbol */ | |||
ucp_Z /* Separator */ | ucp_Z /* Separator */ | |||
}; | }; | |||
/* These are the particular character categories. */ | /* These are the particular character types. */ | |||
enum { | enum { | |||
ucp_Cc, /* Control */ | ucp_Cc, /* Control */ | |||
ucp_Cf, /* Format */ | ucp_Cf, /* Format */ | |||
ucp_Cn, /* Unassigned */ | ucp_Cn, /* Unassigned */ | |||
ucp_Co, /* Private use */ | ucp_Co, /* Private use */ | |||
ucp_Cs, /* Surrogate */ | ucp_Cs, /* Surrogate */ | |||
ucp_Ll, /* Lower case letter */ | ucp_Ll, /* Lower case letter */ | |||
ucp_Lm, /* Modifier letter */ | ucp_Lm, /* Modifier letter */ | |||
ucp_Lo, /* Other letter */ | ucp_Lo, /* Other letter */ | |||
skipping to change at line 66 | skipping to change at line 59 | |||
ucp_Ps, /* Open punctuation */ | ucp_Ps, /* Open punctuation */ | |||
ucp_Sc, /* Currency symbol */ | ucp_Sc, /* Currency symbol */ | |||
ucp_Sk, /* Modifier symbol */ | ucp_Sk, /* Modifier symbol */ | |||
ucp_Sm, /* Mathematical symbol */ | ucp_Sm, /* Mathematical symbol */ | |||
ucp_So, /* Other symbol */ | ucp_So, /* Other symbol */ | |||
ucp_Zl, /* Line separator */ | ucp_Zl, /* Line separator */ | |||
ucp_Zp, /* Paragraph separator */ | ucp_Zp, /* Paragraph separator */ | |||
ucp_Zs /* Space separator */ | ucp_Zs /* Space separator */ | |||
}; | }; | |||
/* These are grapheme break properties. Note that the code for processing t | ||||
hem | ||||
assumes that the values are less than 16. If more values are added that tak | ||||
e | ||||
the number to 16 or more, the code will have to be rewritten. */ | ||||
enum { | ||||
ucp_gbCR, /* 0 */ | ||||
ucp_gbLF, /* 1 */ | ||||
ucp_gbControl, /* 2 */ | ||||
ucp_gbExtend, /* 3 */ | ||||
ucp_gbPrepend, /* 4 */ | ||||
ucp_gbSpacingMark, /* 5 */ | ||||
ucp_gbL, /* 6 Hangul syllable type L */ | ||||
ucp_gbV, /* 7 Hangul syllable type V */ | ||||
ucp_gbT, /* 8 Hangul syllable type T */ | ||||
ucp_gbLV, /* 9 Hangul syllable type LV */ | ||||
ucp_gbLVT, /* 10 Hangul syllable type LVT */ | ||||
ucp_gbRegionalIndicator, /* 11 */ | ||||
ucp_gbOther /* 12 */ | ||||
}; | ||||
/* These are the script identifications. */ | /* These are the script identifications. */ | |||
enum { | enum { | |||
ucp_Arabic, | ucp_Arabic, | |||
ucp_Armenian, | ucp_Armenian, | |||
ucp_Bengali, | ucp_Bengali, | |||
ucp_Bopomofo, | ucp_Bopomofo, | |||
ucp_Braille, | ucp_Braille, | |||
ucp_Buginese, | ucp_Buginese, | |||
ucp_Buhid, | ucp_Buhid, | |||
skipping to change at line 187 | skipping to change at line 160 | |||
ucp_Lisu, | ucp_Lisu, | |||
ucp_Meetei_Mayek, | ucp_Meetei_Mayek, | |||
ucp_Old_South_Arabian, | ucp_Old_South_Arabian, | |||
ucp_Old_Turkic, | ucp_Old_Turkic, | |||
ucp_Samaritan, | ucp_Samaritan, | |||
ucp_Tai_Tham, | ucp_Tai_Tham, | |||
ucp_Tai_Viet, | ucp_Tai_Viet, | |||
/* New for Unicode 6.0.0: */ | /* New for Unicode 6.0.0: */ | |||
ucp_Batak, | ucp_Batak, | |||
ucp_Brahmi, | ucp_Brahmi, | |||
ucp_Mandaic, | ucp_Mandaic | |||
/* New for Unicode 6.1.0: */ | ||||
ucp_Chakma, | ||||
ucp_Meroitic_Cursive, | ||||
ucp_Meroitic_Hieroglyphs, | ||||
ucp_Miao, | ||||
ucp_Sharada, | ||||
ucp_Sora_Sompeng, | ||||
ucp_Takri, | ||||
/* New for Unicode 7.0.0: */ | ||||
ucp_Bassa_Vah, | ||||
ucp_Caucasian_Albanian, | ||||
ucp_Duployan, | ||||
ucp_Elbasan, | ||||
ucp_Grantha, | ||||
ucp_Khojki, | ||||
ucp_Khudawadi, | ||||
ucp_Linear_A, | ||||
ucp_Mahajani, | ||||
ucp_Manichaean, | ||||
ucp_Mende_Kikakui, | ||||
ucp_Modi, | ||||
ucp_Mro, | ||||
ucp_Nabataean, | ||||
ucp_Old_North_Arabian, | ||||
ucp_Old_Permic, | ||||
ucp_Pahawh_Hmong, | ||||
ucp_Palmyrene, | ||||
ucp_Psalter_Pahlavi, | ||||
ucp_Pau_Cin_Hau, | ||||
ucp_Siddham, | ||||
ucp_Tirhuta, | ||||
ucp_Warang_Citi | ||||
}; | }; | |||
#endif | #endif | |||
/* End of ucp.h */ | /* End of ucp.h */ | |||
End of changes. 4 change blocks. | ||||
66 lines changed or deleted | 3 lines changed or added | |||
user_cache_invalidator_job.h | user_cache_invalidator_job.h | |||
---|---|---|---|---|
skipping to change at line 16 | skipping to change at line 16 | |||
* | * | |||
* http://www.apache.org/licenses/LICENSE-2.0 | * http://www.apache.org/licenses/LICENSE-2.0 | |||
* | * | |||
* 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. | |||
*/ | */ | |||
#include "mongo/bson/oid.h" | ||||
#include "mongo/util/background.h" | #include "mongo/util/background.h" | |||
#include <string> | #include <string> | |||
namespace mongo { | namespace mongo { | |||
class AuthorizationManager; | class AuthorizationManager; | |||
// Background job that periodically causes the AuthorizationManager to | /** | |||
throw out its in-memory | * Background job that runs only in mongos and periodically checks in w | |||
// cache of User objects (which contains the users' credentials, roles, | ith the config servers | |||
privileges, etc). | * to determine whether any authorization information has changed, and | |||
if so causes the | ||||
* AuthorizationManager to throw out its in-memory cache of User object | ||||
s (which contains the | ||||
* users' credentials, roles, privileges, etc). | ||||
*/ | ||||
class UserCacheInvalidator : public BackgroundJob { | class UserCacheInvalidator : public BackgroundJob { | |||
public: | public: | |||
UserCacheInvalidator(AuthorizationManager* authzManager) : _authzMa nager(authzManager) {} | explicit UserCacheInvalidator(AuthorizationManager* authzManager); | |||
protected: | protected: | |||
virtual std::string name() const; | virtual std::string name() const; | |||
virtual void run(); | virtual void run(); | |||
private: | private: | |||
AuthorizationManager* _authzManager; | AuthorizationManager* _authzManager; | |||
OID _previousCacheGeneration; | ||||
}; | }; | |||
} // namespace mongo | } // namespace mongo | |||
End of changes. 4 change blocks. | ||||
5 lines changed or deleted | 12 lines changed or added | |||