From 86bd3e6a64bf10a44d117587d340e6d8da1d211f Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Sat, 19 Mar 2016 16:28:34 -0400 Subject: [PATCH] CXX-650 Backport server r2.6.11..r2.6.12 changes Server SHAs picked into this commit: 52ae817 ce9d96d c980c02 ec270ef aa5a2f5 1290ac9 d73c92b --- SConstruct | 18 ++++++++- src/mongo/base/error_codes.err | 1 + src/mongo/platform/random.cpp | 26 ++++++------ src/mongo/platform/random.h | 20 ++++++---- src/mongo/platform/random_test.cpp | 63 ++++++++++++++++++++++++++++++ src/mongo/util/version.cpp | 2 +- 6 files changed, 110 insertions(+), 20 deletions(-) diff --git a/SConstruct b/SConstruct index 884e7688b3..dcac57dbda 100644 --- a/SConstruct +++ b/SConstruct @@ -445,7 +445,17 @@ usePCH = has_option( "usePCH" ) justClientLib = (COMMAND_LINE_TARGETS == ['mongoclient']) -env = Environment( BUILD_DIR=variantDir, +# On some branches, we honor several scons Variables on the command +# line. Those don't exist on 2.6, but it is easy to get in the habit +# of using them. By default SCons silently ignores them, which can be +# very confusing if you say 'scons CC=clang' on the v2.6 branch, for +# instance. We create an empty Variables object here and feed it to +# the Environment constructor so that we can ask for any unknown +# variables (and all should be), below. +env_vars = Variables() + +env = Environment( variables=env_vars, + BUILD_DIR=variantDir, DIST_ARCHIVE_SUFFIX='.tgz', EXTRAPATH=get_option("extrapath"), MODULE_BANNERS=[], @@ -466,6 +476,12 @@ env = Environment( BUILD_DIR=variantDir, CONFIGURELOG = '#' + scons_data_dir + '/config.log' ) +# Report any unknown variables as an error. +unknown_vars = env_vars.UnknownVariables() +if unknown_vars: + print "Unknown variables specified: {0}".format(", ".join(unknown_vars.keys())) + Exit(1) + if has_option("cache"): EnsureSConsVersion( 2, 3, 0 ) if has_option("release"): diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index ac900d23d2..d45ff64dd3 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -87,6 +87,7 @@ error_code("IndexOptionsConflict", 85 ) error_code("IndexKeySpecsConflict", 86 ) error_code("OutdatedClient", 101) error_code("IncompatibleAuditMetadata", 102) +error_code("CappedPositionLost", 103) # Non-sequential error codes (for compatibility only) error_code("NetworkTimeout", 89) diff --git a/src/mongo/platform/random.cpp b/src/mongo/platform/random.cpp index d1a620d6a7..10c197f6d6 100644 --- a/src/mongo/platform/random.cpp +++ b/src/mongo/platform/random.cpp @@ -35,8 +35,8 @@ namespace mongo { // ---- PseudoRandom ----- - int32_t PseudoRandom::nextInt32() { - int32_t t = _x ^ (_x << 11); + uint32_t PseudoRandom::nextUInt32() { + uint32_t t = _x ^ (_x << 11); _x = _y; _y = _z; _z = _w; @@ -44,13 +44,13 @@ namespace mongo { } namespace { - const int32_t default_y = 362436069; - const int32_t default_z = 521288629; - const int32_t default_w = 88675123; + const uint32_t default_y = 362436069; + const uint32_t default_z = 521288629; + const uint32_t default_w = 88675123; } PseudoRandom::PseudoRandom( int32_t seed ) { - _x = seed; + _x = static_cast(seed); _y = default_y; _z = default_z; _w = default_w; @@ -58,7 +58,7 @@ namespace mongo { PseudoRandom::PseudoRandom( uint32_t seed ) { - _x = static_cast(seed); + _x = seed; _y = default_y; _z = default_z; _w = default_w; @@ -66,8 +66,8 @@ namespace mongo { PseudoRandom::PseudoRandom( int64_t seed ) { - int32_t high = seed >> 32; - int32_t low = seed & 0xFFFFFFFF; + uint32_t high = seed >> 32; + uint32_t low = seed & 0xFFFFFFFF; _x = high ^ low; _y = default_y; @@ -75,9 +75,13 @@ namespace mongo { _w = default_w; } + int32_t PseudoRandom::nextInt32() { + return nextUInt32(); + } + int64_t PseudoRandom::nextInt64() { - int64_t a = nextInt32(); - int64_t b = nextInt32(); + uint64_t a = nextUInt32(); + uint64_t b = nextUInt32(); return ( a << 32 ) | b; } diff --git a/src/mongo/platform/random.h b/src/mongo/platform/random.h index 823ea6a08d..da52d05248 100644 --- a/src/mongo/platform/random.h +++ b/src/mongo/platform/random.h @@ -39,17 +39,21 @@ namespace mongo { /** * @return a number between 0 and max */ - int32_t nextInt32( int32_t max ) { return nextInt32() % max; } + int32_t nextInt32( int32_t max ) { + return static_cast(nextInt32()) % static_cast(max); + } /** * @return a number between 0 and max */ - int64_t nextInt64( int64_t max ) { return nextInt64() % max; } + int64_t nextInt64( int64_t max ) { + return static_cast(nextInt64()) % static_cast(max); + } /** * @return a number between 0 and max * - * This makes PsuedoRandom instances passable as the third argument to std::random_shuffle + * This makes PseudoRandom instances passable as the third argument to std::random_shuffle */ intptr_t operator()(intptr_t max) { if (sizeof(intptr_t) == 4) @@ -58,10 +62,12 @@ namespace mongo { } private: - int32_t _x; - int32_t _y; - int32_t _z; - int32_t _w; + uint32_t nextUInt32(); + + uint32_t _x; + uint32_t _y; + uint32_t _z; + uint32_t _w; }; /** diff --git a/src/mongo/platform/random_test.cpp b/src/mongo/platform/random_test.cpp index 1f93e78f31..e9f3e6dac9 100644 --- a/src/mongo/platform/random_test.cpp +++ b/src/mongo/platform/random_test.cpp @@ -17,6 +17,7 @@ */ #include +#include #include "mongo/platform/random.h" @@ -86,6 +87,68 @@ namespace mongo { ASSERT_EQUALS( 100U, s.size() ); } + TEST(RandomTest, NextInt32SanityCheck) { + // Generate 1000 int32s and assert that each bit is set between 40% and 60% of the time. + // This is a bare minimum sanity check, not an attempt to ensure quality random numbers. + + PseudoRandom a(11); + std::vector nums; + for (int i = 0; i < 1000; i++) { + nums.push_back(a.nextInt32()); + } + + for (int bit = 0; bit < 32; bit++) { + int onesCount = 0; + for (size_t i=0; i < nums.size(); i++) { + bool isSet = (nums[i] >> bit) & 1; + if (isSet) + onesCount++; + } + + ASSERT_FALSE(onesCount < 400 || onesCount > 600); + } + } + + TEST(RandomTest, NextInt64SanityCheck) { + // Generate 1000 int64s and assert that each bit is set between 40% and 60% of the time. + // This is a bare minimum sanity check, not an attempt to ensure quality random numbers. + + PseudoRandom a(11); + std::vector nums; + for (int i = 0; i < 1000; i++) { + nums.push_back(a.nextInt64()); + } + + for (int bit = 0; bit < 64; bit++) { + int onesCount = 0; + for (size_t i=0; i < nums.size(); i++) { + bool isSet = (nums[i] >> bit) & 1; + if (isSet) + onesCount++; + } + + ASSERT_FALSE(onesCount < 400 || onesCount > 600); + } + } + + TEST(RandomTest, NextInt32InRange) { + PseudoRandom a(11); + for (int i = 0; i < 1000; i++) { + int32_t res = a.nextInt32(10); + ASSERT_GREATER_THAN_OR_EQUALS(res, 0); + ASSERT_LESS_THAN(res, 10); + } + } + + TEST(RandomTest, NextInt64InRange) { + PseudoRandom a(11); + for (int i = 0; i < 1000; i++) { + int64_t res = a.nextInt64(10); + ASSERT_GREATER_THAN_OR_EQUALS(res, 0); + ASSERT_LESS_THAN(res, 10); + } + } + TEST( RandomTest, Secure1 ) { SecureRandom* a = SecureRandom::create(); diff --git a/src/mongo/util/version.cpp b/src/mongo/util/version.cpp index 54a166ddad..3f7b648026 100644 --- a/src/mongo/util/version.cpp +++ b/src/mongo/util/version.cpp @@ -31,7 +31,7 @@ namespace mongo { * 1.2.3-rc4-pre- * If you really need to do something else you'll need to fix _versionArray() */ - const char versionString[] = "2.6.11"; + const char versionString[] = "2.6.12"; // See unit test for example outputs BSONArray toVersionArray(const char* version){