summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/mmap_v1/data_file.cpp
diff options
context:
space:
mode:
authorEliot Horowitz <eliot@10gen.com>2014-06-16 17:39:45 -0400
committerEliot Horowitz <eliot@10gen.com>2014-06-18 13:54:54 -0400
commite11156fe20421c0f09758cfc6355964159640616 (patch)
tree65b7149c2aebaaea3c27989499de52c8913d9a7f /src/mongo/db/storage/mmap_v1/data_file.cpp
parentcce92a4d63103eb924a81088ad686bf4052a08b2 (diff)
downloadmongo-e11156fe20421c0f09758cfc6355964159640616.tar.gz
SERVER-13635: remove all non storage callers to flushAll
Diffstat (limited to 'src/mongo/db/storage/mmap_v1/data_file.cpp')
-rw-r--r--src/mongo/db/storage/mmap_v1/data_file.cpp232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/mongo/db/storage/mmap_v1/data_file.cpp b/src/mongo/db/storage/mmap_v1/data_file.cpp
new file mode 100644
index 00000000000..044f2ef3656
--- /dev/null
+++ b/src/mongo/db/storage/mmap_v1/data_file.cpp
@@ -0,0 +1,232 @@
+// data_file.cpp
+
+/**
+* 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 <http://www.gnu.org/licenses/>.
+*
+* 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.
+*/
+
+#include "mongo/pch.h"
+
+#include "mongo/db/storage/mmap_v1/data_file.h"
+
+#include <boost/filesystem/operations.hpp>
+
+#include "mongo/db/d_concurrency.h"
+#include "mongo/db/storage/mmap_v1/dur.h"
+#include "mongo/db/lockstate.h"
+#include "mongo/db/operation_context.h"
+#include "mongo/util/file_allocator.h"
+
+namespace mongo {
+
+ BOOST_STATIC_ASSERT( sizeof(DataFileHeader)-4 == 8192 );
+
+ static void data_file_check(void *_mb) {
+ if( sizeof(char *) == 4 )
+ uassert( 10084, "can't map file memory - mongo requires 64 bit build for larger datasets", _mb != 0);
+ else
+ uassert( 10085, "can't map file memory", _mb != 0);
+ }
+
+ int DataFile::maxSize() {
+ if ( sizeof( int* ) == 4 ) {
+ return 512 * 1024 * 1024;
+ }
+ else if (storageGlobalParams.smallfiles) {
+ return 0x7ff00000 >> 2;
+ }
+ else {
+ return 0x7ff00000;
+ }
+ }
+
+ NOINLINE_DECL void DataFile::badOfs2(int ofs) const {
+ uasserted(13441, str::stream() << "bad offset:" << ofs
+ << " accessing file: " << mmf.filename()
+ << ". See http://dochub.mongodb.org/core/data-recovery");
+ }
+
+ NOINLINE_DECL void DataFile::badOfs(int ofs) const {
+ uasserted(13440, str::stream() << "bad offset:" << ofs
+ << " accessing file: " << mmf.filename()
+ << ". See http://dochub.mongodb.org/core/data-recovery");
+ }
+
+ int DataFile::defaultSize( const char *filename ) const {
+ int size;
+ if ( fileNo <= 4 )
+ size = (64*1024*1024) << fileNo;
+ else
+ size = 0x7ff00000;
+ if (storageGlobalParams.smallfiles) {
+ size = size >> 2;
+ }
+ return size;
+ }
+
+ /** @return true if found and opened. if uninitialized (prealloc only) does not open. */
+ Status DataFile::openExisting( OperationContext* txn, const char *filename ) {
+ verify( _mb == 0 );
+ if( !boost::filesystem::exists(filename) )
+ return Status( ErrorCodes::InvalidPath, "DataFile::openExisting - file does not exist" );
+
+ if( !mmf.open(filename,false) ) {
+ return Status( ErrorCodes::InternalError, "DataFile::openExisting - mmf.open failed" );
+ }
+ _mb = mmf.getView(); verify(_mb);
+ unsigned long long sz = mmf.length();
+ verify( sz <= 0x7fffffff );
+ verify( sz % 4096 == 0 );
+ if (sz < 64*1024*1024 && !storageGlobalParams.smallfiles) {
+ if( sz >= 16*1024*1024 && sz % (1024*1024) == 0 ) {
+ log() << "info openExisting file size " << sz
+ << " but storageGlobalParams.smallfiles=false: "
+ << filename << endl;
+ }
+ else {
+ log() << "openExisting size " << sz << " less than minimum file size expectation "
+ << filename << endl;
+ verify(false);
+ }
+ }
+ data_file_check(_mb);
+ header()->checkUpgrade(txn);
+ return Status::OK();
+ }
+
+ void DataFile::open( OperationContext* txn,
+ const char *filename,
+ int minSize,
+ bool preallocateOnly ) {
+ long size = defaultSize( filename );
+ while ( size < minSize ) {
+ if ( size < maxSize() / 2 )
+ size *= 2;
+ else {
+ size = maxSize();
+ break;
+ }
+ }
+ if ( size > maxSize() )
+ size = maxSize();
+
+ verify(size >= 64*1024*1024 || storageGlobalParams.smallfiles);
+ verify( size % 4096 == 0 );
+
+ if ( preallocateOnly ) {
+ if (storageGlobalParams.prealloc) {
+ FileAllocator::get()->requestAllocation( filename, size );
+ }
+ return;
+ }
+
+ {
+ verify( _mb == 0 );
+ unsigned long long sz = size;
+ if( mmf.create(filename, sz, false) )
+ _mb = mmf.getView();
+ verify( sz <= 0x7fffffff );
+ size = (int) sz;
+ }
+ data_file_check(_mb);
+ header()->init(txn, fileNo, size, filename);
+ }
+
+ void DataFile::flush( bool sync ) {
+ mmf.flush( sync );
+ }
+
+ DiskLoc DataFile::allocExtentArea( OperationContext* txn, int size ) {
+
+ massert( 10357, "shutdown in progress", !inShutdown() );
+ massert( 10359, "header==0 on new extent: 32 bit mmap space exceeded?", header() ); // null if file open failed
+
+ verify( size <= header()->unusedLength );
+
+ int offset = header()->unused.getOfs();
+
+ DataFileHeader *h = header();
+ *txn->recoveryUnit()->writing(&h->unused) = DiskLoc( fileNo, offset + size );
+ txn->recoveryUnit()->writingInt(h->unusedLength) = h->unusedLength - size;
+
+ return DiskLoc( fileNo, offset );
+ }
+
+ // -------------------------------------------------------------------------------
+
+ void DataFileHeader::init(OperationContext* txn, int fileno, int filelength, const char* filename) {
+ if ( uninitialized() ) {
+ DEV log() << "datafileheader::init initializing " << filename << " n:" << fileno << endl;
+ if( !(filelength > 32768 ) ) {
+ massert(13640, str::stream() << "DataFileHeader looks corrupt at file open filelength:" << filelength << " fileno:" << fileno, false);
+ }
+
+ {
+ // "something" is too vague, but we checked for the right db to be locked higher up the call stack
+ if (!txn->lockState()->isWriteLocked()) {
+ txn->lockState()->dump();
+ log() << "*** TEMP NOT INITIALIZING FILE " << filename << ", not in a write lock." << endl;
+ log() << "temp bypass until more elaborate change - case that is manifesting is benign anyway" << endl;
+ return;
+ /**
+ log() << "ERROR can't create outside a write lock" << endl;
+ printStackTrace();
+ ::abort();
+ **/
+ }
+ }
+
+ // The writes done in this function must not be rolled back. If the containing
+ // UnitOfWork rolls back it should roll back to the state *after* these writes. This
+ // will leave the file empty, but available for future use. That is why we go directly
+ // to the global dur dirty list rather than going through the OperationContext.
+ getDur().createdFile(filename, filelength);
+ 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->unused.set( fileno, HeaderSize );
+ verify( (data-(char*)this) == HeaderSize );
+ h->unusedLength = fileLength - HeaderSize - 16;
+ h->freeListStart.Null();
+ h->freeListEnd.Null();
+ }
+ else {
+ checkUpgrade(txn);
+ }
+ }
+
+ void DataFileHeader::checkUpgrade(OperationContext* txn) {
+ if ( freeListStart == minDiskLoc ) {
+ // we are upgrading from 2.4 to 2.6
+ invariant( freeListEnd == minDiskLoc ); // both start and end should be (0,0) or real
+ *txn->recoveryUnit()->writing( &freeListStart ) = DiskLoc();
+ *txn->recoveryUnit()->writing( &freeListEnd ) = DiskLoc();
+ }
+ }
+
+}