summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/structure/record_store_v1_base.cpp22
-rw-r--r--src/mongo/db/structure/record_store_v1_simple_test.cpp32
2 files changed, 40 insertions, 14 deletions
diff --git a/src/mongo/db/structure/record_store_v1_base.cpp b/src/mongo/db/structure/record_store_v1_base.cpp
index fa767bfb39d..b3c844687e2 100644
--- a/src/mongo/db/structure/record_store_v1_base.cpp
+++ b/src/mongo/db/structure/record_store_v1_base.cpp
@@ -568,12 +568,9 @@ namespace mongo {
}
if ( r->lengthWithHeaders() ==
- quantizePowerOf2AllocationSpace( r->lengthWithHeaders() - 1 ) ) {
+ quantizePowerOf2AllocationSpace( r->lengthWithHeaders() ) ) {
// Count the number of records having a size consistent with the
// quantizePowerOf2AllocationSpace quantization implementation.
- // Because of SERVER-8311, power of 2 quantization is not idempotent and
- // r->lengthWithHeaders() - 1 must be checked instead of the record
- // length itself.
++nPowerOf2QuantizedSize;
}
@@ -792,13 +789,18 @@ namespace mongo {
}
int RecordStoreV1Base::quantizePowerOf2AllocationSpace(int allocSize) {
- int allocationSize = bucketSizes[ bucket( allocSize ) ];
- if ( allocationSize == bucketSizes[MaxBucket] ) {
- // if we get here, it means we're allocating more than 4mb, so round
- // to the nearest megabyte
- allocationSize = 1 + ( allocSize | ( ( 1 << 20 ) - 1 ) );
+ for ( int i = 0; i < MaxBucket; i++ ) { // skips the largest (16MB) bucket
+ if ( bucketSizes[i] >= allocSize ) {
+ // Return the size of the first bucket sized >= the requested size.
+ return bucketSizes[i];
+ }
}
- return allocationSize;
+
+ // if we get here, it means we're allocating more than 4mb, so round up
+ // to the nearest megabyte >= allocSize
+ const int MB = 1024*1024;
+ invariant(allocSize > 4*MB);
+ return (allocSize + (MB - 1)) & ~(MB - 1); // round up to MB alignment
}
int RecordStoreV1Base::bucket(int size) {
diff --git a/src/mongo/db/structure/record_store_v1_simple_test.cpp b/src/mongo/db/structure/record_store_v1_simple_test.cpp
index 79578272876..c515cde0d8d 100644
--- a/src/mongo/db/structure/record_store_v1_simple_test.cpp
+++ b/src/mongo/db/structure/record_store_v1_simple_test.cpp
@@ -88,6 +88,32 @@ namespace {
}
/**
+ * For buckets up to 4MB powerOf2 allocation should round up to next power of 2. It should be
+ * return the input unmodified if it is already a power of 2.
+ */
+ TEST( SimpleRecordStoreV1, quantizePowerOf2Small ) {
+ // only tests buckets <= 4MB. Higher buckets quatize to 1MB even with powerOf2
+ for (int bucket = 0; bucket < RecordStoreV1Base::MaxBucket; bucket++) {
+ const int size = RecordStoreV1Base::bucketSizes[bucket];
+ const int nextSize = RecordStoreV1Base::bucketSizes[bucket + 1];
+
+ // size - 1 is quantized to size.
+ ASSERT_EQUALS( size,
+ RecordStoreV1Base::quantizePowerOf2AllocationSpace( size - 1 ) );
+
+ // size is quantized to size.
+ ASSERT_EQUALS( size,
+ RecordStoreV1Base::quantizePowerOf2AllocationSpace( size ) );
+
+ // size + 1 is quantized to nextSize (unless > 4MB which is covered by next test)
+ if (size < 4*1024*1024) {
+ ASSERT_EQUALS( nextSize,
+ RecordStoreV1Base::quantizePowerOf2AllocationSpace( size + 1 ) );
+ }
+ }
+ }
+
+ /**
* Within the largest bucket, quantizePowerOf2AllocationSpace quantizes to the nearest
* megabyte boundary.
*/
@@ -102,10 +128,8 @@ namespace {
ASSERT_EQUALS( iSize,
RecordStoreV1Base::quantizePowerOf2AllocationSpace( iSize - 1 ) );
- // iSize is quantized to iSize + 1mb.
- // Descriptive rather than normative test.
- // SERVER-8311 A pre quantized size is rounded to the next quantum level.
- ASSERT_EQUALS( iSize + 0x100000,
+ // iSize is quantized to iSize.
+ ASSERT_EQUALS( iSize,
RecordStoreV1Base::quantizePowerOf2AllocationSpace( iSize ) );
// iSize + 1 is quantized to iSize + 1mb.