summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordwight <dwight@10gen.com>2010-11-15 22:13:48 -0500
committerdwight <dwight@10gen.com>2010-11-15 22:13:48 -0500
commit62eaedd3d21e9778c220e022f28eb67d67e81d8d (patch)
tree6c59a7e3ab63d5e3ad2d1cfd6b42f2651eb767b4
parent16d9785166314fbfb31ea2ede0f06f2951b4b027 (diff)
downloadmongo-62eaedd3d21e9778c220e022f28eb67d67e81d8d.tar.gz
AlignedBuilder dur
-rw-r--r--db/dur.cpp11
-rw-r--r--db/dur_journal.cpp9
-rw-r--r--db/dur_journal.h4
-rw-r--r--util/alignedbuilder.h148
4 files changed, 163 insertions, 9 deletions
diff --git a/db/dur.cpp b/db/dur.cpp
index e80c278bdc0..5100484a858 100644
--- a/db/dur.cpp
+++ b/db/dur.cpp
@@ -47,6 +47,7 @@
#include "dur_journal.h"
#include "../util/mongoutils/hash.h"
#include "../util/timer.h"
+#include "../util/alignedbuilder.h"
namespace mongo {
@@ -110,7 +111,7 @@ namespace mongo {
}
/** caller handles locking */
- static bool PREPLOGBUFFER(BufBuilder& bb) {
+ static bool PREPLOGBUFFER(AlignedBuilder& bb) {
if( writes.empty() )
return false;
@@ -169,18 +170,18 @@ namespace mongo {
return true;
}
- static void WRITETOJOURNAL(const BufBuilder& bb) {
+ static void WRITETOJOURNAL(const AlignedBuilder& bb) {
journal(bb);
}
- static void _go(BufBuilder& bb) {
+ static void _go(AlignedBuilder& bb) {
PREPLOGBUFFER(bb);
// todo: add double buffering so we can be (not even read locked) during WRITETOJOURNAL
WRITETOJOURNAL(bb);
}
- static void go(BufBuilder& bb) {
+ static void go(AlignedBuilder& bb) {
{
readlocktry lk("", 1000);
if( lk.got() ) {
@@ -197,7 +198,7 @@ namespace mongo {
static void durThread() {
Client::initThread("dur");
const int HowOftenToGroupCommitMs = 100;
- BufBuilder bb(1024 * 1024 * 16); // reuse to avoid any heap fragmentation
+ AlignedBuilder bb(1024 * 1024 * 16); // reuse to avoid any heap fragmentation
while( 1 ) {
try {
int millis = HowOftenToGroupCommitMs;
diff --git a/db/dur_journal.cpp b/db/dur_journal.cpp
index f6ea26bb65a..a557c90e9ec 100644
--- a/db/dur_journal.cpp
+++ b/db/dur_journal.cpp
@@ -25,6 +25,7 @@
#include "dur_journal.h"
#include "../util/logfile.h"
#include "../util/timer.h"
+#include "../util/alignedbuilder.h"
#include <boost/static_assert.hpp>
#undef assert
#define assert MONGO_assert
@@ -34,6 +35,8 @@
namespace mongo {
using namespace mongoutils;
+ class AlignedBuilder;
+
namespace dur {
BOOST_STATIC_ASSERT( sizeof(JHeader) == 8192 );
BOOST_STATIC_ASSERT( sizeof(JSectHeader) == 8 );
@@ -66,7 +69,7 @@ namespace mongo {
void open();
void rotate();
- void journal(const BufBuilder& b);
+ void journal(const AlignedBuilder& b);
path getFilePathFor(int filenumber) const;
};
@@ -170,10 +173,10 @@ namespace mongo {
/** write to journal
*/
- void journal(const BufBuilder& b) {
+ void journal(const AlignedBuilder& b) {
j.journal(b);
}
- void Journal::journal(const BufBuilder& b) {
+ void Journal::journal(const AlignedBuilder& b) {
try {
/* todo: roll if too big */
if( lf == 0 )
diff --git a/db/dur_journal.h b/db/dur_journal.h
index 2f1685aca0d..b0b0310014b 100644
--- a/db/dur_journal.h
+++ b/db/dur_journal.h
@@ -19,6 +19,8 @@
#pragma once
namespace mongo {
+ class AlignedBuilder;
+
namespace dur {
/** assure journal/ dir exists. throws */
@@ -31,7 +33,7 @@ namespace mongo {
void journalRotate();
/** write/append to journal */
- void journal(const BufBuilder& b);
+ void journal(const AlignedBuilder& b);
/** flag that something has gone wrong */
void journalingFailure(const char *msg);
diff --git a/util/alignedbuilder.h b/util/alignedbuilder.h
new file mode 100644
index 00000000000..b97c10da9ab
--- /dev/null
+++ b/util/alignedbuilder.h
@@ -0,0 +1,148 @@
+// @file alignedbuilder.h
+
+/**
+* Copyright (C) 2009 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/>.
+*/
+
+#pragma once
+
+namespace mongo {
+
+ /** a page-aligned BufBuilder. */
+ class AlignedBuilder {
+ public:
+ AlignedBuilder(unsigned init_size) : _size(init_size) {
+ _data = (char *) _malloc(_size);
+ if( _data == 0 )
+ msgasserted(10000, "out of memory AlignedBuilder");
+ _len = 0;
+ }
+ ~AlignedBuilder() { kill(); }
+
+ /** reset for a re-use */
+ void reset() { _len = 0; }
+
+ /** leave room for some stuff later */
+ char* skip(unsigned n) { return grow(n); }
+
+ /** note this may be deallocated (realloced) if you keep writing or reset(). */
+ const char* buf() const { return _data; }
+
+ void appendChar(char j){
+ *((char*)grow(sizeof(char))) = j;
+ }
+ void appendNum(char j){
+ *((char*)grow(sizeof(char))) = j;
+ }
+ void appendNum(short j) {
+ *((short*)grow(sizeof(short))) = j;
+ }
+ void appendNum(int j) {
+ *((int*)grow(sizeof(int))) = j;
+ }
+ void appendNum(unsigned j) {
+ *((unsigned*)grow(sizeof(unsigned))) = j;
+ }
+ void appendNum(bool j) {
+ *((bool*)grow(sizeof(bool))) = j;
+ }
+ void appendNum(double j) {
+ *((double*)grow(sizeof(double))) = j;
+ }
+ void appendNum(long long j) {
+ *((long long*)grow(sizeof(long long))) = j;
+ }
+ void appendNum(unsigned long long j) {
+ *((unsigned long long*)grow(sizeof(unsigned long long))) = j;
+ }
+
+ void appendBuf(const void *src, size_t len) {
+ memcpy(grow((unsigned) len), src, len);
+ }
+
+ template<class T>
+ void appendStruct(const T& s) {
+ appendBuf(&s, sizeof(T));
+ }
+
+ void appendStr(const StringData &str , bool includeEOO = true ) {
+ const unsigned len = str.size() + ( includeEOO ? 1 : 0 );
+ memcpy(grow(len), str.data(), len);
+ }
+
+ /** @return the in-use length */
+ unsigned len() const { return _len; }
+
+ private:
+ /** returns the pre-grow write position */
+ inline char* grow(unsigned by) {
+ unsigned oldlen = _len;
+ _len += by;
+ if ( _len > _size ) {
+ grow_reallocate();
+ }
+ return _data + oldlen;
+ }
+
+ /* "slow" portion of 'grow()' */
+ void NOINLINE_DECL grow_reallocate(){
+ unsigned a = _size * 2;
+ assert( a );
+ if ( _len > a )
+ a = _len + 16 * 1024;
+ assert( a < 0x20000000 );
+ _data = (char *) _realloc(_data, a, _len);
+ _size = a;
+ }
+
+ static const unsigned Alignment = 8192;
+ static void _free(void *p) {
+#if defined(_WIN32)
+ VirtualFree(p, 0, MEM_RELEASE);
+#else
+ free(p);
+#endif
+ }
+ static void* _malloc(unsigned sz) {
+#if defined(_WIN32)
+ void *p = VirtualAlloc(0, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+ return p;
+#elif defined(posix_memalign)
+ void *p = 0;
+ int res = posix_memalign(&p, Alignment, sz);
+ msgasserted(10000, "out of memory AlignedBuilder", res == 0);
+#else
+ void *p = malloc(sz);
+ assert( ((size_t) p) % Alignment == 0 );
+ return p;
+#endif
+ }
+ static void* _realloc(void *ptr, unsigned newSize, unsigned oldSize) {
+ void *p = _malloc(newSize);
+ memcpy(p, ptr, oldSize);
+ _free(ptr);
+ return p;
+ }
+ void kill() {
+ _free(_data);
+ _data = 0;
+ }
+
+ char *_data;
+ unsigned _len;
+ unsigned _size;
+ };
+
+}