From 7e7439bab78da9c993fcf566e4ea8d5c0570ad8d Mon Sep 17 00:00:00 2001 From: Mathias Stearn Date: Tue, 23 Sep 2014 17:09:50 -0400 Subject: SERVER-15319 Bump file versions for 2.8-style freelist --- src/mongo/db/db.cpp | 1 - src/mongo/db/index_names.h | 4 +- src/mongo/db/pdfile_version.h | 43 ------------- src/mongo/db/storage/mmap_v1/data_file.cpp | 3 +- src/mongo/db/storage/mmap_v1/data_file.h | 74 ++++++++++++++++++---- .../mmap_v1/mmap_v1_database_catalog_entry.cpp | 44 ++++++------- .../db/storage/mmap_v1/mmap_v1_extent_manager.cpp | 21 ++---- .../db/storage/mmap_v1/mmap_v1_extent_manager.h | 5 +- 8 files changed, 97 insertions(+), 98 deletions(-) delete mode 100644 src/mongo/db/pdfile_version.h (limited to 'src/mongo/db') diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index f2c64765098..2f82a287043 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -65,7 +65,6 @@ #include "mongo/db/log_process_details.h" #include "mongo/db/mongod_options.h" #include "mongo/db/operation_context_impl.h" -#include "mongo/db/pdfile_version.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/range_deleter_service.h" #include "mongo/db/repl/repl_coordinator_global.h" diff --git a/src/mongo/db/index_names.h b/src/mongo/db/index_names.h index 658ddd8459b..728906ed701 100644 --- a/src/mongo/db/index_names.h +++ b/src/mongo/db/index_names.h @@ -71,8 +71,8 @@ namespace mongo { /** * True if is a regular (non-plugin) index or uses a plugin that existed before 2.4. - * These plugins are grandfathered in and allowed to exist in DBs with - * PDFILE_MINOR_VERSION_22_AND_OLDER + * These plugins are grandfathered in and allowed to exist in DBs where + * DataFileVersion::is24IndexClean() returns false. */ static bool existedBefore24(const std::string& name); diff --git a/src/mongo/db/pdfile_version.h b/src/mongo/db/pdfile_version.h deleted file mode 100644 index a83b24cf493..00000000000 --- a/src/mongo/db/pdfile_version.h +++ /dev/null @@ -1,43 +0,0 @@ -/** -* Copyright (C) 2013 10gen Inc. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License, version 3, -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see . -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects for -* all of the code used other than as permitted herein. If you modify file(s) -* with this exception, you may extend this exception to your 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 you delete this -* exception statement from all source files in the program, then also delete -* it in the license file. -*/ - -#pragma once - -namespace mongo { - - // pdfile versions - const int PDFILE_VERSION = 4; - const int PDFILE_VERSION_MINOR_22_AND_OLDER = 5; - const int PDFILE_VERSION_MINOR_24_AND_NEWER = 6; - - // For backward compatibility with versions before 2.4.0 all new DBs start - // with PDFILE_VERSION_MINOR_22_AND_OLDER and are converted when the first - // index using a new plugin is created. See the logic in - // IndexCatalog::_upgradeDatabaseMinorVersionIfNeeded for details - -} // namespace mongo diff --git a/src/mongo/db/storage/mmap_v1/data_file.cpp b/src/mongo/db/storage/mmap_v1/data_file.cpp index c08f00ece21..d8941c341fe 100644 --- a/src/mongo/db/storage/mmap_v1/data_file.cpp +++ b/src/mongo/db/storage/mmap_v1/data_file.cpp @@ -202,8 +202,7 @@ namespace mongo { verify( HeaderSize == 8192 ); DataFileHeader *h = getDur().writing(this); h->fileLength = filelength; - h->version = PDFILE_VERSION; - h->versionMinor = PDFILE_VERSION_MINOR_22_AND_OLDER; // All dbs start like this + h->version = DataFileVersion::defaultForNewFiles(); h->unused.set( fileno, HeaderSize ); verify( (data-(char*)this) == HeaderSize ); h->unusedLength = fileLength - HeaderSize - 16; diff --git a/src/mongo/db/storage/mmap_v1/data_file.h b/src/mongo/db/storage/mmap_v1/data_file.h index b8aa7f4f379..ce5f0b34549 100644 --- a/src/mongo/db/storage/mmap_v1/data_file.h +++ b/src/mongo/db/storage/mmap_v1/data_file.h @@ -31,7 +31,6 @@ #pragma once #include "mongo/db/diskloc.h" -#include "mongo/db/pdfile_version.h" #include "mongo/db/storage/mmap_v1/durable_mapped_file.h" namespace mongo { @@ -39,6 +38,67 @@ namespace mongo { class ExtentManager; class OperationContext; +#pragma pack(1) + class DataFileVersion { + public: + DataFileVersion(uint32_t major, uint32_t minor) :_major(major), _minor(minor) {} + + static DataFileVersion defaultForNewFiles() { + return DataFileVersion(kCurrentMajor, kIndexes24AndNewer + | kMayHave28Freelist + ); + } + + bool isCompatibleWithCurrentCode() const { + if (_major != kCurrentMajor) + return false; + + if (_minor & ~kUsedMinorFlagsMask) + return false; + + const uint32_t indexCleanliness = _minor & kIndexPluginMask; + if (indexCleanliness != kIndexes24AndNewer && indexCleanliness != kIndexes22AndOlder) + return false; + + // We are compatible with either setting of kMayHave28Freelist. + + return true; + } + + bool is24IndexClean() const { return (_minor & kIndexPluginMask) == kIndexes24AndNewer; } + void setIs24IndexClean() { _minor = ((_minor & ~kIndexPluginMask) | kIndexes24AndNewer); } + + bool mayHave28Freelist() const { return _minor & kMayHave28Freelist; } + void setMayHave28Freelist() { _minor |= kMayHave28Freelist; } + + uint32_t major() const { return _major; } + uint32_t minorRaw() const { return _minor; } + + private: + static const uint32_t kCurrentMajor = 4; + + // minor layout: + // first 4 bits - index plugin cleanliness. + // see IndexCatalog::_upgradeDatabaseMinorVersionIfNeeded for details + // 5th bit - 1 if started with 2.8-style freelist implementation (SERVER-14081) + // 6th through 31st bit - reserved and must be set to 0. + static const uint32_t kIndexPluginMask = 0xf; + static const uint32_t kIndexes22AndOlder = 5; + static const uint32_t kIndexes24AndNewer = 6; + + static const uint32_t kMayHave28Freelist = (1 << 4); + + // All set bits we know about are covered by this mask. + static const uint32_t kUsedMinorFlagsMask = 0x1f; + + uint32_t _major; + uint32_t _minor; + }; + + // Note: Intentionally not defining relational operators for DataFileVersion as there is no + // total ordering of all versions now that '_minor' is used as a bit vector. +#pragma pack() + /* a datafile - i.e. the "dbname.<#>" files : ---------------------- @@ -55,8 +115,7 @@ namespace mongo { #pragma pack(1) class DataFileHeader { public: - int version; - int versionMinor; + DataFileVersion version; int fileLength; DiskLoc unused; /* unused is the portion of the file that doesn't belong to any allocated extents. -1 = no more */ int unusedLength; @@ -68,14 +127,7 @@ namespace mongo { enum { HeaderSize = 8192 }; - // all of this should move up to the database level - bool isCurrentVersion() const { - return version == PDFILE_VERSION && ( versionMinor == PDFILE_VERSION_MINOR_22_AND_OLDER - || versionMinor == PDFILE_VERSION_MINOR_24_AND_NEWER - ); - } - - bool uninitialized() const { return version == 0; } + bool uninitialized() const { return version.major() == 0; } void init(OperationContext* txn, int fileno, int filelength, const char* filename); diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp index e219c5cf765..d9872b170b2 100644 --- a/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp +++ b/src/mongo/db/storage/mmap_v1/mmap_v1_database_catalog_entry.cpp @@ -43,12 +43,12 @@ #include "mongo/db/index/hash_access_method.h" #include "mongo/db/index/haystack_access_method.h" #include "mongo/db/index/s2_access_method.h" -#include "mongo/db/pdfile_version.h" #include "mongo/db/server_parameters.h" #include "mongo/db/storage/mmap_v1/btree/btree_interface.h" #include "mongo/db/storage/mmap_v1/catalog/namespace_details.h" #include "mongo/db/storage/mmap_v1/catalog/namespace_details_collection_entry.h" #include "mongo/db/storage/mmap_v1/catalog/namespace_details_rsv1_metadata.h" +#include "mongo/db/storage/mmap_v1/dur.h" #include "mongo/db/storage/mmap_v1/data_file.h" #include "mongo/db/storage/mmap_v1/dur_recovery_unit.h" #include "mongo/db/storage/mmap_v1/record_store_v1_capped.h" @@ -170,6 +170,13 @@ namespace mongo { } } } + + DataFileVersion version = _extentManager.getFileFormat(txn); + if (version.isCompatibleWithCurrentCode() && !version.mayHave28Freelist()) { + // Any DB that can be opened and written to gets this flag set. + version.setMayHave28Freelist(); + _extentManager.setFileFormat(txn, version); + } } wunit.commit(); @@ -435,13 +442,11 @@ namespace mongo { { - int major = 0; - int minor = 0; - _extentManager.getFileFormat( opCtx, &major, &minor ); + const DataFileVersion version = _extentManager.getFileFormat(opCtx); BSONObjBuilder dataFileVersion( output->subobjStart( "dataFileVersion" ) ); - dataFileVersion.append( "major", major ); - dataFileVersion.append( "minor", minor ); + dataFileVersion.append( "major", version.major() ); + dataFileVersion.append( "minor", version.minorRaw() ); dataFileVersion.done(); } } @@ -452,40 +457,33 @@ namespace mongo { if ( _extentManager.numFiles() == 0 ) return false; - int major = 0; - int minor = 0; - - _extentManager.getFileFormat( opCtx, &major, &minor ); + const DataFileVersion version = _extentManager.getFileFormat(opCtx); - invariant( major == PDFILE_VERSION ); + invariant(version.isCompatibleWithCurrentCode()); - return minor == PDFILE_VERSION_MINOR_22_AND_OLDER; + return !version.is24IndexClean(); } void MMAPV1DatabaseCatalogEntry::markIndexSafe24AndUp( OperationContext* opCtx ) { if ( _extentManager.numFiles() == 0 ) return; - int major = 0; - int minor = 0; + DataFileVersion version = _extentManager.getFileFormat(opCtx); - _extentManager.getFileFormat( opCtx, &major, &minor ); - - invariant( major == PDFILE_VERSION ); - - if ( minor == PDFILE_VERSION_MINOR_24_AND_NEWER ) - return; + invariant(version.isCompatibleWithCurrentCode()); - invariant( minor == PDFILE_VERSION_MINOR_22_AND_OLDER ); + if (version.is24IndexClean()) + return; // nothing to do - _extentManager.setFileFormat(opCtx, major, PDFILE_VERSION_MINOR_24_AND_NEWER); + version.setIs24IndexClean(); + _extentManager.setFileFormat(opCtx, version); } bool MMAPV1DatabaseCatalogEntry::currentFilesCompatible( OperationContext* opCtx ) const { if ( _extentManager.numFiles() == 0 ) return true; - return _extentManager.getOpenFile( 0 )->getHeader()->isCurrentVersion(); + return _extentManager.getOpenFile( 0 )->getHeader()->version.isCompatibleWithCurrentCode(); } void MMAPV1DatabaseCatalogEntry::getCollectionNamespaces( std::list* tofill ) const { diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp index f6d18f3090d..ccf903cf035 100644 --- a/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp +++ b/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.cpp @@ -563,27 +563,20 @@ namespace mongo { _size.store(n + 1); } - void MmapV1ExtentManager::getFileFormat( OperationContext* txn, int* major, int* minor ) const { + DataFileVersion MmapV1ExtentManager::getFileFormat(OperationContext* txn) const { if ( numFiles() == 0 ) - return; - const DataFile* df = _getOpenFile( 0 ); - *major = df->getHeader()->version; - *minor = df->getHeader()->versionMinor; - - if ( *major <= 0 || *major >= 100 || - *minor <= 0 || *minor >= 100 ) { - error() << "corrupt pdfile version? major: " << *major << " minor: " << *minor; - fassertFailed( 14026 ); - } + return DataFileVersion(0, 0); + + // We explicitly only look at the first file. + return _getOpenFile(0)->getHeader()->version; } - void MmapV1ExtentManager::setFileFormat(OperationContext* txn, int major, int minor) { + void MmapV1ExtentManager::setFileFormat(OperationContext* txn, DataFileVersion newVersion) { invariant(numFiles() > 0); DataFile* df = _getOpenFile(0); invariant(df); - txn->recoveryUnit()->writingInt(df->getHeader()->version) = major; - txn->recoveryUnit()->writingInt(df->getHeader()->versionMinor) = minor; + *txn->recoveryUnit()->writing(&df->getHeader()->version) = newVersion; } } diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.h b/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.h index e1857db726c..61d2f1cfcb7 100644 --- a/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.h +++ b/src/mongo/db/storage/mmap_v1/mmap_v1_extent_manager.h @@ -45,6 +45,7 @@ namespace mongo { class DataFile; + class DataFileVersion; class Record; class OperationContext; @@ -142,8 +143,8 @@ namespace mongo { /** * Not thread safe, requires a database exclusive lock */ - void getFileFormat(OperationContext* txn, int* major, int* minor) const; - void setFileFormat(OperationContext* txn, int major, int minor); + DataFileVersion getFileFormat(OperationContext* txn) const; + void setFileFormat(OperationContext* txn, DataFileVersion newVersion); const DataFile* getOpenFile( int n ) const { return _getOpenFile( n ); } -- cgit v1.2.1