Files
mongo/db/mongommf.cpp

168 lines
5.3 KiB
C++
Raw Normal View History

2010-10-01 16:14:36 -04:00
// @file mongommf.cpp
/**
* Copyright (C) 2010 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/>.
*/
/* this module adds some of our layers atop memory mapped files - specifically our handling of private views & such
if you don't care about journaling/durability (temp sort files & such) use MemoryMappedFile class, not this.
*/
#include "pch.h"
#include "mongommf.h"
2010-11-14 22:28:04 -05:00
#include "../util/mongoutils/str.h"
2010-10-01 16:14:36 -04:00
2010-11-14 22:28:04 -05:00
using namespace mongoutils;
2010-10-01 16:14:36 -04:00
2010-11-14 22:28:04 -05:00
namespace mongo {
2010-11-13 17:42:41 -05:00
2010-11-14 22:28:04 -05:00
MongoMMF* PointerToMMF::_find(void *p, /*out*/ size_t& ofs) {
std::map< void*, MongoMMF* >::iterator i = _views.upper_bound(((char *)p)+1);
i--;
bool ok = i != _views.end();
if( ok ) {
MongoMMF *mmf = i->second;
assert( mmf );
size_t o = ((char *)p) - ((char*)i->first);
if( o < mmf->length() ) {
ofs = o;
return mmf;
2010-11-13 17:42:41 -05:00
}
}
2010-11-14 22:28:04 -05:00
return 0;
}
2010-11-13 17:42:41 -05:00
2010-11-14 22:28:04 -05:00
/** find associated MMF object for a given pointer.
threadsafe
@param ofs out returns offset into the view of the pointer, if found.
@return the MongoMMF to which this pointer belongs. null if not found.
*/
MongoMMF* PointerToMMF::find(void *p, /*out*/ size_t& ofs) {
mutex::scoped_lock lk(_m);
return _find(p, ofs);
}
2010-11-13 17:42:41 -05:00
2010-11-14 22:28:04 -05:00
PointerToMMF privateViews;
2010-11-13 17:42:41 -05:00
static PointerToMMF ourReadViews; /// _DEBUG build use only (other than existance)
2010-10-04 14:02:52 -04:00
/*static*/ void* MongoMMF::switchToPrivateView(void *readonly_ptr) {
2010-10-01 16:14:36 -04:00
assert( durable );
assert( debug );
2010-11-13 17:42:41 -05:00
void *p = readonly_ptr;
2010-10-01 16:14:36 -04:00
2010-11-13 17:42:41 -05:00
{
2010-11-13 18:32:41 -05:00
size_t ofs=0;
2010-11-13 17:42:41 -05:00
MongoMMF *mmf = ourReadViews.find(p, ofs);
if( mmf ) {
2010-11-04 17:43:02 -04:00
return ((char *)mmf->_view_private) + ofs;
2010-10-01 16:14:36 -04:00
}
}
2010-11-13 17:42:41 -05:00
{
2010-11-13 18:32:41 -05:00
size_t ofs=0;
2010-11-14 22:28:04 -05:00
MongoMMF *mmf = privateViews.find(p, ofs);
2010-11-13 17:42:41 -05:00
if( mmf ) {
log() << "dur: perf warning p=" << p << " is already in the writable view of " << mmf->filename() << endl;
2010-10-01 16:14:36 -04:00
return p;
}
}
2010-11-13 17:42:41 -05:00
// did you call writing() with a pointer that isn't into a datafile?
log() << "error switchToPrivateView " << p << endl;
return p;
2010-10-01 16:14:36 -04:00
}
2010-10-04 14:02:52 -04:00
2010-11-04 17:43:02 -04:00
/* switch to _view_write. normally, this is a bad idea since your changes will not
show up in _view_private if there have been changes there; thus the leading underscore
2010-10-04 15:02:15 -04:00
as a tad of a "warning". but useful when done with some care, such as during
initialization.
2010-10-04 14:02:52 -04:00
*/
2010-10-04 15:02:15 -04:00
/*static*/ void* MongoMMF::_switchToWritableView(void *p) {
2010-10-04 14:02:52 -04:00
RARELY log() << "todo dur not done switchtowritable" << endl;
2010-11-13 17:42:41 -05:00
if( debug )
return switchToPrivateView(p);
2010-10-04 14:02:52 -04:00
return p;
}
2010-10-01 16:14:36 -04:00
2010-11-14 22:28:04 -05:00
void MongoMMF::setPath(string f) {
string suffix;
bool ok = str::rSplitOn(f, '.', _filePath, suffix);
uassert(13520, str::stream() << "MongoMMF only supports filenames in a certain format " << f, ok);
if( suffix == "ns" )
_fileSuffixNo = -1;
else
_fileSuffixNo = (int) str::toUnsigned(suffix);
}
2010-10-13 13:06:49 -04:00
bool MongoMMF::open(string fname, bool sequentialHint) {
2010-11-14 22:28:04 -05:00
setPath(fname);
2010-11-04 17:43:02 -04:00
_view_write = mapWithOptions(fname.c_str(), sequentialHint ? SEQUENTIAL : 0);
2010-11-16 16:27:26 -05:00
return finishOpening();
2010-10-01 16:14:36 -04:00
}
2010-10-13 13:06:49 -04:00
bool MongoMMF::create(string fname, unsigned long long& len, bool sequentialHint) {
2010-11-14 22:28:04 -05:00
setPath(fname);
2010-11-04 17:43:02 -04:00
_view_write = map(fname.c_str(), len, sequentialHint ? SEQUENTIAL : 0);
2010-11-16 16:27:26 -05:00
return finishOpening();
}
bool MongoMMF::finishOpening() {
2010-11-04 17:43:02 -04:00
if( _view_write ) {
2010-10-01 16:14:36 -04:00
if( durable ) {
2010-11-16 16:40:56 -05:00
_view_private = createPrivateMap();
2010-11-14 22:28:04 -05:00
privateViews.add(_view_private, this);
2010-11-13 17:42:41 -05:00
if( debug ) {
_view_readonly = MemoryMappedFile::createReadOnlyMap();
ourReadViews.add(_view_readonly, this);
}
2010-10-01 16:14:36 -04:00
}
2010-11-16 16:40:56 -05:00
else {
_view_private = _view_write;
}
2010-10-01 16:14:36 -04:00
return true;
}
return false;
}
/* we will re-map the private few frequently, thus the use of MoveableBuffer */
MoveableBuffer MongoMMF::getView() {
if( durable && debug )
2010-11-04 17:43:02 -04:00
return _view_readonly;
return _view_private;
2010-10-01 16:14:36 -04:00
}
2010-11-17 13:59:29 -05:00
MongoMMF::MongoMMF() : _dirty(false) {
2010-11-04 17:43:02 -04:00
_view_write = _view_private = _view_readonly = 0;
2010-10-01 16:14:36 -04:00
}
MongoMMF::~MongoMMF() {
close();
}
/*virtual*/ void MongoMMF::close() {
2010-11-13 17:42:41 -05:00
if( durable ) {
2010-11-14 22:28:04 -05:00
privateViews.remove(_view_private);
2010-11-13 17:42:41 -05:00
if( debug ) {
ourReadViews.remove(_view_readonly);
}
2010-10-01 16:14:36 -04:00
}
2010-11-04 17:43:02 -04:00
_view_write = _view_private = _view_readonly = 0;
MemoryMappedFile::close();
2010-10-01 16:14:36 -04:00
}
}