summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/log.cpp69
-rw-r--r--util/log.h6
-rw-r--r--util/net/sock.cpp85
-rw-r--r--util/net/sock.h2
-rw-r--r--util/scopeguard.h432
-rw-r--r--util/version.cpp2
6 files changed, 562 insertions, 34 deletions
diff --git a/util/log.cpp b/util/log.cpp
index bc48584..0dc75ed 100644
--- a/util/log.cpp
+++ b/util/log.cpp
@@ -25,12 +25,16 @@ using namespace std;
#ifdef _WIN32
# include <io.h>
+# include <fcntl.h>
#else
# include <cxxabi.h>
# include <sys/file.h>
#endif
-//#include "../db/jsobj.h"
+#ifdef _WIN32
+# define dup2 _dup2 // Microsoft headers use ISO C names
+# define fileno _fileno
+#endif
namespace mongo {
@@ -85,55 +89,72 @@ namespace mongo {
}
if ( _file ) {
-#ifdef _WIN32
- cout << "log rotation net yet supported on windows" << endl;
- return;
-#else
- struct tm t;
- localtime_r( &_opened , &t );
+#ifdef POSIX_FADV_DONTNEED
+ posix_fadvise(fileno(_file), 0, 0, POSIX_FADV_DONTNEED);
+#endif
+
+ // Rename the (open) existing log file to a timestamped name
stringstream ss;
- ss << _path << "." << terseCurrentTime(false);
+ ss << _path << "." << terseCurrentTime( false );
string s = ss.str();
rename( _path.c_str() , s.c_str() );
-#endif
}
-
- FILE* tmp = freopen(_path.c_str(), (_append ? "a" : "w"), stdout);
- if (!tmp) {
+ FILE* tmp = 0; // The new file using the original logpath name
+
+#if _WIN32
+ // We rename an open log file (above, on next rotation) and the trick to getting Windows to do that is
+ // to open the file with FILE_SHARE_DELETE. So, we can't use the freopen() call that non-Windows
+ // versions use because it would open the file without the FILE_SHARE_DELETE flag we need.
+ //
+ HANDLE newFileHandle = CreateFileA(
+ _path.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if ( INVALID_HANDLE_VALUE != newFileHandle ) {
+ int newFileDescriptor = _open_osfhandle( reinterpret_cast<intptr_t>(newFileHandle), _O_APPEND );
+ tmp = _fdopen( newFileDescriptor, _append ? "a" : "w" );
+ }
+#else
+ tmp = freopen(_path.c_str(), _append ? "a" : "w", stdout);
+#endif
+ if ( !tmp ) {
cerr << "can't open: " << _path.c_str() << " for log file" << endl;
dbexit( EXIT_BADOPTIONS );
- assert(0);
+ assert( 0 );
}
-#ifdef _WIN32 // windows has these functions it just gives them a funny name
-# define dup2 _dup2
-# define fileno _fileno
-#endif
- // redirect stderr to log file
- dup2(fileno(tmp), 2);
+ // redirect stdout and stderr to log file
+ dup2( fileno( tmp ), 1 ); // stdout
+ dup2( fileno( tmp ), 2 ); // stderr
Logstream::setLogFile(tmp); // after this point no thread will be using old file
+#if _WIN32
+ if ( _file )
+ fclose( _file ); // In Windows, we still have the old file open, close it now
+#endif
+
#if 0 // enable to test redirection
cout << "written to cout" << endl;
cerr << "written to cerr" << endl;
log() << "written to log()" << endl;
#endif
- _file = tmp;
- _opened = time(0);
+ _file = tmp; // Save new file for next rotation
}
private:
-
bool _enabled;
string _path;
bool _append;
-
FILE * _file;
- time_t _opened;
} loggingManager;
diff --git a/util/log.h b/util/log.h
index d5c7e55..660bfbe 100644
--- a/util/log.h
+++ b/util/log.h
@@ -507,6 +507,12 @@ namespace mongo {
int x = errno;
cout << "Failed to write to logfile: " << errnoWithDescription(x) << ": " << out << endl;
}
+
+#ifdef POSIX_FADV_DONTNEED
+ // This only applies to pages that have already been flushed
+ RARELY posix_fadvise(fileno(logfile), 0, 0, POSIX_FADV_DONTNEED);
+#endif
+
}
_init();
}
diff --git a/util/net/sock.cpp b/util/net/sock.cpp
index 69c42f2..ac565c3 100644
--- a/util/net/sock.cpp
+++ b/util/net/sock.cpp
@@ -342,6 +342,67 @@ namespace mongo {
// ------------ SSLManager -----------------
#ifdef MONGO_SSL
+ static unsigned long _ssl_id_callback();
+ static void _ssl_locking_callback(int mode, int type, const char *file, int line);
+
+ class SSLThreadInfo {
+ public:
+
+ SSLThreadInfo() {
+ _id = ++_next;
+ CRYPTO_set_id_callback(_ssl_id_callback);
+ CRYPTO_set_locking_callback(_ssl_locking_callback);
+ }
+
+ ~SSLThreadInfo() {
+ CRYPTO_set_id_callback(0);
+ }
+
+ unsigned long id() const { return _id; }
+
+ void lock_callback( int mode, int type, const char *file, int line ) {
+ if ( mode & CRYPTO_LOCK ) {
+ _mutex[type]->lock();
+ }
+ else {
+ _mutex[type]->unlock();
+ }
+ }
+
+ static void init() {
+ while ( (int)_mutex.size() < CRYPTO_num_locks() )
+ _mutex.push_back( new SimpleMutex("SSLThreadInfo") );
+ }
+
+ static SSLThreadInfo* get() {
+ SSLThreadInfo* me = _thread.get();
+ if ( ! me ) {
+ me = new SSLThreadInfo();
+ _thread.reset( me );
+ }
+ return me;
+ }
+
+ private:
+ unsigned _id;
+
+ static AtomicUInt _next;
+ static vector<SimpleMutex*> _mutex;
+ static boost::thread_specific_ptr<SSLThreadInfo> _thread;
+ };
+
+ static unsigned long _ssl_id_callback() {
+ return SSLThreadInfo::get()->id();
+ }
+ static void _ssl_locking_callback(int mode, int type, const char *file, int line) {
+ SSLThreadInfo::get()->lock_callback( mode , type , file , line );
+ }
+
+ AtomicUInt SSLThreadInfo::_next;
+ vector<SimpleMutex*> SSLThreadInfo::_mutex;
+ boost::thread_specific_ptr<SSLThreadInfo> SSLThreadInfo::_thread;
+
+
SSLManager::SSLManager( bool client ) {
_client = client;
SSL_library_init();
@@ -352,6 +413,8 @@ namespace mongo {
massert( 15864 , mongoutils::str::stream() << "can't create SSL Context: " << ERR_error_string(ERR_get_error(), NULL) , _context );
SSL_CTX_set_options( _context, SSL_OP_ALL);
+ SSLThreadInfo::init();
+ SSLThreadInfo::get();
}
void SSLManager::setupPubPriv( const string& privateKeyFile , const string& publicKeyFile ) {
@@ -387,6 +450,7 @@ namespace mongo {
}
SSL * SSLManager::secure( int fd ) {
+ SSLThreadInfo::get();
SSL * ssl = SSL_new( _context );
massert( 15861 , "can't create SSL" , ssl );
SSL_set_fd( ssl , fd );
@@ -415,13 +479,18 @@ namespace mongo {
_bytesOut = 0;
_bytesIn = 0;
#ifdef MONGO_SSL
+ _ssl = 0;
_sslAccepted = 0;
#endif
}
void Socket::close() {
#ifdef MONGO_SSL
- _ssl.reset();
+ if ( _ssl ) {
+ SSL_shutdown( _ssl );
+ SSL_free( _ssl );
+ _ssl = 0;
+ }
#endif
if ( _fd >= 0 ) {
closesocket( _fd );
@@ -433,8 +502,8 @@ namespace mongo {
void Socket::secure( SSLManager * ssl ) {
assert( ssl );
assert( _fd >= 0 );
- _ssl.reset( ssl->secure( _fd ) );
- SSL_connect( _ssl.get() );
+ _ssl = ssl->secure( _fd );
+ SSL_connect( _ssl );
}
void Socket::secureAccepted( SSLManager * ssl ) {
@@ -446,8 +515,8 @@ namespace mongo {
#ifdef MONGO_SSL
if ( _sslAccepted ) {
assert( _fd );
- _ssl.reset( _sslAccepted->secure( _fd ) );
- SSL_accept( _ssl.get() );
+ _ssl = _sslAccepted->secure( _fd );
+ SSL_accept( _ssl );
_sslAccepted = 0;
}
#endif
@@ -510,7 +579,7 @@ namespace mongo {
int Socket::_send( const char * data , int len ) {
#ifdef MONGO_SSL
if ( _ssl ) {
- return SSL_write( _ssl.get() , data , len );
+ return SSL_write( _ssl , data , len );
}
#endif
return ::send( _fd , data , len , portSendFlags );
@@ -524,7 +593,7 @@ namespace mongo {
#ifdef MONGO_SSL
if ( _ssl ) {
- log() << "SSL Error ret: " << ret << " err: " << SSL_get_error( _ssl.get() , ret )
+ log() << "SSL Error ret: " << ret << " err: " << SSL_get_error( _ssl , ret )
<< " " << ERR_error_string(ERR_get_error(), NULL)
<< endl;
}
@@ -679,7 +748,7 @@ namespace mongo {
int Socket::_recv( char *buf, int max ) {
#ifdef MONGO_SSL
if ( _ssl ){
- return SSL_read( _ssl.get() , buf , max );
+ return SSL_read( _ssl , buf , max );
}
#endif
return ::recv( _fd , buf , max , portRecvFlags );
diff --git a/util/net/sock.h b/util/net/sock.h
index 1cd5133..f91c288 100644
--- a/util/net/sock.h
+++ b/util/net/sock.h
@@ -243,7 +243,7 @@ namespace mongo {
long long _bytesOut;
#ifdef MONGO_SSL
- shared_ptr<SSL> _ssl;
+ SSL* _ssl;
SSLManager * _sslAccepted;
#endif
diff --git a/util/scopeguard.h b/util/scopeguard.h
new file mode 100644
index 0000000..8ced04f
--- /dev/null
+++ b/util/scopeguard.h
@@ -0,0 +1,432 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2000 Andrei Alexandrescu
+// Copyright (c) 2000 Petru Marginean
+// Copyright (c) 2005 Joshua Lehrer
+//
+// Permission to use, copy, modify, distribute and sell this software for any
+// purpose is hereby granted without fee, provided that the above copyright
+// notice appear in all copies and that both that copyright notice and this
+// permission notice appear in supporting documentation.
+// The author makes no representations about the
+// suitability of this software for any purpose. It is provided "as is"
+// without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SCOPEGUARD_H_
+#define LOKI_SCOPEGUARD_H_
+
+namespace mongo
+{
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// \class RefToValue
+ ///
+ /// Transports a reference as a value
+ /// Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuard
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ class RefToValue
+ {
+ public:
+
+ RefToValue(T& ref) : ref_(ref)
+ {}
+
+ RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
+ {}
+
+ operator T& () const
+ {
+ return ref_;
+ }
+
+ private:
+ // Disable - not implemented
+ RefToValue();
+ RefToValue& operator=(const RefToValue&);
+
+ T& ref_;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ /// RefToValue creator.
+ ////////////////////////////////////////////////////////////////////////////////
+
+ template <class T>
+ inline RefToValue<T> ByRef(T& t)
+ {
+ return RefToValue<T>(t);
+ }
+
+
+
+
+ ////////////////////////////////////////////
+ /// ScopeGuard
+ /*
+ Trivial example for use:
+
+ FILE* f = fopen("myfile.txt", "w+");
+ if (!f)
+ return error;
+ ON_BLOCK_EXIT(fclose, f);
+
+
+ More complicated example:
+
+ ScopeGuard guard = MakeGuard(my_rollback_func, myparam);
+ ...
+ if (successful) {
+ guard.Dismiss();
+ return;
+ }
+ // guard is still active here and will fire at scope exit
+ ...
+
+
+ */
+
+
+ class ScopeGuardImplBase
+ {
+ ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
+
+ protected:
+
+ ~ScopeGuardImplBase()
+ {}
+
+ ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
+ : dismissed_(other.dismissed_)
+ {
+ other.Dismiss();
+ }
+
+ template <typename J>
+ static void SafeExecute(J& j) throw()
+ {
+ if (!j.dismissed_)
+ try
+ {
+ j.Execute();
+ }
+ catch(...)
+ {}
+ }
+
+ mutable bool dismissed_;
+
+ public:
+ ScopeGuardImplBase() throw() : dismissed_(false)
+ {}
+
+ void Dismiss() const throw()
+ {
+ dismissed_ = true;
+ }
+ };
+
+ ////////////////////////////////////////////////////////////////
+ ///
+ /// \typedef typedef const ScopeGuardImplBase& ScopeGuard
+ ///
+ /// See Andrei's and Petru Marginean's CUJ article
+ /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm
+ ///
+ /// Changes to the original code by Joshua Lehrer:
+ /// http://www.lehrerfamily.com/scopeguard.html
+ ////////////////////////////////////////////////////////////////
+
+ typedef const ScopeGuardImplBase& ScopeGuard;
+
+ template <typename F>
+ class ScopeGuardImpl0 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl0<F> MakeGuard(F fun)
+ {
+ return ScopeGuardImpl0<F>(fun);
+ }
+
+ ~ScopeGuardImpl0() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_();
+ }
+
+ protected:
+ ScopeGuardImpl0(F fun) : fun_(fun)
+ {}
+
+ F fun_;
+ };
+
+ template <typename F>
+ inline ScopeGuardImpl0<F> MakeGuard(F fun)
+ {
+ return ScopeGuardImpl0<F>::MakeGuard(fun);
+ }
+
+ template <typename F, typename P1>
+ class ScopeGuardImpl1 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
+ {
+ return ScopeGuardImpl1<F, P1>(fun, p1);
+ }
+
+ ~ScopeGuardImpl1() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_(p1_);
+ }
+
+ protected:
+ ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1)
+ {}
+
+ F fun_;
+ const P1 p1_;
+ };
+
+ template <typename F, typename P1>
+ inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
+ {
+ return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
+ }
+
+ template <typename F, typename P1, typename P2>
+ class ScopeGuardImpl2: public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
+ {
+ return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
+ }
+
+ ~ScopeGuardImpl2() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_(p1_, p2_);
+ }
+
+ protected:
+ ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
+ {}
+
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ };
+
+ template <typename F, typename P1, typename P2>
+ inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
+ {
+ return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
+ }
+
+ template <typename F, typename P1, typename P2, typename P3>
+ class ScopeGuardImpl3 : public ScopeGuardImplBase
+ {
+ public:
+ static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
+ {
+ return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
+ }
+
+ ~ScopeGuardImpl3() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ fun_(p1_, p2_, p3_);
+ }
+
+ protected:
+ ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
+ {}
+
+ F fun_;
+ const P1 p1_;
+ const P2 p2_;
+ const P3 p3_;
+ };
+
+ template <typename F, typename P1, typename P2, typename P3>
+ inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
+ {
+ return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
+ }
+
+ //************************************************************
+
+ template <class Obj, typename MemFun>
+ class ObjScopeGuardImpl0 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
+ {
+ return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
+ }
+
+ ~ObjScopeGuardImpl0() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ (obj_.*memFun_)();
+ }
+
+ protected:
+ ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun)
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ };
+
+ template <class Obj, typename MemFun>
+ inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
+ {
+ return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
+ }
+
+ template <typename Ret, class Obj1, class Obj2>
+ inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj)
+ {
+ return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun);
+ }
+
+ template <typename Ret, class Obj1, class Obj2>
+ inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj)
+ {
+ return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun);
+ }
+
+ template <class Obj, typename MemFun, typename P1>
+ class ObjScopeGuardImpl1 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
+ {
+ return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
+ }
+
+ ~ObjScopeGuardImpl1() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ (obj_.*memFun_)(p1_);
+ }
+
+ protected:
+ ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1)
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ const P1 p1_;
+ };
+
+ template <class Obj, typename MemFun, typename P1>
+ inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
+ {
+ return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
+ inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1)
+ {
+ return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
+ inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1)
+ {
+ return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
+ }
+
+ template <class Obj, typename MemFun, typename P1, typename P2>
+ class ObjScopeGuardImpl2 : public ScopeGuardImplBase
+ {
+ public:
+ static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
+ {
+ return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
+ }
+
+ ~ObjScopeGuardImpl2() throw()
+ {
+ SafeExecute(*this);
+ }
+
+ void Execute()
+ {
+ (obj_.*memFun_)(p1_, p2_);
+ }
+
+ protected:
+ ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2)
+ {}
+
+ Obj& obj_;
+ MemFun memFun_;
+ const P1 p1_;
+ const P2 p2_;
+ };
+
+ template <class Obj, typename MemFun, typename P1, typename P2>
+ inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
+ {
+ return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
+ inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2)
+ {
+ return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
+ }
+
+ template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
+ inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2)
+ {
+ return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
+ }
+
+} // namespace Loki
+
+#define LOKI_CONCATENATE_DIRECT(s1, s2) s1##s2
+#define LOKI_CONCATENATE(s1, s2) LOKI_CONCATENATE_DIRECT(s1, s2)
+#define LOKI_ANONYMOUS_VARIABLE(str) LOKI_CONCATENATE(str, __LINE__)
+
+#ifdef __GNUC__
+#define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) __attribute__ ((unused)) = MakeGuard
+#define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) __attribute__ ((unused)) = MakeObjGuard
+#else
+#define ON_BLOCK_EXIT ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeGuard
+#define ON_BLOCK_EXIT_OBJ ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = MakeObjGuard
+#endif
+
+#endif //LOKI_SCOPEGUARD_H_
diff --git a/util/version.cpp b/util/version.cpp
index c43180c..883c208 100644
--- a/util/version.cpp
+++ b/util/version.cpp
@@ -38,7 +38,7 @@ namespace mongo {
* 1.2.3-rc4-pre-
* If you really need to do something else you'll need to fix _versionArray()
*/
- const char versionString[] = "2.0.2";
+ const char versionString[] = "2.0.3";
// See unit test for example outputs
static BSONArray _versionArray(const char* version){