0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00
mongodb/util/mmap.h
Mathias Stearn dfa0c41aa1 Prevent calls to pure virtual functions in MongoFile SERVER-988
The issue was that during construction and destruction an object's vtable
points to the current type rather than the most derived type. ~MongoFile() tried
to take a lock, but the function holding the lock tried to use the object,
calling either the close() or flush() virtual methods. The solution was to move
the call that needed the lock to the most derived class's destructor. The
easiest way to increase the probability of this crash is by using --syncdelay 1.
2010-04-08 19:57:48 -04:00

130 lines
3.5 KiB
C++

// mmap.h
/* Copyright 2009 10gen Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
namespace mongo {
/* the administrative-ish stuff here */
class MongoFile {
protected:
virtual void close() = 0;
virtual void flush(bool sync) = 0;
void created(); /* subclass must call after create */
void destroyed(); /* subclass must call in destructor */
public:
virtual long length() = 0;
enum Options {
SEQUENTIAL = 1 // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on windows
};
virtual ~MongoFile() {}
static int flushAll( bool sync ); // returns n flushed
static long long totalMappedLength();
static void closeAllFiles( stringstream &message );
/* can be "overriden" if necessary */
static bool exists(boost::filesystem::path p) {
return boost::filesystem::exists(p);
}
};
class MFTemplate : public MongoFile {
protected:
virtual void close();
virtual void flush(bool sync);
public:
virtual long length();
class Pointer {
public:
void* at(int offset, int len);
void grow(int offset, int len);
bool isNull() const;
};
Pointer map( const char *filename );
Pointer map(const char *_filename, long &length, int options=0);
};
class MemoryMappedFile : public MongoFile {
public:
class Pointer {
char *_base;
public:
Pointer() : _base(0) { }
Pointer(void *p) : _base((char*) p) { }
void* at(int offset, int maxLen) { return _base + offset; }
void grow(int offset, int len) { /* no action required with mem mapped file */ }
bool isNull() const { return _base == 0; }
};
MemoryMappedFile();
~MemoryMappedFile() {
destroyed();
close();
}
void close();
// Throws exception if file doesn't exist. (dm may2010: not sure if this is always true?)
void* map( const char *filename );
/*Pointer pmap( const char *filename ) {
void *p = map(filename);
uassert(13077, "couldn't open/map file", p);
return Pointer(p);
}*/
/* Creates with length if DNE, otherwise uses existing file length,
passed length.
*/
void* map(const char *filename, long &length, int options = 0 );
void flush(bool sync);
/*void* viewOfs() {
return view;
}*/
long length() {
return len;
}
private:
static void updateLength( const char *filename, long &length );
HANDLE fd;
HANDLE maphandle;
void *view;
long len;
};
void printMemInfo( const char * where );
#include "ramstore.h"
//#define _RAMSTORE
#if defined(_RAMSTORE)
typedef RamStoreFile MMF;
#else
typedef MemoryMappedFile MMF;
#endif
} // namespace mongo