diff options
| author | Antonin Kral <a.kral@bobek.cz> | 2012-08-29 20:54:51 +0200 |
|---|---|---|
| committer | Antonin Kral <a.kral@bobek.cz> | 2012-08-29 20:54:51 +0200 |
| commit | 83957b73f9177f6e38bd5375bd93ca1f6a47188c (patch) | |
| tree | f20b7d6ac9a9c64ff5bb6b5910a24abbb356b1d5 /util | |
| parent | 5071d203970edd4c995493d810abe20987e76fe9 (diff) | |
Imported Upstream version 2.2.0upstream/2.2.0
Diffstat (limited to 'util')
114 files changed, 0 insertions, 17170 deletions
diff --git a/util/admin_access.h b/util/admin_access.h deleted file mode 100644 index bb882b2b4c5..00000000000 --- a/util/admin_access.h +++ /dev/null @@ -1,52 +0,0 @@ -/** @file admin_access.h - */ - -/** -* 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/>. -*/ - -#pragma once - -namespace mongo { - - /* - * An AdminAccess is an interface class used to determine if certain users have - * priviledges to a given resource. - * - */ - class AdminAccess { - public: - virtual ~AdminAccess() { } - - /** @return if there are any priviledge users. This should not - * block for long and throw if can't get a lock if needed. - */ - virtual bool haveAdminUsers() const = 0; - - /** @return priviledged user with this name. This should not block - * for long and throw if can't get a lock if needed - */ - virtual BSONObj getAdminUser( const string& username ) const = 0; - }; - - class NoAdminAccess : public AdminAccess { - public: - virtual ~NoAdminAccess() { } - - virtual bool haveAdminUsers() const { return false; } - virtual BSONObj getAdminUser( const string& username ) const { return BSONObj(); } - }; - -} // namespace mongo diff --git a/util/alignedbuilder.cpp b/util/alignedbuilder.cpp deleted file mode 100644 index b2e0461b733..00000000000 --- a/util/alignedbuilder.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// @file alignedbuilder.cpp - -/** -* 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/>. -*/ - -#include "pch.h" -#include "alignedbuilder.h" - -namespace mongo { - - AlignedBuilder::AlignedBuilder(unsigned initSize) { - _len = 0; - _malloc(initSize); - uassert(13584, "out of memory AlignedBuilder", _p._allocationAddress); - } - - BOOST_STATIC_ASSERT(sizeof(void*) == sizeof(size_t)); - - /** reset for a re-use. shrinks if > 128MB */ - void AlignedBuilder::reset() { - _len = 0; - RARELY { - const unsigned sizeCap = 128*1024*1024; - if (_p._size > sizeCap) - _realloc(sizeCap, _len); - } - } - - /** reset with a hint as to the upcoming needed size specified */ - void AlignedBuilder::reset(unsigned sz) { - _len = 0; - unsigned Q = 32 * 1024 * 1024 - 1; - unsigned want = (sz+Q) & (~Q); - if( _p._size == want ) { - return; - } - if( _p._size > want ) { - if( _p._size <= 64 * 1024 * 1024 ) - return; - bool downsize = false; - RARELY { downsize = true; } - if( !downsize ) - return; - } - _realloc(want, _len); - } - - void AlignedBuilder::mallocSelfAligned(unsigned sz) { - assert( sz == _p._size ); - void *p = malloc(sz + Alignment - 1); - _p._allocationAddress = p; - size_t s = (size_t) p; - size_t sold = s; - s += Alignment - 1; - s = (s/Alignment)*Alignment; - assert( s >= sold ); // begining - assert( (s + sz) <= (sold + sz + Alignment - 1) ); //end - _p._data = (char *) s; - } - - /* "slow"/infrequent portion of 'grow()' */ - void NOINLINE_DECL AlignedBuilder::growReallocate(unsigned oldLen) { - dassert( _len > _p._size ); - unsigned a = _p._size; - assert( a ); - while( 1 ) { - if( a < 128 * 1024 * 1024 ) - a *= 2; - else if( sizeof(int*) == 4 ) - a += 32 * 1024 * 1024; - else - a += 64 * 1024 * 1024; - DEV if( a > 256*1024*1024 ) { - log() << "dur AlignedBuilder too big, aborting in _DEBUG build" << endl; - abort(); - } - wassert( a <= 256*1024*1024 ); - assert( a <= 512*1024*1024 ); - if( _len < a ) - break; - } - _realloc(a, oldLen); - } - - void AlignedBuilder::_malloc(unsigned sz) { - _p._size = sz; -#if defined(_WIN32) - void *p = VirtualAlloc(0, sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); - _p._allocationAddress = p; - _p._data = (char *) p; -#elif defined(__linux__) - // in theory #ifdef _POSIX_VERSION should work, but it doesn't on OS X 10.4, and needs to be testeed on solaris. - // so for now, linux only for this. - void *p = 0; - int res = posix_memalign(&p, Alignment, sz); - massert(13524, "out of memory AlignedBuilder", res == 0); - _p._allocationAddress = p; - _p._data = (char *) p; -#else - mallocSelfAligned(sz); - assert( ((size_t) _p._data) % Alignment == 0 ); -#endif - } - - void AlignedBuilder::_realloc(unsigned newSize, unsigned oldLen) { - // posix_memalign alignment is not maintained on reallocs, so we can't use realloc(). - AllocationInfo old = _p; - _malloc(newSize); - assert( oldLen <= _len ); - memcpy(_p._data, old._data, oldLen); - _free(old._allocationAddress); - } - - void AlignedBuilder::_free(void *p) { -#if defined(_WIN32) - VirtualFree(p, 0, MEM_RELEASE); -#else - free(p); -#endif - } - - void AlignedBuilder::kill() { - _free(_p._allocationAddress); - _p._allocationAddress = 0; - _p._data = 0; - } - -} diff --git a/util/alignedbuilder.h b/util/alignedbuilder.h deleted file mode 100644 index 1d246a9d78e..00000000000 --- a/util/alignedbuilder.h +++ /dev/null @@ -1,125 +0,0 @@ -// @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 - -#include "../bson/stringdata.h" - -namespace mongo { - - /** a page-aligned BufBuilder. */ - class AlignedBuilder { - public: - AlignedBuilder(unsigned init_size); - ~AlignedBuilder() { kill(); } - - /** reset with a hint as to the upcoming needed size specified */ - void reset(unsigned sz); - - /** reset for a re-use. shrinks if > 128MB */ - void reset(); - - /** note this may be deallocated (realloced) if you keep writing or reset(). */ - const char* buf() const { return _p._data; } - - /** leave room for some stuff later - @return offset in the buffer that was our current position - */ - size_t skip(unsigned n) { - unsigned l = len(); - grow(n); - return l; - } - - /** if buffer grows pointer no longer valid */ - char* atOfs(unsigned ofs) { return _p._data + ofs; } - - /** if buffer grows pointer no longer valid */ - char* cur() { return _p._data + _len; } - - 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 ); - assert( len < (unsigned) BSONObjMaxUserSize ); - memcpy(grow(len), str.data(), len); - } - - /** @return the in-use length */ - unsigned len() const { return _len; } - - private: - static const unsigned Alignment = 8192; - - /** returns the pre-grow write position */ - inline char* grow(unsigned by) { - unsigned oldlen = _len; - _len += by; - if (MONGO_unlikely( _len > _p._size )) { - growReallocate(oldlen); - } - return _p._data + oldlen; - } - - void growReallocate(unsigned oldLenInUse); - void kill(); - void mallocSelfAligned(unsigned sz); - void _malloc(unsigned sz); - void _realloc(unsigned newSize, unsigned oldLenInUse); - void _free(void*); - - struct AllocationInfo { - char *_data; - void *_allocationAddress; - unsigned _size; - } _p; - unsigned _len; // bytes in use - }; - -} diff --git a/util/allocator.h b/util/allocator.h deleted file mode 100644 index 23ee4ee47b0..00000000000 --- a/util/allocator.h +++ /dev/null @@ -1,37 +0,0 @@ -// allocator.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 { - - inline void * ourmalloc(size_t size) { - void *x = malloc(size); - if ( x == 0 ) dbexit( EXIT_OOM_MALLOC , "malloc fails"); - return x; - } - - inline void * ourrealloc(void *ptr, size_t size) { - void *x = realloc(ptr, size); - if ( x == 0 ) dbexit( EXIT_OOM_REALLOC , "realloc fails"); - return x; - } - -#define MONGO_malloc mongo::ourmalloc -#define MONGO_realloc mongo::ourrealloc - -} // namespace mongo diff --git a/util/array.h b/util/array.h deleted file mode 100644 index 12822252fd7..00000000000 --- a/util/array.h +++ /dev/null @@ -1,127 +0,0 @@ -// array.h - -/* - * Copyright 2010 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. - */ - -namespace mongo { - - /* - * simple array class that does no allocations - * same api as vector - * fixed buffer, so once capacity is exceeded, will assert - * meant to be-reused with clear() - */ - template<typename T> - class FastArray { - public: - FastArray( int capacity=10000 ) - : _capacity( capacity ) , _size(0) , _end(this,capacity) { - _data = new T[capacity]; - } - - ~FastArray() { - delete[] _data; - } - - void clear() { - _size = 0; - } - - T& operator[]( int x ) { - assert( x >= 0 && x < _capacity ); - return _data[x]; - } - - T& getNext() { - return _data[_size++]; - } - - void push_back( const T& t ) { - assert( _size < _capacity ); - _data[_size++] = t; - } - - void sort( int (*comp)(const void *, const void *) ) { - qsort( _data , _size , sizeof(T) , comp ); - } - - int size() { - return _size; - } - - bool hasSpace() { - return _size < _capacity; - } - class iterator { - public: - iterator() { - _it = 0; - _pos = 0; - } - - iterator( FastArray * it , int pos=0 ) { - _it = it; - _pos = pos; - } - - bool operator==(const iterator& other ) const { - return _pos == other._pos; - } - - bool operator!=(const iterator& other ) const { - return _pos != other._pos; - } - - void operator++() { - _pos++; - } - - T& operator*() { - return _it->_data[_pos]; - } - - string toString() const { - stringstream ss; - ss << _pos; - return ss.str(); - } - private: - FastArray * _it; - int _pos; - - friend class FastArray; - }; - - - iterator begin() { - return iterator(this); - } - - iterator end() { - _end._pos = _size; - return _end; - } - - - private: - int _capacity; - int _size; - - iterator _end; - - T * _data; - }; -} diff --git a/util/assert_util.cpp b/util/assert_util.cpp deleted file mode 100644 index da039c09a58..00000000000 --- a/util/assert_util.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// assert_util.cpp - -/* 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. - */ - -#include "pch.h" -#include "assert_util.h" -#include "assert.h" -//#include "file.h" -#include <cmath> -using namespace std; - -#ifndef _WIN32 -#include <cxxabi.h> -#include <sys/file.h> -#endif - -//#include "../bson/bson.h" -#include "../db/jsobj.h" - -namespace mongo { - - AssertionCount assertionCount; - - AssertionCount::AssertionCount() - : regular(0),warning(0),msg(0),user(0),rollovers(0) { - } - - void AssertionCount::rollover() { - rollovers++; - regular = 0; - warning = 0; - msg = 0; - user = 0; - } - - void AssertionCount::condrollover( int newvalue ) { - static int max = (int)pow( 2.0 , 30 ); - if ( newvalue >= max ) - rollover(); - } - - void ExceptionInfo::append( BSONObjBuilder& b , const char * m , const char * c ) const { - if ( msg.empty() ) - b.append( m , "unknown assertion" ); - else - b.append( m , msg ); - - if ( code ) - b.append( c , code ); - } - - string getDbContext(); - - /* "warning" assert -- safe to continue, so we don't throw exception. */ - NOINLINE_DECL void wasserted(const char *msg, const char *file, unsigned line) { - static bool rateLimited; - static time_t lastWhen; - static unsigned lastLine; - if( lastLine == line && time(0)-lastWhen < 5 ) { - if( rateLimited++ == 0 ) { - log() << "rate limiting wassert" << endl; - } - return; - } - lastWhen = time(0); - lastLine = line; - - problem() << "warning assertion failure " << msg << ' ' << file << ' ' << dec << line << endl; - sayDbContext(); - raiseError(0,msg && *msg ? msg : "wassertion failure"); - assertionCount.condrollover( ++assertionCount.warning ); -#if defined(_DEBUG) || defined(_DURABLEDEFAULTON) || defined(_DURABLEDEFAULTOFF) - // this is so we notice in buildbot - log() << "\n\n***aborting after wassert() failure in a debug/test build\n\n" << endl; - abort(); -#endif - } - - NOINLINE_DECL void asserted(const char *msg, const char *file, unsigned line) { - assertionCount.condrollover( ++assertionCount.regular ); - problem() << "Assertion failure " << msg << ' ' << file << ' ' << dec << line << endl; - sayDbContext(); - raiseError(0,msg && *msg ? msg : "assertion failure"); - stringstream temp; - temp << "assertion " << file << ":" << line; - AssertionException e(temp.str(),0); - breakpoint(); -#if defined(_DEBUG) || defined(_DURABLEDEFAULTON) || defined(_DURABLEDEFAULTOFF) - // this is so we notice in buildbot - log() << "\n\n***aborting after assert() failure in a debug/test build\n\n" << endl; - abort(); -#endif - throw e; - } - - NOINLINE_DECL void verifyFailed( int msgid ) { - assertionCount.condrollover( ++assertionCount.regular ); - problem() << "Assertion failure " << msgid << endl; - sayDbContext(); - raiseError(0,"assertion failure"); - stringstream temp; - temp << msgid; - AssertionException e(temp.str(),0); - breakpoint(); -#if defined(_DEBUG) || defined(_DURABLEDEFAULTON) || defined(_DURABLEDEFAULTOFF) - // this is so we notice in buildbot - log() << "\n\n***aborting after verify() failure in a debug/test build\n\n" << endl; - abort(); -#endif - throw e; - } - - void uassert_nothrow(const char *msg) { - raiseError(0,msg); - } - - NOINLINE_DECL void uasserted(int msgid, const char *msg) { - assertionCount.condrollover( ++assertionCount.user ); - LOG(1) << "User Assertion: " << msgid << ":" << msg << endl; - raiseError(msgid,msg); - throw UserException(msgid, msg); - } - - NOINLINE_DECL void msgasserted(int msgid, const char *msg) { - assertionCount.condrollover( ++assertionCount.warning ); - tlog() << "Assertion: " << msgid << ":" << msg << endl; - raiseError(msgid,msg && *msg ? msg : "massert failure"); - breakpoint(); - printStackTrace(); - throw MsgAssertionException(msgid, msg); - } - - NOINLINE_DECL void msgassertedNoTrace(int msgid, const char *msg) { - assertionCount.condrollover( ++assertionCount.warning ); - log() << "Assertion: " << msgid << ":" << msg << endl; - raiseError(msgid,msg && *msg ? msg : "massert failure"); - throw MsgAssertionException(msgid, msg); - } - - NOINLINE_DECL void streamNotGood( int code , string msg , std::ios& myios ) { - stringstream ss; - // errno might not work on all systems for streams - // if it doesn't for a system should deal with here - ss << msg << " stream invalid: " << errnoWithDescription(); - throw UserException( code , ss.str() ); - } - - string errnoWithPrefix( const char * prefix ) { - stringstream ss; - if ( prefix ) - ss << prefix << ": "; - ss << errnoWithDescription(); - return ss.str(); - } - - string demangleName( const type_info& typeinfo ) { -#ifdef _WIN32 - return typeinfo.name(); -#else - int status; - - char * niceName = abi::__cxa_demangle(typeinfo.name(), 0, 0, &status); - if ( ! niceName ) - return typeinfo.name(); - - string s = niceName; - free(niceName); - return s; -#endif - } - - NOINLINE_DECL ErrorMsg::ErrorMsg(const char *msg, char ch) { - int l = strlen(msg); - assert( l < 128); - memcpy(buf, msg, l); - char *p = buf + l; - p[0] = ch; - p[1] = 0; - } - - NOINLINE_DECL ErrorMsg::ErrorMsg(const char *msg, unsigned val) { - int l = strlen(msg); - assert( l < 128); - memcpy(buf, msg, l); - char *p = buf + l; - sprintf(p, "%u", val); - } - -} - diff --git a/util/assert_util.h b/util/assert_util.h deleted file mode 100644 index c35f651828b..00000000000 --- a/util/assert_util.h +++ /dev/null @@ -1,249 +0,0 @@ -// assert_util.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 - -#include "../db/lasterror.h" - -// MONGO_NORETURN undefed at end of file -#ifdef __GNUC__ -# define MONGO_NORETURN __attribute__((__noreturn__)) -#else -# define MONGO_NORETURN -#endif - -namespace mongo { - - enum CommonErrorCodes { - DatabaseDifferCaseCode = 13297 , - StaleConfigInContextCode = 13388 - }; - - class AssertionCount { - public: - AssertionCount(); - void rollover(); - void condrollover( int newValue ); - - int regular; - int warning; - int msg; - int user; - int rollovers; - }; - - extern AssertionCount assertionCount; - - struct ExceptionInfo { - ExceptionInfo() : msg(""),code(-1) {} - ExceptionInfo( const char * m , int c ) - : msg( m ) , code( c ) { - } - ExceptionInfo( const string& m , int c ) - : msg( m ) , code( c ) { - } - void append( BSONObjBuilder& b , const char * m = "$err" , const char * c = "code" ) const ; - string toString() const { stringstream ss; ss << "exception: " << code << " " << msg; return ss.str(); } - bool empty() const { return msg.empty(); } - - void reset(){ msg = ""; code=-1; } - - string msg; - int code; - }; - - /** helper class that builds error strings. lighter weight than a StringBuilder, albeit less flexible. - NOINLINE_DECL used in the constructor implementations as we are assuming this is a cold code path when used. - - example: - throw UserException(123, ErrorMsg("blah", num_val)); - */ - class ErrorMsg { - public: - ErrorMsg(const char *msg, char ch); - ErrorMsg(const char *msg, unsigned val); - operator string() const { return buf; } - private: - char buf[256]; - }; - - class DBException : public std::exception { - public: - DBException( const ExceptionInfo& ei ) : _ei(ei) {} - DBException( const char * msg , int code ) : _ei(msg,code) {} - DBException( const string& msg , int code ) : _ei(msg,code) {} - virtual ~DBException() throw() { } - - virtual const char* what() const throw() { return _ei.msg.c_str(); } - virtual int getCode() const { return _ei.code; } - - virtual void appendPrefix( stringstream& ss ) const { } - - virtual string toString() const { - stringstream ss; ss << getCode() << " " << what(); return ss.str(); - return ss.str(); - } - - const ExceptionInfo& getInfo() const { return _ei; } - - protected: - ExceptionInfo _ei; - }; - - class AssertionException : public DBException { - public: - - AssertionException( const ExceptionInfo& ei ) : DBException(ei) {} - AssertionException( const char * msg , int code ) : DBException(msg,code) {} - AssertionException( const string& msg , int code ) : DBException(msg,code) {} - - virtual ~AssertionException() throw() { } - - virtual bool severe() { return true; } - virtual bool isUserAssertion() { return false; } - - /* true if an interrupted exception - see KillCurrentOp */ - bool interrupted() { - return _ei.code == 11600 || _ei.code == 11601; - } - }; - - /* UserExceptions are valid errors that a user can cause, like out of disk space or duplicate key */ - class UserException : public AssertionException { - public: - UserException(int c , const string& m) : AssertionException( m , c ) {} - - virtual bool severe() { return false; } - virtual bool isUserAssertion() { return true; } - virtual void appendPrefix( stringstream& ss ) const { ss << "userassert:"; } - }; - - class MsgAssertionException : public AssertionException { - public: - MsgAssertionException( const ExceptionInfo& ei ) : AssertionException( ei ) {} - MsgAssertionException(int c, const string& m) : AssertionException( m , c ) {} - virtual bool severe() { return false; } - virtual void appendPrefix( stringstream& ss ) const { ss << "massert:"; } - }; - - void asserted(const char *msg, const char *file, unsigned line) MONGO_NORETURN; - void wasserted(const char *msg, const char *file, unsigned line); - void verifyFailed( int msgid ); - - /** a "user assertion". throws UserAssertion. logs. typically used for errors that a user - could cause, such as duplicate key, disk full, etc. - */ - void uasserted(int msgid, const char *msg) MONGO_NORETURN; - inline void uasserted(int msgid , string msg) { uasserted(msgid, msg.c_str()); } - - /** reported via lasterror, but don't throw exception */ - void uassert_nothrow(const char *msg); - - /** msgassert and massert are for errors that are internal but have a well defined error text string. - a stack trace is logged. - */ - void msgassertedNoTrace(int msgid, const char *msg) MONGO_NORETURN; - inline void msgassertedNoTrace(int msgid, const string& msg) { msgassertedNoTrace( msgid , msg.c_str() ); } - void msgasserted(int msgid, const char *msg) MONGO_NORETURN; - inline void msgasserted(int msgid, string msg) { msgasserted(msgid, msg.c_str()); } - - /* convert various types of exceptions to strings */ - inline string causedBy( const char* e ){ return (string)" :: caused by :: " + e; } - inline string causedBy( const DBException& e ){ return causedBy( e.toString().c_str() ); } - inline string causedBy( const std::exception& e ){ return causedBy( e.what() ); } - inline string causedBy( const string& e ){ return causedBy( e.c_str() ); } - - /** in the mongodb source, use verify() instead of assert(). verify is always evaluated even in release builds. */ - inline void verify( int msgid , bool testOK ) { if ( ! testOK ) verifyFailed( msgid ); } - -#define MONGO_assert(_Expression) (void)( MONGO_likely(!!(_Expression)) || (mongo::asserted(#_Expression, __FILE__, __LINE__), 0) ) - - /* "user assert". if asserts, user did something wrong, not our code */ -#define MONGO_uassert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || (mongo::uasserted(msgid, msg), 0) ) - - /* warning only - keeps going */ -#define MONGO_wassert(_Expression) (void)( MONGO_likely(!!(_Expression)) || (mongo::wasserted(#_Expression, __FILE__, __LINE__), 0) ) - - /* display a message, no context, and throw assertionexception - - easy way to throw an exception and log something without our stack trace - display happening. - */ -#define MONGO_massert(msgid, msg, expr) (void)( MONGO_likely(!!(expr)) || (mongo::msgasserted(msgid, msg), 0) ) - - /* dassert is 'debug assert' -- might want to turn off for production as these - could be slow. - */ -#if defined(_DEBUG) -# define MONGO_dassert assert -#else -# define MONGO_dassert(x) -#endif - - // some special ids that we want to duplicate - - // > 10000 asserts - // < 10000 UserException - - enum { ASSERT_ID_DUPKEY = 11000 }; - - /* throws a uassertion with an appropriate msg */ - void streamNotGood( int code , string msg , std::ios& myios ) MONGO_NORETURN; - - inline void assertStreamGood(unsigned msgid, string msg, std::ios& myios) { - if( !myios.good() ) streamNotGood(msgid, msg, myios); - } - - string demangleName( const type_info& typeinfo ); - -} // namespace mongo - -#define BOOST_CHECK_EXCEPTION MONGO_BOOST_CHECK_EXCEPTION -#define MONGO_BOOST_CHECK_EXCEPTION( expression ) \ - try { \ - expression; \ - } catch ( const std::exception &e ) { \ - stringstream ss; \ - ss << "caught boost exception: " << e.what() << ' ' << __FILE__ << ' ' << __LINE__; \ - msgasserted( 13294 , ss.str() ); \ - } catch ( ... ) { \ - massert( 10437 , "unknown boost failed" , false ); \ - } - -#define MONGO_BOOST_CHECK_EXCEPTION_WITH_MSG( expression, msg ) \ - try { \ - expression; \ - } catch ( const std::exception &e ) { \ - stringstream ss; \ - ss << msg << " caught boost exception: " << e.what(); \ - msgasserted( 14043 , ss.str() ); \ - } catch ( ... ) { \ - msgasserted( 14044 , string("unknown boost failed ") + msg ); \ - } - -#define DESTRUCTOR_GUARD MONGO_DESTRUCTOR_GUARD -#define MONGO_DESTRUCTOR_GUARD( expression ) \ - try { \ - expression; \ - } catch ( const std::exception &e ) { \ - problem() << "caught exception (" << e.what() << ") in destructor (" << __FUNCTION__ << ")" << endl; \ - } catch ( ... ) { \ - problem() << "caught unknown exception in destructor (" << __FUNCTION__ << ")" << endl; \ - } - -#undef MONGO_NORETURN diff --git a/util/background.cpp b/util/background.cpp deleted file mode 100644 index 215b27155a4..00000000000 --- a/util/background.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// @file background.cpp - -/* 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. - */ - -#include "pch.h" - -#include "concurrency/mutex.h" -#include "concurrency/spin_lock.h" - -#include "background.h" -#include "time_support.h" -#include "timer.h" - -#include "mongoutils/str.h" - -namespace mongo { - - // both the BackgroundJob and the internal thread point to JobStatus - struct BackgroundJob::JobStatus { - JobStatus( bool delFlag ) - : deleteSelf(delFlag), m("backgroundJob"), state(NotStarted) { } - - const bool deleteSelf; - - mongo::mutex m; // protects state below - boost::condition finished; // means _state == Done - State state; - }; - - BackgroundJob::BackgroundJob( bool selfDelete ) { - _status.reset( new JobStatus( selfDelete ) ); - } - - // Background object can be only be destroyed after jobBody() ran - void BackgroundJob::jobBody( boost::shared_ptr<JobStatus> status ) { - LOG(1) << "BackgroundJob starting: " << name() << endl; - { - scoped_lock l( status->m ); - massert( 13643 , mongoutils::str::stream() << "backgroundjob already started: " << name() , status->state == NotStarted ); - status->state = Running; - } - - const string threadName = name(); - if( ! threadName.empty() ) - setThreadName( threadName.c_str() ); - - try { - run(); - } - catch ( std::exception& e ) { - log( LL_ERROR ) << "backgroundjob " << name() << "error: " << e.what() << endl; - } - catch(...) { - log( LL_ERROR ) << "uncaught exception in BackgroundJob " << name() << endl; - } - - { - scoped_lock l( status->m ); - status->state = Done; - status->finished.notify_all(); - } - - if( status->deleteSelf ) - delete this; - } - - BackgroundJob& BackgroundJob::go() { - boost::thread t( boost::bind( &BackgroundJob::jobBody , this, _status ) ); - return *this; - } - - bool BackgroundJob::wait( unsigned msTimeOut ) { - assert( !_status->deleteSelf ); // you cannot call wait on a self-deleting job - scoped_lock l( _status->m ); - while ( _status->state != Done ) { - if ( msTimeOut ) { - // add msTimeOut millisecond to current time - boost::xtime xt; - boost::xtime_get( &xt, boost::TIME_UTC ); - - unsigned long long ns = msTimeOut * 1000000ULL; // milli to nano - if ( xt.nsec + ns < 1000000000 ) { - xt.nsec = (xtime::xtime_nsec_t) (xt.nsec + ns); - } - else { - xt.sec += 1 + ns / 1000000000; - xt.nsec = ( ns + xt.nsec ) % 1000000000; - } - - if ( ! _status->finished.timed_wait( l.boost() , xt ) ) - return false; - - } - else { - _status->finished.wait( l.boost() ); - } - } - return true; - } - - BackgroundJob::State BackgroundJob::getState() const { - scoped_lock l( _status->m); - return _status->state; - } - - bool BackgroundJob::running() const { - scoped_lock l( _status->m); - return _status->state == Running; - } - - // ------------------------- - - PeriodicTask::PeriodicTask() { - if ( ! theRunner ) - theRunner = new Runner(); - theRunner->add( this ); - } - - PeriodicTask::~PeriodicTask() { - theRunner->remove( this ); - } - - void PeriodicTask::Runner::add( PeriodicTask* task ) { - scoped_spinlock lk( _lock ); - _tasks.push_back( task ); - } - - void PeriodicTask::Runner::remove( PeriodicTask* task ) { - scoped_spinlock lk( _lock ); - for ( size_t i=0; i<_tasks.size(); i++ ) { - if ( _tasks[i] == task ) { - _tasks[i] = 0; - break; - } - } - } - - void PeriodicTask::Runner::run() { - int sleeptime = 60; - DEV sleeptime = 5; // to catch race conditions - - while ( ! inShutdown() ) { - - sleepsecs( sleeptime ); - - scoped_spinlock lk( _lock ); - - size_t size = _tasks.size(); - - for ( size_t i=0; i<size; i++ ) { - PeriodicTask * t = _tasks[i]; - if ( ! t ) - continue; - - if ( inShutdown() ) - break; - - Timer timer; - try { - t->taskDoWork(); - } - catch ( std::exception& e ) { - error() << "task: " << t->taskName() << " failed: " << e.what() << endl; - } - catch ( ... ) { - error() << "task: " << t->taskName() << " failed with unknown error" << endl; - } - - int ms = timer.millis(); - LOG( ms <= 3 ? 1 : 0 ) << "task: " << t->taskName() << " took: " << ms << "ms" << endl; - } - } - } - - PeriodicTask::Runner* PeriodicTask::theRunner = 0; - -} // namespace mongo diff --git a/util/background.h b/util/background.h deleted file mode 100644 index 496a1f44f88..00000000000 --- a/util/background.h +++ /dev/null @@ -1,155 +0,0 @@ -// @file background.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 - -#include "concurrency/spin_lock.h" - -namespace mongo { - - /** - * Background thread dispatching. - * subclass and define run() - * - * It is ok to call go(), that is, run the job, more than once -- if the - * previous invocation has finished. Thus one pattern of use is to embed - * a backgroundjob in your object and reuse it (or same thing with - * inheritance). Each go() call spawns a new thread. - * - * Thread safety: - * note when job destructs, the thread is not terminated if still running. - * generally if the thread could still be running, allocate the job dynamically - * and set deleteSelf to true. - * - * go() and wait() are not thread safe - * run() will be executed on the background thread - * BackgroundJob object must exist for as long the background thread is running - */ - - class BackgroundJob : boost::noncopyable { - protected: - /** - * sub-class must intantiate the BackgrounJob - * - * @param selfDelete if set to true, object will destruct itself after the run() finished - * @note selfDelete instantes cannot be wait()-ed upon - */ - explicit BackgroundJob(bool selfDelete = false); - - virtual string name() const = 0; - - /** - * define this to do your work. - * after this returns, state is set to done. - * after this returns, deleted if deleteSelf true. - * - * NOTE: - * if run() throws, the exception will be caught within 'this' object and will ultimately lead to the - * BackgroundJob's thread being finished, as if run() returned. - * - */ - virtual void run() = 0; - - public: - enum State { - NotStarted, - Running, - Done - }; - - virtual ~BackgroundJob() { } - - /** - * starts job. - * returns immediatelly after dispatching. - * - * @note the BackgroundJob object must live for as long the thread is still running, ie - * until getState() returns Done. - */ - BackgroundJob& go(); - - /** - * wait for completion. - * - * @param msTimeOut maximum amount of time to wait in millisecons - * @return true if did not time out. false otherwise. - * - * @note you can call wait() more than once if the first call times out. - * but you cannot call wait on a self-deleting job. - */ - bool wait( unsigned msTimeOut = 0 ); - - // accessors - State getState() const; - bool running() const; - - private: - struct JobStatus; - boost::shared_ptr<JobStatus> _status; // shared between 'this' and body() thread - - void jobBody( boost::shared_ptr<JobStatus> status ); - - }; - - /** - * these run "roughly" every minute - * instantiate statically - * class MyTask : public PeriodicTask { - * public: - * virtual string name() const { return "MyTask; " } - * virtual void doWork() { log() << "hi" << endl; } - * } myTask; - */ - class PeriodicTask { - public: - PeriodicTask(); - virtual ~PeriodicTask(); - - virtual void taskDoWork() = 0; - virtual string taskName() const = 0; - - class Runner : public BackgroundJob { - public: - virtual ~Runner(){} - - virtual string name() const { return "PeriodicTask::Runner"; } - - virtual void run(); - - void add( PeriodicTask* task ); - void remove( PeriodicTask* task ); - - private: - - SpinLock _lock; - - // these are NOT owned by Runner - // Runner will not delete these - // this never gets smaller - // only fields replaced with nulls - vector<PeriodicTask*> _tasks; - - }; - - static Runner* theRunner; - - }; - - - - -} // namespace mongo diff --git a/util/base64.cpp b/util/base64.cpp deleted file mode 100644 index aff06e26126..00000000000 --- a/util/base64.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// util/base64.cpp - - -/* 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. - */ - -#include "pch.h" -#include "base64.h" - -namespace mongo { - namespace base64 { - - Alphabet alphabet; - - void encode( stringstream& ss , const char * data , int size ) { - for ( int i=0; i<size; i+=3 ) { - int left = size - i; - const unsigned char * start = (const unsigned char*)data + i; - - // byte 0 - ss << alphabet.e(start[0]>>2); - - // byte 1 - unsigned char temp = ( start[0] << 4 ); - if ( left == 1 ) { - ss << alphabet.e(temp); - break; - } - temp |= ( ( start[1] >> 4 ) & 0xF ); - ss << alphabet.e(temp); - - // byte 2 - temp = ( start[1] & 0xF ) << 2; - if ( left == 2 ) { - ss << alphabet.e(temp); - break; - } - temp |= ( ( start[2] >> 6 ) & 0x3 ); - ss << alphabet.e(temp); - - // byte 3 - ss << alphabet.e(start[2] & 0x3f); - } - - int mod = size % 3; - if ( mod == 1 ) { - ss << "=="; - } - else if ( mod == 2 ) { - ss << "="; - } - } - - - string encode( const char * data , int size ) { - stringstream ss; - encode( ss , data ,size ); - return ss.str(); - } - - string encode( const string& s ) { - return encode( s.c_str() , s.size() ); - } - - - void decode( stringstream& ss , const string& s ) { - uassert( 10270 , "invalid base64" , s.size() % 4 == 0 ); - const unsigned char * data = (const unsigned char*)s.c_str(); - int size = s.size(); - - unsigned char buf[3]; - for ( int i=0; i<size; i+=4) { - const unsigned char * start = data + i; - buf[0] = ( ( alphabet.decode[start[0]] << 2 ) & 0xFC ) | ( ( alphabet.decode[start[1]] >> 4 ) & 0x3 ); - buf[1] = ( ( alphabet.decode[start[1]] << 4 ) & 0xF0 ) | ( ( alphabet.decode[start[2]] >> 2 ) & 0xF ); - buf[2] = ( ( alphabet.decode[start[2]] << 6 ) & 0xC0 ) | ( ( alphabet.decode[start[3]] & 0x3F ) ); - - int len = 3; - if ( start[3] == '=' ) { - len = 2; - if ( start[2] == '=' ) { - len = 1; - } - } - ss.write( (const char*)buf , len ); - } - } - - string decode( const string& s ) { - stringstream ss; - decode( ss , s ); - return ss.str(); - } - - } -} - diff --git a/util/base64.h b/util/base64.h deleted file mode 100644 index 505b5d78cca..00000000000 --- a/util/base64.h +++ /dev/null @@ -1,68 +0,0 @@ -// util/base64.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 { - namespace base64 { - - class Alphabet { - public: - Alphabet() - : encode((unsigned char*) - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789" - "+/") - , decode(new unsigned char[257]) { - memset( decode.get() , 0 , 256 ); - for ( int i=0; i<64; i++ ) { - decode[ encode[i] ] = i; - } - - test(); - } - void test() { - assert( strlen( (char*)encode ) == 64 ); - for ( int i=0; i<26; i++ ) - assert( encode[i] == toupper( encode[i+26] ) ); - } - - char e( int x ) { - return encode[x&0x3f]; - } - - private: - const unsigned char * encode; - public: - boost::scoped_array<unsigned char> decode; - }; - - extern Alphabet alphabet; - - - void encode( stringstream& ss , const char * data , int size ); - string encode( const char * data , int size ); - string encode( const string& s ); - - void decode( stringstream& ss , const string& s ); - string decode( const string& s ); - - - void testAlphabet(); - } -} diff --git a/util/bson_util.h b/util/bson_util.h deleted file mode 100644 index 973e31f1af1..00000000000 --- a/util/bson_util.h +++ /dev/null @@ -1,42 +0,0 @@ -// bson_util.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 - -#include "../pch.h" - -namespace mongo { - -template <typename T> -void bsonArrToNumVector(BSONElement el, vector<T>& results){ - - if(el.type() == Array){ - - vector<BSONElement> elements = el.Array(); - - for(vector<BSONElement>::iterator i = elements.begin(); i != elements.end(); ++i){ - results.push_back( (T) (*i).Number() ); - } - } - else if(el.isNumber()){ - results.push_back( (T) el.Number() ); - } - -} - - -} diff --git a/util/bufreader.h b/util/bufreader.h deleted file mode 100644 index 53f0ba744e2..00000000000 --- a/util/bufreader.h +++ /dev/null @@ -1,100 +0,0 @@ -// @file bufreader.h parse a memory region into usable pieces - -/** -* 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 { - - /** helper to read and parse a block of memory - methods throw the eof exception if the operation would pass the end of the - buffer with which we are working. - */ - class BufReader : boost::noncopyable { - public: - class eof : public std::exception { - public: - eof() { } - virtual const char * what() { return "BufReader eof"; } - }; - - BufReader(const void *p, unsigned len) : _start(p), _pos(p), _end(((char *)_pos)+len) { } - - bool atEof() const { return _pos == _end; } - - /** read in the object specified, and advance buffer pointer */ - template <typename T> - void read(T &t) { - T* cur = (T*) _pos; - T *next = cur + 1; - if( _end < next ) throw eof(); - t = *cur; - _pos = next; - } - - /** verify we can look at t, but do not advance */ - template <typename T> - void peek(T &t) { - T* cur = (T*) _pos; - T *next = cur + 1; - if( _end < next ) throw eof(); - t = *cur; - } - - /** return current offset into buffer */ - unsigned offset() const { return (char*)_pos - (char*)_start; } - - /** return remaining bytes */ - unsigned remaining() const { return (char*)_end -(char*)_pos; } - - /** back up by nbytes */ - void rewind(unsigned nbytes) { - _pos = ((char *) _pos) - nbytes; - assert( _pos >= _start ); - } - - /** return current position pointer, and advance by len */ - const void* skip(unsigned len) { - const char *nxt = ((char *) _pos) + len; - if( _end < nxt ) throw eof(); - const void *p = _pos; - _pos = nxt; - return p; - } - - void readStr(string& s) { - StringBuilder b; - while( 1 ) { - char ch; - read(ch); - if( ch == 0 ) - break; - b << ch; - } - s = b.str(); - } - - const void* pos() { return _pos; } - const void* start() { return _start; } - - private: - const void *_start; - const void *_pos; - const void *_end; - }; - -} diff --git a/util/checksum.h b/util/checksum.h deleted file mode 100644 index 009ab56fbeb..00000000000 --- a/util/checksum.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once
-#include "../pch.h"
-namespace mongo {
- /** a simple, rather dumb, but very fast checksum. see perftests.cpp for unit tests. */
- struct Checksum {
- union {
- unsigned char bytes[16];
- unsigned long long words[2];
- };
-
- // if you change this you must bump dur::CurrentVersion
- void gen(const void *buf, unsigned len) {
- wassert( ((size_t)buf) % 8 == 0 ); // performance warning
- unsigned n = len / 8 / 2;
- const unsigned long long *p = (const unsigned long long *) buf;
- unsigned long long a = 0;
- for( unsigned i = 0; i < n; i++ ) {
- a += (*p ^ i);
- p++;
- }
- unsigned long long b = 0;
- for( unsigned i = 0; i < n; i++ ) {
- b += (*p ^ i);
- p++;
- }
- unsigned long long c = 0;
- for( unsigned i = n * 2 * 8; i < len; i++ ) { // 0-7 bytes left
- c = (c << 8) | ((const char *)buf)[i];
- }
- words[0] = a ^ len;
- words[1] = b ^ c;
- }
-
- bool operator==(const Checksum& rhs) const { return words[0]==rhs.words[0] && words[1]==rhs.words[1]; }
- bool operator!=(const Checksum& rhs) const { return words[0]!=rhs.words[0] || words[1]!=rhs.words[1]; }
- };
-}
diff --git a/util/compress.cpp b/util/compress.cpp deleted file mode 100644 index bcde488b88b..00000000000 --- a/util/compress.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// @file compress.cpp - -#include "../third_party/snappy/snappy.h" -#include "compress.h" -#include <string> -#include <string.h> -#include <assert.h> - -namespace mongo { - - void rawCompress(const char* input, - size_t input_length, - char* compressed, - size_t* compressed_length) - { - snappy::RawCompress(input, input_length, compressed, compressed_length); - } - - size_t maxCompressedLength(size_t source_len) { - return snappy::MaxCompressedLength(source_len); - } - - size_t compress(const char* input, size_t input_length, std::string* output) { - return snappy::Compress(input, input_length, output); - } - - bool uncompress(const char* compressed, size_t compressed_length, std::string* uncompressed) { - return snappy::Uncompress(compressed, compressed_length, uncompressed); - } - -} diff --git a/util/compress.h b/util/compress.h deleted file mode 100644 index 5bc5a3392bb..00000000000 --- a/util/compress.h +++ /dev/null @@ -1,21 +0,0 @@ -// @file compress.h - -#pragma once - -#include <string> - -namespace mongo { - - size_t compress(const char* input, size_t input_length, std::string* output); - - bool uncompress(const char* compressed, size_t compressed_length, std::string* uncompressed); - - size_t maxCompressedLength(size_t source_len); - void rawCompress(const char* input, - size_t input_length, - char* compressed, - size_t* compressed_length); - -} - - diff --git a/util/concurrency/README b/util/concurrency/README deleted file mode 100644 index 1d72a1ce4ec..00000000000 --- a/util/concurrency/README +++ /dev/null @@ -1,19 +0,0 @@ -util/concurrency/ files - -list.h - a list class that is lock-free for reads -rwlock.h - read/write locks (RWLock) -msg.h - message passing between threads -task.h - an abstraction around threads -mutex.h - small enhancements that wrap boost::mutex -mvar.h - This is based on haskell's MVar synchronization primitive: - http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Control-Concurrent-MVar.html - It is a thread-safe queue that can hold at most one object. - You can also think of it as a box that can be either full or empty. -value.h - Atomic wrapper for values/objects that are copy constructable / assignable -thread_pool.h -spinlock.h -synchronization.h - A class to establish a sinchronization point between two threads. One thread is the waiter and one - is the notifier. After the notification event, both proceed normally. diff --git a/util/concurrency/list.h b/util/concurrency/list.h deleted file mode 100644 index 01bae6fa8a2..00000000000 --- a/util/concurrency/list.h +++ /dev/null @@ -1,97 +0,0 @@ -// list.h - -/** -* Copyright (C) 2008 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 { - - /* this class uses a mutex for writes, but not for reads. - we can get fancier later... - - struct Member : public List1<Member>::Base { - const char *host; - int port; - }; - List1<Member> _members; - _members.head()->next(); - - */ - template<typename T> - class List1 : boost::noncopyable { - public: - /* next() and head() return 0 at end of list */ - - List1() : _head(0), _m("List1"), _orphans(0) { } - - class Base { - friend class List1; - T *_next; - public: - Base() : _next(0){} - ~Base() { wassert(false); } // we never want this to happen - T* next() const { return _next; } - }; - - /** note this is safe: - - T* p = mylist.head(); - if( p ) - use(p); - - and this is not: - - if( mylist.head() ) - use( mylist.head() ); // could become 0 - */ - T* head() const { return (T*) _head; } - - void push(T* t) { - assert( t->_next == 0 ); - scoped_lock lk(_m); - t->_next = (T*) _head; - _head = t; - } - - // intentionally leaks. - void orphanAll() { - scoped_lock lk(_m); - _head = 0; - } - - /* t is not deleted, but is removed from the list. (orphaned) */ - void orphan(T* t) { - scoped_lock lk(_m); - T *&prev = (T*&) _head; - T *n = prev; - while( n != t ) { - uassert( 14050 , "List1: item to orphan not in list", n ); - prev = n->_next; - n = prev; - } - prev = t->_next; - if( ++_orphans > 500 ) - log() << "warning List1 orphans=" << _orphans << '\n'; - } - - private: - volatile T *_head; - mongo::mutex _m; - int _orphans; - }; - -}; diff --git a/util/concurrency/msg.h b/util/concurrency/msg.h deleted file mode 100644 index f7c6788dadc..00000000000 --- a/util/concurrency/msg.h +++ /dev/null @@ -1,61 +0,0 @@ -// @file msg.h - interthread message passing - -/** -* Copyright (C) 2008 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,b -* 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 - -#include <deque> -#include "task.h" - -namespace mongo { - - namespace task { - - typedef boost::function<void()> lam; - - /** typical usage is: task::fork( new Server("threadname") ); */ - class Server : public Task { - public: - /** send a message to the port */ - void send(lam); - - Server(string name) : _name(name), rq(false) { } - virtual ~Server() { } - - /** send message but block until function completes */ - void call(const lam&); - - void requeue() { rq = true; } - - protected: - /* REMINDER : for use in mongod, you will want to have this call Client::initThread(). */ - virtual void starting() { } - - private: - virtual bool initClient() { return true; } - virtual string name() const { return _name; } - void doWork(); - deque<lam> d; - boost::mutex m; - boost::condition c; - string _name; - bool rq; - }; - - } - -} diff --git a/util/concurrency/mutex.h b/util/concurrency/mutex.h deleted file mode 100644 index f17c3f0891d..00000000000 --- a/util/concurrency/mutex.h +++ /dev/null @@ -1,279 +0,0 @@ -// @file mutex.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 - -#include <map> -#include <set> -#include "../heapcheck.h" - -namespace mongo { - - void printStackTrace( ostream &o ); - - class mutex; - - inline boost::xtime incxtimemillis( long long s ) { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += (int)( s / 1000 ); - xt.nsec += (int)(( s % 1000 ) * 1000000); - if ( xt.nsec >= 1000000000 ) { - xt.nsec -= 1000000000; - xt.sec++; - } - return xt; - } - - /** only used on _DEBUG builds. - MutexDebugger checks that we always acquire locks for multiple mutexes in a consistant (acyclic) order. - If we were inconsistent we could deadlock. - */ - class MutexDebugger { - typedef const char * mid; // mid = mutex ID - typedef map<mid,int> Preceeding; - map< mid, int > maxNest; - boost::thread_specific_ptr< Preceeding > us; - map< mid, set<mid> > followers; - boost::mutex &x; - unsigned magic; - void aBreakPoint() { } // for debugging - public: - // set these to create an assert that - // b must never be locked before a - // so - // a.lock(); b.lock(); is fine - // b.lock(); alone is fine too - // only checked on _DEBUG builds. - string a,b; - - /** outputs some diagnostic info on mutexes (on _DEBUG builds) */ - void programEnding(); - - MutexDebugger(); - - void entering(mid m) { - if( this == 0 ) return; - assert( magic == 0x12345678 ); - - Preceeding *_preceeding = us.get(); - if( _preceeding == 0 ) - us.reset( _preceeding = new Preceeding() ); - Preceeding &preceeding = *_preceeding; - - if( a == m ) { - aBreakPoint(); - if( preceeding[b.c_str()] ) { - cout << "****** MutexDebugger error! warning " << b << " was locked before " << a << endl; - assert(false); - } - } - - preceeding[m]++; - if( preceeding[m] > 1 ) { - // recursive re-locking. - if( preceeding[m] > maxNest[m] ) - maxNest[m] = preceeding[m]; - return; - } - - bool failed = false; - string err; - { - boost::mutex::scoped_lock lk(x); - followers[m]; - for( Preceeding::iterator i = preceeding.begin(); i != preceeding.end(); i++ ) { - if( m != i->first && i->second > 0 ) { - followers[i->first].insert(m); - if( followers[m].count(i->first) != 0 ) { - failed = true; - stringstream ss; - mid bad = i->first; - ss << "mutex problem" << - "\n when locking " << m << - "\n " << bad << " was already locked and should not be." - "\n set a and b above to debug.\n"; - stringstream q; - for( Preceeding::iterator i = preceeding.begin(); i != preceeding.end(); i++ ) { - if( i->first != m && i->first != bad && i->second > 0 ) - q << " " << i->first << '\n'; - } - string also = q.str(); - if( !also.empty() ) - ss << "also locked before " << m << " in this thread (no particular order):\n" << also; - err = ss.str(); - break; - } - } - } - } - if( failed ) { - cout << err << endl; - assert( 0 ); - } - } - void leaving(mid m) { - if( this == 0 ) return; // still in startup pre-main() - Preceeding& preceeding = *us.get(); - preceeding[m]--; - if( preceeding[m] < 0 ) { - cout << "ERROR: lock count for " << m << " is " << preceeding[m] << endl; - assert( preceeding[m] >= 0 ); - } - } - }; - extern MutexDebugger &mutexDebugger; - - // If you create a local static instance of this class, that instance will be destroyed - // before all global static objects are destroyed, so _destroyingStatics will be set - // to true before the global static variables are destroyed. - class StaticObserver : boost::noncopyable { - public: - static bool _destroyingStatics; - ~StaticObserver() { _destroyingStatics = true; } - }; - - /** On pthread systems, it is an error to destroy a mutex while held (boost mutex - * may use pthread). Static global mutexes may be held upon shutdown in our - * implementation, and this way we avoid destroying them. - * NOT recursive. - */ - class mutex : boost::noncopyable { - public: -#if defined(_DEBUG) - const char * const _name; - mutex(const char *name) : _name(name) -#else - mutex(const char *) -#endif - { - _m = new boost::timed_mutex(); - IGNORE_OBJECT( _m ); // Turn-off heap checking on _m - } - ~mutex() { - if( !StaticObserver::_destroyingStatics ) { - UNIGNORE_OBJECT( _m ); - delete _m; - } - } - - class try_lock : boost::noncopyable { - public: - try_lock( mongo::mutex &m , int millis = 0 ) - : _l( m.boost() , incxtimemillis( millis ) ) , -#if BOOST_VERSION >= 103500 - ok( _l.owns_lock() ) -#else - ok( _l.locked() ) -#endif - { } - private: - boost::timed_mutex::scoped_timed_lock _l; - public: - const bool ok; - }; - - class scoped_lock : boost::noncopyable { - public: -#if defined(_DEBUG) - struct PostStaticCheck { - PostStaticCheck() { - if ( StaticObserver::_destroyingStatics ) { - cout << "trying to lock a mongo::mutex during static shutdown" << endl; - printStackTrace( cout ); - } - } - }; - - PostStaticCheck _check; - mongo::mutex * const _mut; -#endif - scoped_lock( mongo::mutex &m ) : -#if defined(_DEBUG) - _mut(&m), -#endif - _l( m.boost() ) { -#if defined(_DEBUG) - mutexDebugger.entering(_mut->_name); -#endif - } - ~scoped_lock() { -#if defined(_DEBUG) - mutexDebugger.leaving(_mut->_name); -#endif - } - boost::timed_mutex::scoped_lock &boost() { return _l; } - private: - boost::timed_mutex::scoped_lock _l; - }; - private: - boost::timed_mutex &boost() { return *_m; } - boost::timed_mutex *_m; - }; - - typedef mutex::scoped_lock scoped_lock; - typedef boost::recursive_mutex::scoped_lock recursive_scoped_lock; - - /** The concept with SimpleMutex is that it is a basic lock/unlock with no - special functionality (such as try and try timeout). Thus it can be - implemented using OS-specific facilities in all environments (if desired). - On Windows, the implementation below is faster than boost mutex. - */ -#if defined(_WIN32) - class SimpleMutex : boost::noncopyable { - CRITICAL_SECTION _cs; - public: - SimpleMutex(const char *name) { InitializeCriticalSection(&_cs); } - ~SimpleMutex() { DeleteCriticalSection(&_cs); } - - void lock() { EnterCriticalSection(&_cs); } - void unlock() { LeaveCriticalSection(&_cs); } - - class scoped_lock : boost::noncopyable { - SimpleMutex& _m; - public: - scoped_lock( SimpleMutex &m ) : _m(m) { _m.lock(); } - ~scoped_lock() { _m.unlock(); } - }; - }; -#else - class SimpleMutex : boost::noncopyable { - public: - SimpleMutex(const char* name) { assert( pthread_mutex_init(&_lock,0) == 0 ); } - ~SimpleMutex(){ - if ( ! StaticObserver::_destroyingStatics ) { - assert( pthread_mutex_destroy(&_lock) == 0 ); - } - } - - void lock() { assert( pthread_mutex_lock(&_lock) == 0 ); } - void unlock() { assert( pthread_mutex_unlock(&_lock) == 0 ); } - - class scoped_lock : boost::noncopyable { - SimpleMutex& _m; - public: - scoped_lock( SimpleMutex &m ) : _m(m) { _m.lock(); } - ~scoped_lock() { _m.unlock(); } - }; - - private: - pthread_mutex_t _lock; - }; - -#endif - -} diff --git a/util/concurrency/mvar.h b/util/concurrency/mvar.h deleted file mode 100644 index 9c7a505b6d5..00000000000 --- a/util/concurrency/mvar.h +++ /dev/null @@ -1,116 +0,0 @@ -// mvar.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. - */ - -namespace mongo { - - /* This is based on haskell's MVar synchronization primitive: - * http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.2.0.0/Control-Concurrent-MVar.html - * - * It is a thread-safe queue that can hold at most one object. - * You can also think of it as a box that can be either full or empty. - */ - - template <typename T> - class MVar { - public: - enum State {EMPTY=0, FULL}; - - // create an empty MVar - MVar() - : _state(EMPTY) - {} - - // creates a full MVar - MVar(const T& val) - : _state(FULL) - , _value(val) - {} - - // puts val into the MVar and returns true or returns false if full - // never blocks - bool tryPut(const T& val) { - // intentionally repeat test before and after lock - if (_state == FULL) return false; - Mutex::scoped_lock lock(_mutex); - if (_state == FULL) return false; - - _state = FULL; - _value = val; - - // unblock threads waiting to 'take' - _condition.notify_all(); - - return true; - } - - // puts val into the MVar - // will block if the MVar is already full - void put(const T& val) { - Mutex::scoped_lock lock(_mutex); - while (!tryPut(val)) { - // unlocks lock while waiting and relocks before returning - _condition.wait(lock); - } - } - - // takes val out of the MVar and returns true or returns false if empty - // never blocks - bool tryTake(T& out) { - // intentionally repeat test before and after lock - if (_state == EMPTY) return false; - Mutex::scoped_lock lock(_mutex); - if (_state == EMPTY) return false; - - _state = EMPTY; - out = _value; - - // unblock threads waiting to 'put' - _condition.notify_all(); - - return true; - } - - // takes val out of the MVar - // will block if the MVar is empty - T take() { - T ret = T(); - - Mutex::scoped_lock lock(_mutex); - while (!tryTake(ret)) { - // unlocks lock while waiting and relocks before returning - _condition.wait(lock); - } - - return ret; - } - - - // Note: this is fast because there is no locking, but state could - // change before you get a chance to act on it. - // Mainly useful for sanity checks / asserts. - State getState() { return _state; } - - - private: - State _state; - T _value; - typedef boost::recursive_mutex Mutex; - Mutex _mutex; - boost::condition _condition; - }; - -} diff --git a/util/concurrency/race.h b/util/concurrency/race.h deleted file mode 100644 index 4644e373cda..00000000000 --- a/util/concurrency/race.h +++ /dev/null @@ -1,115 +0,0 @@ -#pragma once - -#include "../goodies.h" // printStackTrace - -namespace mongo { - - /** some self-testing of synchronization and attempts to catch race conditions. - - use something like: - - CodeBlock myBlock; - - void foo() { - CodeBlock::Within w(myBlock); - ... - } - - In _DEBUG builds, will (sometimes/maybe) fail if two threads are in the same code block at - the same time. Also detects and disallows recursion. - */ - -#ifdef _WIN32 - typedef unsigned threadId_t; -#else - typedef pthread_t threadId_t; -#endif - - -#if defined(_DEBUG) - - namespace race { - - class CodePoint { - public: - string lastName; - threadId_t lastTid; - string file; - CodePoint(string f) : lastTid(0), file(f) { } - }; - class Check { - public: - Check(CodePoint& p) { - threadId_t t = GetCurrentThreadId(); - if( p.lastTid == 0 ) { - p.lastTid = t; - p.lastName = getThreadName(); - } - else if( t != p.lastTid ) { - log() << "\n\n\n\n\nRACE? error assert\n " << p.file << '\n' - << " " << p.lastName - << " " << getThreadName() << "\n\n" << endl; - mongoAbort("racecheck"); - } - }; - }; - - } - -#define RACECHECK - // dm TODO - the right code for this file is in a different branch at the moment (merge) - //#define RACECHECK - //static race::CodePoint __cp(__FILE__); - //race::Check __ck(__cp); - - class CodeBlock { - volatile int n; - threadId_t tid; - void fail() { - log() << "synchronization (race condition) failure" << endl; - printStackTrace(); - ::abort(); - } - void enter() { - if( ++n != 1 ) fail(); -#if defined(_WIN32) - tid = GetCurrentThreadId(); -#endif - } - void leave() { - if( --n != 0 ) fail(); - } - public: - CodeBlock() : n(0) { } - - class Within { - CodeBlock& _s; - public: - Within(CodeBlock& s) : _s(s) { _s.enter(); } - ~Within() { _s.leave(); } - }; - - void assertWithin() { - assert( n == 1 ); -#if defined(_WIN32) - assert( GetCurrentThreadId() == tid ); -#endif - } - }; - -#else - -#define RACECHECK - - class CodeBlock{ - public: - class Within { - public: - Within(CodeBlock&) { } - }; - void assertWithin() { } - }; - -#endif - -} // namespace diff --git a/util/concurrency/rwlock.h b/util/concurrency/rwlock.h deleted file mode 100644 index ed5bda07519..00000000000 --- a/util/concurrency/rwlock.h +++ /dev/null @@ -1,396 +0,0 @@ -// @file rwlock.h generic reader-writer lock (cross platform support) - -/* - * 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/>. - */ - -#pragma once - -#include "mutex.h" -#include "../time_support.h" - -// this requires newer windows versions -// it works better than sharable_mutex under high contention -#if defined(_WIN64) -//#define MONGO_USE_SRW_ON_WINDOWS 1 -#endif - -#if !defined(MONGO_USE_SRW_ON_WINDOWS) - -#if BOOST_VERSION >= 103500 -# define BOOST_RWLOCK -#else -# if defined(_WIN32) -# error need boost >= 1.35 for windows -# endif -# include <pthread.h> -#endif - -#if defined(_WIN32) -# include "shared_mutex_win.hpp" -namespace mongo { - typedef boost::modified_shared_mutex shared_mutex; -} -# undef assert -# define assert MONGO_assert -#elif defined(BOOST_RWLOCK) -# include <boost/thread/shared_mutex.hpp> -# undef assert -# define assert MONGO_assert -#endif - -#endif - -namespace mongo { - -#if defined(MONGO_USE_SRW_ON_WINDOWS) && defined(_WIN32) - - // Windows RWLock implementation (requires newer versions of windows thus the above macro) - class RWLock : boost::noncopyable { - public: - RWLock(const char *, int lowPriorityWaitMS=0 ) : _lowPriorityWaitMS(lowPriorityWaitMS) - { InitializeSRWLock(&_lock); } - ~RWLock() { } - const char * implType() const { return "WINSRW"; } - int lowPriorityWaitMS() const { return _lowPriorityWaitMS; } - void lock() { AcquireSRWLockExclusive(&_lock); } - void unlock() { ReleaseSRWLockExclusive(&_lock); } - void lock_shared() { AcquireSRWLockShared(&_lock); } - void unlock_shared() { ReleaseSRWLockShared(&_lock); } - bool lock_shared_try( int millis ) { - if( TryAcquireSRWLockShared(&_lock) ) - return true; - if( millis == 0 ) - return false; - unsigned long long end = curTimeMicros64() + millis*1000; - while( 1 ) { - Sleep(1); - if( TryAcquireSRWLockShared(&_lock) ) - return true; - if( curTimeMicros64() >= end ) - break; - } - return false; - } - bool lock_try( int millis = 0 ) { - if( TryAcquireSRWLockExclusive(&_lock) ) // quick check to optimistically avoid calling curTimeMicros64 - return true; - if( millis == 0 ) - return false; - unsigned long long end = curTimeMicros64() + millis*1000; - do { - Sleep(1); - if( TryAcquireSRWLockExclusive(&_lock) ) - return true; - } while( curTimeMicros64() < end ); - return false; - } - private: - SRWLOCK _lock; - const int _lowPriorityWaitMS; - }; - -#elif defined(BOOST_RWLOCK) - - // Boost based RWLock implementation - class RWLock : boost::noncopyable { - shared_mutex _m; - const int _lowPriorityWaitMS; - public: - const char * const _name; - - RWLock(const char *name, int lowPriorityWait=0) : _lowPriorityWaitMS(lowPriorityWait) , _name(name) { } - - const char * implType() const { return "boost"; } - - int lowPriorityWaitMS() const { return _lowPriorityWaitMS; } - - void lock() { - _m.lock(); - DEV mutexDebugger.entering(_name); - } - - /*void lock() { - // This sequence gives us the lock semantics we want: specifically that write lock acquisition is - // greedy EXCEPT when someone already is in upgradable state. - lockAsUpgradable(); - upgrade(); - DEV mutexDebugger.entering(_name); - }*/ - - void unlock() { - DEV mutexDebugger.leaving(_name); - _m.unlock(); - } - - void lockAsUpgradable() { - _m.lock_upgrade(); - } - void unlockFromUpgradable() { // upgradable -> unlocked - _m.unlock_upgrade(); - } - void upgrade() { // upgradable -> exclusive lock - _m.unlock_upgrade_and_lock(); - } - - void lock_shared() { - _m.lock_shared(); - } - void unlock_shared() { - _m.unlock_shared(); - } - - bool lock_shared_try( int millis ) { - if( _m.timed_lock_shared( boost::posix_time::milliseconds(millis) ) ) { - return true; - } - return false; - } - - bool lock_try( int millis = 0 ) { - if( _m.timed_lock( boost::posix_time::milliseconds(millis) ) ) { - DEV mutexDebugger.entering(_name); - return true; - } - return false; - } - }; - -#else - - // Posix RWLock implementation - class RWLock : boost::noncopyable { - pthread_rwlock_t _lock; - const int _lowPriorityWaitMS; - static void check( int x ) { - if( MONGO_likely(x == 0) ) - return; - log() << "pthread rwlock failed: " << x << endl; - assert( x == 0 ); - } - - public: - const char *_name; - RWLock(const char *name, int lowPriorityWaitMS=0) : _lowPriorityWaitMS(lowPriorityWaitMS), _name(name) - { - check( pthread_rwlock_init( &_lock , 0 ) ); - } - - ~RWLock() { - if ( ! StaticObserver::_destroyingStatics ) { - wassert( pthread_rwlock_destroy( &_lock ) == 0 ); // wassert as don't want to throw from a destructor - } - } - - const char * implType() const { return "posix"; } - - int lowPriorityWaitMS() const { return _lowPriorityWaitMS; } - - void lock() { - check( pthread_rwlock_wrlock( &_lock ) ); - DEV mutexDebugger.entering(_name); - } - void unlock() { - DEV mutexDebugger.leaving(_name); - check( pthread_rwlock_unlock( &_lock ) ); - } - - void lock_shared() { - check( pthread_rwlock_rdlock( &_lock ) ); - } - - void unlock_shared() { - check( pthread_rwlock_unlock( &_lock ) ); - } - - bool lock_shared_try( int millis ) { - return _try( millis , false ); - } - - bool lock_try( int millis = 0 ) { - if( _try( millis , true ) ) { - DEV mutexDebugger.entering(_name); - return true; - } - return false; - } - - bool _try( int millis , bool write ) { - while ( true ) { - int x = write ? - pthread_rwlock_trywrlock( &_lock ) : - pthread_rwlock_tryrdlock( &_lock ); - - if ( x <= 0 ) { - return true; - } - - if ( millis-- <= 0 ) - return false; - - if ( x == EBUSY ) { - sleepmillis(1); - continue; - } - check(x); - } - - return false; - } - - }; - -#endif - - /** throws on failure to acquire in the specified time period. */ - class rwlock_try_write : boost::noncopyable { - public: - struct exception { }; - rwlock_try_write(RWLock& l, int millis = 0) : _l(l) { - if( !l.lock_try(millis) ) - throw exception(); - } - ~rwlock_try_write() { _l.unlock(); } - private: - RWLock& _l; - }; - - class rwlock_shared : boost::noncopyable { - public: - rwlock_shared(RWLock& rwlock) : _r(rwlock) {_r.lock_shared(); } - ~rwlock_shared() { _r.unlock_shared(); } - private: - RWLock& _r; - }; - - /* scoped lock for RWLock */ - class rwlock : boost::noncopyable { - public: - /** - * @param write acquire write lock if true sharable if false - * @param lowPriority if > 0, will try to get the lock non-greedily for that many ms - */ - rwlock( const RWLock& lock , bool write, /* bool alreadyHaveLock = false , */int lowPriorityWaitMS = 0 ) - : _lock( (RWLock&)lock ) , _write( write ) { - - { - if ( _write ) { - - if ( ! lowPriorityWaitMS && lock.lowPriorityWaitMS() ) - lowPriorityWaitMS = lock.lowPriorityWaitMS(); - - if ( lowPriorityWaitMS ) { - bool got = false; - for ( int i=0; i<lowPriorityWaitMS; i++ ) { - if ( _lock.lock_try(0) ) { - got = true; - break; - } - - int sleep = 1; - if ( i > ( lowPriorityWaitMS / 20 ) ) - sleep = 10; - sleepmillis(sleep); - i += ( sleep - 1 ); - } - if ( ! got ) { - log() << "couldn't get lazy rwlock" << endl; - _lock.lock(); - } - } - else { - _lock.lock(); - } - - } - else { - _lock.lock_shared(); - } - } - } - ~rwlock() { - if ( _write ) - _lock.unlock(); - else - _lock.unlock_shared(); - } - private: - RWLock& _lock; - const bool _write; - }; - - /** recursive on shared locks is ok for this implementation */ - class RWLockRecursive : boost::noncopyable { - ThreadLocalValue<int> _state; - RWLock _lk; - friend class Exclusive; - public: - /** @param lpwaitms lazy wait */ - RWLockRecursive(const char *name, int lpwaitms) : _lk(name, lpwaitms) { } - - void assertExclusivelyLocked() { - dassert( _state.get() < 0 ); - } - - // RWLockRecursive::Exclusive scoped lock - class Exclusive : boost::noncopyable { - RWLockRecursive& _r; - rwlock *_scopedLock; - public: - Exclusive(RWLockRecursive& r) : _r(r), _scopedLock(0) { - int s = _r._state.get(); - dassert( s <= 0 ); - if( s == 0 ) - _scopedLock = new rwlock(_r._lk, true); - _r._state.set(s-1); - } - ~Exclusive() { - int s = _r._state.get(); - DEV wassert( s < 0 ); // wassert: don't throw from destructors - _r._state.set(s+1); - delete _scopedLock; - } - }; - - // RWLockRecursive::Shared scoped lock - class Shared : boost::noncopyable { - RWLockRecursive& _r; - bool _alreadyExclusive; - public: - Shared(RWLockRecursive& r) : _r(r) { - int s = _r._state.get(); - _alreadyExclusive = s < 0; - if( !_alreadyExclusive ) { - dassert( s >= 0 ); // -1 would mean exclusive - if( s == 0 ) - _r._lk.lock_shared(); - _r._state.set(s+1); - } - } - ~Shared() { - if( _alreadyExclusive ) { - DEV wassert( _r._state.get() < 0 ); - } - else { - int s = _r._state.get() - 1; - if( s == 0 ) - _r._lk.unlock_shared(); - _r._state.set(s); - DEV wassert( s >= 0 ); - } - } - }; - }; -} diff --git a/util/concurrency/shared_mutex_win.hpp b/util/concurrency/shared_mutex_win.hpp deleted file mode 100644 index e850fc6bab4..00000000000 --- a/util/concurrency/shared_mutex_win.hpp +++ /dev/null @@ -1,594 +0,0 @@ -#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP_MODIFIED
-#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP_MODIFIED
-
-// (C) Copyright 2006-8 Anthony Williams
-//
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-
-/* MongoDB :
- Slightly modified boost file to not die above 127 pending writes
- Here is what changed (from boost 1.42.0 shared_mutex.hpp):
- 1,2c1,2
- < #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
- < #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
- ---
- > #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP_MODIFIED
- > #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP_MODIFIED
- 22c27
- < class shared_mutex:
- ---
- > class modified_shared_mutex:
- 73c78
- < shared_mutex():
- ---
- > modified_shared_mutex():
- 84c89
- < ~shared_mutex()
- ---
- > ~modified_shared_mutex()
- 283a289,290
- > if( new_state.exclusive_waiting == 127 ) // the maximum already!
- > break;
-*/
-
-#include <boost/assert.hpp>
-#include <boost/detail/interlocked.hpp>
-#include <boost/thread/win32/thread_primitives.hpp>
-#include <boost/static_assert.hpp>
-#include <limits.h>
-#include <boost/utility.hpp>
-#include <boost/thread/thread_time.hpp>
-
-#include <boost/config/abi_prefix.hpp>
-
-namespace boost
-{
- class modified_shared_mutex:
- private boost::noncopyable
- {
- private:
- struct state_data
- {
- unsigned shared_count:11,
- shared_waiting:11,
- exclusive:1,
- upgrade:1,
- exclusive_waiting:7,
- exclusive_waiting_blocked:1;
-
- friend bool operator==(state_data const& lhs,state_data const& rhs)
- {
- return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
- }
- };
-
-
- template<typename T>
- T interlocked_compare_exchange(T* target,T new_value,T comparand)
- {
- BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
- long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
- *reinterpret_cast<long*>(&new_value),
- *reinterpret_cast<long*>(&comparand));
- return *reinterpret_cast<T const*>(&res);
- }
-
- state_data state;
- detail::win32::handle semaphores[2];
- detail::win32::handle &unlock_sem;
- detail::win32::handle &exclusive_sem;
- detail::win32::handle upgrade_sem;
-
- void release_waiters(state_data old_state)
- {
- if(old_state.exclusive_waiting)
- {
- BOOST_VERIFY(detail::win32::ReleaseSemaphore(exclusive_sem,1,0)!=0);
- }
-
- if(old_state.shared_waiting || old_state.exclusive_waiting)
- {
- BOOST_VERIFY(detail::win32::ReleaseSemaphore(unlock_sem,old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
- }
- }
-
-
- public:
- modified_shared_mutex():
- unlock_sem(semaphores[0]),
- exclusive_sem(semaphores[1])
- {
- unlock_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
- exclusive_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
- upgrade_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
- state_data state_={0};
- state=state_;
- }
-
- ~modified_shared_mutex()
- {
- detail::win32::CloseHandle(upgrade_sem);
- detail::win32::CloseHandle(unlock_sem);
- detail::win32::CloseHandle(exclusive_sem);
- }
-
- bool try_lock_shared()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
- {
- ++new_state.shared_count;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
- }
-
- void lock_shared()
- {
- BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
- }
-
- template<typename TimeDuration>
- bool timed_lock_shared(TimeDuration const & relative_time)
- {
- return timed_lock_shared(get_system_time()+relative_time);
- }
-
- bool timed_lock_shared(boost::system_time const& wait_until)
- {
- for(;;)
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.exclusive || new_state.exclusive_waiting_blocked)
- {
- ++new_state.shared_waiting;
- }
- else
- {
- ++new_state.shared_count;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
-
- if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
- {
- return true;
- }
-
- unsigned long const res=detail::win32::WaitForSingleObject(unlock_sem,::boost::detail::get_milliseconds_until(wait_until));
- if(res==detail::win32::timeout)
- {
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.exclusive || new_state.exclusive_waiting_blocked)
- {
- if(new_state.shared_waiting)
- {
- --new_state.shared_waiting;
- }
- }
- else
- {
- ++new_state.shared_count;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
-
- if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
- {
- return true;
- }
- return false;
- }
-
- BOOST_ASSERT(res==0);
- }
- }
-
- void unlock_shared()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- bool const last_reader=!--new_state.shared_count;
-
- if(last_reader)
- {
- if(new_state.upgrade)
- {
- new_state.upgrade=false;
- new_state.exclusive=true;
- }
- else
- {
- if(new_state.exclusive_waiting)
- {
- --new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=false;
- }
- new_state.shared_waiting=0;
- }
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- if(last_reader)
- {
- if(old_state.upgrade)
- {
- BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
- }
- else
- {
- release_waiters(old_state);
- }
- }
- break;
- }
- old_state=current_state;
- }
- }
-
- void lock()
- {
- BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
- }
-
- template<typename TimeDuration>
- bool timed_lock(TimeDuration const & relative_time)
- {
- return timed_lock(get_system_time()+relative_time);
- }
-
- bool try_lock()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.shared_count || new_state.exclusive)
- {
- return false;
- }
- else
- {
- new_state.exclusive=true;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- return true;
- }
-
-
- bool timed_lock(boost::system_time const& wait_until)
- {
- for(;;)
- {
- state_data old_state=state;
-
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.shared_count || new_state.exclusive)
- {
- if( new_state.exclusive_waiting == 127 ) // the maximum already!
- break;
- ++new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=true;
- }
- else
- {
- new_state.exclusive=true;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
-
- if(!old_state.shared_count && !old_state.exclusive)
- {
- return true;
- }
- unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,true,::boost::detail::get_milliseconds_until(wait_until));
- if(wait_res==detail::win32::timeout)
- {
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.shared_count || new_state.exclusive)
- {
- if(new_state.exclusive_waiting)
- {
- if(!--new_state.exclusive_waiting)
- {
- new_state.exclusive_waiting_blocked=false;
- }
- }
- }
- else
- {
- new_state.exclusive=true;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- if(!old_state.shared_count && !old_state.exclusive)
- {
- return true;
- }
- return false;
- }
- BOOST_ASSERT(wait_res<2);
- }
- }
-
- void unlock()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- new_state.exclusive=false;
- if(new_state.exclusive_waiting)
- {
- --new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=false;
- }
- new_state.shared_waiting=0;
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- release_waiters(old_state);
- }
-
- void lock_upgrade()
- {
- for(;;)
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
- {
- ++new_state.shared_waiting;
- }
- else
- {
- ++new_state.shared_count;
- new_state.upgrade=true;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
-
- if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
- {
- return;
- }
-
- BOOST_VERIFY(!detail::win32::WaitForSingleObject(unlock_sem,detail::win32::infinite));
- }
- }
-
- bool try_lock_upgrade()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
- {
- return false;
- }
- else
- {
- ++new_state.shared_count;
- new_state.upgrade=true;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- return true;
- }
-
- void unlock_upgrade()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- new_state.upgrade=false;
- bool const last_reader=!--new_state.shared_count;
-
- if(last_reader)
- {
- if(new_state.exclusive_waiting)
- {
- --new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=false;
- }
- new_state.shared_waiting=0;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- if(last_reader)
- {
- release_waiters(old_state);
- }
- break;
- }
- old_state=current_state;
- }
- }
-
- void unlock_upgrade_and_lock()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- bool const last_reader=!--new_state.shared_count;
-
- if(last_reader)
- {
- new_state.upgrade=false;
- new_state.exclusive=true;
- }
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- if(!last_reader)
- {
- BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
- }
- break;
- }
- old_state=current_state;
- }
- }
-
- void unlock_and_lock_upgrade()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- new_state.exclusive=false;
- new_state.upgrade=true;
- ++new_state.shared_count;
- if(new_state.exclusive_waiting)
- {
- --new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=false;
- }
- new_state.shared_waiting=0;
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- release_waiters(old_state);
- }
-
- void unlock_and_lock_shared()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- new_state.exclusive=false;
- ++new_state.shared_count;
- if(new_state.exclusive_waiting)
- {
- --new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=false;
- }
- new_state.shared_waiting=0;
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- release_waiters(old_state);
- }
-
- void unlock_upgrade_and_lock_shared()
- {
- state_data old_state=state;
- for(;;)
- {
- state_data new_state=old_state;
- new_state.upgrade=false;
- if(new_state.exclusive_waiting)
- {
- --new_state.exclusive_waiting;
- new_state.exclusive_waiting_blocked=false;
- }
- new_state.shared_waiting=0;
-
- state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
- if(current_state==old_state)
- {
- break;
- }
- old_state=current_state;
- }
- release_waiters(old_state);
- }
-
- };
-}
-
-#include <boost/config/abi_suffix.hpp>
-
-#endif
diff --git a/util/concurrency/spin_lock.cpp b/util/concurrency/spin_lock.cpp deleted file mode 100644 index 52bd218dcb6..00000000000 --- a/util/concurrency/spin_lock.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// spin_lock.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/>. -*/ - -#include "pch.h" -#include <time.h> -#include "spin_lock.h" - -namespace mongo { - - SpinLock::~SpinLock() { -#if defined(_WIN32) - DeleteCriticalSection(&_cs); -#elif defined(__USE_XOPEN2K) - pthread_spin_destroy(&_lock); -#endif - } - - SpinLock::SpinLock() -#if defined(_WIN32) - { InitializeCriticalSectionAndSpinCount(&_cs, 4000); } -#elif defined(__USE_XOPEN2K) - { pthread_spin_init( &_lock , 0 ); } -#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) - : _locked( false ) { } -#else - : _mutex( "SpinLock" ) { } -#endif - - void SpinLock::lock() { -#if defined(_WIN32) - EnterCriticalSection(&_cs); -#elif defined(__USE_XOPEN2K) - - /** - * this is designed to perform close to the default spin lock - * the reason for the mild insanity is to prevent horrible performance - * when contention spikes - * it allows spinlocks to be used in many more places - * which is good because even with this change they are about 8x faster on linux - */ - - if ( pthread_spin_trylock( &_lock ) == 0 ) - return; - - for ( int i=0; i<1000; i++ ) - if ( pthread_spin_trylock( &_lock ) == 0 ) - return; - - for ( int i=0; i<1000; i++ ) { - if ( pthread_spin_trylock( &_lock ) == 0 ) - return; - pthread_yield(); - } - - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 5000000; - - while ( pthread_spin_trylock( &_lock ) != 0 ) { - nanosleep(&t, NULL); - } - -#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) - // fast path - if (!_locked && !__sync_lock_test_and_set(&_locked, true)) { - return; - } - - // wait for lock - int wait = 1000; - while ((wait-- > 0) && (_locked)) {} - - // if failed to grab lock, sleep - struct timespec t; - t.tv_sec = 0; - t.tv_nsec = 5000000; - while (__sync_lock_test_and_set(&_locked, true)) { - nanosleep(&t, NULL); - } -#else - // WARNING Missing spin lock in this platform. This can potentially - // be slow. - _mutex.lock(); - -#endif - } - - void SpinLock::unlock() { -#if defined(_WIN32) - LeaveCriticalSection(&_cs); -#elif defined(__USE_XOPEN2K) - pthread_spin_unlock(&_lock); -#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) - __sync_lock_release(&_locked); -#else - _mutex.unlock(); -#endif - } - - bool SpinLock::isfast() { -#if defined(_WIN32) - return true; -#elif defined(__USE_XOPEN2K) - return true; -#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) - return true; -#else - return false; -#endif - } - - -} // namespace mongo diff --git a/util/concurrency/spin_lock.h b/util/concurrency/spin_lock.h deleted file mode 100644 index 65ecb152ddb..00000000000 --- a/util/concurrency/spin_lock.h +++ /dev/null @@ -1,63 +0,0 @@ -// spin_lock.h - -/** -* Copyright (C) 2008 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 - -#include "mutex.h" - -namespace mongo { - - /** - * The spinlock currently requires late GCC support routines to be efficient. - * Other platforms default to a mutex implemenation. - */ - class SpinLock : boost::noncopyable { - public: - SpinLock(); - ~SpinLock(); - - void lock(); - void unlock(); - - static bool isfast(); // true if a real spinlock on this platform - - private: -#if defined(_WIN32) - CRITICAL_SECTION _cs; -#elif defined(__USE_XOPEN2K) - pthread_spinlock_t _lock; -#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) - volatile bool _locked; -#else - // default to a mutex if not implemented - SimpleMutex _mutex; -#endif - }; - - class scoped_spinlock : boost::noncopyable { - public: - scoped_spinlock( SpinLock& l ) : _l(l) { - _l.lock(); - } - ~scoped_spinlock() { - _l.unlock();} - private: - SpinLock& _l; - }; - -} // namespace mongo diff --git a/util/concurrency/synchronization.cpp b/util/concurrency/synchronization.cpp deleted file mode 100644 index ce2547c25eb..00000000000 --- a/util/concurrency/synchronization.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// synchronization.cpp - -/* Copyright 2010 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. - */ - -#include "pch.h" -#include "synchronization.h" - -namespace mongo { - - Notification::Notification() : _mutex ( "Notification" ) , _notified( false ) { - } - - Notification::~Notification() { } - - void Notification::waitToBeNotified() { - scoped_lock lock( _mutex ); - while ( ! _notified ) - _condition.wait( lock.boost() ); - } - - void Notification::notifyOne() { - scoped_lock lock( _mutex ); - assert( !_notified ); - _notified = true; - _condition.notify_one(); - } - - /* --- NotifyAll --- */ - - NotifyAll::NotifyAll() : _mutex("NotifyAll") { - _lastDone = 0; - _lastReturned = 0; - _nWaiting = 0; - } - - NotifyAll::When NotifyAll::now() { - scoped_lock lock( _mutex ); - return ++_lastReturned; - } - - void NotifyAll::waitFor(When e) { - scoped_lock lock( _mutex ); - ++_nWaiting; - while( _lastDone < e ) { - _condition.wait( lock.boost() ); - } - } - - void NotifyAll::awaitBeyondNow() { - scoped_lock lock( _mutex ); - ++_nWaiting; - When e = ++_lastReturned; - while( _lastDone <= e ) { - _condition.wait( lock.boost() ); - } - } - - void NotifyAll::notifyAll(When e) { - scoped_lock lock( _mutex ); - _lastDone = e; - _nWaiting = 0; - _condition.notify_all(); - } - -} // namespace mongo diff --git a/util/concurrency/synchronization.h b/util/concurrency/synchronization.h deleted file mode 100644 index a0e89f7246b..00000000000 --- a/util/concurrency/synchronization.h +++ /dev/null @@ -1,85 +0,0 @@ -// synchronization.h - -/* Copyright 2010 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 - -#include <boost/thread/condition.hpp> -#include "mutex.h" - -namespace mongo { - - /* - * A class to establish a synchronization point between two threads. One thread is the waiter and one is - * the notifier. After the notification event, both proceed normally. - * - * This class is thread-safe. - */ - class Notification { - public: - Notification(); - ~Notification(); - - /* - * Blocks until the method 'notifyOne()' is called. - */ - void waitToBeNotified(); - - /* - * Notifies the waiter of '*this' that it can proceed. Can only be called once. - */ - void notifyOne(); - - private: - mongo::mutex _mutex; // protects state below - bool _notified; // was notifyOne() issued? - boost::condition _condition; // cond over _notified being true - }; - - /** establishes a synchronization point between threads. N threads are waits and one is notifier. - threadsafe. - */ - class NotifyAll : boost::noncopyable { - public: - NotifyAll(); - - typedef unsigned long long When; - - When now(); - - /** awaits the next notifyAll() call by another thread. notifications that precede this - call are ignored -- we are looking for a fresh event. - */ - void waitFor(When); - - /** a bit faster than waitFor( now() ) */ - void awaitBeyondNow(); - - /** may be called multiple times. notifies all waiters */ - void notifyAll(When); - - /** indicates how many threads are waiting for a notify. */ - unsigned nWaiting() const { return _nWaiting; } - - private: - mongo::mutex _mutex; - boost::condition _condition; - When _lastDone; - When _lastReturned; - unsigned _nWaiting; - }; - -} // namespace mongo diff --git a/util/concurrency/task.cpp b/util/concurrency/task.cpp deleted file mode 100644 index d84cd71dceb..00000000000 --- a/util/concurrency/task.cpp +++ /dev/null @@ -1,180 +0,0 @@ -// @file task.cpp - -/** -* Copyright (C) 2008 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,b -* 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/>. -*/ - -#include "pch.h" - -#include <boost/thread/condition.hpp> - -#include "task.h" -#include "../goodies.h" -#include "../unittest.h" -#include "../time_support.h" - -namespace mongo { - - namespace task { - - /*void foo() { - boost::mutex m; - boost::mutex::scoped_lock lk(m); - boost::condition cond; - cond.wait(lk); - cond.notify_one(); - }*/ - - Task::Task() - : BackgroundJob( true /* deleteSelf */ ) { - n = 0; - repeat = 0; - } - - void Task::halt() { repeat = 0; } - - void Task::run() { - assert( n == 0 ); - while( 1 ) { - n++; - try { - doWork(); - } - catch(...) { } - if( repeat == 0 ) - break; - sleepmillis(repeat); - if( inShutdown() ) - break; - } - } - - void Task::begin() { - go(); - } - - void fork(Task *t) { - t->begin(); - } - - void repeat(Task *t, unsigned millis) { - t->repeat = millis; - t->begin(); - } - - } -} - -#include "msg.h" - -/* task::Server */ - -namespace mongo { - namespace task { - - /* to get back a return value */ - struct Ret { - Ret() : done(false) { } - bool done; - boost::mutex m; - boost::condition c; - const lam *msg; - void f() { - (*msg)(); - done = true; - c.notify_one(); - } - }; - - void Server::call( const lam& msg ) { - Ret r; - r.msg = &msg; - lam f = boost::bind(&Ret::f, &r); - send(f); - { - boost::mutex::scoped_lock lk(r.m); - while( !r.done ) - r.c.wait(lk); - } - } - - void Server::send( lam msg ) { - { - boost::mutex::scoped_lock lk(m); - d.push_back(msg); - } - c.notify_one(); - } - - void Server::doWork() { - starting(); - while( 1 ) { - lam f; - try { - boost::mutex::scoped_lock lk(m); - while( d.empty() ) - c.wait(lk); - f = d.front(); - d.pop_front(); - } - catch(...) { - log() << "ERROR exception in Server:doWork?" << endl; - } - try { - f(); - if( rq ) { - rq = false; - { - boost::mutex::scoped_lock lk(m); - d.push_back(f); - } - } - } - catch(std::exception& e) { - log() << "Server::doWork task:" << name() << " exception:" << e.what() << endl; - } - catch(const char *p) { - log() << "Server::doWork task:" << name() << " unknown c exception:" << - ((p&&strlen(p)<800)?p:"?") << endl; - } - catch(...) { - log() << "Server::doWork unknown exception task:" << name() << endl; - } - } - } - - static Server *s; - static void abc(int i) { - cout << "Hello " << i << endl; - s->requeue(); - } - class TaskUnitTest : public mongo::UnitTest { - public: - virtual void run() { - lam f = boost::bind(abc, 3); - //f(); - - s = new Server("unittest"); - fork(s); - s->send(f); - - sleepsecs(30); - cout <<" done" << endl; - - } - }; // not running. taskunittest; - - } -} diff --git a/util/concurrency/task.h b/util/concurrency/task.h deleted file mode 100644 index d7b45eeef24..00000000000 --- a/util/concurrency/task.h +++ /dev/null @@ -1,72 +0,0 @@ -// @file task.h - -/** -* Copyright (C) 2008 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,b -* 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 - -#include "../background.h" - -namespace mongo { - - namespace task { - - /** abstraction around threads. simpler than BackgroundJob which is used behind the scenes. - allocate the Task dynamically. when the thread terminates, the Task object will delete itself. - */ - class Task : private BackgroundJob { - protected: - virtual void doWork() = 0; // implement the task here. - virtual string name() const = 0; // name the threada - public: - Task(); - - /** for a repeating task, stop after current invocation ends. can be called by other threads - as long as the Task is still in scope. - */ - void halt(); - private: - unsigned n, repeat; - friend void fork(Task* t); - friend void repeat(Task* t, unsigned millis); - virtual void run(); - //virtual void ending() { } - void begin(); - }; - - /** run once */ - void fork(Task *t); - - /** run doWork() over and over, with a pause between runs of millis */ - void repeat(Task *t, unsigned millis); - - /*** Example *** - inline void sample() { - class Sample : public Task { - public: - int result; - virtual void doWork() { result = 1234; } - Sample() : result(0) { } - }; - shared_ptr<Sample> q( new Sample() ); - fork(q); - cout << q->result << endl; // could print 1234 or 0. - } - */ - - } - -} diff --git a/util/concurrency/thread_pool.cpp b/util/concurrency/thread_pool.cpp deleted file mode 100644 index 1c258847cb5..00000000000 --- a/util/concurrency/thread_pool.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* threadpool.cpp -*/ - -/* 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. - */ - -#include "pch.h" -#include "thread_pool.h" -#include "mvar.h" - -namespace mongo { - namespace threadpool { - - // Worker thread - class Worker : boost::noncopyable { - public: - explicit Worker(ThreadPool& owner) - : _owner(owner) - , _is_done(true) - , _thread(boost::bind(&Worker::loop, this)) - {} - - // destructor will block until current operation is completed - // Acts as a "join" on this thread - ~Worker() { - _task.put(Task()); - _thread.join(); - } - - void set_task(Task& func) { - assert(!func.empty()); - assert(_is_done); - _is_done = false; - - _task.put(func); - } - - private: - ThreadPool& _owner; - MVar<Task> _task; - bool _is_done; // only used for error detection - boost::thread _thread; - - void loop() { - while (true) { - Task task = _task.take(); - if (task.empty()) - break; // ends the thread - - try { - task(); - } - catch (std::exception e) { - log() << "Unhandled exception in worker thread: " << e.what() << endl;; - } - catch (...) { - log() << "Unhandled non-exception in worker thread" << endl; - } - _is_done = true; - _owner.task_done(this); - } - } - }; - - ThreadPool::ThreadPool(int nThreads) - : _mutex("ThreadPool"), _tasksRemaining(0) - , _nThreads(nThreads) { - scoped_lock lock(_mutex); - while (nThreads-- > 0) { - Worker* worker = new Worker(*this); - _freeWorkers.push_front(worker); - } - } - - ThreadPool::~ThreadPool() { - join(); - - assert(_tasks.empty()); - - // O(n) but n should be small - assert(_freeWorkers.size() == (unsigned)_nThreads); - - while(!_freeWorkers.empty()) { - delete _freeWorkers.front(); - _freeWorkers.pop_front(); - } - } - - void ThreadPool::join() { - scoped_lock lock(_mutex); - while(_tasksRemaining) { - _condition.wait(lock.boost()); - } - } - - void ThreadPool::schedule(Task task) { - scoped_lock lock(_mutex); - - _tasksRemaining++; - - if (!_freeWorkers.empty()) { - _freeWorkers.front()->set_task(task); - _freeWorkers.pop_front(); - } - else { - _tasks.push_back(task); - } - } - - // should only be called by a worker from the worker thread - void ThreadPool::task_done(Worker* worker) { - scoped_lock lock(_mutex); - - if (!_tasks.empty()) { - worker->set_task(_tasks.front()); - _tasks.pop_front(); - } - else { - _freeWorkers.push_front(worker); - } - - _tasksRemaining--; - - if(_tasksRemaining == 0) - _condition.notify_all(); - } - - } //namespace threadpool -} //namespace mongo diff --git a/util/concurrency/thread_pool.h b/util/concurrency/thread_pool.h deleted file mode 100644 index b348ed1d01b..00000000000 --- a/util/concurrency/thread_pool.h +++ /dev/null @@ -1,82 +0,0 @@ -// thread_pool.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 - -#include <boost/function.hpp> -#include <boost/bind.hpp> -#undef assert -#define assert MONGO_assert - -namespace mongo { - - namespace threadpool { - class Worker; - - typedef boost::function<void(void)> Task; //nullary function or functor - - // exported to the mongo namespace - class ThreadPool : boost::noncopyable { - public: - explicit ThreadPool(int nThreads=8); - - // blocks until all tasks are complete (tasks_remaining() == 0) - // You should not call schedule while in the destructor - ~ThreadPool(); - - // blocks until all tasks are complete (tasks_remaining() == 0) - // does not prevent new tasks from being scheduled so could wait forever. - // Also, new tasks could be scheduled after this returns. - void join(); - - // task will be copied a few times so make sure it's relatively cheap - void schedule(Task task); - - // Helpers that wrap schedule and boost::bind. - // Functor and args will be copied a few times so make sure it's relatively cheap - template<typename F, typename A> - void schedule(F f, A a) { schedule(boost::bind(f,a)); } - template<typename F, typename A, typename B> - void schedule(F f, A a, B b) { schedule(boost::bind(f,a,b)); } - template<typename F, typename A, typename B, typename C> - void schedule(F f, A a, B b, C c) { schedule(boost::bind(f,a,b,c)); } - template<typename F, typename A, typename B, typename C, typename D> - void schedule(F f, A a, B b, C c, D d) { schedule(boost::bind(f,a,b,c,d)); } - template<typename F, typename A, typename B, typename C, typename D, typename E> - void schedule(F f, A a, B b, C c, D d, E e) { schedule(boost::bind(f,a,b,c,d,e)); } - - int tasks_remaining() { return _tasksRemaining; } - - private: - mongo::mutex _mutex; - boost::condition _condition; - - list<Worker*> _freeWorkers; //used as LIFO stack (always front) - list<Task> _tasks; //used as FIFO queue (push_back, pop_front) - int _tasksRemaining; // in queue + currently processing - int _nThreads; // only used for sanity checking. could be removed in the future. - - // should only be called by a worker from the worker's thread - void task_done(Worker* worker); - friend class Worker; - }; - - } //namespace threadpool - - using threadpool::ThreadPool; - -} //namespace mongo diff --git a/util/concurrency/value.h b/util/concurrency/value.h deleted file mode 100644 index 897fa95af1e..00000000000 --- a/util/concurrency/value.h +++ /dev/null @@ -1,132 +0,0 @@ -/* @file value.h - concurrency helpers DiagStr, Guarded -*/ - -/** -* Copyright (C) 2008 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,b -* 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 - -#include "mutex.h" -#include "spin_lock.h" - -namespace mongo { - - /** declare that a variable that is "guarded" by a mutex. - - The decl documents the rule. For example "counta and countb are guarded by xyzMutex": - - Guarded<int, xyzMutex> counta; - Guarded<int, xyzMutex> countb; - - Upon use, specify the scoped_lock object. This makes it hard for someone - later to forget to be in the lock. Check is made that it is the right lock in _DEBUG - builds at runtime. - */ - template <typename T, mutex& BY> - class Guarded : boost::noncopyable { - T _val; - public: - T& ref(const scoped_lock& lk) { - dassert( lk._mut == &BY ); - return _val; - } - }; - - class DiagStr { - string _s; - mutable SpinLock m; - public: - DiagStr(const DiagStr& r) : _s(r.get()) { } - DiagStr() { } - bool empty() const { - scoped_spinlock lk(m); - return _s.empty(); - } - string get() const { - scoped_spinlock lk(m); - return _s; - } - - void set(const char *s) { - scoped_spinlock lk(m); - _s = s; - } - void set(const string& s) { - scoped_spinlock lk(m); - _s = s; - } - operator string() const { return get(); } - void operator=(const string& s) { set(s); } - void operator=(const DiagStr& rhs) { - scoped_spinlock lk(m); - _s = rhs.get(); - } - }; - -#if 0 // not including in 2.0 - - /** Thread safe map. - Be careful not to use this too much or it could make things slow; - if not a hot code path no problem. - - Examples: - - mapsf<int,int> mp; - - int x = mp.get(); - - map<int,int> two; - mp.swap(two); - - { - mapsf<int,int>::ref r(mp); - r[9] = 1; - map<int,int>::iterator i = r.r.begin(); - } - - */ - template< class K, class V > - struct mapsf : boost::noncopyable { - SimpleMutex m; - map<K,V> val; - friend struct ref; - public: - mapsf() : m("mapsf") { } - void swap(map<K,V>& rhs) { - SimpleMutex::scoped_lock lk(m); - val.swap(rhs); - } - // safe as we pass by value: - V get(K k) { - SimpleMutex::scoped_lock lk(m); - map<K,V>::iterator i = val.find(k); - if( i == val.end() ) - return K(); - return i->second; - } - // think about deadlocks when using ref. the other methods - // above will always be safe as they are "leaf" operations. - struct ref { - SimpleMutex::scoped_lock lk; - public: - map<K,V> const &r; - ref(mapsf<K,V> &m) : lk(m.m), r(m.val) { } - V& operator[](const K& k) { return r[k]; } - }; - }; -#endif -} diff --git a/util/concurrency/vars.cpp b/util/concurrency/vars.cpp deleted file mode 100644 index b561ccce003..00000000000 --- a/util/concurrency/vars.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// vars.cpp - -/** -* Copyright (C) 2008 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,b -* 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/>. -*/ - -#include "pch.h" -#include "mutex.h" -#include "value.h" - -namespace mongo { - - // intentional leak. otherwise destructor orders can be problematic at termination. - MutexDebugger &mutexDebugger = *(new MutexDebugger()); - - MutexDebugger::MutexDebugger() : - x( *(new boost::mutex()) ), magic(0x12345678) { - // optional way to debug lock order - /* - a = "a_lock"; - b = "b_lock"; - */ - } - - void MutexDebugger::programEnding() { - if( logLevel>=1 && followers.size() ) { - std::cout << followers.size() << " mutexes in program" << endl; - for( map< mid, set<mid> >::iterator i = followers.begin(); i != followers.end(); i++ ) { - cout << i->first; - if( maxNest[i->first] > 1 ) - cout << " maxNest:" << maxNest[i->first]; - cout << '\n'; - for( set<mid>::iterator j = i->second.begin(); j != i->second.end(); j++ ) - cout << " " << *j << '\n'; - } - cout.flush(); - } - } - -} diff --git a/util/debug_util.cpp b/util/debug_util.cpp deleted file mode 100644 index 8ba6534ef7c..00000000000 --- a/util/debug_util.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// debug_util.cpp - -/* 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. - */ - -#include "pch.h" -#include "../db/cmdline.h" -#include "../db/jsobj.h" - -namespace mongo { - -#if defined(USE_GDBSERVER) - /* Magic gdb trampoline - * Do not call directly! call setupSIGTRAPforGDB() - * Assumptions: - * 1) gdbserver is on your path - * 2) You have run "handle SIGSTOP noprint" in gdb - * 3) cmdLine.port + 2000 is free - */ - void launchGDB(int) { - // Don't come back here - signal(SIGTRAP, SIG_IGN); - - int newPort = cmdLine.port + 2000; - string newPortStr = "localhost:" + BSONObjBuilder::numStr(newPort); - string pidToDebug = BSONObjBuilder::numStr(getpid()); - - cout << "\n\n\t**** Launching gdbserver on " << newPortStr << " ****" << endl << endl; - if (fork() == 0) { - //child - execlp("gdbserver", "gdbserver", "--attach", newPortStr.c_str(), pidToDebug.c_str(), NULL); - perror(NULL); - } - else { - //parent - raise(SIGSTOP); // pause all threads until gdb connects and continues - raise(SIGTRAP); // break inside gdbserver - } - } - - void setupSIGTRAPforGDB() { - assert( signal(SIGTRAP , launchGDB ) != SIG_ERR ); - } -#else - void setupSIGTRAPforGDB() { - } -#endif -} diff --git a/util/debug_util.h b/util/debug_util.h deleted file mode 100644 index abed8d94924..00000000000 --- a/util/debug_util.h +++ /dev/null @@ -1,106 +0,0 @@ -// debug_util.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 - -#ifndef _WIN32 -#include <signal.h> -#endif - -namespace mongo { - -// for debugging - typedef struct _Ints { - int i[100]; - } *Ints; - typedef struct _Chars { - char c[200]; - } *Chars; - - typedef char CHARS[400]; - - typedef struct _OWS { - int size; - char type; - char string[400]; - } *OWS; - -#if defined(_DEBUG) - enum {DEBUG_BUILD = 1}; -#else - enum {DEBUG_BUILD = 0}; -#endif - -#define MONGO_DEV if( DEBUG_BUILD ) -#define DEV MONGO_DEV - -#define MONGO_DEBUGGING if( 0 ) -#define DEBUGGING MONGO_DEBUGGING - -// The following declare one unique counter per enclosing function. -// NOTE The implementation double-increments on a match, but we don't really care. -#define MONGO_SOMETIMES( occasion, howOften ) for( static unsigned occasion = 0; ++occasion % howOften == 0; ) -#define SOMETIMES MONGO_SOMETIMES - -#define MONGO_OCCASIONALLY SOMETIMES( occasionally, 16 ) -#define OCCASIONALLY MONGO_OCCASIONALLY - -#define MONGO_RARELY SOMETIMES( rarely, 128 ) -#define RARELY MONGO_RARELY - -#define MONGO_ONCE for( static bool undone = true; undone; undone = false ) -#define ONCE MONGO_ONCE - -#if defined(_WIN32) - inline int strcasecmp(const char* s1, const char* s2) {return _stricmp(s1, s2);} -#endif - - // Sets SIGTRAP handler to launch GDB - // Noop unless on *NIX and compiled with _DEBUG - void setupSIGTRAPforGDB(); - - extern int tlogLevel; - - inline void breakpoint() { - if ( tlogLevel < 0 ) - return; -#ifdef _WIN32 - //DEV DebugBreak(); -#endif -#ifndef _WIN32 - // code to raise a breakpoint in GDB - ONCE { - //prevent SIGTRAP from crashing the program if default action is specified and we are not in gdb - struct sigaction current; - sigaction(SIGTRAP, NULL, ¤t); - if (current.sa_handler == SIG_DFL) { - signal(SIGTRAP, SIG_IGN); - } - } - - raise(SIGTRAP); -#endif - } - - - // conditional breakpoint - inline void breakif(bool test) { - if (test) - breakpoint(); - } - -} // namespace mongo diff --git a/util/embedded_builder.h b/util/embedded_builder.h deleted file mode 100644 index abf518e2583..00000000000 --- a/util/embedded_builder.h +++ /dev/null @@ -1,92 +0,0 @@ -// embedded_builder.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 { - - // utility class for assembling hierarchical objects - class EmbeddedBuilder { - public: - EmbeddedBuilder( BSONObjBuilder *b ) { - _builders.push_back( make_pair( "", b ) ); - } - // It is assumed that the calls to prepareContext will be made with the 'name' - // parameter in lex ascending order. - void prepareContext( string &name ) { - int i = 1, n = _builders.size(); - while( i < n && - name.substr( 0, _builders[ i ].first.length() ) == _builders[ i ].first && - ( name[ _builders[i].first.length() ] == '.' || name[ _builders[i].first.length() ] == 0 ) - ) { - name = name.substr( _builders[ i ].first.length() + 1 ); - ++i; - } - for( int j = n - 1; j >= i; --j ) { - popBuilder(); - } - for( string next = splitDot( name ); !next.empty(); next = splitDot( name ) ) { - addBuilder( next ); - } - } - void appendAs( const BSONElement &e, string name ) { - if ( e.type() == Object && e.valuesize() == 5 ) { // empty object -- this way we can add to it later - string dummyName = name + ".foo"; - prepareContext( dummyName ); - return; - } - prepareContext( name ); - back()->appendAs( e, name ); - } - BufBuilder &subarrayStartAs( string name ) { - prepareContext( name ); - return back()->subarrayStart( name ); - } - void done() { - while( ! _builderStorage.empty() ) - popBuilder(); - } - - static string splitDot( string & str ) { - size_t pos = str.find( '.' ); - if ( pos == string::npos ) - return ""; - string ret = str.substr( 0, pos ); - str = str.substr( pos + 1 ); - return ret; - } - - private: - void addBuilder( const string &name ) { - shared_ptr< BSONObjBuilder > newBuilder( new BSONObjBuilder( back()->subobjStart( name ) ) ); - _builders.push_back( make_pair( name, newBuilder.get() ) ); - _builderStorage.push_back( newBuilder ); - } - void popBuilder() { - back()->done(); - _builders.pop_back(); - _builderStorage.pop_back(); - } - - BSONObjBuilder *back() { return _builders.back().second; } - - vector< pair< string, BSONObjBuilder * > > _builders; - vector< shared_ptr< BSONObjBuilder > > _builderStorage; - - }; - -} //namespace mongo diff --git a/util/file.h b/util/file.h deleted file mode 100644 index 368e6927b43..00000000000 --- a/util/file.h +++ /dev/null @@ -1,230 +0,0 @@ -// file.h cross platform basic file class. supports 64 bit offsets and such. - -/* 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 - -#if !defined(_WIN32) -#include "errno.h" -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/statvfs.h> -#endif -#include "text.h" - -namespace mongo { - -#ifndef __sunos__ - typedef uint64_t fileofs; -#else - typedef boost::uint64_t fileofs; -#endif - - /* NOTE: not thread-safe. (at least the windows implementation isn't. */ - - class FileInterface { - public: - void open(const char *fn) {} - void write(fileofs o, const char *data, unsigned len) {} - void read(fileofs o, char *data, unsigned len) {} - bool bad() {return false;} - bool is_open() {return false;} - fileofs len() { return 0; } - void fsync() { assert(false); } - - // shrink file to size bytes. No-op if file already smaller. - void truncate(fileofs size); - - /** @return -1 if error or unavailable */ - static boost::intmax_t freeSpace(const string &path) { assert(false); return -1; } - }; - -#if defined(_WIN32) -#include <io.h> - - class File : public FileInterface { - HANDLE fd; - bool _bad; - string _name; - void err(BOOL b=false) { /* false = error happened */ - if( !b && !_bad ) { - _bad = true; - log() << "File " << _name << "I/O error " << GetLastError() << '\n'; - } - } - public: - File() { - fd = INVALID_HANDLE_VALUE; - _bad = true; - } - ~File() { - if( is_open() ) CloseHandle(fd); - fd = INVALID_HANDLE_VALUE; - } - void open(const char *filename, bool readOnly=false , bool direct=false) { - _name = filename; - fd = CreateFile( - toNativeString(filename).c_str(), - ( readOnly ? 0 : GENERIC_WRITE ) | GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, - NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if( !is_open() ) { - DWORD e = GetLastError(); - log() << "Create/Open File failed " << filename << ' ' << errnoWithDescription(e) << endl; - } - else - _bad = false; - } - static boost::intmax_t freeSpace(const string &path) { - ULARGE_INTEGER avail; - if( GetDiskFreeSpaceEx(toNativeString(path.c_str()).c_str(), &avail, NULL, NULL) ) { - return avail.QuadPart; - } - DWORD e = GetLastError(); - log() << "GetDiskFreeSpaceEx fails errno: " << e << endl; - return -1; - } - void write(fileofs o, const char *data, unsigned len) { - LARGE_INTEGER li; - li.QuadPart = o; - SetFilePointerEx(fd, li, NULL, FILE_BEGIN); - DWORD written; - err( WriteFile(fd, data, len, &written, NULL) ); - } - void read(fileofs o, char *data, unsigned len) { - DWORD read; - LARGE_INTEGER li; - li.QuadPart = o; - SetFilePointerEx(fd, li, NULL, FILE_BEGIN); - int ok = ReadFile(fd, data, len, &read, 0); - if( !ok ) - err(ok); - else - massert( 10438 , "ReadFile error - truncated file?", read == len); - } - bool bad() { return _bad; } - bool is_open() { return fd != INVALID_HANDLE_VALUE; } - fileofs len() { - LARGE_INTEGER li; - li.LowPart = GetFileSize(fd, (DWORD *) &li.HighPart); - if( li.HighPart == 0 && li.LowPart == INVALID_FILE_SIZE ) { - err( false ); - return 0; - } - return li.QuadPart; - } - void fsync() { FlushFileBuffers(fd); } - - void truncate(fileofs size) { - if (len() <= size) - return; - - LARGE_INTEGER li; - li.QuadPart = size; - if (SetFilePointerEx(fd, li, NULL, FILE_BEGIN) == 0){ - err(false); - return; //couldn't seek - } - - err(SetEndOfFile(fd)); - } - }; - -#else - - class File : public FileInterface { - public: - int fd; - private: - bool _bad; - void err(bool ok) { - if( !ok && !_bad ) { - _bad = true; - log() << "File I/O " << errnoWithDescription() << '\n'; - } - } - public: - File() { - fd = -1; - _bad = true; - } - ~File() { - if( is_open() ) ::close(fd); - fd = -1; - } - -#ifndef O_NOATIME -#define O_NOATIME 0 -#endif - - void open(const char *filename, bool readOnly=false , bool direct=false) { - fd = ::open(filename, - O_CREAT | ( readOnly ? 0 : ( O_RDWR | O_NOATIME ) ) -#if defined(O_DIRECT) - | ( direct ? O_DIRECT : 0 ) -#endif - , - S_IRUSR | S_IWUSR); - if ( fd <= 0 ) { - out() << "couldn't open " << filename << ' ' << errnoWithDescription() << endl; - return; - } - _bad = false; - } - void write(fileofs o, const char *data, unsigned len) { - err( ::pwrite(fd, data, len, o) == (int) len ); - } - void read(fileofs o, char *data, unsigned len) { - ssize_t s = ::pread(fd, data, len, o); - if( s == -1 ) { - err(false); - } - else if( s != (int) len ) { - _bad = true; - log() << "File error read:" << s << " bytes, wanted:" << len << " ofs:" << o << endl; - } - } - bool bad() { return _bad; } - bool is_open() { return fd > 0; } - fileofs len() { - off_t o = lseek(fd, 0, SEEK_END); - if( o != (off_t) -1 ) - return o; - err(false); - return 0; - } - void fsync() { ::fsync(fd); } - static boost::intmax_t freeSpace ( const string &path ) { - struct statvfs info; - assert( !statvfs( path.c_str() , &info ) ); - return boost::intmax_t( info.f_bavail ) * info.f_frsize; - } - - void truncate(fileofs size) { - if (len() <= size) - return; - - err(ftruncate(fd, size) == 0); - } - }; - - -#endif - - -} - diff --git a/util/file_allocator.cpp b/util/file_allocator.cpp deleted file mode 100644 index b0572f971bd..00000000000 --- a/util/file_allocator.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// @file file_allocator.cpp - -/* 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. - */ - -#include "pch.h" -#include <fcntl.h> -#include <errno.h> - -#if defined(__freebsd__) || defined(__openbsd__) -#include <sys/stat.h> -#endif - -#include "timer.h" -#include "mongoutils/str.h" -using namespace mongoutils; - -#ifndef O_NOATIME -#define O_NOATIME (0) -#endif - -#include "file_allocator.h" -#include "paths.h" - -namespace mongo { - - boost::filesystem::path ensureParentDirCreated(const boost::filesystem::path& p){ - const boost::filesystem::path parent = p.branch_path(); - - if (! boost::filesystem::exists(parent)){ - ensureParentDirCreated(parent); - log() << "creating directory " << parent.string() << endl; - boost::filesystem::create_directory(parent); - flushMyDirectory(parent); // flushes grandparent to ensure parent exists after crash - } - - assert(boost::filesystem::is_directory(parent)); - return parent; - } - -#if defined(_WIN32) - FileAllocator::FileAllocator() { - } - - void FileAllocator::start() { - } - - void FileAllocator::requestAllocation( const string &name, long &size ) { - /* Some of the system calls in the file allocator don't work in win, - so no win support - 32 or 64 bit. Plus we don't seem to need preallocation - on windows anyway as we don't have to pre-zero the file there. - */ - } - - void FileAllocator::allocateAsap( const string &name, unsigned long long &size ) { - // no-op - } - - void FileAllocator::waitUntilFinished() const { - // no-op - } - - void FileAllocator::ensureLength(int fd , long size) { - // we don't zero on windows - // TODO : we should to avoid fragmentation - } - - bool FileAllocator::hasFailed() const { - return false; - } - -#else - - FileAllocator::FileAllocator() - : _pendingMutex("FileAllocator"), _failed() { - } - - - void FileAllocator::start() { - boost::thread t( boost::bind( &FileAllocator::run , this ) ); - } - - void FileAllocator::requestAllocation( const string &name, long &size ) { - scoped_lock lk( _pendingMutex ); - if ( _failed ) - return; - long oldSize = prevSize( name ); - if ( oldSize != -1 ) { - size = oldSize; - return; - } - _pending.push_back( name ); - _pendingSize[ name ] = size; - _pendingUpdated.notify_all(); - } - - void FileAllocator::allocateAsap( const string &name, unsigned long long &size ) { - scoped_lock lk( _pendingMutex ); - long oldSize = prevSize( name ); - if ( oldSize != -1 ) { - size = oldSize; - if ( !inProgress( name ) ) - return; - } - checkFailure(); - _pendingSize[ name ] = size; - if ( _pending.size() == 0 ) - _pending.push_back( name ); - else if ( _pending.front() != name ) { - _pending.remove( name ); - list< string >::iterator i = _pending.begin(); - ++i; - _pending.insert( i, name ); - } - _pendingUpdated.notify_all(); - while( inProgress( name ) ) { - checkFailure(); - _pendingUpdated.wait( lk.boost() ); - } - - } - - void FileAllocator::waitUntilFinished() const { - if ( _failed ) - return; - scoped_lock lk( _pendingMutex ); - while( _pending.size() != 0 ) - _pendingUpdated.wait( lk.boost() ); - } - - void FileAllocator::ensureLength(int fd , long size) { -#if defined(__linux__) - int ret = posix_fallocate(fd,0,size); - if ( ret == 0 ) - return; - - log() << "FileAllocator: posix_fallocate failed: " << errnoWithDescription( ret ) << " falling back" << endl; -#endif - - off_t filelen = lseek(fd, 0, SEEK_END); - if ( filelen < size ) { - if (filelen != 0) { - stringstream ss; - ss << "failure creating new datafile; lseek failed for fd " << fd << " with errno: " << errnoWithDescription(); - uassert( 10440 , ss.str(), filelen == 0 ); - } - // Check for end of disk. - - uassert( 10441 , str::stream() << "Unable to allocate new file of size " << size << ' ' << errnoWithDescription(), - size - 1 == lseek(fd, size - 1, SEEK_SET) ); - uassert( 10442 , str::stream() << "Unable to allocate new file of size " << size << ' ' << errnoWithDescription(), - 1 == write(fd, "", 1) ); - lseek(fd, 0, SEEK_SET); - - const long z = 256 * 1024; - const boost::scoped_array<char> buf_holder (new char[z]); - char* buf = buf_holder.get(); - memset(buf, 0, z); - long left = size; - while ( left > 0 ) { - long towrite = left; - if ( towrite > z ) - towrite = z; - - int written = write( fd , buf , towrite ); - uassert( 10443 , errnoWithPrefix("FileAllocator: file write failed" ), written > 0 ); - left -= written; - } - } - } - - bool FileAllocator::hasFailed() const { - return _failed; - } - - void FileAllocator::checkFailure() { - if (_failed) { - // we want to log the problem (diskfull.js expects it) but we do not want to dump a stack tracke - msgassertedNoTrace( 12520, "new file allocation failure" ); - } - } - - long FileAllocator::prevSize( const string &name ) const { - if ( _pendingSize.count( name ) > 0 ) - return _pendingSize[ name ]; - if ( boost::filesystem::exists( name ) ) - return boost::filesystem::file_size( name ); - return -1; - } - - // caller must hold _pendingMutex lock. - bool FileAllocator::inProgress( const string &name ) const { - for( list< string >::const_iterator i = _pending.begin(); i != _pending.end(); ++i ) - if ( *i == name ) - return true; - return false; - } - - string makeTempFileName( path root ) { - while( 1 ) { - path p = root / "_tmp"; - stringstream ss; - ss << (unsigned) rand(); - p /= ss.str(); - string fn = p.string(); - if( !boost::filesystem::exists(p) ) - return fn; - } - return ""; - } - - void FileAllocator::run( FileAllocator * fa ) { - setThreadName( "FileAllocator" ); - while( 1 ) { - { - scoped_lock lk( fa->_pendingMutex ); - if ( fa->_pending.size() == 0 ) - fa->_pendingUpdated.wait( lk.boost() ); - } - while( 1 ) { - string name; - long size; - { - scoped_lock lk( fa->_pendingMutex ); - if ( fa->_pending.size() == 0 ) - break; - name = fa->_pending.front(); - size = fa->_pendingSize[ name ]; - } - - string tmp; - long fd = 0; - try { - log() << "allocating new datafile " << name << ", filling with zeroes..." << endl; - - boost::filesystem::path parent = ensureParentDirCreated(name); - tmp = makeTempFileName( parent ); - ensureParentDirCreated(tmp); - - fd = open(tmp.c_str(), O_CREAT | O_RDWR | O_NOATIME, S_IRUSR | S_IWUSR); - if ( fd <= 0 ) { - log() << "FileAllocator: couldn't create " << name << " (" << tmp << ") " << errnoWithDescription() << endl; - uasserted(10439, ""); - } - -#if defined(POSIX_FADV_DONTNEED) - if( posix_fadvise(fd, 0, size, POSIX_FADV_DONTNEED) ) { - log() << "warning: posix_fadvise fails " << name << " (" << tmp << ") " << errnoWithDescription() << endl; - } -#endif - - Timer t; - - /* make sure the file is the full desired length */ - ensureLength( fd , size ); - - close( fd ); - fd = 0; - - if( rename(tmp.c_str(), name.c_str()) ) { - log() << "error: couldn't rename " << tmp << " to " << name << ' ' << errnoWithDescription() << endl; - uasserted(13653, ""); - } - flushMyDirectory(name); - - log() << "done allocating datafile " << name << ", " - << "size: " << size/1024/1024 << "MB, " - << " took " << ((double)t.millis())/1000.0 << " secs" - << endl; - - // no longer in a failed state. allow new writers. - fa->_failed = false; - } - catch ( ... ) { - if ( fd > 0 ) - close( fd ); - log() << "error failed to allocate new file: " << name - << " size: " << size << ' ' << errnoWithDescription() << warnings; - log() << " will try again in 10 seconds" << endl; // not going to warning logs - try { - if ( tmp.size() ) - BOOST_CHECK_EXCEPTION( boost::filesystem::remove( tmp ) ); - BOOST_CHECK_EXCEPTION( boost::filesystem::remove( name ) ); - } - catch ( ... ) { - } - scoped_lock lk( fa->_pendingMutex ); - fa->_failed = true; - // not erasing from pending - fa->_pendingUpdated.notify_all(); - - - sleepsecs(10); - continue; - } - - { - scoped_lock lk( fa->_pendingMutex ); - fa->_pendingSize.erase( name ); - fa->_pending.pop_front(); - fa->_pendingUpdated.notify_all(); - } - } - } - } - -#endif - - FileAllocator* FileAllocator::_instance = 0; - - FileAllocator* FileAllocator::get(){ - if ( ! _instance ) - _instance = new FileAllocator(); - return _instance; - } - -} // namespace mongo diff --git a/util/file_allocator.h b/util/file_allocator.h deleted file mode 100644 index 7c3cacb2888..00000000000 --- a/util/file_allocator.h +++ /dev/null @@ -1,91 +0,0 @@ -// @file file_allocator.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. - */ - -#include "../pch.h" - -namespace mongo { - - /* - * Handles allocation of contiguous files on disk. Allocation may be - * requested asynchronously or synchronously. - * singleton - */ - class FileAllocator : boost::noncopyable { - /* - * The public functions may not be called concurrently. The allocation - * functions may be called multiple times per file, but only the first - * size specified per file will be used. - */ - public: - void start(); - - /** - * May be called if file exists. If file exists, or its allocation has - * been requested, size is updated to match existing file size. - */ - void requestAllocation( const string &name, long &size ); - - - /** - * Returns when file has been allocated. If file exists, size is - * updated to match existing file size. - */ - void allocateAsap( const string &name, unsigned long long &size ); - - void waitUntilFinished() const; - - bool hasFailed() const; - - static void ensureLength(int fd , long size); - - /** @return the singletone */ - static FileAllocator * get(); - - private: - - FileAllocator(); - -#if !defined(_WIN32) - void checkFailure(); - - // caller must hold pendingMutex_ lock. Returns size if allocated or - // allocation requested, -1 otherwise. - long prevSize( const string &name ) const; - - // caller must hold pendingMutex_ lock. - bool inProgress( const string &name ) const; - - /** called from the worked thread */ - static void run( FileAllocator * fa ); - - mutable mongo::mutex _pendingMutex; - mutable boost::condition _pendingUpdated; - - list< string > _pending; - mutable map< string, long > _pendingSize; - - bool _failed; -#endif - - static FileAllocator* _instance; - - }; - - /** like "mkdir -p" but on parent dir of p rather than p itself */ - boost::filesystem::path ensureParentDirCreated(const boost::filesystem::path& p); - -} // namespace mongo diff --git a/util/goodies.h b/util/goodies.h deleted file mode 100644 index 735aa8be7ce..00000000000 --- a/util/goodies.h +++ /dev/null @@ -1,508 +0,0 @@ -// @file goodies.h -// miscellaneous - -/* 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 - -#include "../bson/util/misc.h" -#include "concurrency/mutex.h" - -namespace mongo { - - /* @return a dump of the buffer as hex byte ascii output */ - string hexdump(const char *data, unsigned len); - - /** - * @return if this name has an increasing counter associated, return the value - * otherwise 0 - */ - unsigned setThreadName(const char * name); - string getThreadName(); - - template<class T> - inline string ToString(const T& t) { - stringstream s; - s << t; - return s.str(); - } - -#if !defined(_WIN32) && !defined(NOEXECINFO) && !defined(__freebsd__) && !defined(__openbsd__) && !defined(__sun__) - -} // namespace mongo - -#include <pthread.h> -#include <execinfo.h> - -namespace mongo { - - inline pthread_t GetCurrentThreadId() { - return pthread_self(); - } - - /* use "addr2line -CFe <exe>" to parse. */ - inline void printStackTrace( ostream &o = cout ) { - void *b[20]; - - int size = backtrace(b, 20); - for (int i = 0; i < size; i++) - o << hex << b[i] << dec << ' '; - o << endl; - - char **strings; - - strings = backtrace_symbols(b, size); - for (int i = 0; i < size; i++) - o << ' ' << strings[i] << '\n'; - o.flush(); - free (strings); - } -#else - inline void printStackTrace( ostream &o = cout ) { } -#endif - - bool isPrime(int n); - int nextPrime(int n); - - inline void dumpmemory(const char *data, int len) { - if ( len > 1024 ) - len = 1024; - try { - const char *q = data; - const char *p = q; - while ( len > 0 ) { - for ( int i = 0; i < 16; i++ ) { - if ( *p >= 32 && *p <= 126 ) - cout << *p; - else - cout << '.'; - p++; - } - cout << " "; - p -= 16; - for ( int i = 0; i < 16; i++ ) - cout << (unsigned) ((unsigned char)*p++) << ' '; - cout << endl; - len -= 16; - } - } - catch (...) { - } - } - -// PRINT(2+2); prints "2+2: 4" -#define MONGO_PRINT(x) cout << #x ": " << (x) << endl -#define PRINT MONGO_PRINT -// PRINTFL; prints file:line -#define MONGO_PRINTFL cout << __FILE__ ":" << __LINE__ << endl -#define PRINTFL MONGO_PRINTFL -#define MONGO_FLOG log() << __FILE__ ":" << __LINE__ << endl -#define FLOG MONGO_FLOG - -#undef assert -#define assert MONGO_assert - - inline bool startsWith(const char *str, const char *prefix) { - size_t l = strlen(prefix); - if ( strlen(str) < l ) return false; - return strncmp(str, prefix, l) == 0; - } - inline bool startsWith(string s, string p) { return startsWith(s.c_str(), p.c_str()); } - - inline bool endsWith(const char *p, const char *suffix) { - size_t a = strlen(p); - size_t b = strlen(suffix); - if ( b > a ) return false; - return strcmp(p + a - b, suffix) == 0; - } - - inline unsigned long swapEndian(unsigned long x) { - return - ((x & 0xff) << 24) | - ((x & 0xff00) << 8) | - ((x & 0xff0000) >> 8) | - ((x & 0xff000000) >> 24); - } - -#if defined(BOOST_LITTLE_ENDIAN) - inline unsigned long fixEndian(unsigned long x) { - return x; - } -#else - inline unsigned long fixEndian(unsigned long x) { - return swapEndian(x); - } -#endif - -#if !defined(_WIN32) - typedef int HANDLE; - inline void strcpy_s(char *dst, unsigned len, const char *src) { - assert( strlen(src) < len ); - strcpy(dst, src); - } -#else - typedef void *HANDLE; -#endif - - /* thread local "value" rather than a pointer - good for things which have copy constructors (and the copy constructor is fast enough) - e.g. - ThreadLocalValue<int> myint; - */ - template<class T> - class ThreadLocalValue { - public: - ThreadLocalValue( T def = 0 ) : _default( def ) { } - - T get() const { - T * val = _val.get(); - if ( val ) - return *val; - return _default; - } - - void set( const T& i ) { - T *v = _val.get(); - if( v ) { - *v = i; - return; - } - v = new T(i); - _val.reset( v ); - } - - private: - boost::thread_specific_ptr<T> _val; - const T _default; - }; - - class ProgressMeter : boost::noncopyable { - public: - ProgressMeter( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ) { - reset( total , secondsBetween , checkInterval ); - } - - ProgressMeter() { - _active = 0; - } - - // typically you do ProgressMeterHolder - void reset( unsigned long long total , int secondsBetween = 3 , int checkInterval = 100 ) { - _total = total; - _secondsBetween = secondsBetween; - _checkInterval = checkInterval; - - _done = 0; - _hits = 0; - _lastTime = (int)time(0); - - _active = 1; - } - - void finished() { - _active = 0; - } - - bool isActive() { - return _active; - } - - /** - * @param n how far along we are relative to the total # we set in CurOp::setMessage - * @return if row was printed - */ - bool hit( int n = 1 ) { - if ( ! _active ) { - cout << "warning: hit on in-active ProgressMeter" << endl; - return false; - } - - _done += n; - _hits++; - if ( _hits % _checkInterval ) - return false; - - int t = (int) time(0); - if ( t - _lastTime < _secondsBetween ) - return false; - - if ( _total > 0 ) { - int per = (int)( ( (double)_done * 100.0 ) / (double)_total ); - cout << "\t\t" << _done << "/" << _total << "\t" << per << "%" << endl; - } - _lastTime = t; - return true; - } - - void setTotalWhileRunning( unsigned long long total ) { - _total = total; - } - - unsigned long long done() const { return _done; } - - unsigned long long hits() const { return _hits; } - - unsigned long long total() const { return _total; } - - string toString() const { - if ( ! _active ) - return ""; - stringstream buf; - buf << _done << "/" << _total << " " << (_done*100)/_total << "%"; - return buf.str(); - } - - bool operator==( const ProgressMeter& other ) const { - return this == &other; - } - private: - - bool _active; - - unsigned long long _total; - int _secondsBetween; - int _checkInterval; - - unsigned long long _done; - unsigned long long _hits; - int _lastTime; - }; - - // e.g.: - // CurOp * op = cc().curop(); - // ProgressMeterHolder pm( op->setMessage( "index: (1/3) external sort" , d->stats.nrecords , 10 ) ); - // loop { pm.hit(); } - class ProgressMeterHolder : boost::noncopyable { - public: - ProgressMeterHolder( ProgressMeter& pm ) - : _pm( pm ) { - } - - ~ProgressMeterHolder() { - _pm.finished(); - } - - ProgressMeter* operator->() { - return &_pm; - } - - bool hit( int n = 1 ) { - return _pm.hit( n ); - } - - void finished() { - _pm.finished(); - } - - bool operator==( const ProgressMeter& other ) { - return _pm == other; - } - - private: - ProgressMeter& _pm; - }; - - class TicketHolder { - public: - TicketHolder( int num ) : _mutex("TicketHolder") { - _outof = num; - _num = num; - } - - bool tryAcquire() { - scoped_lock lk( _mutex ); - return _tryAcquire(); - } - - void waitForTicket() { - scoped_lock lk( _mutex ); - - while( ! _tryAcquire() ) { - _newTicket.wait( lk.boost() ); - } - } - - void release() { - { - scoped_lock lk( _mutex ); - _num++; - } - _newTicket.notify_one(); - } - - void resize( int newSize ) { - { - scoped_lock lk( _mutex ); - - int used = _outof - _num; - if ( used > newSize ) { - cout << "ERROR: can't resize since we're using (" << used << ") more than newSize(" << newSize << ")" << endl; - return; - } - - _outof = newSize; - _num = _outof - used; - } - - // Potentially wasteful, but easier to see is correct - _newTicket.notify_all(); - } - - int available() const { - return _num; - } - - int used() const { - return _outof - _num; - } - - int outof() const { return _outof; } - - private: - - bool _tryAcquire(){ - if ( _num <= 0 ) { - if ( _num < 0 ) { - cerr << "DISASTER! in TicketHolder" << endl; - } - return false; - } - _num--; - return true; - } - - int _outof; - int _num; - mongo::mutex _mutex; - boost::condition_variable_any _newTicket; - }; - - class TicketHolderReleaser { - public: - TicketHolderReleaser( TicketHolder * holder ) { - _holder = holder; - } - - ~TicketHolderReleaser() { - _holder->release(); - } - private: - TicketHolder * _holder; - }; - - - /** - * this is a thread safe string - * you will never get a bad pointer, though data may be mungedd - */ - class ThreadSafeString { - public: - ThreadSafeString( size_t size=256 ) - : _size( size ) , _buf( new char[size] ) { - memset( _buf , 0 , _size ); - } - - ThreadSafeString( const ThreadSafeString& other ) - : _size( other._size ) , _buf( new char[_size] ) { - strncpy( _buf , other._buf , _size ); - } - - ~ThreadSafeString() { - delete[] _buf; - _buf = 0; - } - - string toString() const { - string s = _buf; - return s; - } - - ThreadSafeString& operator=( const char * str ) { - size_t s = strlen(str); - if ( s >= _size - 2 ) - s = _size - 2; - strncpy( _buf , str , s ); - _buf[s] = 0; - return *this; - } - - bool operator==( const ThreadSafeString& other ) const { - return strcmp( _buf , other._buf ) == 0; - } - - bool operator==( const char * str ) const { - return strcmp( _buf , str ) == 0; - } - - bool operator!=( const char * str ) const { - return strcmp( _buf , str ) != 0; - } - - bool empty() const { - return _buf == 0 || _buf[0] == 0; - } - - private: - size_t _size; - char * _buf; - }; - - ostream& operator<<( ostream &s, const ThreadSafeString &o ); - - /** A generic pointer type for function arguments. - * It will convert from any pointer type except auto_ptr. - * Semantics are the same as passing the pointer returned from get() - * const ptr<T> => T * const - * ptr<const T> => T const * or const T* - */ - template <typename T> - struct ptr { - - ptr() : _p(NULL) {} - - // convert to ptr<T> - ptr(T* p) : _p(p) {} // needed for NULL - template<typename U> ptr(U* p) : _p(p) {} - template<typename U> ptr(const ptr<U>& p) : _p(p) {} - template<typename U> ptr(const boost::shared_ptr<U>& p) : _p(p.get()) {} - template<typename U> ptr(const boost::scoped_ptr<U>& p) : _p(p.get()) {} - //template<typename U> ptr(const auto_ptr<U>& p) : _p(p.get()) {} - - // assign to ptr<T> - ptr& operator= (T* p) { _p = p; return *this; } // needed for NULL - template<typename U> ptr& operator= (U* p) { _p = p; return *this; } - template<typename U> ptr& operator= (const ptr<U>& p) { _p = p; return *this; } - template<typename U> ptr& operator= (const boost::shared_ptr<U>& p) { _p = p.get(); return *this; } - template<typename U> ptr& operator= (const boost::scoped_ptr<U>& p) { _p = p.get(); return *this; } - //template<typename U> ptr& operator= (const auto_ptr<U>& p) { _p = p.get(); return *this; } - - // use - T* operator->() const { return _p; } - T& operator*() const { return *_p; } - - // convert from ptr<T> - operator T* () const { return _p; } - - private: - T* _p; - }; - - - - /** Hmmmm */ - using namespace boost; - -} // namespace mongo diff --git a/util/hashtab.h b/util/hashtab.h deleted file mode 100644 index f1a33068e07..00000000000 --- a/util/hashtab.h +++ /dev/null @@ -1,179 +0,0 @@ -/* hashtab.h - - Simple, fixed size hash table. Darn simple. - - Uses a contiguous block of memory, so you can put it in a memory mapped file very easily. -*/ - -/* 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 - -#include "../pch.h" -#include <map> -#include "../db/dur.h" - -namespace mongo { - -#pragma pack(1) - - /* you should define: - - int Key::hash() return > 0 always. - */ - - template < - class Key, - class Type - > - class HashTable : boost::noncopyable { - public: - const char *name; - struct Node { - int hash; - Key k; - Type value; - bool inUse() { - return hash != 0; - } - void setUnused() { - hash = 0; - } - }; - void* _buf; - int n; // number of hashtable buckets - int maxChain; - - Node& nodes(int i) { - Node *nodes = (Node *) _buf; - return nodes[i]; - } - - int _find(const Key& k, bool& found) { - found = false; - int h = k.hash(); - int i = h % n; - int start = i; - int chain = 0; - int firstNonUsed = -1; - while ( 1 ) { - if ( !nodes(i).inUse() ) { - if ( firstNonUsed < 0 ) - firstNonUsed = i; - } - - if ( nodes(i).hash == h && nodes(i).k == k ) { - if ( chain >= 200 ) - out() << "warning: hashtable " << name << " long chain " << endl; - found = true; - return i; - } - chain++; - i = (i+1) % n; - if ( i == start ) { - // shouldn't get here / defensive for infinite loops - out() << "error: hashtable " << name << " is full n:" << n << endl; - return -1; - } - if( chain >= maxChain ) { - if ( firstNonUsed >= 0 ) - return firstNonUsed; - out() << "error: hashtable " << name << " max chain reached:" << maxChain << endl; - return -1; - } - } - } - - public: - /* buf must be all zeroes on initialization. */ - HashTable(void* buf, int buflen, const char *_name) : name(_name) { - int m = sizeof(Node); - // out() << "hashtab init, buflen:" << buflen << " m:" << m << endl; - n = buflen / m; - if ( (n & 1) == 0 ) - n--; - maxChain = (int) (n * 0.05); - _buf = buf; - //nodes = (Node *) buf; - - if ( sizeof(Node) != 628 ) { - out() << "HashTable() " << _name << " sizeof(node):" << sizeof(Node) << " n:" << n << " sizeof(Key): " << sizeof(Key) << " sizeof(Type):" << sizeof(Type) << endl; - assert( sizeof(Node) == 628 ); - } - - } - - Type* get(const Key& k) { - bool found; - int i = _find(k, found); - if ( found ) - return &nodes(i).value; - return 0; - } - - void kill(const Key& k) { - bool found; - int i = _find(k, found); - if ( i >= 0 && found ) { - Node* n = &nodes(i); - n = getDur().writing(n); - n->k.kill(); - n->setUnused(); - } - } - - /** returns false if too full */ - bool put(const Key& k, const Type& value) { - bool found; - int i = _find(k, found); - if ( i < 0 ) - return false; - Node* n = getDur().writing( &nodes(i) ); - if ( !found ) { - n->k = k; - n->hash = k.hash(); - } - else { - assert( n->hash == k.hash() ); - } - n->value = value; - return true; - } - - typedef void (*IteratorCallback)( const Key& k , Type& v ); - void iterAll( IteratorCallback callback ) { - for ( int i=0; i<n; i++ ) { - if ( nodes(i).inUse() ) { - callback( nodes(i).k , nodes(i).value ); - } - } - } - - // TODO: should probably use boost::bind for this, but didn't want to look at it - typedef void (*IteratorCallback2)( const Key& k , Type& v , void * extra ); - void iterAll( IteratorCallback2 callback , void * extra ) { - for ( int i=0; i<n; i++ ) { - if ( nodes(i).inUse() ) { - callback( nodes(i).k , nodes(i).value , extra ); - } - } - } - - }; - -#pragma pack() - -} // namespace mongo diff --git a/util/heapcheck.h b/util/heapcheck.h deleted file mode 100644 index 95da9538db5..00000000000 --- a/util/heapcheck.h +++ /dev/null @@ -1,33 +0,0 @@ -// @file heapcheck.h - -/** -* 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/>. -*/ - -#pragma once - -#if defined(HEAP_CHECKING) - -#include <google/heap-checker.h> - -#define IGNORE_OBJECT( a ) HeapLeakChecker::IgnoreObject( a ) -#define UNIGNORE_OBJECT( a ) HeapLeakChecker::UnIgnoreObject( a ) - -#else - -#define IGNORE_OBJECT( a ) -#define UNIGNORE_OBJECT( a ) - -#endif diff --git a/util/hex.h b/util/hex.h deleted file mode 100644 index 8cf30f2d9d3..00000000000 --- a/util/hex.h +++ /dev/null @@ -1,67 +0,0 @@ -// util/hex.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 { - //can't use hex namespace because it conflicts with hex iostream function - inline int fromHex( char c ) { - if ( '0' <= c && c <= '9' ) - return c - '0'; - if ( 'a' <= c && c <= 'f' ) - return c - 'a' + 10; - if ( 'A' <= c && c <= 'F' ) - return c - 'A' + 10; - assert( false ); - return 0xff; - } - inline char fromHex( const char *c ) { - return (char)(( fromHex( c[ 0 ] ) << 4 ) | fromHex( c[ 1 ] )); - } - - inline string toHex(const void* inRaw, int len) { - static const char hexchars[] = "0123456789ABCDEF"; - - StringBuilder out; - const char* in = reinterpret_cast<const char*>(inRaw); - for (int i=0; i<len; ++i) { - char c = in[i]; - char hi = hexchars[(c & 0xF0) >> 4]; - char lo = hexchars[(c & 0x0F)]; - - out << hi << lo; - } - - return out.str(); - } - - inline string toHexLower(const void* inRaw, int len) { - static const char hexchars[] = "0123456789abcdef"; - - StringBuilder out; - const char* in = reinterpret_cast<const char*>(inRaw); - for (int i=0; i<len; ++i) { - char c = in[i]; - char hi = hexchars[(c & 0xF0) >> 4]; - char lo = hexchars[(c & 0x0F)]; - - out << hi << lo; - } - - return out.str(); - } -} diff --git a/util/histogram.cpp b/util/histogram.cpp deleted file mode 100644 index 17a85059d58..00000000000 --- a/util/histogram.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// histogram.cc - -/** -* 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/>. -*/ - -#include <iomanip> -#include <limits> -#include <sstream> - -#include "histogram.h" - -namespace mongo { - - using std::ostringstream; - using std::setfill; - using std::setw; - - Histogram::Histogram( const Options& opts ) - : _initialValue( opts.initialValue ) - , _numBuckets( opts.numBuckets ) - , _boundaries( new uint32_t[_numBuckets] ) - , _buckets( new uint64_t[_numBuckets] ) { - - // TODO more sanity checks - // + not too few buckets - // + initialBucket and bucketSize fit within 32 bit ints - - // _boundaries store the maximum value falling in that bucket. - if ( opts.exponential ) { - uint32_t twoPow = 1; // 2^0 - for ( uint32_t i = 0; i < _numBuckets - 1; i++) { - _boundaries[i] = _initialValue + opts.bucketSize * twoPow; - twoPow *= 2; // 2^i+1 - } - } - else { - _boundaries[0] = _initialValue + opts.bucketSize; - for ( uint32_t i = 1; i < _numBuckets - 1; i++ ) { - _boundaries[i] = _boundaries[ i-1 ] + opts.bucketSize; - } - } - _boundaries[ _numBuckets-1 ] = std::numeric_limits<uint32_t>::max(); - - for ( uint32_t i = 0; i < _numBuckets; i++ ) { - _buckets[i] = 0; - } - } - - Histogram::~Histogram() { - delete [] _boundaries; - delete [] _buckets; - } - - void Histogram::insert( uint32_t element ) { - if ( element < _initialValue) return; - - _buckets[ _findBucket(element) ] += 1; - } - - string Histogram::toHTML() const { - uint64_t max = 0; - for ( uint32_t i = 0; i < _numBuckets; i++ ) { - if ( _buckets[i] > max ) { - max = _buckets[i]; - } - } - if ( max == 0 ) { - return "histogram is empty\n"; - } - - // normalize buckets to max - const int maxBar = 20; - ostringstream ss; - for ( uint32_t i = 0; i < _numBuckets; i++ ) { - int barSize = _buckets[i] * maxBar / max; - ss << string( barSize,'*' ) - << setfill(' ') << setw( maxBar-barSize + 12 ) - << _boundaries[i] << '\n'; - } - - return ss.str(); - } - - uint64_t Histogram::getCount( uint32_t bucket ) const { - if ( bucket >= _numBuckets ) return 0; - - return _buckets[ bucket ]; - } - - uint32_t Histogram::getBoundary( uint32_t bucket ) const { - if ( bucket >= _numBuckets ) return 0; - - return _boundaries[ bucket ]; - } - - uint32_t Histogram::getBucketsNum() const { - return _numBuckets; - } - - uint32_t Histogram::_findBucket( uint32_t element ) const { - // TODO assert not too small a value? - - uint32_t low = 0; - uint32_t high = _numBuckets - 1; - while ( low < high ) { - // low + ( (high - low) / 2 ); - uint32_t mid = ( low + high ) >> 1; - if ( element > _boundaries[ mid ] ) { - low = mid + 1; - } - else { - high = mid; - } - } - return low; - } - -} // namespace mongo diff --git a/util/histogram.h b/util/histogram.h deleted file mode 100644 index 40ec5628dda..00000000000 --- a/util/histogram.h +++ /dev/null @@ -1,128 +0,0 @@ -// histogram.h - -/** -* Copyright (C) 2008 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/>. -*/ - -#ifndef UTIL_HISTOGRAM_HEADER -#define UTIL_HISTOGRAM_HEADER - -#include "../pch.h" - -#include <string> - -namespace mongo { - - using std::string; - - /** - * A histogram for a 32-bit integer range. - */ - class Histogram { - public: - /** - * Construct a histogram with 'numBuckets' buckets, optionally - * having the first bucket start at 'initialValue' rather than - * 0. By default, the histogram buckets will be 'bucketSize' wide. - * - * Usage example: - * Histogram::Options opts; - * opts.numBuckets = 3; - * opts.bucketSize = 10; - * Histogram h( opts ); - * - * Generates the bucket ranges [0..10],[11..20],[21..max_int] - * - * Alternatively, the flag 'exponential' could be turned on, in - * which case a bucket's maximum value will be - * initialValue + bucketSize * 2 ^ [0..numBuckets-1] - * - * Usage example: - * Histogram::Options opts; - * opts.numBuckets = 4; - * opts.bucketSize = 125; - * opts.exponential = true; - * Histogram h( opts ); - * - * Generates the bucket ranges [0..125],[126..250],[251..500],[501..max_int] - */ - struct Options { - boost::uint32_t numBuckets; - boost::uint32_t bucketSize; - boost::uint32_t initialValue; - - // use exponential buckets? - bool exponential; - - Options() - : numBuckets(0) - , bucketSize(0) - , initialValue(0) - , exponential(false) {} - }; - explicit Histogram( const Options& opts ); - ~Histogram(); - - /** - * Find the bucket that 'element' falls into and increment its count. - */ - void insert( boost::uint32_t element ); - - /** - * Render the histogram as string that can be used inside an - * HTML doc. - */ - string toHTML() const; - - // testing interface below -- consider it private - - /** - * Return the count for the 'bucket'-th bucket. - */ - boost::uint64_t getCount( boost::uint32_t bucket ) const; - - /** - * Return the maximum element that would fall in the - * 'bucket'-th bucket. - */ - boost::uint32_t getBoundary( boost::uint32_t bucket ) const; - - /** - * Return the number of buckets in this histogram. - */ - boost::uint32_t getBucketsNum() const; - - private: - /** - * Returns the bucket where 'element' should fall - * into. Currently assumes that 'element' is greater than the - * minimum 'inialValue'. - */ - boost::uint32_t _findBucket( boost::uint32_t element ) const; - - boost::uint32_t _initialValue; // no value lower than it is recorded - boost::uint32_t _numBuckets; // total buckets in the histogram - - // all below owned here - boost::uint32_t* _boundaries; // maximum element of each bucket - boost::uint64_t* _buckets; // current count of each bucket - - Histogram( const Histogram& ); - Histogram& operator=( const Histogram& ); - }; - -} // namespace mongo - -#endif // UTIL_HISTOGRAM_HEADER diff --git a/util/log.cpp b/util/log.cpp deleted file mode 100644 index 0dc75eddf6e..00000000000 --- a/util/log.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/** @file log.cpp - */ - -/* 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. - */ - -#include "pch.h" -#include "assert_util.h" -#include "assert.h" -#include <cmath> -#include "time_support.h" -using namespace std; - -#ifdef _WIN32 -# include <io.h> -# include <fcntl.h> -#else -# include <cxxabi.h> -# include <sys/file.h> -#endif - -#ifdef _WIN32 -# define dup2 _dup2 // Microsoft headers use ISO C names -# define fileno _fileno -#endif - -namespace mongo { - - Nullstream nullstream; - vector<Tee*>* Logstream::globalTees = 0; - - thread_specific_ptr<Logstream> Logstream::tsp; - - class LoggingManager { - public: - LoggingManager() - : _enabled(0) , _file(0) { - } - - void start( const string& lp , bool append ) { - uassert( 10268 , "LoggingManager already started" , ! _enabled ); - _append = append; - - bool exists = boost::filesystem::exists(lp); - - // test path - FILE * test = fopen( lp.c_str() , _append ? "a" : "w" ); - if ( ! test ) { - if (boost::filesystem::is_directory(lp)) { - cout << "logpath [" << lp << "] should be a file name not a directory" << endl; - } - else { - cout << "can't open [" << lp << "] for log file: " << errnoWithDescription() << endl; - } - dbexit( EXIT_BADOPTIONS ); - assert( 0 ); - } - - if (append && exists){ - // two blank lines before and after - const string msg = "\n\n***** SERVER RESTARTED *****\n\n\n"; - massert(14036, errnoWithPrefix("couldn't write to log file"), - fwrite(msg.data(), 1, msg.size(), test) == msg.size()); - } - - fclose( test ); - - _path = lp; - _enabled = 1; - rotate(); - } - - void rotate() { - if ( ! _enabled ) { - cout << "LoggingManager not enabled" << endl; - return; - } - - if ( _file ) { - -#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 ); - string s = ss.str(); - rename( _path.c_str() , s.c_str() ); - } - - 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 ); - } - - // 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; // Save new file for next rotation - } - - private: - bool _enabled; - string _path; - bool _append; - FILE * _file; - - } loggingManager; - - void initLogging( const string& lp , bool append ) { - cout << "all output going to: " << lp << endl; - loggingManager.start( lp , append ); - } - - void rotateLogs( int signal ) { - loggingManager.rotate(); - } - - // done *before* static initialization - FILE* Logstream::logfile = stdout; - -} diff --git a/util/log.h b/util/log.h deleted file mode 100644 index 660bfbee30e..00000000000 --- a/util/log.h +++ /dev/null @@ -1,531 +0,0 @@ -// @file log.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 - -#include <string.h> -#include <errno.h> -#include "../bson/util/builder.h" - -#ifndef _WIN32 -//#include <syslog.h> -#endif - -namespace mongo { - - enum LogLevel { LL_DEBUG , LL_INFO , LL_NOTICE , LL_WARNING , LL_ERROR , LL_SEVERE }; - - inline const char * logLevelToString( LogLevel l ) { - switch ( l ) { - case LL_DEBUG: - case LL_INFO: - case LL_NOTICE: - return ""; - case LL_WARNING: - return "warning" ; - case LL_ERROR: - return "ERROR"; - case LL_SEVERE: - return "SEVERE"; - default: - return "UNKNOWN"; - } - } - - class LabeledLevel { - public: - - LabeledLevel( int level ) : _level( level ) {} - LabeledLevel( const char* label, int level ) : _label( label ), _level( level ) {} - LabeledLevel( const string& label, int level ) : _label( label ), _level( level ) {} - - LabeledLevel operator+( int i ) const { - return LabeledLevel( _label, _level + i ); - } - - LabeledLevel operator+( const char* label ) const { - if( _label == "" ) - return LabeledLevel( label, _level ); - return LabeledLevel( _label + string("::") + label, _level ); - } - - LabeledLevel operator+( string& label ) const { - return LabeledLevel( _label + string("::") + label, _level ); - } - - LabeledLevel operator-( int i ) const { - return LabeledLevel( _label, _level - i ); - } - - const string& getLabel() const { return _label; } - int getLevel() const { return _level; } - - private: - string _label; - int _level; - }; - - class LazyString { - public: - virtual ~LazyString() {} - virtual string val() const = 0; - }; - - // Utility class for stringifying object only when val() called. - template< class T > - class LazyStringImpl : public LazyString { - public: - LazyStringImpl( const T &t ) : t_( t ) {} - virtual string val() const { return t_.toString(); } - private: - const T& t_; - }; - - class Tee { - public: - virtual ~Tee() {} - virtual void write(LogLevel level , const string& str) = 0; - }; - - class Nullstream { - public: - virtual Nullstream& operator<< (Tee* tee) { - return *this; - } - virtual ~Nullstream() {} - virtual Nullstream& operator<<(const char *) { - return *this; - } - virtual Nullstream& operator<<(const string& ) { - return *this; - } - virtual Nullstream& operator<<(const StringData& ) { - return *this; - } - virtual Nullstream& operator<<(char *) { - return *this; - } - virtual Nullstream& operator<<(char) { - return *this; - } - virtual Nullstream& operator<<(int) { - return *this; - } - virtual Nullstream& operator<<(ExitCode) { - return *this; - } - virtual Nullstream& operator<<(unsigned long) { - return *this; - } - virtual Nullstream& operator<<(long) { - return *this; - } - virtual Nullstream& operator<<(unsigned) { - return *this; - } - virtual Nullstream& operator<<(unsigned short) { - return *this; - } - virtual Nullstream& operator<<(double) { - return *this; - } - virtual Nullstream& operator<<(void *) { - return *this; - } - virtual Nullstream& operator<<(const void *) { - return *this; - } - virtual Nullstream& operator<<(long long) { - return *this; - } - virtual Nullstream& operator<<(unsigned long long) { - return *this; - } - virtual Nullstream& operator<<(bool) { - return *this; - } - virtual Nullstream& operator<<(const LazyString&) { - return *this; - } - template< class T > - Nullstream& operator<<(T *t) { - return operator<<( static_cast<void*>( t ) ); - } - template< class T > - Nullstream& operator<<(const T *t) { - return operator<<( static_cast<const void*>( t ) ); - } - template< class T > - Nullstream& operator<<(const shared_ptr<T> p ) { - T * t = p.get(); - if ( ! t ) - *this << "null"; - else - *this << *t; - return *this; - } - template< class T > - Nullstream& operator<<(const T &t) { - return operator<<( static_cast<const LazyString&>( LazyStringImpl< T >( t ) ) ); - } - - virtual Nullstream& operator<< (ostream& ( *endl )(ostream&)) { - return *this; - } - virtual Nullstream& operator<< (ios_base& (*hex)(ios_base&)) { - return *this; - } - - virtual void flush(Tee *t = 0) {} - }; - extern Nullstream nullstream; - - class Logstream : public Nullstream { - static mongo::mutex mutex; - static int doneSetup; - stringstream ss; - int indent; - LogLevel logLevel; - static FILE* logfile; - static boost::scoped_ptr<ostream> stream; - static vector<Tee*> * globalTees; - public: - inline static void logLockless( const StringData& s ); - - static void setLogFile(FILE* f) { - scoped_lock lk(mutex); - logfile = f; - } - - static int magicNumber() { - return 1717; - } - - static int getLogDesc() { - int fd = -1; - if (logfile != NULL) -#if defined(_WIN32) - // the ISO C++ conformant name is _fileno - fd = _fileno( logfile ); -#else - fd = fileno( logfile ); -#endif - return fd; - } - - inline void flush(Tee *t = 0); - - inline Nullstream& setLogLevel(LogLevel l) { - logLevel = l; - return *this; - } - - /** note these are virtual */ - Logstream& operator<<(const char *x) { ss << x; return *this; } - Logstream& operator<<(const string& x) { ss << x; return *this; } - Logstream& operator<<(const StringData& x) { ss << x.data(); return *this; } - Logstream& operator<<(char *x) { ss << x; return *this; } - Logstream& operator<<(char x) { ss << x; return *this; } - Logstream& operator<<(int x) { ss << x; return *this; } - Logstream& operator<<(ExitCode x) { ss << x; return *this; } - Logstream& operator<<(long x) { ss << x; return *this; } - Logstream& operator<<(unsigned long x) { ss << x; return *this; } - Logstream& operator<<(unsigned x) { ss << x; return *this; } - Logstream& operator<<(unsigned short x){ ss << x; return *this; } - Logstream& operator<<(double x) { ss << x; return *this; } - Logstream& operator<<(void *x) { ss << x; return *this; } - Logstream& operator<<(const void *x) { ss << x; return *this; } - Logstream& operator<<(long long x) { ss << x; return *this; } - Logstream& operator<<(unsigned long long x) { ss << x; return *this; } - Logstream& operator<<(bool x) { ss << x; return *this; } - - Logstream& operator<<(const LazyString& x) { - ss << x.val(); - return *this; - } - Nullstream& operator<< (Tee* tee) { - ss << '\n'; - flush(tee); - return *this; - } - Logstream& operator<< (ostream& ( *_endl )(ostream&)) { - ss << '\n'; - flush(0); - return *this; - } - Logstream& operator<< (ios_base& (*_hex)(ios_base&)) { - ss << _hex; - return *this; - } - - Logstream& prolog() { - return *this; - } - - void addGlobalTee( Tee * t ) { - if ( ! globalTees ) - globalTees = new vector<Tee*>(); - globalTees->push_back( t ); - } - - void indentInc(){ indent++; } - void indentDec(){ indent--; } - int getIndent() const { return indent; } - - private: - static thread_specific_ptr<Logstream> tsp; - Logstream() { - indent = 0; - _init(); - } - void _init() { - ss.str(""); - logLevel = LL_INFO; - } - public: - static Logstream& get() { - if ( StaticObserver::_destroyingStatics ) { - cout << "Logstream::get called in uninitialized state" << endl; - } - Logstream *p = tsp.get(); - if( p == 0 ) - tsp.reset( p = new Logstream() ); - return *p; - } - }; - - extern int logLevel; - extern int tlogLevel; - - inline Nullstream& out( int level = 0 ) { - if ( level > logLevel ) - return nullstream; - return Logstream::get(); - } - - /* flush the log stream if the log level is - at the specified level or higher. */ - inline void logflush(int level = 0) { - if( level > logLevel ) - Logstream::get().flush(0); - } - - /* without prolog */ - inline Nullstream& _log( int level = 0 ) { - if ( level > logLevel ) - return nullstream; - return Logstream::get(); - } - - /** logging which we may not want during unit tests (dbtests) runs. - set tlogLevel to -1 to suppress tlog() output in a test program. */ - inline Nullstream& tlog( int level = 0 ) { - if ( level > tlogLevel || level > logLevel ) - return nullstream; - return Logstream::get().prolog(); - } - - inline Nullstream& log( int level ) { - if ( level > logLevel ) - return nullstream; - return Logstream::get().prolog(); - } - -#define MONGO_LOG(level) if ( MONGO_unlikely(logLevel >= (level)) ) log( level ) -#define LOG MONGO_LOG - - inline Nullstream& log( LogLevel l ) { - return Logstream::get().prolog().setLogLevel( l ); - } - - inline Nullstream& log( const LabeledLevel& ll ) { - Nullstream& stream = log( ll.getLevel() ); - if( ll.getLabel() != "" ) - stream << "[" << ll.getLabel() << "] "; - return stream; - } - - inline Nullstream& log() { - return Logstream::get().prolog(); - } - - inline Nullstream& error() { - return log( LL_ERROR ); - } - - inline Nullstream& warning() { - return log( LL_WARNING ); - } - - /* default impl returns "" -- mongod overrides */ - extern const char * (*getcurns)(); - - inline Nullstream& problem( int level = 0 ) { - if ( level > logLevel ) - return nullstream; - Logstream& l = Logstream::get().prolog(); - l << ' ' << getcurns() << ' '; - return l; - } - - /** - log to a file rather than stdout - defined in assert_util.cpp - */ - void initLogging( const string& logpath , bool append ); - void rotateLogs( int signal = 0 ); - - std::string toUtf8String(const std::wstring& wide); - - inline string errnoWithDescription(int x = errno) { - stringstream s; - s << "errno:" << x << ' '; - -#if defined(_WIN32) - LPTSTR errorText = NULL; - FormatMessage( - FORMAT_MESSAGE_FROM_SYSTEM - |FORMAT_MESSAGE_ALLOCATE_BUFFER - |FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - x, 0, - (LPTSTR) &errorText, // output - 0, // minimum size for output buffer - NULL); - if( errorText ) { - string x = toUtf8String(errorText); - for( string::iterator i = x.begin(); i != x.end(); i++ ) { - if( *i == '\n' || *i == '\r' ) - break; - s << *i; - } - LocalFree(errorText); - } - else - s << strerror(x); - /* - DWORD n = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, x, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, 0, NULL); - */ -#else - s << strerror(x); -#endif - return s.str(); - } - - /** output the error # and error message with prefix. - handy for use as parm in uassert/massert. - */ - string errnoWithPrefix( const char * prefix ); - - void Logstream::logLockless( const StringData& s ) { - if ( s.size() == 0 ) - return; - - if ( doneSetup == 1717 ) { - if (fwrite(s.data(), s.size(), 1, logfile)) { - fflush(logfile); - } - else { - int x = errno; - cout << "Failed to write to logfile: " << errnoWithDescription(x) << endl; - } - } - else { - cout << s.data(); - cout.flush(); - } - } - - void Logstream::flush(Tee *t) { - // this ensures things are sane - if ( doneSetup == 1717 ) { - string msg = ss.str(); - string threadName = getThreadName(); - const char * type = logLevelToString(logLevel); - - int spaceNeeded = (int)(msg.size() + 64 + threadName.size()); - int bufSize = 128; - while ( bufSize < spaceNeeded ) - bufSize += 128; - - BufBuilder b(bufSize); - time_t_to_String( time(0) , b.grow(20) ); - if (!threadName.empty()) { - b.appendChar( '[' ); - b.appendStr( threadName , false ); - b.appendChar( ']' ); - b.appendChar( ' ' ); - } - - for ( int i=0; i<indent; i++ ) - b.appendChar( '\t' ); - - if ( type[0] ) { - b.appendStr( type , false ); - b.appendStr( ": " , false ); - } - - b.appendStr( msg ); - - string out( b.buf() , b.len() - 1); - - scoped_lock lk(mutex); - - if( t ) t->write(logLevel,out); - if ( globalTees ) { - for ( unsigned i=0; i<globalTees->size(); i++ ) - (*globalTees)[i]->write(logLevel,out); - } - -#ifndef _WIN32 - //syslog( LOG_INFO , "%s" , cc ); -#endif - if(fwrite(out.data(), out.size(), 1, logfile)) { - fflush(logfile); - } - else { - 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(); - } - - struct LogIndentLevel { - LogIndentLevel(){ - Logstream::get().indentInc(); - } - ~LogIndentLevel(){ - Logstream::get().indentDec(); - } - }; - - extern Tee* const warnings; // Things put here go in serverStatus - -} // namespace mongo diff --git a/util/logfile.cpp b/util/logfile.cpp deleted file mode 100644 index 65c56e220a4..00000000000 --- a/util/logfile.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// @file logfile.cpp simple file log writing / journaling - -/** -* Copyright (C) 2008 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/>. -*/ - -#include "pch.h" -#include "logfile.h" -#include "text.h" -#include "mongoutils/str.h" -#include "unittest.h" - -using namespace mongoutils; - -namespace mongo { - struct LogfileTest : public UnitTest { - LogfileTest() { } - void run() { - if( 0 && debug ) { - try { - LogFile f("logfile_test"); - void *p = malloc(16384); - char *buf = (char*) p; - buf += 4095; - buf = (char*) (((size_t)buf)&(~0xfff)); - memset(buf, 'z', 8192); - buf[8190] = '\n'; - buf[8191] = 'B'; - buf[0] = 'A'; - f.synchronousAppend(buf, 8192); - f.synchronousAppend(buf, 8192); - free(p); - } - catch(DBException& e ) { - log() << "logfile.cpp test failed : " << e.what() << endl; - throw; - } - } - } - } __test; -} - -#if defined(_WIN32) - -namespace mongo { - - LogFile::LogFile(string name) : _name(name) { - _fd = CreateFile( - toNativeString(name.c_str()).c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS, - FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH, - NULL); - if( _fd == INVALID_HANDLE_VALUE ) { - DWORD e = GetLastError(); - uasserted(13518, str::stream() << "couldn't open file " << name << " for writing " << errnoWithDescription(e)); - } - SetFilePointer(_fd, 0, 0, FILE_BEGIN); - } - - LogFile::~LogFile() { - if( _fd != INVALID_HANDLE_VALUE ) - CloseHandle(_fd); - } - - void LogFile::truncate() { - verify(15870, _fd != INVALID_HANDLE_VALUE); - - if (!SetEndOfFile(_fd)){ - msgasserted(15871, "Couldn't truncate file: " + errnoWithDescription()); - } - } - - void LogFile::synchronousAppend(const void *_buf, size_t _len) { - const size_t BlockSize = 8 * 1024 * 1024; - assert(_fd); - assert(_len % 4096 == 0); - const char *buf = (const char *) _buf; - size_t left = _len; - while( left ) { - size_t toWrite = min(left, BlockSize); - DWORD written; - if( !WriteFile(_fd, buf, toWrite, &written, NULL) ) { - DWORD e = GetLastError(); - if( e == 87 ) - msgasserted(13519, "error 87 appending to file - invalid parameter"); - else - uasserted(13517, str::stream() << "error appending to file " << _name << ' ' << _len << ' ' << toWrite << ' ' << errnoWithDescription(e)); - } - else { - dassert( written == toWrite ); - } - left -= written; - buf += written; - } - } - -} - -#else - -// posix - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include "paths.h" - -namespace mongo { - - LogFile::LogFile(string name) : _name(name) { - int options = O_CREAT - | O_WRONLY -#if defined(O_DIRECT) - | O_DIRECT -#endif -#if defined(O_NOATIME) - | O_NOATIME -#endif - ; - - _fd = open(name.c_str(), options, S_IRUSR | S_IWUSR); - -#if defined(O_DIRECT) - _direct = true; - if( _fd < 0 ) { - _direct = false; - options &= ~O_DIRECT; - _fd = open(name.c_str(), options, S_IRUSR | S_IWUSR); - } -#else - _direct = false; -#endif - - if( _fd < 0 ) { - uasserted(13516, str::stream() << "couldn't open file " << name << " for writing " << errnoWithDescription()); - } - - flushMyDirectory(name); - } - - LogFile::~LogFile() { - if( _fd >= 0 ) - close(_fd); - _fd = -1; - } - - void LogFile::truncate() { - verify(15872, _fd >= 0); - - BOOST_STATIC_ASSERT(sizeof(off_t) == 8); // we don't want overflow here - const off_t pos = lseek(_fd, 0, SEEK_CUR); // doesn't actually seek - if (ftruncate(_fd, pos) != 0){ - msgasserted(15873, "Couldn't truncate file: " + errnoWithDescription()); - } - } - - void LogFile::synchronousAppend(const void *b, size_t len) { - - const char *buf = static_cast<const char *>( b ); - ssize_t charsToWrite = static_cast<ssize_t>( len ); - - if (charsToWrite < 0 || _fd < 0) { - log() << "LogFile::synchronousAppend preconditions not met."; - ::abort(); - } - -#ifdef POSIX_FADV_DONTNEED - const off_t pos = lseek(_fd, 0, SEEK_CUR); // doesn't actually seek -#endif - - while ( charsToWrite > 0 ) { - const ssize_t written = write( _fd, buf, static_cast<size_t>( charsToWrite ) ); - if ( -1 == written ) { - log() << "LogFile::synchronousAppend failed with " << charsToWrite - << " bytes unwritten out of " << len << " bytes; b=" << b << ' ' - << errnoWithDescription() << std::endl; - ::abort(); - } - buf += written; - charsToWrite -= written; - } - - if( -#if defined(__linux__) - fdatasync(_fd) < 0 -#else - fsync(_fd) -#endif - ) { - log() << "error appending to file on fsync " << ' ' << errnoWithDescription(); - ::abort(); - } - -#ifdef POSIX_FADV_DONTNEED - if (!_direct) - posix_fadvise(_fd, pos, len, POSIX_FADV_DONTNEED); -#endif - } - -} - -#endif diff --git a/util/logfile.h b/util/logfile.h deleted file mode 100644 index f6d1c94bf22..00000000000 --- a/util/logfile.h +++ /dev/null @@ -1,53 +0,0 @@ -// @file logfile.h simple file log writing / journaling - -/** -* 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/>. -*/ - -#pragma once - -namespace mongo { - - class LogFile { - public: - /** create the file and open. must not already exist. - throws UserAssertion on i/o error - */ - LogFile(string name); - - /** closes */ - ~LogFile(); - - /** append to file. does not return until sync'd. uses direct i/o when possible. - throws UserAssertion on an i/o error - note direct i/o may have alignment requirements - */ - void synchronousAppend(const void *buf, size_t len); - - const string _name; - - void truncate(); // Removes extra data after current position - - private: -#if defined(_WIN32) - typedef HANDLE fd_type; -#else - typedef int fd_type; -#endif - fd_type _fd; - bool _direct; // are we using direct I/O - }; - -} diff --git a/util/lruishmap.h b/util/lruishmap.h deleted file mode 100644 index ba91bf6f0f6..00000000000 --- a/util/lruishmap.h +++ /dev/null @@ -1,78 +0,0 @@ -// lru-ish map.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 - -#include "../pch.h" -#include "../util/goodies.h" - -namespace mongo { - - /* Your K object must define: - int hash() - must always return > 0. - operator== - */ - - template <class K, class V, int MaxChain> - class LRUishMap { - public: - LRUishMap(int _n) { - n = nextPrime(_n); - keys = new K[n]; - hashes = new int[n]; - for ( int i = 0; i < n; i++ ) hashes[i] = 0; - } - ~LRUishMap() { - delete[] keys; - delete[] hashes; - } - - int _find(const K& k, bool& found) { - int h = k.hash(); - assert( h > 0 ); - int j = h % n; - int first = j; - for ( int i = 0; i < MaxChain; i++ ) { - if ( hashes[j] == h ) { - if ( keys[j] == k ) { - found = true; - return j; - } - } - else if ( hashes[j] == 0 ) { - found = false; - return j; - } - } - found = false; - return first; - } - - V* find(const K& k) { - bool found; - int j = _find(k, found); - return found ? &values[j] : 0; - } - - private: - int n; - K *keys; - int *hashes; - V *values; - }; - -} // namespace mongo diff --git a/util/md5.c b/util/md5.c deleted file mode 100644 index c35d96c5ef5..00000000000 --- a/util/md5.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order - either statically or dynamically; added missing #include <string.h> - in library. - 2002-03-11 lpd Corrected argument list for main(), and added int return - type, in test program and T value program. - 2002-02-21 lpd Added missing #include <stdio.h> in test program. - 2000-07-03 lpd Patched to eliminate warnings about "constant is - unsigned in ANSI C, signed in traditional"; made test program - self-checking. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). - 1999-05-03 lpd Original version. - */ - -#include "md5.h" -#include <string.h> - -#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ -#ifdef ARCH_IS_BIG_ENDIAN -# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) -#else -# define BYTE_ORDER 0 -#endif - -#define T_MASK ((md5_word_t)~0) -#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) -#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) -#define T3 0x242070db -#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) -#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) -#define T6 0x4787c62a -#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) -#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) -#define T9 0x698098d8 -#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) -#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) -#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) -#define T13 0x6b901122 -#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) -#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) -#define T16 0x49b40821 -#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) -#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) -#define T19 0x265e5a51 -#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) -#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) -#define T22 0x02441453 -#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) -#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) -#define T25 0x21e1cde6 -#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) -#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) -#define T28 0x455a14ed -#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) -#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) -#define T31 0x676f02d9 -#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) -#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) -#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) -#define T35 0x6d9d6122 -#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) -#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) -#define T38 0x4bdecfa9 -#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) -#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) -#define T41 0x289b7ec6 -#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) -#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) -#define T44 0x04881d05 -#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) -#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) -#define T47 0x1fa27cf8 -#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) -#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) -#define T50 0x432aff97 -#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) -#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) -#define T53 0x655b59c3 -#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) -#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) -#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) -#define T57 0x6fa87e4f -#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) -#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) -#define T60 0x4e0811a1 -#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) -#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) -#define T63 0x2ad7d2bb -#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) - - -static void -md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/) -{ - md5_word_t - a = pms->abcd[0], b = pms->abcd[1], - c = pms->abcd[2], d = pms->abcd[3]; - md5_word_t t; -#if BYTE_ORDER > 0 - /* Define storage only for big-endian CPUs. */ - md5_word_t X[16]; -#else - /* Define storage for little-endian or both types of CPUs. */ - md5_word_t xbuf[16]; - const md5_word_t *X; -#endif - - { -#if BYTE_ORDER == 0 - /* - * Determine dynamically whether this is a big-endian or - * little-endian machine, since we can use a more efficient - * algorithm on the latter. - */ - static const int w = 1; - - if (*((const md5_byte_t *)&w)) /* dynamic little-endian */ -#endif -#if BYTE_ORDER <= 0 /* little-endian */ - { - /* - * On little-endian machines, we can process properly aligned - * data without copying it. - */ - if (!((data - (const md5_byte_t *)0) & 3)) { - /* data are properly aligned */ - X = (const md5_word_t *)data; - } else { - /* not aligned */ - memcpy(xbuf, data, 64); - X = xbuf; - } - } -#endif -#if BYTE_ORDER == 0 - else /* dynamic big-endian */ -#endif -#if BYTE_ORDER >= 0 /* big-endian */ - { - /* - * On big-endian machines, we must arrange the bytes in the - * right order. - */ - const md5_byte_t *xp = data; - int i; - -# if BYTE_ORDER == 0 - X = xbuf; /* (dynamic only) */ -# else -# define xbuf X /* (static only) */ -# endif - for (i = 0; i < 16; ++i, xp += 4) - xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); - } -#endif - } - -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - - /* Round 1. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + F(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 7, T1); - SET(d, a, b, c, 1, 12, T2); - SET(c, d, a, b, 2, 17, T3); - SET(b, c, d, a, 3, 22, T4); - SET(a, b, c, d, 4, 7, T5); - SET(d, a, b, c, 5, 12, T6); - SET(c, d, a, b, 6, 17, T7); - SET(b, c, d, a, 7, 22, T8); - SET(a, b, c, d, 8, 7, T9); - SET(d, a, b, c, 9, 12, T10); - SET(c, d, a, b, 10, 17, T11); - SET(b, c, d, a, 11, 22, T12); - SET(a, b, c, d, 12, 7, T13); - SET(d, a, b, c, 13, 12, T14); - SET(c, d, a, b, 14, 17, T15); - SET(b, c, d, a, 15, 22, T16); -#undef SET - - /* Round 2. */ - /* Let [abcd k s i] denote the operation - a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + G(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 1, 5, T17); - SET(d, a, b, c, 6, 9, T18); - SET(c, d, a, b, 11, 14, T19); - SET(b, c, d, a, 0, 20, T20); - SET(a, b, c, d, 5, 5, T21); - SET(d, a, b, c, 10, 9, T22); - SET(c, d, a, b, 15, 14, T23); - SET(b, c, d, a, 4, 20, T24); - SET(a, b, c, d, 9, 5, T25); - SET(d, a, b, c, 14, 9, T26); - SET(c, d, a, b, 3, 14, T27); - SET(b, c, d, a, 8, 20, T28); - SET(a, b, c, d, 13, 5, T29); - SET(d, a, b, c, 2, 9, T30); - SET(c, d, a, b, 7, 14, T31); - SET(b, c, d, a, 12, 20, T32); -#undef SET - - /* Round 3. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + H(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 5, 4, T33); - SET(d, a, b, c, 8, 11, T34); - SET(c, d, a, b, 11, 16, T35); - SET(b, c, d, a, 14, 23, T36); - SET(a, b, c, d, 1, 4, T37); - SET(d, a, b, c, 4, 11, T38); - SET(c, d, a, b, 7, 16, T39); - SET(b, c, d, a, 10, 23, T40); - SET(a, b, c, d, 13, 4, T41); - SET(d, a, b, c, 0, 11, T42); - SET(c, d, a, b, 3, 16, T43); - SET(b, c, d, a, 6, 23, T44); - SET(a, b, c, d, 9, 4, T45); - SET(d, a, b, c, 12, 11, T46); - SET(c, d, a, b, 15, 16, T47); - SET(b, c, d, a, 2, 23, T48); -#undef SET - - /* Round 4. */ - /* Let [abcd k s t] denote the operation - a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ - t = a + I(b,c,d) + X[k] + Ti;\ - a = ROTATE_LEFT(t, s) + b - /* Do the following 16 operations. */ - SET(a, b, c, d, 0, 6, T49); - SET(d, a, b, c, 7, 10, T50); - SET(c, d, a, b, 14, 15, T51); - SET(b, c, d, a, 5, 21, T52); - SET(a, b, c, d, 12, 6, T53); - SET(d, a, b, c, 3, 10, T54); - SET(c, d, a, b, 10, 15, T55); - SET(b, c, d, a, 1, 21, T56); - SET(a, b, c, d, 8, 6, T57); - SET(d, a, b, c, 15, 10, T58); - SET(c, d, a, b, 6, 15, T59); - SET(b, c, d, a, 13, 21, T60); - SET(a, b, c, d, 4, 6, T61); - SET(d, a, b, c, 11, 10, T62); - SET(c, d, a, b, 2, 15, T63); - SET(b, c, d, a, 9, 21, T64); -#undef SET - - /* Then perform the following additions. (That is increment each - of the four registers by the value it had before this block - was started.) */ - pms->abcd[0] += a; - pms->abcd[1] += b; - pms->abcd[2] += c; - pms->abcd[3] += d; -} - -void -md5_init(md5_state_t *pms) -{ - pms->count[0] = pms->count[1] = 0; - pms->abcd[0] = 0x67452301; - pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; - pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; - pms->abcd[3] = 0x10325476; -} - -void -md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes) -{ - const md5_byte_t *p = data; - int left = nbytes; - int offset = (pms->count[0] >> 3) & 63; - md5_word_t nbits = (md5_word_t)(nbytes << 3); - - if (nbytes <= 0) - return; - - /* Update the message length. */ - pms->count[1] += nbytes >> 29; - pms->count[0] += nbits; - if (pms->count[0] < nbits) - pms->count[1]++; - - /* Process an initial partial block. */ - if (offset) { - int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); - - memcpy(pms->buf + offset, p, copy); - if (offset + copy < 64) - return; - p += copy; - left -= copy; - md5_process(pms, pms->buf); - } - - /* Process full blocks. */ - for (; left >= 64; p += 64, left -= 64) - md5_process(pms, p); - - /* Process a final partial block. */ - if (left) - memcpy(pms->buf, p, left); -} - -void -md5_finish(md5_state_t *pms, md5_byte_t digest[16]) -{ - static const md5_byte_t pad[64] = { - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - md5_byte_t data[8]; - int i; - - /* Save the length before padding. */ - for (i = 0; i < 8; ++i) - data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); - /* Pad to 56 bytes mod 64. */ - md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); - /* Append the length. */ - md5_append(pms, data, 8); - for (i = 0; i < 16; ++i) - digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); -} diff --git a/util/md5.h b/util/md5.h deleted file mode 100644 index a3f3b6db0e2..00000000000 --- a/util/md5.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.h is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Removed support for non-ANSI compilers; removed - references to Ghostscript; clarified derivation from RFC 1321; - now handles byte order either statically or dynamically. - 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. - 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); - added conditionalization for C++ compilation from Martin - Purschke <purschke@bnl.gov>. - 1999-05-03 lpd Original version. - */ - -#ifndef md5_INCLUDED -# define md5_INCLUDED - -/* - * This package supports both compile-time and run-time determination of CPU - * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be - * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is - * defined as non-zero, the code will be compiled to run only on big-endian - * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to - * run on either big- or little-endian CPUs, but will run slightly less - * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. - */ - -typedef unsigned char md5_byte_t; /* 8-bit byte */ -typedef unsigned int md5_word_t; /* 32-bit word */ - -/* Define the state of the MD5 Algorithm. */ -typedef struct md5_state_s { - md5_word_t count[2]; /* message length in bits, lsw first */ - md5_word_t abcd[4]; /* digest buffer */ - md5_byte_t buf[64]; /* accumulate block */ -} md5_state_t; - -#ifdef __cplusplus -extern "C" -{ -#endif - - /* Initialize the algorithm. */ - void md5_init(md5_state_t *pms); - - /* Append a string to the message. */ - void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes); - - /* Finish the message and return the digest. */ - void md5_finish(md5_state_t *pms, md5_byte_t digest[16]); - -#ifdef __cplusplus -} /* end extern "C" */ -#endif - -#endif /* md5_INCLUDED */ diff --git a/util/md5.hpp b/util/md5.hpp deleted file mode 100644 index dc061719747..00000000000 --- a/util/md5.hpp +++ /dev/null @@ -1,58 +0,0 @@ -// md5.hpp - -/* 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 - -#include "md5.h" - -namespace mongo { - - typedef unsigned char md5digest[16]; - - inline void md5(const void *buf, int nbytes, md5digest digest) { - md5_state_t st; - md5_init(&st); - md5_append(&st, (const md5_byte_t *) buf, nbytes); - md5_finish(&st, digest); - } - - inline void md5(const char *str, md5digest digest) { - md5(str, strlen(str), digest); - } - - inline std::string digestToString( md5digest digest ){ - static const char * letters = "0123456789abcdef"; - stringstream ss; - for ( int i=0; i<16; i++){ - unsigned char c = digest[i]; - ss << letters[ ( c >> 4 ) & 0xf ] << letters[ c & 0xf ]; - } - return ss.str(); - } - - inline std::string md5simpledigest( const void* buf, int nbytes){ - md5digest d; - md5( buf, nbytes , d ); - return digestToString( d ); - } - - inline std::string md5simpledigest( string s ){ - return md5simpledigest(s.data(), s.size()); - } - - -} // namespace mongo diff --git a/util/md5main.cpp b/util/md5main.cpp deleted file mode 100644 index 9995fee8fa7..00000000000 --- a/util/md5main.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright (C) 2002 Aladdin Enterprises. All rights reserved. - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - L. Peter Deutsch - ghost@aladdin.com - - */ -/* $Id: md5main.c,v 1.1 2002/04/13 19:20:28 lpd Exp $ */ -/* - Independent implementation of MD5 (RFC 1321). - - This code implements the MD5 Algorithm defined in RFC 1321, whose - text is available at - http://www.ietf.org/rfc/rfc1321.txt - The code is derived from the text of the RFC, including the test suite - (section A.5) but excluding the rest of Appendix A. It does not include - any code or documentation that is identified in the RFC as being - copyrighted. - - The original and principal author of md5.c is L. Peter Deutsch - <ghost@aladdin.com>. Other authors are noted in the change history - that follows (in reverse chronological order): - - 2002-04-13 lpd Splits off main program into a separate file, md5main.c. - */ - -#include "pch.h" -#include "md5.h" -#include <math.h> -#include <stdio.h> -#include <string.h> - -/* - * This file builds an executable that performs various functions related - * to the MD5 library. Typical compilation: - * gcc -o md5main -lm md5main.c md5.c - */ -static const char *const usage = "\ -Usage:\n\ - md5main --test # run the self-test (A.5 of RFC 1321)\n\ - md5main --t-values # print the T values for the library\n\ - md5main --version # print the version of the package\n\ -"; -static const char *const version = "2002-04-13"; - -/* modified: not static, renamed */ -/* Run the self-test. */ -/*static*/ int -//do_test(void) -do_md5_test(void) { - static const char *const test[7*2] = { - "", "d41d8cd98f00b204e9800998ecf8427e", - "a", "0cc175b9c0f1b6a831c399e269772661", - "abc", "900150983cd24fb0d6963f7d28e17f72", - "message digest", "f96b697d7cb7938d525a2f31aaf161d0", - "abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "d174ab98d277d9f5a5611c2c9f419d9f", - "12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a" - }; - int i; - int status = 0; - - for (i = 0; i < 7*2; i += 2) { - md5_state_t state; - md5_byte_t digest[16]; - char hex_output[16*2 + 1]; - int di; - - md5_init(&state); - md5_append(&state, (const md5_byte_t *)test[i], strlen(test[i])); - md5_finish(&state, digest); - for (di = 0; di < 16; ++di) - sprintf(hex_output + di * 2, "%02x", digest[di]); - if (strcmp(hex_output, test[i + 1])) { - printf("MD5 (\"%s\") = ", test[i]); - puts(hex_output); - printf("**** ERROR, should be: %s\n", test[i + 1]); - status = 1; - } - } -// if (status == 0) - /*modified commented out: puts("md5 self-test completed successfully."); */ - return status; -} - -/* Print the T values. */ -static int -do_t_values(void) { - int i; - for (i = 1; i <= 64; ++i) { - unsigned long v = (unsigned long)(4294967296.0 * fabs(sin((double)i))); - - /* - * The following nonsense is only to avoid compiler warnings about - * "integer constant is unsigned in ANSI C, signed with -traditional". - */ - if (v >> 31) { - printf("#define T%d /* 0x%08lx */ (T_MASK ^ 0x%08lx)\n", i, - v, (unsigned long)(unsigned int)(~v)); - } - else { - printf("#define T%d 0x%08lx\n", i, v); - } - } - return 0; -} - -/* modified from original code changed function name main->md5main */ -/* Main program */ -int -md5main(int argc, char *argv[]) { - if (argc == 2) { - if (!strcmp(argv[1], "--test")) - return do_md5_test(); - if (!strcmp(argv[1], "--t-values")) - return do_t_values(); - if (!strcmp(argv[1], "--version")) { - puts(version); - return 0; - } - } - puts(usage); - return 0; -} - diff --git a/util/mmap.cpp b/util/mmap.cpp deleted file mode 100644 index fa9ab735ef4..00000000000 --- a/util/mmap.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// mmap.cpp - -/* 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. - */ - -#include "pch.h" -#include "mmap.h" -#include "processinfo.h" -#include "concurrency/rwlock.h" -#include "../db/namespace.h" -#include "../db/cmdline.h" - -namespace mongo { - - set<MongoFile*> MongoFile::mmfiles; - map<string,MongoFile*> MongoFile::pathToFile; - - /* Create. Must not exist. - @param zero fill file with zeros when true - */ - void* MemoryMappedFile::create(string filename, unsigned long long len, bool zero) { - uassert( 13468, string("can't create file already exists ") + filename, !exists(filename) ); - void *p = map(filename.c_str(), len); - if( p && zero ) { - size_t sz = (size_t) len; - assert( len == sz ); - memset(p, 0, sz); - } - return p; - } - - /*static*/ void MemoryMappedFile::updateLength( const char *filename, unsigned long long &length ) { - if ( !boost::filesystem::exists( filename ) ) - return; - // make sure we map full length if preexisting file. - boost::uintmax_t l = boost::filesystem::file_size( filename ); - length = l; - } - - void* MemoryMappedFile::map(const char *filename) { - unsigned long long l = boost::filesystem::file_size( filename ); - return map( filename , l ); - } - void* MemoryMappedFile::mapWithOptions(const char *filename, int options) { - unsigned long long l = boost::filesystem::file_size( filename ); - return map( filename , l, options ); - } - - /* --- MongoFile ------------------------------------------------- - this is the administrative stuff - */ - - RWLockRecursive MongoFile::mmmutex("mmmutex",10*60*1000 /* 10 minutes */); - - /* subclass must call in destructor (or at close). - removes this from pathToFile and other maps - safe to call more than once, albeit might be wasted work - ideal to call close to the close, if the close is well before object destruction - */ - void MongoFile::destroyed() { - mmmutex.assertExclusivelyLocked(); - mmfiles.erase(this); - pathToFile.erase( filename() ); - } - - /*static*/ - void MongoFile::closeAllFiles( stringstream &message ) { - static int closingAllFiles = 0; - if ( closingAllFiles ) { - message << "warning closingAllFiles=" << closingAllFiles << endl; - return; - } - ++closingAllFiles; - - RWLockRecursive::Exclusive lk(mmmutex); - - ProgressMeter pm( mmfiles.size() , 2 , 1 ); - set<MongoFile*> temp = mmfiles; - for ( set<MongoFile*>::iterator i = temp.begin(); i != temp.end(); i++ ) { - (*i)->close(); // close() now removes from mmfiles - pm.hit(); - } - message << "closeAllFiles() finished"; - --closingAllFiles; - } - - /*static*/ long long MongoFile::totalMappedLength() { - unsigned long long total = 0; - - RWLockRecursive::Shared lk(mmmutex); - for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) - total += (*i)->length(); - - return total; - } - - void nullFunc() { } - - // callback notifications - void (*MongoFile::notifyPreFlush)() = nullFunc; - void (*MongoFile::notifyPostFlush)() = nullFunc; - - /*static*/ int MongoFile::flushAll( bool sync ) { - notifyPreFlush(); - int x = _flushAll(sync); - notifyPostFlush(); - return x; - } - - /*static*/ int MongoFile::_flushAll( bool sync ) { - if ( ! sync ) { - int num = 0; - RWLockRecursive::Shared lk(mmmutex); - for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) { - num++; - MongoFile * mmf = *i; - if ( ! mmf ) - continue; - - mmf->flush( sync ); - } - return num; - } - - // want to do it sync - set<MongoFile*> seen; - while ( true ) { - auto_ptr<Flushable> f; - { - RWLockRecursive::Shared lk(mmmutex); - for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) { - MongoFile * mmf = *i; - if ( ! mmf ) - continue; - if ( seen.count( mmf ) ) - continue; - f.reset( mmf->prepareFlush() ); - seen.insert( mmf ); - break; - } - } - if ( ! f.get() ) - break; - - f->flush(); - } - return seen.size(); - } - - void MongoFile::created() { - RWLockRecursive::Exclusive lk(mmmutex); - mmfiles.insert(this); - } - - void MongoFile::setFilename(string fn) { - RWLockRecursive::Exclusive lk(mmmutex); - assert( _filename.empty() ); - _filename = fn; - MongoFile *&ptf = pathToFile[fn]; - massert(13617, "MongoFile : multiple opens of same filename", ptf == 0); - ptf = this; - } - -#if defined(_DEBUG) - void MongoFile::markAllWritable() { - if( cmdLine.dur ) - return; - RWLockRecursive::Shared lk(mmmutex); - for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) { - MongoFile * mmf = *i; - if (mmf) mmf->_lock(); - } - } - - void MongoFile::unmarkAllWritable() { - if( cmdLine.dur ) - return; - RWLockRecursive::Shared lk(mmmutex); - for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) { - MongoFile * mmf = *i; - if (mmf) mmf->_unlock(); - } - } -#endif -} // namespace mongo diff --git a/util/mmap.h b/util/mmap.h deleted file mode 100644 index 2bb9c160249..00000000000 --- a/util/mmap.h +++ /dev/null @@ -1,280 +0,0 @@ -// 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 -#include <boost/thread/xtime.hpp> -#include "concurrency/rwlock.h" - -namespace mongo { - - class MAdvise { - void *_p; - unsigned _len; - public: - enum Advice { Sequential=1 }; - MAdvise(void *p, unsigned len, Advice a); - ~MAdvise(); // destructor resets the range to MADV_NORMAL - }; - - /* the administrative-ish stuff here */ - class MongoFile : boost::noncopyable { - public: - /** Flushable has to fail nicely if the underlying object gets killed */ - class Flushable { - public: - virtual ~Flushable() {} - virtual void flush() = 0; - }; - - virtual ~MongoFile() {} - - enum Options { - SEQUENTIAL = 1, // hint - e.g. FILE_FLAG_SEQUENTIAL_SCAN on windows - READONLY = 2 // not contractually guaranteed, but if specified the impl has option to fault writes - }; - - /** @param fun is called for each MongoFile. - calledl from within a mutex that MongoFile uses. so be careful not to deadlock. - */ - template < class F > - static void forEach( F fun ); - - /** note: you need to be in mmmutex when using this. forEach (above) handles that for you automatically. -*/ - static set<MongoFile*>& getAllFiles() { return mmfiles; } - - // callbacks if you need them - static void (*notifyPreFlush)(); - static void (*notifyPostFlush)(); - - static int flushAll( bool sync ); // returns n flushed - static long long totalMappedLength(); - static void closeAllFiles( stringstream &message ); - -#if defined(_DEBUG) - static void markAllWritable(); - static void unmarkAllWritable(); -#else - static void markAllWritable() { } - static void unmarkAllWritable() { } -#endif - - static bool exists(boost::filesystem::path p) { return boost::filesystem::exists(p); } - - virtual bool isMongoMMF() { return false; } - - string filename() const { return _filename; } - void setFilename(string fn); - - private: - string _filename; - static int _flushAll( bool sync ); // returns n flushed - protected: - virtual void close() = 0; - virtual void flush(bool sync) = 0; - /** - * returns a thread safe object that you can call flush on - * Flushable has to fail nicely if the underlying object gets killed - */ - virtual Flushable * prepareFlush() = 0; - - void created(); /* subclass must call after create */ - - /* subclass must call in destructor (or at close). - removes this from pathToFile and other maps - safe to call more than once, albeit might be wasted work - ideal to call close to the close, if the close is well before object destruction - */ - void destroyed(); - - virtual unsigned long long length() const = 0; - - // only supporting on posix mmap - virtual void _lock() {} - virtual void _unlock() {} - - static set<MongoFile*> mmfiles; - public: - static map<string,MongoFile*> pathToFile; - - // lock order: lock dbMutex before this if you lock both - static RWLockRecursive mmmutex; - }; - - /** look up a MMF by filename. scoped mutex locking convention. - example: - MMFFinderByName finder; - MongoMMF *a = finder.find("file_name_a"); - MongoMMF *b = finder.find("file_name_b"); - */ - class MongoFileFinder : boost::noncopyable { - public: - MongoFileFinder() : _lk(MongoFile::mmmutex) { } - - /** @return The MongoFile object associated with the specified file name. If no file is open - with the specified name, returns null. - */ - MongoFile* findByPath(string path) { - map<string,MongoFile*>::iterator i = MongoFile::pathToFile.find(path); - return i == MongoFile::pathToFile.end() ? NULL : i->second; - } - - private: - RWLockRecursive::Shared _lk; - }; - - struct MongoFileAllowWrites { - MongoFileAllowWrites() { - MongoFile::markAllWritable(); - } - ~MongoFileAllowWrites() { - MongoFile::unmarkAllWritable(); - } - }; - - class MemoryMappedFile : public MongoFile { - protected: - virtual void* viewForFlushing() { - if( views.size() == 0 ) - return 0; - assert( views.size() == 1 ); - return views[0]; - } - public: - MemoryMappedFile(); - - virtual ~MemoryMappedFile() { - RWLockRecursive::Exclusive lk(mmmutex); - close(); - } - - virtual void close(); - - // Throws exception if file doesn't exist. (dm may2010: not sure if this is always true?) - void* map(const char *filename); - - /** @param options see MongoFile::Options */ - void* mapWithOptions(const char *filename, int options); - - /* Creates with length if DNE, otherwise uses existing file length, - passed length. - @param options MongoFile::Options bits - */ - void* map(const char *filename, unsigned long long &length, int options = 0 ); - - /* Create. Must not exist. - @param zero fill file with zeros when true - */ - void* create(string filename, unsigned long long len, bool zero); - - void flush(bool sync); - virtual Flushable * prepareFlush(); - - long shortLength() const { return (long) len; } - unsigned long long length() const { return len; } - - /** create a new view with the specified properties. - automatically cleaned up upon close/destruction of the MemoryMappedFile object. - */ - void* createReadOnlyMap(); - void* createPrivateMap(); - - /** make the private map range writable (necessary for our windows implementation) */ - static void makeWritable(void *, unsigned len) -#if defined(_WIN32) - ; -#else - { } -#endif - - private: - static void updateLength( const char *filename, unsigned long long &length ); - - HANDLE fd; - HANDLE maphandle; - vector<void *> views; - unsigned long long len; - -#ifdef _WIN32 - boost::shared_ptr<mutex> _flushMutex; - void clearWritableBits(void *privateView); - public: - static const unsigned ChunkSize = 64 * 1024 * 1024; - static const unsigned NChunks = 1024 * 1024; -#else - void clearWritableBits(void *privateView) { } -#endif - - protected: - // only posix mmap implementations will support this - virtual void _lock(); - virtual void _unlock(); - - /** close the current private view and open a new replacement */ - void* remapPrivateView(void *oldPrivateAddr); - }; - - typedef MemoryMappedFile MMF; - - /** p is called from within a mutex that MongoFile uses. so be careful not to deadlock. */ - template < class F > - inline void MongoFile::forEach( F p ) { - RWLockRecursive::Shared lklk(mmmutex); - for ( set<MongoFile*>::iterator i = mmfiles.begin(); i != mmfiles.end(); i++ ) - p(*i); - } - -#if defined(_WIN32) - class ourbitset { - volatile unsigned bits[MemoryMappedFile::NChunks]; // volatile as we are doing double check locking - public: - ourbitset() { - memset((void*) bits, 0, sizeof(bits)); - } - bool get(unsigned i) const { - unsigned x = i / 32; - assert( x < MemoryMappedFile::NChunks ); - return (bits[x] & (1 << (i%32))) != 0; - } - void set(unsigned i) { - unsigned x = i / 32; - wassert( x < (MemoryMappedFile::NChunks*2/3) ); // warn if getting close to limit - assert( x < MemoryMappedFile::NChunks ); - bits[x] |= (1 << (i%32)); - } - void clear(unsigned i) { - unsigned x = i / 32; - assert( x < MemoryMappedFile::NChunks ); - bits[x] &= ~(1 << (i%32)); - } - }; - extern ourbitset writable; - void makeChunkWritable(size_t chunkno); - inline void MemoryMappedFile::makeWritable(void *_p, unsigned len) { - size_t p = (size_t) _p; - unsigned a = p/ChunkSize; - unsigned b = (p+len)/ChunkSize; - for( unsigned i = a; i <= b; i++ ) { - if( !writable.get(i) ) { - makeChunkWritable(i); - } - } - } - extern void* getNextMemoryMappedFileLocation( unsigned long long mmfSize ); -#endif - -} // namespace mongo diff --git a/util/mmap_mm.cpp b/util/mmap_mm.cpp deleted file mode 100644 index ec2400e02d3..00000000000 --- a/util/mmap_mm.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// mmap_mm.cpp - in memory (no file) version - -/* 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. - */ - -#include "pch.h" -#include "mmap.h" - -/* in memory (no file) version */ - -namespace mongo { - - MemoryMappedFile::MemoryMappedFile() { - fd = 0; - maphandle = 0; - view = 0; - len = 0; - } - - void MemoryMappedFile::close() { - if ( view ) - free( view ); - view = 0; - len = 0; - } - - void* MemoryMappedFile::map(const char *filename, long& length , int options ) { - assert( length ); - view = malloc( length ); - return view; - } - - void MemoryMappedFile::flush(bool sync) { - } - - void MemoryMappedFile::_lock() {} - void MemoryMappedFile::_unlock() {} - -} - diff --git a/util/mmap_posix.cpp b/util/mmap_posix.cpp deleted file mode 100644 index 5b5e86d7c0c..00000000000 --- a/util/mmap_posix.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// mmap_posix.cpp - -/* 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. - */ - -#include "pch.h" -#include "mmap.h" -#include "file_allocator.h" -#include "../db/concurrency.h" -#include <errno.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include "../util/processinfo.h" -#include "mongoutils/str.h" -using namespace mongoutils; - -namespace mongo { - - MemoryMappedFile::MemoryMappedFile() { - fd = 0; - maphandle = 0; - len = 0; - created(); - } - - void MemoryMappedFile::close() { - mmmutex.assertExclusivelyLocked(); - for( vector<void*>::iterator i = views.begin(); i != views.end(); i++ ) { - munmap(*i,len); - } - views.clear(); - - if ( fd ) - ::close(fd); - fd = 0; - destroyed(); // cleans up from the master list of mmaps - } - -#ifndef O_NOATIME -#define O_NOATIME (0) -#endif - -#ifndef MAP_NORESERVE -#define MAP_NORESERVE (0) -#endif - -#if defined(__sunos__) - MAdvise::MAdvise(void *,unsigned, Advice) { } - MAdvise::~MAdvise() { } -#else - MAdvise::MAdvise(void *p, unsigned len, Advice a) : _p(p), _len(len) { - assert( a == Sequential ); // more later - madvise(_p,_len,MADV_SEQUENTIAL); - } - MAdvise::~MAdvise() { - madvise(_p,_len,MADV_NORMAL); - } -#endif - - void* MemoryMappedFile::map(const char *filename, unsigned long long &length, int options) { - // length may be updated by callee. - setFilename(filename); - FileAllocator::get()->allocateAsap( filename, length ); - len = length; - - massert( 10446 , str::stream() << "mmap: can't map area of size 0 file: " << filename, length > 0 ); - - fd = open(filename, O_RDWR | O_NOATIME); - if ( fd <= 0 ) { - log() << "couldn't open " << filename << ' ' << errnoWithDescription() << endl; - fd = 0; // our sentinel for not opened - return 0; - } - - unsigned long long filelen = lseek(fd, 0, SEEK_END); - uassert(10447, str::stream() << "map file alloc failed, wanted: " << length << " filelen: " << filelen << ' ' << sizeof(size_t), filelen == length ); - lseek( fd, 0, SEEK_SET ); - - void * view = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if ( view == MAP_FAILED ) { - error() << " mmap() failed for " << filename << " len:" << length << " " << errnoWithDescription() << endl; - if ( errno == ENOMEM ) { - if( sizeof(void*) == 4 ) - error() << "mmap failed with out of memory. You are using a 32-bit build and probably need to upgrade to 64" << endl; - else - error() << "mmap failed with out of memory. (64 bit build)" << endl; - } - return 0; - } - - -#if defined(__sunos__) -#warning madvise not supported on solaris yet -#else - if ( options & SEQUENTIAL ) { - if ( madvise( view , length , MADV_SEQUENTIAL ) ) { - warning() << "map: madvise failed for " << filename << ' ' << errnoWithDescription() << endl; - } - } -#endif - - views.push_back( view ); - - DEV if (! dbMutex.info().isLocked()) { - _unlock(); - } - - return view; - } - - void* MemoryMappedFile::createReadOnlyMap() { - void * x = mmap( /*start*/0 , len , PROT_READ , MAP_SHARED , fd , 0 ); - if( x == MAP_FAILED ) { - if ( errno == ENOMEM ) { - if( sizeof(void*) == 4 ) - error() << "mmap ro failed with out of memory. You are using a 32-bit build and probably need to upgrade to 64" << endl; - else - error() << "mmap ro failed with out of memory. (64 bit build)" << endl; - } - return 0; - } - return x; - } - - void* MemoryMappedFile::createPrivateMap() { - void * x = mmap( /*start*/0 , len , PROT_READ|PROT_WRITE , MAP_PRIVATE|MAP_NORESERVE , fd , 0 ); - if( x == MAP_FAILED ) { - if ( errno == ENOMEM ) { - if( sizeof(void*) == 4 ) { - error() << "mmap private failed with out of memory. You are using a 32-bit build and probably need to upgrade to 64" << endl; - } - else { - error() << "mmap private failed with out of memory. (64 bit build)" << endl; - } - } - else { - error() << "mmap private failed " << errnoWithDescription() << endl; - } - return 0; - } - - views.push_back(x); - return x; - } - - void* MemoryMappedFile::remapPrivateView(void *oldPrivateAddr) { - // don't unmap, just mmap over the old region - void * x = mmap( oldPrivateAddr, len , PROT_READ|PROT_WRITE , MAP_PRIVATE|MAP_NORESERVE|MAP_FIXED , fd , 0 ); - if( x == MAP_FAILED ) { - int err = errno; - error() << "13601 Couldn't remap private view: " << errnoWithDescription(err) << endl; - log() << "aborting" << endl; - printMemInfo(); - abort(); - } - assert( x == oldPrivateAddr ); - return x; - } - - void MemoryMappedFile::flush(bool sync) { - if ( views.empty() || fd == 0 ) - return; - if ( msync(viewForFlushing(), len, sync ? MS_SYNC : MS_ASYNC) ) - problem() << "msync " << errnoWithDescription() << endl; - } - - class PosixFlushable : public MemoryMappedFile::Flushable { - public: - PosixFlushable( void * view , HANDLE fd , long len ) - : _view( view ) , _fd( fd ) , _len(len) { - } - - void flush() { - if ( _view && _fd ) - if ( msync(_view, _len, MS_SYNC ) ) - problem() << "msync " << errnoWithDescription() << endl; - - } - - void * _view; - HANDLE _fd; - long _len; - }; - - MemoryMappedFile::Flushable * MemoryMappedFile::prepareFlush() { - return new PosixFlushable( viewForFlushing() , fd , len ); - } - - void MemoryMappedFile::_lock() { - if (! views.empty() && isMongoMMF() ) - assert(mprotect(views[0], len, PROT_READ | PROT_WRITE) == 0); - } - - void MemoryMappedFile::_unlock() { - if (! views.empty() && isMongoMMF() ) - assert(mprotect(views[0], len, PROT_READ) == 0); - } - -} // namespace mongo - diff --git a/util/mmap_win.cpp b/util/mmap_win.cpp deleted file mode 100644 index f17e0a26848..00000000000 --- a/util/mmap_win.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// mmap_win.cpp - -/* 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. - */ - -#include "pch.h" -#include "mmap.h" -#include "text.h" -#include "../db/mongommf.h" -#include "../db/concurrency.h" -#include "timer.h" - -namespace mongo { - - mutex mapViewMutex("mapView"); - ourbitset writable; - - MAdvise::MAdvise(void *,unsigned, Advice) { } - MAdvise::~MAdvise() { } - - static unsigned long long _nextMemoryMappedFileLocation = 256LL * 1024LL * 1024LL * 1024LL; - static SimpleMutex _nextMemoryMappedFileLocationMutex( "nextMemoryMappedFileLocationMutex" ); - - void* getNextMemoryMappedFileLocation( unsigned long long mmfSize ) { - if ( 4 == sizeof(void*) ) { - return 0; - } - SimpleMutex::scoped_lock lk( _nextMemoryMappedFileLocationMutex ); - static unsigned long long granularity = 0; - if ( 0 == granularity ) { - SYSTEM_INFO systemInfo; - GetSystemInfo( &systemInfo ); - granularity = static_cast<unsigned long long>( systemInfo.dwAllocationGranularity ); - } - unsigned long long thisMemoryMappedFileLocation = _nextMemoryMappedFileLocation; - mmfSize = ( mmfSize + granularity - 1) & ~( granularity - 1 ); - _nextMemoryMappedFileLocation += mmfSize; - return reinterpret_cast<void*>( static_cast<uintptr_t>( thisMemoryMappedFileLocation ) ); - } - - /** notification on unmapping so we can clear writable bits */ - void MemoryMappedFile::clearWritableBits(void *p) { - for( unsigned i = ((size_t)p)/ChunkSize; i <= (((size_t)p)+len)/ChunkSize; i++ ) { - writable.clear(i); - assert( !writable.get(i) ); - } - } - - MemoryMappedFile::MemoryMappedFile() - : _flushMutex(new mutex("flushMutex")) { - fd = 0; - maphandle = 0; - len = 0; - created(); - } - - void MemoryMappedFile::close() { - mmmutex.assertExclusivelyLocked(); - for( vector<void*>::iterator i = views.begin(); i != views.end(); i++ ) { - clearWritableBits(*i); - UnmapViewOfFile(*i); - } - views.clear(); - if ( maphandle ) - CloseHandle(maphandle); - maphandle = 0; - if ( fd ) - CloseHandle(fd); - fd = 0; - destroyed(); // cleans up from the master list of mmaps - } - - unsigned long long mapped = 0; - - void* MemoryMappedFile::createReadOnlyMap() { - assert( maphandle ); - scoped_lock lk(mapViewMutex); - LPVOID thisAddress = getNextMemoryMappedFileLocation( len ); - void* readOnlyMapAddress = MapViewOfFileEx( - maphandle, // file mapping handle - FILE_MAP_READ, // access - 0, 0, // file offset, high and low - 0, // bytes to map, 0 == all - thisAddress ); // address to place file - if ( 0 == readOnlyMapAddress ) { - DWORD dosError = GetLastError(); - log() << "MapViewOfFileEx for " << filename() - << " failed with " << errnoWithDescription( dosError ) - << " (file size is " << len << ")" - << " in MemoryMappedFile::createReadOnlyMap, terminating" - << endl; - ::abort(); - } - views.push_back( readOnlyMapAddress ); - return readOnlyMapAddress; - } - - void* MemoryMappedFile::map(const char *filenameIn, unsigned long long &length, int options) { - assert( fd == 0 && len == 0 ); // can't open more than once - setFilename(filenameIn); - /* big hack here: Babble uses db names with colons. doesn't seem to work on windows. temporary perhaps. */ - char filename[256]; - strncpy(filename, filenameIn, 255); - filename[255] = 0; - { - size_t len = strlen( filename ); - for ( size_t i=len-1; i>=0; i-- ) { - if ( filename[i] == '/' || - filename[i] == '\\' ) - break; - - if ( filename[i] == ':' ) - filename[i] = '_'; - } - } - - updateLength( filename, length ); - - { - DWORD createOptions = FILE_ATTRIBUTE_NORMAL; - if ( options & SEQUENTIAL ) - createOptions |= FILE_FLAG_SEQUENTIAL_SCAN; - DWORD rw = GENERIC_READ | GENERIC_WRITE; - fd = CreateFile( - toNativeString(filename).c_str(), - rw, // desired access - FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode - NULL, // security - OPEN_ALWAYS, // create disposition - createOptions , // flags - NULL); // hTempl - if ( fd == INVALID_HANDLE_VALUE ) { - DWORD e = GetLastError(); - log() << "Create/OpenFile failed " << filename << " errno:" << e << endl; - return 0; - } - } - - mapped += length; - - { - DWORD flProtect = PAGE_READWRITE; //(options & READONLY)?PAGE_READONLY:PAGE_READWRITE; - maphandle = CreateFileMapping(fd, NULL, flProtect, - length >> 32 /*maxsizehigh*/, - (unsigned) length /*maxsizelow*/, - NULL/*lpName*/); - if ( maphandle == NULL ) { - DWORD e = GetLastError(); // log() call was killing lasterror before we get to that point in the stream - log() << "CreateFileMapping failed " << filename << ' ' << errnoWithDescription(e) << endl; - close(); - return 0; - } - } - - void *view = 0; - { - scoped_lock lk(mapViewMutex); - DWORD access = ( options & READONLY ) ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS; - LPVOID thisAddress = getNextMemoryMappedFileLocation( length ); - view = MapViewOfFileEx( - maphandle, // file mapping handle - access, // access - 0, 0, // file offset, high and low - 0, // bytes to map, 0 == all - thisAddress ); // address to place file - } - { - if ( view == 0 ) { - DWORD dosError = GetLastError(); - log() << "MapViewOfFileEx for " << filename - << " failed with " << errnoWithDescription( dosError ) - << " (file size is " << length << ")" - << " in MemoryMappedFile::map, terminating" - << endl; - close(); - ::abort(); - } - } - views.push_back(view); - len = length; - - return view; - } - - class WindowsFlushable : public MemoryMappedFile::Flushable { - public: - WindowsFlushable( void * view , HANDLE fd , string filename , boost::shared_ptr<mutex> flushMutex ) - : _view(view) , _fd(fd) , _filename(filename) , _flushMutex(flushMutex) - {} - - void flush() { - if (!_view || !_fd) - return; - - scoped_lock lk(*_flushMutex); - - int loopCount = 0; - bool success = false; - bool timeout = false; - int dosError = ERROR_SUCCESS; - const int maximumTimeInSeconds = 60 * 15; - Timer t; - while ( !success && !timeout ) { - ++loopCount; - success = FALSE != FlushViewOfFile( _view, 0 ); - if ( !success ) { - dosError = GetLastError(); - if ( dosError != ERROR_LOCK_VIOLATION ) { - break; - } - timeout = t.seconds() > maximumTimeInSeconds; - } - } - if ( success && loopCount > 1 ) { - log() << "FlushViewOfFile for " << _filename - << " succeeded after " << loopCount - << " attempts taking " << t.millis() - << " ms" << endl; - } - else if ( !success ) { - log() << "FlushViewOfFile for " << _filename - << " failed with error " << dosError - << " after " << loopCount - << " attempts taking " << t.millis() - << " ms" << endl; - // Abort here to avoid data corruption - abort(); - } - - success = FALSE != FlushFileBuffers(_fd); - if (!success) { - int err = GetLastError(); - out() << "FlushFileBuffers failed " << err << " file: " << _filename << endl; - } - } - - void * _view; - HANDLE _fd; - string _filename; - boost::shared_ptr<mutex> _flushMutex; - }; - - void MemoryMappedFile::flush(bool sync) { - uassert(13056, "Async flushing not supported on windows", sync); - if( !views.empty() ) { - WindowsFlushable f( viewForFlushing() , fd , filename() , _flushMutex); - f.flush(); - } - } - - MemoryMappedFile::Flushable * MemoryMappedFile::prepareFlush() { - return new WindowsFlushable( viewForFlushing() , fd , filename() , _flushMutex ); - } - void MemoryMappedFile::_lock() {} - void MemoryMappedFile::_unlock() {} - -} diff --git a/util/mongoutils/README b/util/mongoutils/README deleted file mode 100755 index f61277c7409..00000000000 --- a/util/mongoutils/README +++ /dev/null @@ -1,15 +0,0 @@ - mongoutils namespace requirements: - - (1) code is not database specific, rather, true utilities - (2) are cross platform - (3) may require boost headers, but not libs - (4) are clean and easy to use in any c++ project without pulling in lots of other stuff. - specifically, does not use anything in the mongo namespace! - (5) apache license - (6) must be documented! if you aren't going to bother (but don't do that), stick it in util. - (7) ideally header only (in the spirit of #3) - - So basically, easy to use, general purpose stuff, with no arduous dependencies to drop into - any new project. - - *** PLACE UNIT TESTS IN mongoutils/test.cpp *** diff --git a/util/mongoutils/checksum.h b/util/mongoutils/checksum.h deleted file mode 100644 index ea3d05131ce..00000000000 --- a/util/mongoutils/checksum.h +++ /dev/null @@ -1,32 +0,0 @@ -/** @file checksum.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 mongoutils { - - /** - * this is a silly temporary implementation - */ - inline int checksum( const char* x , int size ) { - int ck = 0; - for ( int i=0; i<size; i++ ) - ck += ( (int)x[i] * ( i + 1 ) ); - return ck; - } - -} diff --git a/util/mongoutils/hash.h b/util/mongoutils/hash.h deleted file mode 100644 index 49f30b3242a..00000000000 --- a/util/mongoutils/hash.h +++ /dev/null @@ -1,41 +0,0 @@ -/** @file hash.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 mongoutils { - - /** @return hash of a pointer to an unsigned. so you get a 32 bit hash out, regardless of whether - pointers are 32 or 64 bit on the particular platform. - - is there a faster way to impl this that hashes just as well? - */ - inline unsigned hashPointer(void *v) { - unsigned x = 0; - unsigned char *p = (unsigned char *) &v; - for( unsigned i = 0; i < sizeof(void*); i++ ) { - x = x * 131 + p[i]; - } - return x; - } - - inline unsigned hash(unsigned u) { - unsigned char *p = (unsigned char *) &u; - return (((((p[3] * 131) + p[2]) * 131) + p[1]) * 131) + p[0]; - } - -} diff --git a/util/mongoutils/html.h b/util/mongoutils/html.h deleted file mode 100644 index f79e6ca514f..00000000000 --- a/util/mongoutils/html.h +++ /dev/null @@ -1,158 +0,0 @@ -// @file html.h - -#pragma once - -/* Things in the mongoutils namespace - (1) are not database specific, rather, true utilities - (2) are cross platform - (3) may require boost headers, but not libs - (4) are clean and easy to use in any c++ project without pulling in lots of other stuff -*/ - -/* Copyright 2010 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. - */ - -#include <sstream> - -namespace mongoutils { - - namespace html { - - using namespace std; - - inline string _end() { return "</body></html>"; } - inline string _table() { return "</table>\n\n"; } - inline string _tr() { return "</tr>\n"; } - - inline string tr() { return "<tr>"; } - inline string tr(string a, string b) { - stringstream ss; - ss << "<tr><td>" << a << "</td><td>" << b << "</td></tr>\n"; - return ss.str(); - } - template <class T> - inline string td(T x) { - stringstream ss; - ss << "<td>" << x << "</td>"; - return ss.str(); - } - inline string td(string x) { - return "<td>" + x + "</td>"; - } - inline string th(string x) { - return "<th>" + x + "</th>"; - } - - inline void tablecell( stringstream& ss , bool b ) { - ss << "<td>" << (b ? "<b>X</b>" : "") << "</td>"; - } - - template< typename T> - inline void tablecell( stringstream& ss , const T& t ) { - ss << "<td>" << t << "</td>"; - } - - inline string table(const char *headers[] = 0, bool border = true) { - stringstream ss; - ss << "\n<table " - << (border?"border=1 ":"") - << "cellpadding=2 cellspacing=0>\n"; - if( headers ) { - ss << "<tr>"; - while( *headers ) { - ss << "<th>" << *headers << "</th>"; - headers++; - } - ss << "</tr>\n"; - } - return ss.str(); - } - - inline string start(string title) { - stringstream ss; - ss << "<html><head>\n<title>"; - ss << title; - ss << "</title>\n"; - - ss << "<style type=\"text/css\" media=\"screen\">" - "body { font-family: helvetica, arial, san-serif }\n" - "table { border-collapse:collapse; border-color:#999; margin-top:.5em }\n" - "th { background-color:#bbb; color:#000 }\n" - "td,th { padding:.25em }\n" - "</style>\n"; - - ss << "</head>\n<body>\n"; - return ss.str(); - } - - inline string red(string contentHtml, bool color=true) { - if( !color ) return contentHtml; - stringstream ss; - ss << "<span style=\"color:#A00;\">" << contentHtml << "</span>"; - return ss.str(); - } - inline string grey(string contentHtml, bool color=true) { - if( !color ) return contentHtml; - stringstream ss; - ss << "<span style=\"color:#888;\">" << contentHtml << "</span>"; - return ss.str(); - } - inline string blue(string contentHtml, bool color=true) { - if( !color ) return contentHtml; - stringstream ss; - ss << "<span style=\"color:#00A;\">" << contentHtml << "</span>"; - return ss.str(); - } - inline string yellow(string contentHtml, bool color=true) { - if( !color ) return contentHtml; - stringstream ss; - ss << "<span style=\"color:#A80;\">" << contentHtml << "</span>"; - return ss.str(); - } - inline string green(string contentHtml, bool color=true) { - if( !color ) return contentHtml; - stringstream ss; - ss << "<span style=\"color:#0A0;\">" << contentHtml << "</span>"; - return ss.str(); - } - - inline string p(string contentHtml) { - stringstream ss; - ss << "<p>" << contentHtml << "</p>\n"; - return ss.str(); - } - - inline string h2(string contentHtml) { - stringstream ss; - ss << "<h2>" << contentHtml << "</h2>\n"; - return ss.str(); - } - - /* does NOT escape the strings. */ - inline string a(string href, string title="", string contentHtml = "") { - stringstream ss; - ss << "<a"; - if( !href.empty() ) ss << " href=\"" << href << '"'; - if( !title.empty() ) ss << " title=\"" << title << '"'; - ss << '>'; - if( !contentHtml.empty() ) { - ss << contentHtml << "</a>"; - } - return ss.str(); - } - - } - -} diff --git a/util/mongoutils/mongoutils.vcxproj b/util/mongoutils/mongoutils.vcxproj deleted file mode 100755 index f6ec0935ca9..00000000000 --- a/util/mongoutils/mongoutils.vcxproj +++ /dev/null @@ -1,75 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{7B84584E-92BC-4DB9-971B-A1A8F93E5053}</ProjectGuid>
- <RootNamespace>mongoutils</RootNamespace>
- <ProjectName>mongoutils test program</ProjectName>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>Application</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup />
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>c:\boost;\boost</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <AdditionalIncludeDirectories>c:\boost;\boost</AdditionalIncludeDirectories>
- </ClCompile>
- <Link>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="test.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="html.h" />
- <ClInclude Include="str.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project>
\ No newline at end of file diff --git a/util/mongoutils/mongoutils.vcxproj.filters b/util/mongoutils/mongoutils.vcxproj.filters deleted file mode 100755 index 84ecbffede0..00000000000 --- a/util/mongoutils/mongoutils.vcxproj.filters +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <ClCompile Include="test.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="html.h" />
- <ClInclude Include="str.h" />
- </ItemGroup>
-</Project>
\ No newline at end of file diff --git a/util/mongoutils/str.h b/util/mongoutils/str.h deleted file mode 100644 index 57b94fadd48..00000000000 --- a/util/mongoutils/str.h +++ /dev/null @@ -1,208 +0,0 @@ -// @file str.h - -/* Copyright 2010 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 - -/* Things in the mongoutils namespace - (1) are not database specific, rather, true utilities - (2) are cross platform - (3) may require boost headers, but not libs - (4) are clean and easy to use in any c++ project without pulling in lots of other stuff - - Note: within this module, we use int for all offsets -- there are no unsigned offsets - and no size_t's. If you need 3 gigabyte long strings, don't use this module. -*/ - -#include <string> -#include <sstream> - -// this violates the README rules for mongoutils: -#include "../../bson/util/builder.h" - -namespace mongoutils { - - namespace str { - - typedef std::string string; - - /** the idea here is to make one liners easy. e.g.: - - return str::stream() << 1 << ' ' << 2; - - since the following doesn't work: - - (stringstream() << 1).str(); - */ - class stream { - public: - mongo::StringBuilder ss; - template<class T> - stream& operator<<(const T& v) { - ss << v; - return *this; - } - operator std::string () const { return ss.str(); } - }; - - inline bool startsWith(const char *str, const char *prefix) { - const char *s = str; - const char *p = prefix; - while( *p ) { - if( *p != *s ) return false; - p++; s++; - } - return true; - } - inline bool startsWith(string s, string p) { return startsWith(s.c_str(), p.c_str()); } - - inline bool endsWith(string s, string p) { - int l = p.size(); - int x = s.size(); - if( x < l ) return false; - return strncmp(s.c_str()+x-l, p.c_str(), l) == 0; - } - - inline bool equals( const char * a , const char * b ) { return strcmp( a , b ) == 0; } - - /** find char x, and return rest of string thereafter, or "" if not found */ - inline const char * after(const char *s, char x) { - const char *p = strchr(s, x); - return (p != 0) ? p+1 : ""; - } - inline string after(const string& s, char x) { - const char *p = strchr(s.c_str(), x); - return (p != 0) ? string(p+1) : ""; - } - - /** find string x, and return rest of string thereafter, or "" if not found */ - inline const char * after(const char *s, const char *x) { - const char *p = strstr(s, x); - return (p != 0) ? p+strlen(x) : ""; - } - inline string after(string s, string x) { - const char *p = strstr(s.c_str(), x.c_str()); - return (p != 0) ? string(p+x.size()) : ""; - } - - /** @return true if s contains x */ - inline bool contains(string s, string x) { - return strstr(s.c_str(), x.c_str()) != 0; - } - inline bool contains(string s, char x) { - return strchr(s.c_str(), x) != 0; - } - - /** @return everything before the character x, else entire string */ - inline string before(const string& s, char x) { - const char *p = strchr(s.c_str(), x); - return (p != 0) ? s.substr(0, p-s.c_str()) : s; - } - - /** @return everything before the string x, else entire string */ - inline string before(const string& s, const string& x) { - const char *p = strstr(s.c_str(), x.c_str()); - return (p != 0) ? s.substr(0, p-s.c_str()) : s; - } - - /** check if if strings share a common starting prefix - @return offset of divergence (or length if equal). 0=nothing in common. */ - inline int shareCommonPrefix(const char *p, const char *q) { - int ofs = 0; - while( 1 ) { - if( *p == 0 || *q == 0 ) - break; - if( *p != *q ) - break; - p++; q++; ofs++; - } - return ofs; - } - inline int shareCommonPrefix(const string &a, const string &b) - { return shareCommonPrefix(a.c_str(), b.c_str()); } - - /** string to unsigned. zero if not a number. can end with non-num chars */ - inline unsigned toUnsigned(const string& a) { - unsigned x = 0; - const char *p = a.c_str(); - while( 1 ) { - if( !isdigit(*p) ) - break; - x = x * 10 + (*p - '0'); - p++; - } - return x; - } - - /** split a string on a specific char. We don't split N times, just once - on the first occurrence. If char not present entire string is in L - and R is empty. - @return true if char found - */ - inline bool splitOn(const string &s, char c, string& L, string& R) { - const char *start = s.c_str(); - const char *p = strchr(start, c); - if( p == 0 ) { - L = s; R.clear(); - return false; - } - L = string(start, p-start); - R = string(p+1); - return true; - } - /** split scanning reverse direction. Splits ONCE ONLY. */ - inline bool rSplitOn(const string &s, char c, string& L, string& R) { - const char *start = s.c_str(); - const char *p = strrchr(start, c); - if( p == 0 ) { - L = s; R.clear(); - return false; - } - L = string(start, p-start); - R = string(p+1); - return true; - } - - /** @return number of occurrences of c in s */ - inline unsigned count( const string& s , char c ) { - unsigned n=0; - for ( unsigned i=0; i<s.size(); i++ ) - if ( s[i] == c ) - n++; - return n; - } - - /** trim leading spaces. spaces only, not tabs etc. */ - inline string ltrim(const string& s) { - const char *p = s.c_str(); - while( *p == ' ' ) p++; - return p; - } - - /** remove trailing chars in place */ - inline void stripTrailing(string& s, const char *chars) { - string::iterator i = s.end(); - while( s.begin() != i ) { - i--; - if( contains(chars, *i) ) { - s.erase(i); - } - } - } - - } - -} diff --git a/util/mongoutils/test.cpp b/util/mongoutils/test.cpp deleted file mode 100644 index 45268c5ca49..00000000000 --- a/util/mongoutils/test.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* @file test.cpp - utils/mongoutils/test.cpp - unit tests for mongoutils -*/ - -/* - * Copyright 2010 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. - */ - -#include <assert.h> -#include "str.h" -#include "html.h" - -using namespace std; -using namespace mongoutils; - -int main() { - { - string s = "abcde"; - str::stripTrailing(s, "ef"); - assert( s == "abcd" ); - str::stripTrailing(s, "abcd"); - assert( s.empty() ); - s = "abcddd"; - str::stripTrailing(s, "d"); - assert( s == "abc" ); - } - - string x = str::after("abcde", 'c'); - assert( x == "de" ); - assert( str::after("abcde", 'x') == "" ); - return 0; -} diff --git a/util/moveablebuffer.h b/util/moveablebuffer.h deleted file mode 100644 index e01f2d8d9a4..00000000000 --- a/util/moveablebuffer.h +++ /dev/null @@ -1,51 +0,0 @@ -/* moveablebuffer.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 { - - /** this is a sort of smart pointer class where we can move where something is and all the pointers will adjust. - not threadsafe. - */ - struct MoveableBuffer { - MoveableBuffer(); - MoveableBuffer(void *); - MoveableBuffer& operator=(const MoveableBuffer&); - ~MoveableBuffer(); - - void *p; - }; - - /* implementation (inlines) below */ - - // this is a temp stub implementation...not really done yet - just having everything compile & such for checkpointing into git - - inline MoveableBuffer::MoveableBuffer() : p(0) { } - - inline MoveableBuffer::MoveableBuffer(void *_p) : p(_p) { } - - inline MoveableBuffer& MoveableBuffer::operator=(const MoveableBuffer& r) { - p = r.p; - return *this; - } - - inline MoveableBuffer::~MoveableBuffer() { - } - -} diff --git a/util/net/hostandport.h b/util/net/hostandport.h deleted file mode 100644 index 573e8eef1fb..00000000000 --- a/util/net/hostandport.h +++ /dev/null @@ -1,165 +0,0 @@ -// hostandport.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 - -#include "sock.h" -#include "../../db/cmdline.h" -#include "../mongoutils/str.h" - -namespace mongo { - - using namespace mongoutils; - - /** helper for manipulating host:port connection endpoints. - */ - struct HostAndPort { - HostAndPort() : _port(-1) { } - - /** From a string hostname[:portnumber] - Throws user assertion if bad config string or bad port #. - */ - HostAndPort(string s); - - /** @param p port number. -1 is ok to use default. */ - HostAndPort(string h, int p /*= -1*/) : _host(h), _port(p) { } - - HostAndPort(const SockAddr& sock ) - : _host( sock.getAddr() ) , _port( sock.getPort() ) { - } - - static HostAndPort me() { - return HostAndPort("localhost", cmdLine.port); - } - - /* uses real hostname instead of localhost */ - static HostAndPort Me(); - - bool operator<(const HostAndPort& r) const { - if( _host < r._host ) - return true; - if( _host == r._host ) - return port() < r.port(); - return false; - } - - bool operator==(const HostAndPort& r) const { - return _host == r._host && port() == r.port(); - } - - bool operator!=(const HostAndPort& r) const { - return _host != r._host || port() != r.port(); - } - - /* returns true if the host/port combo identifies this process instance. */ - bool isSelf() const; // defined in message.cpp - - bool isLocalHost() const; - - /** - * @param includePort host:port if true, host otherwise - */ - string toString( bool includePort=true ) const; - - operator string() const { return toString(); } - - string host() const { return _host; } - - int port() const { return _port >= 0 ? _port : CmdLine::DefaultDBPort; } - bool hasPort() const { return _port >= 0; } - void setPort( int port ) { _port = port; } - - private: - // invariant (except full obj assignment): - string _host; - int _port; // -1 indicates unspecified - }; - - inline HostAndPort HostAndPort::Me() { - const char* ips = cmdLine.bind_ip.c_str(); - while(*ips) { - string ip; - const char * comma = strchr(ips, ','); - if (comma) { - ip = string(ips, comma - ips); - ips = comma + 1; - } - else { - ip = string(ips); - ips = ""; - } - HostAndPort h = HostAndPort(ip, cmdLine.port); - if (!h.isLocalHost()) { - return h; - } - } - - string h = getHostName(); - assert( !h.empty() ); - assert( h != "localhost" ); - return HostAndPort(h, cmdLine.port); - } - - inline string HostAndPort::toString( bool includePort ) const { - if ( ! includePort ) - return _host; - - stringstream ss; - ss << _host; - if ( _port != -1 ) { - ss << ':'; -#if defined(_DEBUG) - if( _port >= 44000 && _port < 44100 ) { - log() << "warning: special debug port 44xxx used" << endl; - ss << _port+1; - } - else - ss << _port; -#else - ss << _port; -#endif - } - return ss.str(); - } - - inline bool HostAndPort::isLocalHost() const { - return ( _host == "localhost" - || startsWith(_host.c_str(), "127.") - || _host == "::1" - || _host == "anonymous unix socket" - || _host.c_str()[0] == '/' // unix socket - ); - } - - inline HostAndPort::HostAndPort(string s) { - const char *p = s.c_str(); - uassert(13110, "HostAndPort: bad config string", *p); - const char *colon = strrchr(p, ':'); - if( colon ) { - int port = atoi(colon+1); - uassert(13095, "HostAndPort: bad port #", port > 0); - _host = string(p,colon-p); - _port = port; - } - else { - // no port specified. - _host = p; - _port = -1; - } - } - -} diff --git a/util/net/httpclient.cpp b/util/net/httpclient.cpp deleted file mode 100644 index 16eaa0ae80a..00000000000 --- a/util/net/httpclient.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// httpclient.cpp - -/* 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. - */ - -#include "pch.h" -#include "httpclient.h" -#include "sock.h" -#include "message.h" -#include "message_port.h" -#include "../mongoutils/str.h" -#include "../../bson/util/builder.h" - -namespace mongo { - - //#define HD(x) cout << x << endl; -#define HD(x) - - - int HttpClient::get( string url , Result * result ) { - return _go( "GET" , url , 0 , result ); - } - - int HttpClient::post( string url , string data , Result * result ) { - return _go( "POST" , url , data.c_str() , result ); - } - - int HttpClient::_go( const char * command , string url , const char * body , Result * result ) { - bool ssl = false; - if ( url.find( "https://" ) == 0 ) { - ssl = true; - url = url.substr( 8 ); - } - else { - uassert( 10271 , "invalid url" , url.find( "http://" ) == 0 ); - url = url.substr( 7 ); - } - - string host , path; - if ( url.find( "/" ) == string::npos ) { - host = url; - path = "/"; - } - else { - host = url.substr( 0 , url.find( "/" ) ); - path = url.substr( url.find( "/" ) ); - } - - - HD( "host [" << host << "]" ); - HD( "path [" << path << "]" ); - - string server = host; - int port = ssl ? 443 : 80; - - string::size_type idx = host.find( ":" ); - if ( idx != string::npos ) { - server = host.substr( 0 , idx ); - string t = host.substr( idx + 1 ); - port = atoi( t.c_str() ); - } - - HD( "server [" << server << "]" ); - HD( "port [" << port << "]" ); - - string req; - { - stringstream ss; - ss << command << " " << path << " HTTP/1.1\r\n"; - ss << "Host: " << host << "\r\n"; - ss << "Connection: Close\r\n"; - ss << "User-Agent: mongodb http client\r\n"; - if ( body ) { - ss << "Content-Length: " << strlen( body ) << "\r\n"; - } - ss << "\r\n"; - if ( body ) { - ss << body; - } - - req = ss.str(); - } - - SockAddr addr( server.c_str() , port ); - HD( "addr: " << addr.toString() ); - - Socket sock; - if ( ! sock.connect( addr ) ) - return -1; - - if ( ssl ) { -#ifdef MONGO_SSL - _checkSSLManager(); - sock.secure( _sslManager.get() ); -#else - uasserted( 15862 , "no ssl support" ); -#endif - } - - { - const char * out = req.c_str(); - int toSend = req.size(); - sock.send( out , toSend, "_go" ); - } - - char buf[4096]; - int got = sock.unsafe_recv( buf , 4096 ); - buf[got] = 0; - - int rc; - char version[32]; - assert( sscanf( buf , "%s %d" , version , &rc ) == 2 ); - HD( "rc: " << rc ); - - StringBuilder sb; - if ( result ) - sb << buf; - - while ( ( got = sock.unsafe_recv( buf , 4096 ) ) > 0) { - if ( result ) - sb << buf; - } - - if ( result ) { - result->_init( rc , sb.str() ); - } - - return rc; - } - - void HttpClient::Result::_init( int code , string entire ) { - _code = code; - _entireResponse = entire; - - while ( true ) { - size_t i = entire.find( '\n' ); - if ( i == string::npos ) { - // invalid - break; - } - - string h = entire.substr( 0 , i ); - entire = entire.substr( i + 1 ); - - if ( h.size() && h[h.size()-1] == '\r' ) - h = h.substr( 0 , h.size() - 1 ); - - if ( h.size() == 0 ) - break; - - i = h.find( ':' ); - if ( i != string::npos ) - _headers[h.substr(0,i)] = str::ltrim(h.substr(i+1)); - } - - _body = entire; - } - -#ifdef MONGO_SSL - void HttpClient::_checkSSLManager() { - _sslManager.reset( new SSLManager( true ) ); - } -#endif - -} diff --git a/util/net/httpclient.h b/util/net/httpclient.h deleted file mode 100644 index 126969f4f70..00000000000 --- a/util/net/httpclient.h +++ /dev/null @@ -1,78 +0,0 @@ -// httpclient.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 - -#include "../../pch.h" -#include "sock.h" - -namespace mongo { - - class HttpClient : boost::noncopyable { - public: - - typedef map<string,string> Headers; - - class Result { - public: - Result() {} - - const string& getEntireResponse() const { - return _entireResponse; - } - - Headers getHeaders() const { - return _headers; - } - - const string& getBody() const { - return _body; - } - - private: - - void _init( int code , string entire ); - - int _code; - string _entireResponse; - - Headers _headers; - string _body; - - friend class HttpClient; - }; - - /** - * @return response code - */ - int get( string url , Result * result = 0 ); - - /** - * @return response code - */ - int post( string url , string body , Result * result = 0 ); - - private: - int _go( const char * command , string url , const char * body , Result * result ); - -#ifdef MONGO_SSL - void _checkSSLManager(); - - scoped_ptr<SSLManager> _sslManager; -#endif - }; -} diff --git a/util/net/listen.cpp b/util/net/listen.cpp deleted file mode 100644 index 6ee25b4583f..00000000000 --- a/util/net/listen.cpp +++ /dev/null @@ -1,391 +0,0 @@ -// listen.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. - */ - - -#include "pch.h" -#include "listen.h" -#include "message_port.h" - -#ifndef _WIN32 - -# ifndef __sunos__ -# include <ifaddrs.h> -# endif -# include <sys/resource.h> -# include <sys/stat.h> - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> -#include <errno.h> -#include <netdb.h> -#ifdef __openbsd__ -# include <sys/uio.h> -#endif - -#else - -// errno doesn't work for winsock. -#undef errno -#define errno WSAGetLastError() - -#endif - -namespace mongo { - - - void checkTicketNumbers(); - - - // ----- Listener ------- - - const Listener* Listener::_timeTracker; - - vector<SockAddr> ipToAddrs(const char* ips, int port, bool useUnixSockets) { - vector<SockAddr> out; - if (*ips == '\0') { - out.push_back(SockAddr("0.0.0.0", port)); // IPv4 all - - if (IPv6Enabled()) - out.push_back(SockAddr("::", port)); // IPv6 all -#ifndef _WIN32 - if (useUnixSockets) - out.push_back(SockAddr(makeUnixSockPath(port).c_str(), port)); // Unix socket -#endif - return out; - } - - while(*ips) { - string ip; - const char * comma = strchr(ips, ','); - if (comma) { - ip = string(ips, comma - ips); - ips = comma + 1; - } - else { - ip = string(ips); - ips = ""; - } - - SockAddr sa(ip.c_str(), port); - out.push_back(sa); - -#ifndef _WIN32 - if (useUnixSockets && (sa.getAddr() == "127.0.0.1" || sa.getAddr() == "0.0.0.0")) // only IPv4 - out.push_back(SockAddr(makeUnixSockPath(port).c_str(), port)); -#endif - } - return out; - - } - - Listener::Listener(const string& name, const string &ip, int port, bool logConnect ) - : _port(port), _name(name), _ip(ip), _logConnect(logConnect), _elapsedTime(0) { -#ifdef MONGO_SSL - _ssl = 0; - _sslPort = 0; - - if ( cmdLine.sslOnNormalPorts && cmdLine.sslServerManager ) { - secure( cmdLine.sslServerManager ); - } -#endif - } - - Listener::~Listener() { - if ( _timeTracker == this ) - _timeTracker = 0; - } - -#ifdef MONGO_SSL - void Listener::secure( SSLManager* manager ) { - _ssl = manager; - } - - void Listener::addSecurePort( SSLManager* manager , int additionalPort ) { - _ssl = manager; - _sslPort = additionalPort; - } - -#endif - - bool Listener::_setupSockets( const vector<SockAddr>& mine , vector<int>& socks ) { - for (vector<SockAddr>::const_iterator it=mine.begin(), end=mine.end(); it != end; ++it) { - const SockAddr& me = *it; - - SOCKET sock = ::socket(me.getType(), SOCK_STREAM, 0); - massert( 15863 , str::stream() << "listen(): invalid socket? " << errnoWithDescription() , sock >= 0 ); - - if (me.getType() == AF_UNIX) { -#if !defined(_WIN32) - if (unlink(me.getAddr().c_str()) == -1) { - int x = errno; - if (x != ENOENT) { - log() << "couldn't unlink socket file " << me << errnoWithDescription(x) << " skipping" << endl; - continue; - } - } -#endif - } - else if (me.getType() == AF_INET6) { - // IPv6 can also accept IPv4 connections as mapped addresses (::ffff:127.0.0.1) - // That causes a conflict if we don't do set it to IPV6_ONLY - const int one = 1; - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*) &one, sizeof(one)); - } - -#if !defined(_WIN32) - { - const int one = 1; - if ( setsockopt( sock , SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0 ) - out() << "Failed to set socket opt, SO_REUSEADDR" << endl; - } -#endif - - if ( ::bind(sock, me.raw(), me.addressSize) != 0 ) { - int x = errno; - error() << "listen(): bind() failed " << errnoWithDescription(x) << " for socket: " << me.toString() << endl; - if ( x == EADDRINUSE ) - error() << " addr already in use" << endl; - closesocket(sock); - return false; - } - -#if !defined(_WIN32) - if (me.getType() == AF_UNIX) { - if (chmod(me.getAddr().c_str(), 0777) == -1) { - error() << "couldn't chmod socket file " << me << errnoWithDescription() << endl; - } - ListeningSockets::get()->addPath( me.getAddr() ); - } -#endif - - if ( ::listen(sock, 128) != 0 ) { - error() << "listen(): listen() failed " << errnoWithDescription() << endl; - closesocket(sock); - return false; - } - - ListeningSockets::get()->add( sock ); - - socks.push_back(sock); - } - - return true; - } - - void Listener::initAndListen() { - checkTicketNumbers(); - vector<int> socks; - set<int> sslSocks; - - { // normal sockets - vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _port, (!cmdLine.noUnixSocket && useUnixSockets())); - if ( ! _setupSockets( mine , socks ) ) - return; - } - -#ifdef MONGO_SSL - if ( _ssl && _sslPort > 0 ) { - unsigned prev = socks.size(); - - vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _sslPort, false ); - if ( ! _setupSockets( mine , socks ) ) - return; - - for ( unsigned i=prev; i<socks.size(); i++ ) { - sslSocks.insert( socks[i] ); - } - - } -#endif - - SOCKET maxfd = 0; // needed for select() - for ( unsigned i=0; i<socks.size(); i++ ) { - if ( socks[i] > maxfd ) - maxfd = socks[i]; - } - -#ifdef MONGO_SSL - if ( _ssl == 0 ) { - _logListen( _port , false ); - } - else if ( _sslPort == 0 ) { - _logListen( _port , true ); - } - else { - // both - _logListen( _port , false ); - _logListen( _sslPort , true ); - } -#else - _logListen( _port , false ); -#endif - - static long connNumber = 0; - struct timeval maxSelectTime; - while ( ! inShutdown() ) { - fd_set fds[1]; - FD_ZERO(fds); - - for (vector<int>::iterator it=socks.begin(), end=socks.end(); it != end; ++it) { - FD_SET(*it, fds); - } - - maxSelectTime.tv_sec = 0; - maxSelectTime.tv_usec = 10000; - const int ret = select(maxfd+1, fds, NULL, NULL, &maxSelectTime); - - if (ret == 0) { -#if defined(__linux__) - _elapsedTime += ( 10000 - maxSelectTime.tv_usec ) / 1000; -#else - _elapsedTime += 10; -#endif - continue; - } - - if (ret < 0) { - int x = errno; -#ifdef EINTR - if ( x == EINTR ) { - log() << "select() signal caught, continuing" << endl; - continue; - } -#endif - if ( ! inShutdown() ) - log() << "select() failure: ret=" << ret << " " << errnoWithDescription(x) << endl; - return; - } - -#if defined(__linux__) - _elapsedTime += max(ret, (int)(( 10000 - maxSelectTime.tv_usec ) / 1000)); -#else - _elapsedTime += ret; // assume 1ms to grab connection. very rough -#endif - - for (vector<int>::iterator it=socks.begin(), end=socks.end(); it != end; ++it) { - if (! (FD_ISSET(*it, fds))) - continue; - - SockAddr from; - int s = accept(*it, from.raw(), &from.addressSize); - if ( s < 0 ) { - int x = errno; // so no global issues - if ( x == ECONNABORTED || x == EBADF ) { - log() << "Listener on port " << _port << " aborted" << endl; - return; - } - if ( x == 0 && inShutdown() ) { - return; // socket closed - } - if( !inShutdown() ) { - log() << "Listener: accept() returns " << s << " " << errnoWithDescription(x) << endl; - if (x == EMFILE || x == ENFILE) { - // Connection still in listen queue but we can't accept it yet - error() << "Out of file descriptors. Waiting one second before trying to accept more connections." << warnings; - sleepsecs(1); - } - } - continue; - } - if (from.getType() != AF_UNIX) - disableNagle(s); - if ( _logConnect && ! cmdLine.quiet ) - log() << "connection accepted from " << from.toString() << " #" << ++connNumber << endl; - - Socket newSock = Socket(s, from); -#ifdef MONGO_SSL - if ( _ssl && ( _sslPort == 0 || sslSocks.count(*it) ) ) { - newSock.secureAccepted( _ssl ); - } -#endif - accepted( newSock ); - } - } - } - - void Listener::_logListen( int port , bool ssl ) { - log() << _name << ( _name.size() ? " " : "" ) << "waiting for connections on port " << port << ( ssl ? " ssl" : "" ) << endl; - } - - - void Listener::accepted(Socket socket) { - accepted( new MessagingPort(socket) ); - } - - void Listener::accepted(MessagingPort *mp) { - assert(!"You must overwrite one of the accepted methods"); - } - - // ----- ListeningSockets ------- - - ListeningSockets* ListeningSockets::_instance = new ListeningSockets(); - - ListeningSockets* ListeningSockets::get() { - return _instance; - } - - // ------ connection ticket and control ------ - - const int DEFAULT_MAX_CONN = 20000; - const int MAX_MAX_CONN = 20000; - - int getMaxConnections() { -#ifdef _WIN32 - return DEFAULT_MAX_CONN; -#else - struct rlimit limit; - assert( getrlimit(RLIMIT_NOFILE,&limit) == 0 ); - - int max = (int)(limit.rlim_cur * .8); - - log(1) << "fd limit" - << " hard:" << limit.rlim_max - << " soft:" << limit.rlim_cur - << " max conn: " << max - << endl; - - if ( max > MAX_MAX_CONN ) - max = MAX_MAX_CONN; - - return max; -#endif - } - - void checkTicketNumbers() { - int want = getMaxConnections(); - int current = connTicketHolder.outof(); - if ( current != DEFAULT_MAX_CONN ) { - if ( current < want ) { - // they want fewer than they can handle - // which is fine - log(1) << " only allowing " << current << " connections" << endl; - return; - } - if ( current > want ) { - log() << " --maxConns too high, can only handle " << want << endl; - } - } - connTicketHolder.resize( want ); - } - - TicketHolder connTicketHolder(DEFAULT_MAX_CONN); - -} diff --git a/util/net/listen.h b/util/net/listen.h deleted file mode 100644 index a2289bc219f..00000000000 --- a/util/net/listen.h +++ /dev/null @@ -1,194 +0,0 @@ -// listen.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 - -#include "sock.h" - -namespace mongo { - - class MessagingPort; - - class Listener : boost::noncopyable { - public: - - Listener(const string& name, const string &ip, int port, bool logConnect=true ); - - virtual ~Listener(); - -#ifdef MONGO_SSL - /** - * make this an ssl socket - * ownership of SSLManager remains with the caller - */ - void secure( SSLManager* manager ); - - void addSecurePort( SSLManager* manager , int additionalPort ); -#endif - - void initAndListen(); // never returns unless error (start a thread) - - /* spawn a thread, etc., then return */ - virtual void accepted(Socket socket); - virtual void accepted(MessagingPort *mp); - - const int _port; - - /** - * @return a rough estimate of elapsed time since the server started - */ - long long getMyElapsedTimeMillis() const { return _elapsedTime; } - - void setAsTimeTracker() { - _timeTracker = this; - } - - static const Listener* getTimeTracker() { - return _timeTracker; - } - - static long long getElapsedTimeMillis() { - if ( _timeTracker ) - return _timeTracker->getMyElapsedTimeMillis(); - - // should this assert or throw? seems like callers may not expect to get zero back, certainly not forever. - return 0; - } - - private: - string _name; - string _ip; - bool _logConnect; - long long _elapsedTime; - -#ifdef MONGO_SSL - SSLManager* _ssl; - int _sslPort; -#endif - - /** - * @return true iff everything went ok - */ - bool _setupSockets( const vector<SockAddr>& mine , vector<int>& socks ); - - void _logListen( int port , bool ssl ); - - static const Listener* _timeTracker; - - virtual bool useUnixSockets() const { return false; } - }; - - /** - * keep track of elapsed time - * after a set amount of time, tells you to do something - * only in this file because depends on Listener - */ - class ElapsedTracker { - public: - ElapsedTracker( int hitsBetweenMarks , int msBetweenMarks ) - : _h( hitsBetweenMarks ) , _ms( msBetweenMarks ) , _pings(0) { - _last = Listener::getElapsedTimeMillis(); - } - - /** - * call this for every iteration - * returns true if one of the triggers has gone off - */ - bool ping() { - if ( ( ++_pings % _h ) == 0 ) { - _last = Listener::getElapsedTimeMillis(); - return true; - } - - long long now = Listener::getElapsedTimeMillis(); - if ( now - _last > _ms ) { - _last = now; - return true; - } - - return false; - } - - void resetLastTime() { - _last = Listener::getElapsedTimeMillis(); - } - - private: - int _h; - int _ms; - - unsigned long long _pings; - - long long _last; - - }; - - class ListeningSockets { - public: - ListeningSockets() - : _mutex("ListeningSockets") - , _sockets( new set<int>() ) - , _socketPaths( new set<string>() ) - { } - void add( int sock ) { - scoped_lock lk( _mutex ); - _sockets->insert( sock ); - } - void addPath( string path ) { - scoped_lock lk( _mutex ); - _socketPaths->insert( path ); - } - void remove( int sock ) { - scoped_lock lk( _mutex ); - _sockets->erase( sock ); - } - void closeAll() { - set<int>* sockets; - set<string>* paths; - - { - scoped_lock lk( _mutex ); - sockets = _sockets; - _sockets = new set<int>(); - paths = _socketPaths; - _socketPaths = new set<string>(); - } - - for ( set<int>::iterator i=sockets->begin(); i!=sockets->end(); i++ ) { - int sock = *i; - log() << "closing listening socket: " << sock << endl; - closesocket( sock ); - } - - for ( set<string>::iterator i=paths->begin(); i!=paths->end(); i++ ) { - string path = *i; - log() << "removing socket file: " << path << endl; - ::remove( path.c_str() ); - } - } - static ListeningSockets* get(); - private: - mongo::mutex _mutex; - set<int>* _sockets; - set<string>* _socketPaths; // for unix domain sockets - static ListeningSockets* _instance; - }; - - - extern TicketHolder connTicketHolder; - -} diff --git a/util/net/message.cpp b/util/net/message.cpp deleted file mode 100644 index a84e5c48c5c..00000000000 --- a/util/net/message.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// message.cpp - -/* 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. - */ - -#include "pch.h" - -#include <fcntl.h> -#include <errno.h> -#include <time.h> - -#include "message.h" -#include "message_port.h" -#include "listen.h" - -#include "../goodies.h" -#include "../../client/dbclient.h" - -namespace mongo { - - void Message::send( MessagingPort &p, const char *context ) { - if ( empty() ) { - return; - } - if ( _buf != 0 ) { - p.send( (char*)_buf, _buf->len, context ); - } - else { - p.send( _data, context ); - } - } - - MSGID NextMsgId; - - /*struct MsgStart { - MsgStart() { - NextMsgId = (((unsigned) time(0)) << 16) ^ curTimeMillis(); - assert(MsgDataHeaderSize == 16); - } - } msgstart;*/ - - MSGID nextMessageId() { - MSGID msgid = NextMsgId++; - return msgid; - } - - bool doesOpGetAResponse( int op ) { - return op == dbQuery || op == dbGetMore; - } - - -} // namespace mongo diff --git a/util/net/message.h b/util/net/message.h deleted file mode 100644 index 16da5d64e7e..00000000000 --- a/util/net/message.h +++ /dev/null @@ -1,312 +0,0 @@ -// message.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 - -#include "sock.h" -#include "../../bson/util/atomic_int.h" -#include "hostandport.h" - -namespace mongo { - - class Message; - class MessagingPort; - class PiggyBackData; - - typedef AtomicUInt MSGID; - - enum Operations { - opReply = 1, /* reply. responseTo is set. */ - dbMsg = 1000, /* generic msg command followed by a string */ - dbUpdate = 2001, /* update object */ - dbInsert = 2002, - //dbGetByOID = 2003, - dbQuery = 2004, - dbGetMore = 2005, - dbDelete = 2006, - dbKillCursors = 2007 - }; - - bool doesOpGetAResponse( int op ); - - inline const char * opToString( int op ) { - switch ( op ) { - case 0: return "none"; - case opReply: return "reply"; - case dbMsg: return "msg"; - case dbUpdate: return "update"; - case dbInsert: return "insert"; - case dbQuery: return "query"; - case dbGetMore: return "getmore"; - case dbDelete: return "remove"; - case dbKillCursors: return "killcursors"; - default: - PRINT(op); - assert(0); - return ""; - } - } - - inline bool opIsWrite( int op ) { - switch ( op ) { - - case 0: - case opReply: - case dbMsg: - case dbQuery: - case dbGetMore: - case dbKillCursors: - return false; - - case dbUpdate: - case dbInsert: - case dbDelete: - return false; - - default: - PRINT(op); - assert(0); - return ""; - } - - } - -#pragma pack(1) - /* see http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol - */ - struct MSGHEADER { - int messageLength; // total message size, including this - int requestID; // identifier for this message - int responseTo; // requestID from the original request - // (used in reponses from db) - int opCode; - }; - struct OP_GETMORE : public MSGHEADER { - MSGHEADER header; // standard message header - int ZERO_or_flags; // 0 - reserved for future use - //cstring fullCollectionName; // "dbname.collectionname" - //int32 numberToReturn; // number of documents to return - //int64 cursorID; // cursorID from the OP_REPLY - }; -#pragma pack() - -#pragma pack(1) - /* todo merge this with MSGHEADER (or inherit from it). */ - struct MsgData { - int len; /* len of the msg, including this field */ - MSGID id; /* request/reply id's match... */ - MSGID responseTo; /* id of the message we are responding to */ - short _operation; - char _flags; - char _version; - int operation() const { - return _operation; - } - void setOperation(int o) { - _flags = 0; - _version = 0; - _operation = o; - } - char _data[4]; - - int& dataAsInt() { - return *((int *) _data); - } - - bool valid() { - if ( len <= 0 || len > ( 4 * BSONObjMaxInternalSize ) ) - return false; - if ( _operation < 0 || _operation > 30000 ) - return false; - return true; - } - - long long getCursor() { - assert( responseTo > 0 ); - assert( _operation == opReply ); - long long * l = (long long *)(_data + 4); - return l[0]; - } - - int dataLen(); // len without header - }; - const int MsgDataHeaderSize = sizeof(MsgData) - 4; - inline int MsgData::dataLen() { - return len - MsgDataHeaderSize; - } -#pragma pack() - - class Message { - public: - // we assume here that a vector with initial size 0 does no allocation (0 is the default, but wanted to make it explicit). - Message() : _buf( 0 ), _data( 0 ), _freeIt( false ) {} - Message( void * data , bool freeIt ) : - _buf( 0 ), _data( 0 ), _freeIt( false ) { - _setData( reinterpret_cast< MsgData* >( data ), freeIt ); - }; - Message(Message& r) : _buf( 0 ), _data( 0 ), _freeIt( false ) { - *this = r; - } - ~Message() { - reset(); - } - - SockAddr _from; - - MsgData *header() const { - assert( !empty() ); - return _buf ? _buf : reinterpret_cast< MsgData* > ( _data[ 0 ].first ); - } - int operation() const { return header()->operation(); } - - MsgData *singleData() const { - massert( 13273, "single data buffer expected", _buf ); - return header(); - } - - bool empty() const { return !_buf && _data.empty(); } - - int size() const { - int res = 0; - if ( _buf ) { - res = _buf->len; - } - else { - for (MsgVec::const_iterator it = _data.begin(); it != _data.end(); ++it) { - res += it->second; - } - } - return res; - } - - int dataSize() const { return size() - sizeof(MSGHEADER); } - - // concat multiple buffers - noop if <2 buffers already, otherwise can be expensive copy - // can get rid of this if we make response handling smarter - void concat() { - if ( _buf || empty() ) { - return; - } - - assert( _freeIt ); - int totalSize = 0; - for( vector< pair< char *, int > >::const_iterator i = _data.begin(); i != _data.end(); ++i ) { - totalSize += i->second; - } - char *buf = (char*)malloc( totalSize ); - char *p = buf; - for( vector< pair< char *, int > >::const_iterator i = _data.begin(); i != _data.end(); ++i ) { - memcpy( p, i->first, i->second ); - p += i->second; - } - reset(); - _setData( (MsgData*)buf, true ); - } - - // vector swap() so this is fast - Message& operator=(Message& r) { - assert( empty() ); - assert( r._freeIt ); - _buf = r._buf; - r._buf = 0; - if ( r._data.size() > 0 ) { - _data.swap( r._data ); - } - r._freeIt = false; - _freeIt = true; - return *this; - } - - void reset() { - if ( _freeIt ) { - if ( _buf ) { - free( _buf ); - } - for( vector< pair< char *, int > >::const_iterator i = _data.begin(); i != _data.end(); ++i ) { - free(i->first); - } - } - _buf = 0; - _data.clear(); - _freeIt = false; - } - - // use to add a buffer - // assumes message will free everything - void appendData(char *d, int size) { - if ( size <= 0 ) { - return; - } - if ( empty() ) { - MsgData *md = (MsgData*)d; - md->len = size; // can be updated later if more buffers added - _setData( md, true ); - return; - } - assert( _freeIt ); - if ( _buf ) { - _data.push_back( make_pair( (char*)_buf, _buf->len ) ); - _buf = 0; - } - _data.push_back( make_pair( d, size ) ); - header()->len += size; - } - - // use to set first buffer if empty - void setData(MsgData *d, bool freeIt) { - assert( empty() ); - _setData( d, freeIt ); - } - void setData(int operation, const char *msgtxt) { - setData(operation, msgtxt, strlen(msgtxt)+1); - } - void setData(int operation, const char *msgdata, size_t len) { - assert( empty() ); - size_t dataLen = len + sizeof(MsgData) - 4; - MsgData *d = (MsgData *) malloc(dataLen); - memcpy(d->_data, msgdata, len); - d->len = fixEndian(dataLen); - d->setOperation(operation); - _setData( d, true ); - } - - bool doIFreeIt() { - return _freeIt; - } - - void send( MessagingPort &p, const char *context ); - - string toString() const; - - private: - void _setData( MsgData *d, bool freeIt ) { - _freeIt = freeIt; - _buf = d; - } - // if just one buffer, keep it in _buf, otherwise keep a sequence of buffers in _data - MsgData * _buf; - // byte buffer(s) - the first must contain at least a full MsgData unless using _buf for storage instead - typedef vector< pair< char*, int > > MsgVec; - MsgVec _data; - bool _freeIt; - }; - - - MSGID nextMessageId(); - - -} // namespace mongo diff --git a/util/net/message_port.cpp b/util/net/message_port.cpp deleted file mode 100644 index 29764c3ecdc..00000000000 --- a/util/net/message_port.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// message_port.cpp - -/* 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. - */ - -#include "pch.h" - -#include <fcntl.h> -#include <errno.h> -#include <time.h> - -#include "message.h" -#include "message_port.h" -#include "listen.h" - -#include "../goodies.h" -#include "../background.h" -#include "../time_support.h" -#include "../../db/cmdline.h" -#include "../../client/dbclient.h" - - -#ifndef _WIN32 -# ifndef __sunos__ -# include <ifaddrs.h> -# endif -# include <sys/resource.h> -# include <sys/stat.h> -#else - -// errno doesn't work for winsock. -#undef errno -#define errno WSAGetLastError() - -#endif - -namespace mongo { - - -// if you want trace output: -#define mmm(x) - - /* messagingport -------------------------------------------------------------- */ - - class PiggyBackData { - public: - PiggyBackData( MessagingPort * port ) { - _port = port; - _buf = new char[1300]; - _cur = _buf; - } - - ~PiggyBackData() { - DESTRUCTOR_GUARD ( - flush(); - delete[]( _cur ); - ); - } - - void append( Message& m ) { - assert( m.header()->len <= 1300 ); - - if ( len() + m.header()->len > 1300 ) - flush(); - - memcpy( _cur , m.singleData() , m.header()->len ); - _cur += m.header()->len; - } - - void flush() { - if ( _buf == _cur ) - return; - - _port->send( _buf , len(), "flush" ); - _cur = _buf; - } - - int len() const { return _cur - _buf; } - - private: - MessagingPort* _port; - char * _buf; - char * _cur; - }; - - class Ports { - set<MessagingPort*> ports; - mongo::mutex m; - public: - Ports() : ports(), m("Ports") {} - void closeAll(unsigned skip_mask) { - scoped_lock bl(m); - for ( set<MessagingPort*>::iterator i = ports.begin(); i != ports.end(); i++ ) { - if( (*i)->tag & skip_mask ) - continue; - (*i)->shutdown(); - } - } - void insert(MessagingPort* p) { - scoped_lock bl(m); - ports.insert(p); - } - void erase(MessagingPort* p) { - scoped_lock bl(m); - ports.erase(p); - } - }; - - // we "new" this so it is still be around when other automatic global vars - // are being destructed during termination. - Ports& ports = *(new Ports()); - - void MessagingPort::closeAllSockets(unsigned mask) { - ports.closeAll(mask); - } - - MessagingPort::MessagingPort(int fd, const SockAddr& remote) - : Socket( fd , remote ) , piggyBackData(0) { - ports.insert(this); - } - - MessagingPort::MessagingPort( double timeout, int ll ) - : Socket( timeout, ll ) { - ports.insert(this); - piggyBackData = 0; - } - - MessagingPort::MessagingPort( Socket& sock ) - : Socket( sock ) , piggyBackData( 0 ) { - ports.insert(this); - } - - void MessagingPort::shutdown() { - close(); - } - - MessagingPort::~MessagingPort() { - if ( piggyBackData ) - delete( piggyBackData ); - shutdown(); - ports.erase(this); - } - - bool MessagingPort::recv(Message& m) { - try { -again: - mmm( log() << "* recv() sock:" << this->sock << endl; ) - int len = -1; - - char *lenbuf = (char *) &len; - int lft = 4; - Socket::recv( lenbuf, lft ); - - if ( len < 16 || len > 48000000 ) { // messages must be large enough for headers - if ( len == -1 ) { - // Endian check from the client, after connecting, to see what mode server is running in. - unsigned foo = 0x10203040; - send( (char *) &foo, 4, "endian" ); - goto again; - } - - if ( len == 542393671 ) { - // an http GET - log(_logLevel) << "looks like you're trying to access db over http on native driver port. please add 1000 for webserver" << endl; - string msg = "You are trying to access MongoDB on the native driver port. For http diagnostic access, add 1000 to the port number\n"; - stringstream ss; - ss << "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: " << msg.size() << "\r\n\r\n" << msg; - string s = ss.str(); - send( s.c_str(), s.size(), "http" ); - return false; - } - log(0) << "recv(): message len " << len << " is too large" << len << endl; - return false; - } - - int z = (len+1023)&0xfffffc00; - assert(z>=len); - MsgData *md = (MsgData *) malloc(z); - assert(md); - md->len = len; - - char *p = (char *) &md->id; - int left = len -4; - - try { - Socket::recv( p, left ); - } - catch (...) { - free(md); - throw; - } - - m.setData(md, true); - return true; - - } - catch ( const SocketException & e ) { - log(_logLevel + (e.shouldPrint() ? 0 : 1) ) << "SocketException: remote: " << remote() << " error: " << e << endl; - m.reset(); - return false; - } - } - - void MessagingPort::reply(Message& received, Message& response) { - say(/*received.from, */response, received.header()->id); - } - - void MessagingPort::reply(Message& received, Message& response, MSGID responseTo) { - say(/*received.from, */response, responseTo); - } - - bool MessagingPort::call(Message& toSend, Message& response) { - mmm( log() << "*call()" << endl; ) - say(toSend); - return recv( toSend , response ); - } - - bool MessagingPort::recv( const Message& toSend , Message& response ) { - while ( 1 ) { - bool ok = recv(response); - if ( !ok ) - return false; - //log() << "got response: " << response.data->responseTo << endl; - if ( response.header()->responseTo == toSend.header()->id ) - break; - error() << "MessagingPort::call() wrong id got:" << hex << (unsigned)response.header()->responseTo << " expect:" << (unsigned)toSend.header()->id << '\n' - << dec - << " toSend op: " << (unsigned)toSend.operation() << '\n' - << " response msgid:" << (unsigned)response.header()->id << '\n' - << " response len: " << (unsigned)response.header()->len << '\n' - << " response op: " << response.operation() << '\n' - << " remote: " << remoteString() << endl; - assert(false); - response.reset(); - } - mmm( log() << "*call() end" << endl; ) - return true; - } - - void MessagingPort::say(Message& toSend, int responseTo) { - assert( !toSend.empty() ); - mmm( log() << "* say() sock:" << this->sock << " thr:" << GetCurrentThreadId() << endl; ) - toSend.header()->id = nextMessageId(); - toSend.header()->responseTo = responseTo; - - if ( piggyBackData && piggyBackData->len() ) { - mmm( log() << "* have piggy back" << endl; ) - if ( ( piggyBackData->len() + toSend.header()->len ) > 1300 ) { - // won't fit in a packet - so just send it off - piggyBackData->flush(); - } - else { - piggyBackData->append( toSend ); - piggyBackData->flush(); - return; - } - } - - toSend.send( *this, "say" ); - } - - void MessagingPort::piggyBack( Message& toSend , int responseTo ) { - - if ( toSend.header()->len > 1300 ) { - // not worth saving because its almost an entire packet - say( toSend ); - return; - } - - // we're going to be storing this, so need to set it up - toSend.header()->id = nextMessageId(); - toSend.header()->responseTo = responseTo; - - if ( ! piggyBackData ) - piggyBackData = new PiggyBackData( this ); - - piggyBackData->append( toSend ); - } - - HostAndPort MessagingPort::remote() const { - if ( ! _remoteParsed.hasPort() ) - _remoteParsed = HostAndPort( remoteAddr() ); - return _remoteParsed; - } - - -} // namespace mongo diff --git a/util/net/message_port.h b/util/net/message_port.h deleted file mode 100644 index 22ecafecfbc..00000000000 --- a/util/net/message_port.h +++ /dev/null @@ -1,107 +0,0 @@ -// message_port.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 - -#include "sock.h" -#include "message.h" - -namespace mongo { - - class MessagingPort; - class PiggyBackData; - - typedef AtomicUInt MSGID; - - class AbstractMessagingPort : boost::noncopyable { - public: - AbstractMessagingPort() : tag(0) {} - virtual ~AbstractMessagingPort() { } - virtual void reply(Message& received, Message& response, MSGID responseTo) = 0; // like the reply below, but doesn't rely on received.data still being available - virtual void reply(Message& received, Message& response) = 0; - - virtual HostAndPort remote() const = 0; - virtual unsigned remotePort() const = 0; - - private: - - public: - // TODO make this private with some helpers - - /* ports can be tagged with various classes. see closeAllSockets(tag). defaults to 0. */ - unsigned tag; - - }; - - class MessagingPort : public AbstractMessagingPort , public Socket { - public: - MessagingPort(int fd, const SockAddr& remote); - - // in some cases the timeout will actually be 2x this value - eg we do a partial send, - // then the timeout fires, then we try to send again, then the timeout fires again with - // no data sent, then we detect that the other side is down - MessagingPort(double so_timeout = 0, int logLevel = 0 ); - - MessagingPort(Socket& socket); - - virtual ~MessagingPort(); - - void shutdown(); - - /* it's assumed if you reuse a message object, that it doesn't cross MessagingPort's. - also, the Message data will go out of scope on the subsequent recv call. - */ - bool recv(Message& m); - void reply(Message& received, Message& response, MSGID responseTo); - void reply(Message& received, Message& response); - bool call(Message& toSend, Message& response); - - void say(Message& toSend, int responseTo = -1); - - /** - * this is used for doing 'async' queries - * instead of doing call( to , from ) - * you would do - * say( to ) - * recv( from ) - * Note: if you fail to call recv and someone else uses this port, - * horrible things will happend - */ - bool recv( const Message& sent , Message& response ); - - void piggyBack( Message& toSend , int responseTo = -1 ); - - unsigned remotePort() const { return Socket::remotePort(); } - virtual HostAndPort remote() const; - - - private: - - PiggyBackData * piggyBackData; - - // this is the parsed version of remote - // mutable because its initialized only on call to remote() - mutable HostAndPort _remoteParsed; - - public: - static void closeAllSockets(unsigned tagMask = 0xffffffff); - - friend class PiggyBackData; - }; - - -} // namespace mongo diff --git a/util/net/message_server.h b/util/net/message_server.h deleted file mode 100644 index ae77b97bb0f..00000000000 --- a/util/net/message_server.h +++ /dev/null @@ -1,66 +0,0 @@ -// message_server.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. - */ - -/* - abstract database server - async io core, worker thread system - */ - -#pragma once - -#include "../../pch.h" - -namespace mongo { - - class MessageHandler { - public: - virtual ~MessageHandler() {} - - /** - * called once when a socket is connected - */ - virtual void connected( AbstractMessagingPort* p ) = 0; - - /** - * called every time a message comes in - * handler is responsible for responding to client - */ - virtual void process( Message& m , AbstractMessagingPort* p , LastError * err ) = 0; - - /** - * called once when a socket is disconnected - */ - virtual void disconnected( AbstractMessagingPort* p ) = 0; - }; - - class MessageServer { - public: - struct Options { - int port; // port to bind to - string ipList; // addresses to bind to - - Options() : port(0), ipList("") {} - }; - - virtual ~MessageServer() {} - virtual void run() = 0; - virtual void setAsTimeTracker() = 0; - }; - - // TODO use a factory here to decide between port and asio variations - MessageServer * createServer( const MessageServer::Options& opts , MessageHandler * handler ); -} diff --git a/util/net/message_server_asio.cpp b/util/net/message_server_asio.cpp deleted file mode 100644 index 0c6a7d925da..00000000000 --- a/util/net/message_server_asio.cpp +++ /dev/null @@ -1,261 +0,0 @@ -// message_server_asio.cpp - -/* 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. - */ - -#ifdef USE_ASIO - -#include <boost/asio.hpp> -#include <boost/bind.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> - -#include <iostream> -#include <vector> - -#include "message.h" -#include "message_server.h" -#include "../util/concurrency/mvar.h" - -using namespace boost; -using namespace boost::asio; -using namespace boost::asio::ip; - -namespace mongo { - class MessageServerSession; - - namespace { - class StickyThread { - public: - StickyThread() - : _thread(boost::ref(*this)) - {} - - ~StickyThread() { - _mss.put(boost::shared_ptr<MessageServerSession>()); - _thread.join(); - } - - void ready(boost::shared_ptr<MessageServerSession> mss) { - _mss.put(mss); - } - - void operator() () { - boost::shared_ptr<MessageServerSession> mss; - while((mss = _mss.take())) { // intentionally not using == - task(mss.get()); - mss.reset(); - } - } - - private: - boost::thread _thread; - inline void task(MessageServerSession* mss); // must be defined after MessageServerSession - - MVar<boost::shared_ptr<MessageServerSession> > _mss; // populated when given a task - }; - - vector<boost::shared_ptr<StickyThread> > thread_pool; - mongo::mutex tp_mutex; // this is only needed if io_service::run() is called from multiple threads - } - - class MessageServerSession : public boost::enable_shared_from_this<MessageServerSession> , public AbstractMessagingPort { - public: - MessageServerSession( MessageHandler * handler , io_service& ioservice ) - : _handler( handler ) - , _socket( ioservice ) - , _portCache(0) - { } - - ~MessageServerSession() { - cout << "disconnect from: " << _socket.remote_endpoint() << endl; - } - - tcp::socket& socket() { - return _socket; - } - - void start() { - cout << "MessageServerSession start from:" << _socket.remote_endpoint() << endl; - _startHeaderRead(); - } - - void handleReadHeader( const boost::system::error_code& error ) { - if ( _inHeader.len == 0 ) - return; - - if ( ! _inHeader.valid() ) { - cout << " got invalid header from: " << _socket.remote_endpoint() << " closing connected" << endl; - return; - } - - char * raw = (char*)malloc( _inHeader.len ); - - MsgData * data = (MsgData*)raw; - memcpy( data , &_inHeader , sizeof( _inHeader ) ); - assert( data->len == _inHeader.len ); - - uassert( 10273 , "_cur not empty! pipelining requests not supported" , ! _cur.data ); - - _cur.setData( data , true ); - async_read( _socket , - buffer( raw + sizeof( _inHeader ) , _inHeader.len - sizeof( _inHeader ) ) , - boost::bind( &MessageServerSession::handleReadBody , shared_from_this() , boost::asio::placeholders::error ) ); - } - - void handleReadBody( const boost::system::error_code& error ) { - if (!_myThread) { - mongo::mutex::scoped_lock(tp_mutex); - if (!thread_pool.empty()) { - _myThread = thread_pool.back(); - thread_pool.pop_back(); - } - } - - if (!_myThread) // pool is empty - _myThread.reset(new StickyThread()); - - assert(_myThread); - - _myThread->ready(shared_from_this()); - } - - void process() { - _handler->process( _cur , this ); - - if (_reply.data) { - async_write( _socket , - buffer( (char*)_reply.data , _reply.data->len ) , - boost::bind( &MessageServerSession::handleWriteDone , shared_from_this() , boost::asio::placeholders::error ) ); - } - else { - _cur.reset(); - _startHeaderRead(); - } - } - - void handleWriteDone( const boost::system::error_code& error ) { - { - // return thread to pool after we have sent data to the client - mongo::mutex::scoped_lock(tp_mutex); - assert(_myThread); - thread_pool.push_back(_myThread); - _myThread.reset(); - } - _cur.reset(); - _reply.reset(); - _startHeaderRead(); - } - - virtual void reply( Message& received, Message& response ) { - reply( received , response , received.data->id ); - } - - virtual void reply( Message& query , Message& toSend, MSGID responseTo ) { - _reply = toSend; - - _reply.data->id = nextMessageId(); - _reply.data->responseTo = responseTo; - uassert( 10274 , "pipelining requests doesn't work yet" , query.data->id == _cur.data->id ); - } - - - virtual unsigned remotePort() { - if (!_portCache) - _portCache = _socket.remote_endpoint().port(); //this is expensive - return _portCache; - } - - private: - - void _startHeaderRead() { - _inHeader.len = 0; - async_read( _socket , - buffer( &_inHeader , sizeof( _inHeader ) ) , - boost::bind( &MessageServerSession::handleReadHeader , shared_from_this() , boost::asio::placeholders::error ) ); - } - - MessageHandler * _handler; - tcp::socket _socket; - MsgData _inHeader; - Message _cur; - Message _reply; - - unsigned _portCache; - - boost::shared_ptr<StickyThread> _myThread; - }; - - void StickyThread::task(MessageServerSession* mss) { - mss->process(); - } - - - class AsyncMessageServer : public MessageServer { - public: - // TODO accept an IP address to bind to - AsyncMessageServer( const MessageServer::Options& opts , MessageHandler * handler ) - : _port( opts.port ) - , _handler(handler) - , _endpoint( tcp::v4() , opts.port ) - , _acceptor( _ioservice , _endpoint ) { - _accept(); - } - virtual ~AsyncMessageServer() { - - } - - void run() { - cout << "AsyncMessageServer starting to listen on: " << _port << endl; - boost::thread other(boost::bind(&io_service::run, &_ioservice)); - _ioservice.run(); - cout << "AsyncMessageServer done listening on: " << _port << endl; - } - - void handleAccept( shared_ptr<MessageServerSession> session , - const boost::system::error_code& error ) { - if ( error ) { - cout << "handleAccept error!" << endl; - return; - } - session->start(); - _accept(); - } - - void _accept( ) { - shared_ptr<MessageServerSession> session( new MessageServerSession( _handler , _ioservice ) ); - _acceptor.async_accept( session->socket() , - boost::bind( &AsyncMessageServer::handleAccept, - this, - session, - boost::asio::placeholders::error ) - ); - } - - private: - int _port; - MessageHandler * _handler; - io_service _ioservice; - tcp::endpoint _endpoint; - tcp::acceptor _acceptor; - }; - - MessageServer * createServer( const MessageServer::Options& opts , MessageHandler * handler ) { - return new AsyncMessageServer( opts , handler ); - } - -} - -#endif diff --git a/util/net/message_server_port.cpp b/util/net/message_server_port.cpp deleted file mode 100644 index ac137125470..00000000000 --- a/util/net/message_server_port.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// message_server_port.cpp - -/* 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. - */ - -#include "pch.h" - -#ifndef USE_ASIO - -#include "message.h" -#include "message_port.h" -#include "message_server.h" -#include "listen.h" - -#include "../../db/cmdline.h" -#include "../../db/lasterror.h" -#include "../../db/stats/counters.h" - -#ifdef __linux__ // TODO: consider making this ifndef _WIN32 -# include <sys/resource.h> -#endif - -namespace mongo { - - namespace pms { - - MessageHandler * handler; - - void threadRun( MessagingPort * inPort) { - TicketHolderReleaser connTicketReleaser( &connTicketHolder ); - - setThreadName( "conn" ); - - assert( inPort ); - inPort->setLogLevel(1); - scoped_ptr<MessagingPort> p( inPort ); - - p->postFork(); - - string otherSide; - - Message m; - try { - LastError * le = new LastError(); - lastError.reset( le ); // lastError now has ownership - - otherSide = p->remoteString(); - - handler->connected( p.get() ); - - while ( ! inShutdown() ) { - m.reset(); - p->clearCounters(); - - if ( ! p->recv(m) ) { - if( !cmdLine.quiet ) - log() << "end connection " << otherSide << endl; - p->shutdown(); - break; - } - - handler->process( m , p.get() , le ); - networkCounter.hit( p->getBytesIn() , p->getBytesOut() ); - } - } - catch ( AssertionException& e ) { - log() << "AssertionException handling request, closing client connection: " << e << endl; - p->shutdown(); - } - catch ( SocketException& e ) { - log() << "SocketException handling request, closing client connection: " << e << endl; - p->shutdown(); - } - catch ( const ClockSkewException & ) { - log() << "ClockSkewException - shutting down" << endl; - exitCleanly( EXIT_CLOCK_SKEW ); - } - catch ( const DBException& e ) { // must be right above std::exception to avoid catching subclasses - log() << "DBException handling request, closing client connection: " << e << endl; - p->shutdown(); - } - catch ( std::exception &e ) { - error() << "Uncaught std::exception: " << e.what() << ", terminating" << endl; - dbexit( EXIT_UNCAUGHT ); - } - catch ( ... ) { - error() << "Uncaught exception, terminating" << endl; - dbexit( EXIT_UNCAUGHT ); - } - - handler->disconnected( p.get() ); - } - - } - - class PortMessageServer : public MessageServer , public Listener { - public: - PortMessageServer( const MessageServer::Options& opts, MessageHandler * handler ) : - Listener( "" , opts.ipList, opts.port ) { - - uassert( 10275 , "multiple PortMessageServer not supported" , ! pms::handler ); - pms::handler = handler; - } - - virtual void accepted(MessagingPort * p) { - - if ( ! connTicketHolder.tryAcquire() ) { - log() << "connection refused because too many open connections: " << connTicketHolder.used() << endl; - - // TODO: would be nice if we notified them... - p->shutdown(); - delete p; - - sleepmillis(2); // otherwise we'll hard loop - return; - } - - try { -#ifndef __linux__ // TODO: consider making this ifdef _WIN32 - boost::thread thr( boost::bind( &pms::threadRun , p ) ); -#else - pthread_attr_t attrs; - pthread_attr_init(&attrs); - pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); - - static const size_t STACK_SIZE = 1024*1024; // if we change this we need to update the warning - - struct rlimit limits; - verify(15887, getrlimit(RLIMIT_STACK, &limits) == 0); - if (limits.rlim_cur > STACK_SIZE) { - pthread_attr_setstacksize(&attrs, (DEBUG_BUILD - ? (STACK_SIZE / 2) - : STACK_SIZE)); - } else if (limits.rlim_cur < 1024*1024) { - warning() << "Stack size set to " << (limits.rlim_cur/1024) << "KB. We suggest 1MB" << endl; - } - - - pthread_t thread; - int failed = pthread_create(&thread, &attrs, (void*(*)(void*)) &pms::threadRun, p); - - pthread_attr_destroy(&attrs); - - if (failed) { - log() << "pthread_create failed: " << errnoWithDescription(failed) << endl; - throw boost::thread_resource_error(); // for consistency with boost::thread - } -#endif - } - catch ( boost::thread_resource_error& ) { - connTicketHolder.release(); - log() << "can't create new thread, closing connection" << endl; - - p->shutdown(); - delete p; - - sleepmillis(2); - } - catch ( ... ) { - connTicketHolder.release(); - log() << "unknown error accepting new socket" << endl; - - p->shutdown(); - delete p; - - sleepmillis(2); - } - - } - - virtual void setAsTimeTracker() { - Listener::setAsTimeTracker(); - } - - void run() { - initAndListen(); - } - - virtual bool useUnixSockets() const { return true; } - }; - - - MessageServer * createServer( const MessageServer::Options& opts , MessageHandler * handler ) { - return new PortMessageServer( opts , handler ); - } - -} - -#endif diff --git a/util/net/miniwebserver.cpp b/util/net/miniwebserver.cpp deleted file mode 100644 index f0b58569d22..00000000000 --- a/util/net/miniwebserver.cpp +++ /dev/null @@ -1,212 +0,0 @@ -// miniwebserver.cpp - -/* 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. - */ - -#include "pch.h" -#include "miniwebserver.h" -#include "../hex.h" - -#include "pcrecpp.h" - -namespace mongo { - - MiniWebServer::MiniWebServer(const string& name, const string &ip, int port) - : Listener(name, ip, port, false) - {} - - string MiniWebServer::parseURL( const char * buf ) { - const char * urlStart = strchr( buf , ' ' ); - if ( ! urlStart ) - return "/"; - - urlStart++; - - const char * end = strchr( urlStart , ' ' ); - if ( ! end ) { - end = strchr( urlStart , '\r' ); - if ( ! end ) { - end = strchr( urlStart , '\n' ); - } - } - - if ( ! end ) - return "/"; - - int diff = (int)(end-urlStart); - if ( diff < 0 || diff > 255 ) - return "/"; - - return string( urlStart , (int)(end-urlStart) ); - } - - void MiniWebServer::parseParams( BSONObj & params , string query ) { - if ( query.size() == 0 ) - return; - - BSONObjBuilder b; - while ( query.size() ) { - - string::size_type amp = query.find( "&" ); - - string cur; - if ( amp == string::npos ) { - cur = query; - query = ""; - } - else { - cur = query.substr( 0 , amp ); - query = query.substr( amp + 1 ); - } - - string::size_type eq = cur.find( "=" ); - if ( eq == string::npos ) - continue; - - b.append( urlDecode(cur.substr(0,eq)) , urlDecode(cur.substr(eq+1) ) ); - } - - params = b.obj(); - } - - string MiniWebServer::parseMethod( const char * headers ) { - const char * end = strchr( headers , ' ' ); - if ( ! end ) - return "GET"; - return string( headers , (int)(end-headers) ); - } - - const char *MiniWebServer::body( const char *buf ) { - const char *ret = strstr( buf, "\r\n\r\n" ); - return ret ? ret + 4 : ret; - } - - bool MiniWebServer::fullReceive( const char *buf ) { - const char *bod = body( buf ); - if ( !bod ) - return false; - const char *lenString = "Content-Length:"; - const char *lengthLoc = strstr( buf, lenString ); - if ( !lengthLoc ) - return true; - lengthLoc += strlen( lenString ); - long len = strtol( lengthLoc, 0, 10 ); - if ( long( strlen( bod ) ) == len ) - return true; - return false; - } - - void MiniWebServer::accepted(Socket sock) { - sock.postFork(); - sock.setTimeout(8); - char buf[4096]; - int len = 0; - while ( 1 ) { - int left = sizeof(buf) - 1 - len; - if( left == 0 ) - break; - int x = sock.unsafe_recv( buf + len , left ); - if ( x <= 0 ) { - sock.close(); - return; - } - len += x; - buf[ len ] = 0; - if ( fullReceive( buf ) ) { - break; - } - } - buf[len] = 0; - - string responseMsg; - int responseCode = 599; - vector<string> headers; - - try { - doRequest(buf, parseURL( buf ), responseMsg, responseCode, headers, sock.remoteAddr() ); - } - catch ( std::exception& e ) { - responseCode = 500; - responseMsg = "error loading page: "; - responseMsg += e.what(); - } - catch ( ... ) { - responseCode = 500; - responseMsg = "unknown error loading page"; - } - - stringstream ss; - ss << "HTTP/1.0 " << responseCode; - if ( responseCode == 200 ) ss << " OK"; - ss << "\r\n"; - if ( headers.empty() ) { - ss << "Content-Type: text/html\r\n"; - } - else { - for ( vector<string>::iterator i = headers.begin(); i != headers.end(); i++ ) { - assert( strncmp("Content-Length", i->c_str(), 14) ); - ss << *i << "\r\n"; - } - } - ss << "Connection: close\r\n"; - ss << "Content-Length: " << responseMsg.size() << "\r\n"; - ss << "\r\n"; - ss << responseMsg; - string response = ss.str(); - - try { - sock.send( response.c_str(), response.size() , "http response" ); - sock.close(); - } - catch ( SocketException& e ) { - log(1) << "couldn't send data to http client: " << e << endl; - } - } - - string MiniWebServer::getHeader( const char * req , string wanted ) { - const char * headers = strchr( req , '\n' ); - if ( ! headers ) - return ""; - pcrecpp::StringPiece input( headers + 1 ); - - string name; - string val; - pcrecpp::RE re("([\\w\\-]+): (.*?)\r?\n"); - while ( re.Consume( &input, &name, &val) ) { - if ( name == wanted ) - return val; - } - return ""; - } - - string MiniWebServer::urlDecode(const char* s) { - stringstream out; - while(*s) { - if (*s == '+') { - out << ' '; - } - else if (*s == '%') { - out << fromHex(s+1); - s+=2; - } - else { - out << *s; - } - s++; - } - return out.str(); - } - -} // namespace mongo diff --git a/util/net/miniwebserver.h b/util/net/miniwebserver.h deleted file mode 100644 index 1fb6b3f2e65..00000000000 --- a/util/net/miniwebserver.h +++ /dev/null @@ -1,60 +0,0 @@ -// miniwebserver.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 - -#include "../../pch.h" -#include "message.h" -#include "message_port.h" -#include "listen.h" -#include "../../db/jsobj.h" - -namespace mongo { - - class MiniWebServer : public Listener { - public: - MiniWebServer(const string& name, const string &ip, int _port); - virtual ~MiniWebServer() {} - - virtual void doRequest( - const char *rq, // the full request - string url, - // set these and return them: - string& responseMsg, - int& responseCode, - vector<string>& headers, // if completely empty, content-type: text/html will be added - const SockAddr &from - ) = 0; - - // --- static helpers ---- - - static void parseParams( BSONObj & params , string query ); - - static string parseURL( const char * buf ); - static string parseMethod( const char * headers ); - static string getHeader( const char * headers , string name ); - static const char *body( const char *buf ); - - static string urlDecode(const char* s); - static string urlDecode(string s) {return urlDecode(s.c_str());} - - private: - void accepted(Socket socket); - static bool fullReceive( const char *buf ); - }; - -} // namespace mongo diff --git a/util/net/sock.cpp b/util/net/sock.cpp deleted file mode 100644 index a032e50b646..00000000000 --- a/util/net/sock.cpp +++ /dev/null @@ -1,782 +0,0 @@ -// @file sock.cpp - -/* 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. - */ - -#include "pch.h" -#include "sock.h" -#include "../background.h" - -#if !defined(_WIN32) -# include <sys/socket.h> -# include <sys/types.h> -# include <sys/socket.h> -# include <sys/un.h> -# include <netinet/in.h> -# include <netinet/tcp.h> -# include <arpa/inet.h> -# include <errno.h> -# include <netdb.h> -# if defined(__openbsd__) -# include <sys/uio.h> -# endif -#endif - -#ifdef MONGO_SSL -#include <openssl/err.h> -#include <openssl/ssl.h> -#endif - - -namespace mongo { - - static bool ipv6 = false; - void enableIPv6(bool state) { ipv6 = state; } - bool IPv6Enabled() { return ipv6; } - - void setSockTimeouts(int sock, double secs) { - struct timeval tv; - tv.tv_sec = (int)secs; - tv.tv_usec = (int)((long long)(secs*1000*1000) % (1000*1000)); - bool report = logLevel > 3; // solaris doesn't provide these - DEV report = true; -#if defined(_WIN32) - tv.tv_sec *= 1000; // Windows timeout is a DWORD, in milliseconds. - int status = setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv.tv_sec, sizeof(DWORD) ) == 0; - if( report && (status == SOCKET_ERROR) ) log() << "unable to set SO_RCVTIMEO" << endl; - status = setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv.tv_sec, sizeof(DWORD) ) == 0; - DEV if( report && (status == SOCKET_ERROR) ) log() << "unable to set SO_SNDTIMEO" << endl; -#else - bool ok = setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, (char *) &tv, sizeof(tv) ) == 0; - if( report && !ok ) log() << "unable to set SO_RCVTIMEO" << endl; - ok = setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, (char *) &tv, sizeof(tv) ) == 0; - DEV if( report && !ok ) log() << "unable to set SO_SNDTIMEO" << endl; -#endif - } - -#if defined(_WIN32) - void disableNagle(int sock) { - int x = 1; - if ( setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &x, sizeof(x)) ) - error() << "disableNagle failed" << endl; - if ( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &x, sizeof(x)) ) - error() << "SO_KEEPALIVE failed" << endl; - } -#else - - void disableNagle(int sock) { - int x = 1; - -#ifdef SOL_TCP - int level = SOL_TCP; -#else - int level = SOL_SOCKET; -#endif - - if ( setsockopt(sock, level, TCP_NODELAY, (char *) &x, sizeof(x)) ) - error() << "disableNagle failed: " << errnoWithDescription() << endl; - -#ifdef SO_KEEPALIVE - if ( setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &x, sizeof(x)) ) - error() << "SO_KEEPALIVE failed: " << errnoWithDescription() << endl; - -# ifdef __linux__ - socklen_t len = sizeof(x); - if ( getsockopt(sock, level, TCP_KEEPIDLE, (char *) &x, &len) ) - error() << "can't get TCP_KEEPIDLE: " << errnoWithDescription() << endl; - - if (x > 300) { - x = 300; - if ( setsockopt(sock, level, TCP_KEEPIDLE, (char *) &x, sizeof(x)) ) { - error() << "can't set TCP_KEEPIDLE: " << errnoWithDescription() << endl; - } - } - - len = sizeof(x); // just in case it changed - if ( getsockopt(sock, level, TCP_KEEPINTVL, (char *) &x, &len) ) - error() << "can't get TCP_KEEPINTVL: " << errnoWithDescription() << endl; - - if (x > 300) { - x = 300; - if ( setsockopt(sock, level, TCP_KEEPINTVL, (char *) &x, sizeof(x)) ) { - error() << "can't set TCP_KEEPINTVL: " << errnoWithDescription() << endl; - } - } -# endif -#endif - - } - -#endif - - string getAddrInfoStrError(int code) { -#if !defined(_WIN32) - return gai_strerror(code); -#else - /* gai_strerrorA is not threadsafe on windows. don't use it. */ - return errnoWithDescription(code); -#endif - } - - - // --- SockAddr - - SockAddr::SockAddr(int sourcePort) { - memset(as<sockaddr_in>().sin_zero, 0, sizeof(as<sockaddr_in>().sin_zero)); - as<sockaddr_in>().sin_family = AF_INET; - as<sockaddr_in>().sin_port = htons(sourcePort); - as<sockaddr_in>().sin_addr.s_addr = htonl(INADDR_ANY); - addressSize = sizeof(sockaddr_in); - } - - SockAddr::SockAddr(const char * iporhost , int port) { - if (!strcmp(iporhost, "localhost")) - iporhost = "127.0.0.1"; - - if (strchr(iporhost, '/')) { -#ifdef _WIN32 - uassert(13080, "no unix socket support on windows", false); -#endif - uassert(13079, "path to unix socket too long", strlen(iporhost) < sizeof(as<sockaddr_un>().sun_path)); - as<sockaddr_un>().sun_family = AF_UNIX; - strcpy(as<sockaddr_un>().sun_path, iporhost); - addressSize = sizeof(sockaddr_un); - } - else { - addrinfo* addrs = NULL; - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_socktype = SOCK_STREAM; - //hints.ai_flags = AI_ADDRCONFIG; // This is often recommended but don't do it. SERVER-1579 - hints.ai_flags |= AI_NUMERICHOST; // first pass tries w/o DNS lookup - hints.ai_family = (IPv6Enabled() ? AF_UNSPEC : AF_INET); - - StringBuilder ss; - ss << port; - int ret = getaddrinfo(iporhost, ss.str().c_str(), &hints, &addrs); - - // old C compilers on IPv6-capable hosts return EAI_NODATA error -#ifdef EAI_NODATA - int nodata = (ret == EAI_NODATA); -#else - int nodata = false; -#endif - if (ret == EAI_NONAME || nodata) { - // iporhost isn't an IP address, allow DNS lookup - hints.ai_flags &= ~AI_NUMERICHOST; - ret = getaddrinfo(iporhost, ss.str().c_str(), &hints, &addrs); - } - - if (ret) { - // don't log if this as it is a CRT construction and log() may not work yet. - if( strcmp("0.0.0.0", iporhost) ) { - log() << "getaddrinfo(\"" << iporhost << "\") failed: " << gai_strerror(ret) << endl; - } - *this = SockAddr(port); - } - else { - //TODO: handle other addresses in linked list; - assert(addrs->ai_addrlen <= sizeof(sa)); - memcpy(&sa, addrs->ai_addr, addrs->ai_addrlen); - addressSize = addrs->ai_addrlen; - freeaddrinfo(addrs); - } - } - } - - bool SockAddr::isLocalHost() const { - switch (getType()) { - case AF_INET: return getAddr() == "127.0.0.1"; - case AF_INET6: return getAddr() == "::1"; - case AF_UNIX: return true; - default: return false; - } - assert(false); - return false; - } - - string SockAddr::toString(bool includePort) const { - string out = getAddr(); - if (includePort && getType() != AF_UNIX && getType() != AF_UNSPEC) - out += mongoutils::str::stream() << ':' << getPort(); - return out; - } - - sa_family_t SockAddr::getType() const { - return sa.ss_family; - } - - unsigned SockAddr::getPort() const { - switch (getType()) { - case AF_INET: return ntohs(as<sockaddr_in>().sin_port); - case AF_INET6: return ntohs(as<sockaddr_in6>().sin6_port); - case AF_UNIX: return 0; - case AF_UNSPEC: return 0; - default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return 0; - } - } - - string SockAddr::getAddr() const { - switch (getType()) { - case AF_INET: - case AF_INET6: { - const int buflen=128; - char buffer[buflen]; - int ret = getnameinfo(raw(), addressSize, buffer, buflen, NULL, 0, NI_NUMERICHOST); - massert(13082, getAddrInfoStrError(ret), ret == 0); - return buffer; - } - - case AF_UNIX: return (addressSize > 2 ? as<sockaddr_un>().sun_path : "anonymous unix socket"); - case AF_UNSPEC: return "(NONE)"; - default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); return ""; - } - } - - bool SockAddr::operator==(const SockAddr& r) const { - if (getType() != r.getType()) - return false; - - if (getPort() != r.getPort()) - return false; - - switch (getType()) { - case AF_INET: return as<sockaddr_in>().sin_addr.s_addr == r.as<sockaddr_in>().sin_addr.s_addr; - case AF_INET6: return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, r.as<sockaddr_in6>().sin6_addr.s6_addr, sizeof(in6_addr)) == 0; - case AF_UNIX: return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) == 0; - case AF_UNSPEC: return true; // assume all unspecified addresses are the same - default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); - } - return false; - } - - bool SockAddr::operator!=(const SockAddr& r) const { - return !(*this == r); - } - - bool SockAddr::operator<(const SockAddr& r) const { - if (getType() < r.getType()) - return true; - else if (getType() > r.getType()) - return false; - - if (getPort() < r.getPort()) - return true; - else if (getPort() > r.getPort()) - return false; - - switch (getType()) { - case AF_INET: return as<sockaddr_in>().sin_addr.s_addr < r.as<sockaddr_in>().sin_addr.s_addr; - case AF_INET6: return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, r.as<sockaddr_in6>().sin6_addr.s6_addr, sizeof(in6_addr)) < 0; - case AF_UNIX: return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) < 0; - case AF_UNSPEC: return false; - default: massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); - } - return false; - } - - SockAddr unknownAddress( "0.0.0.0", 0 ); - - // ------ hostname ------------------- - - string hostbyname(const char *hostname) { - string addr = SockAddr(hostname, 0).getAddr(); - if (addr == "0.0.0.0") - return ""; - else - return addr; - } - - // --- my -- - - string getHostName() { - char buf[256]; - int ec = gethostname(buf, 127); - if ( ec || *buf == 0 ) { - log() << "can't get this server's hostname " << errnoWithDescription() << endl; - return ""; - } - return buf; - } - - - string _hostNameCached; - static void _hostNameCachedInit() { - _hostNameCached = getHostName(); - } - boost::once_flag _hostNameCachedInitFlags = BOOST_ONCE_INIT; - - string getHostNameCached() { - boost::call_once( _hostNameCachedInit , _hostNameCachedInitFlags ); - return _hostNameCached; - } - - // --------- SocketException ---------- - -#ifdef MSG_NOSIGNAL - const int portSendFlags = MSG_NOSIGNAL; - const int portRecvFlags = MSG_NOSIGNAL; -#else - const int portSendFlags = 0; - const int portRecvFlags = 0; -#endif - - string SocketException::toString() const { - stringstream ss; - ss << _ei.code << " socket exception [" << _type << "] "; - - if ( _server.size() ) - ss << "server [" << _server << "] "; - - if ( _extra.size() ) - ss << _extra; - - return ss.str(); - } - - - // ------------ 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(); - SSL_load_error_strings(); - ERR_load_crypto_strings(); - - _context = SSL_CTX_new( client ? SSLv23_client_method() : SSLv23_server_method() ); - 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 ) { - massert( 15865 , - mongoutils::str::stream() << "Can't read SSL certificate from file " - << publicKeyFile << ":" << ERR_error_string(ERR_get_error(), NULL) , - SSL_CTX_use_certificate_file(_context, publicKeyFile.c_str(), SSL_FILETYPE_PEM) ); - - - massert( 15866 , - mongoutils::str::stream() << "Can't read SSL private key from file " - << privateKeyFile << " : " << ERR_error_string(ERR_get_error(), NULL) , - SSL_CTX_use_PrivateKey_file(_context, privateKeyFile.c_str(), SSL_FILETYPE_PEM) ); - } - - - int SSLManager::password_cb(char *buf,int num, int rwflag,void *userdata){ - SSLManager* sm = (SSLManager*)userdata; - string pass = sm->_password; - strcpy(buf,pass.c_str()); - return(pass.size()); - } - - void SSLManager::setupPEM( const string& keyFile , const string& password ) { - _password = password; - - massert( 15867 , "Can't read certificate file" , SSL_CTX_use_certificate_chain_file( _context , keyFile.c_str() ) ); - - SSL_CTX_set_default_passwd_cb_userdata( _context , this ); - SSL_CTX_set_default_passwd_cb( _context, &SSLManager::password_cb ); - - massert( 15868 , "Can't read key file" , SSL_CTX_use_PrivateKey_file( _context , keyFile.c_str() , SSL_FILETYPE_PEM ) ); - } - - SSL * SSLManager::secure( int fd ) { - SSLThreadInfo::get(); - SSL * ssl = SSL_new( _context ); - massert( 15861 , "can't create SSL" , ssl ); - SSL_set_fd( ssl , fd ); - return ssl; - } - - -#endif - - // ------------ Socket ----------------- - - Socket::Socket(int fd , const SockAddr& remote) : - _fd(fd), _remote(remote), _timeout(0) { - _logLevel = 0; - _init(); - } - - Socket::Socket( double timeout, int ll ) { - _logLevel = ll; - _fd = -1; - _timeout = timeout; - _init(); - } - - void Socket::_init() { - _bytesOut = 0; - _bytesIn = 0; -#ifdef MONGO_SSL - _ssl = 0; - _sslAccepted = 0; -#endif - } - - void Socket::close() { -#ifdef MONGO_SSL - if ( _ssl ) { - SSL_shutdown( _ssl ); - SSL_free( _ssl ); - _ssl = 0; - } -#endif - if ( _fd >= 0 ) { - closesocket( _fd ); - _fd = -1; - } - } - -#ifdef MONGO_SSL - void Socket::secure( SSLManager * ssl ) { - assert( ssl ); - assert( _fd >= 0 ); - _ssl = ssl->secure( _fd ); - SSL_connect( _ssl ); - } - - void Socket::secureAccepted( SSLManager * ssl ) { - _sslAccepted = ssl; - } -#endif - - void Socket::postFork() { -#ifdef MONGO_SSL - if ( _sslAccepted ) { - assert( _fd ); - _ssl = _sslAccepted->secure( _fd ); - SSL_accept( _ssl ); - _sslAccepted = 0; - } -#endif - } - - class ConnectBG : public BackgroundJob { - public: - ConnectBG(int sock, SockAddr remote) : _sock(sock), _remote(remote) { } - - void run() { _res = ::connect(_sock, _remote.raw(), _remote.addressSize); } - string name() const { return "ConnectBG"; } - int inError() const { return _res; } - - private: - int _sock; - int _res; - SockAddr _remote; - }; - - bool Socket::connect(SockAddr& remote) { - _remote = remote; - - _fd = socket(remote.getType(), SOCK_STREAM, 0); - if ( _fd == INVALID_SOCKET ) { - log(_logLevel) << "ERROR: connect invalid socket " << errnoWithDescription() << endl; - return false; - } - - if ( _timeout > 0 ) { - setTimeout( _timeout ); - } - - ConnectBG bg(_fd, remote); - bg.go(); - if ( bg.wait(5000) ) { - if ( bg.inError() ) { - close(); - return false; - } - } - else { - // time out the connect - close(); - bg.wait(); // so bg stays in scope until bg thread terminates - return false; - } - - if (remote.getType() != AF_UNIX) - disableNagle(_fd); - -#ifdef SO_NOSIGPIPE - // osx - const int one = 1; - setsockopt( _fd , SOL_SOCKET, SO_NOSIGPIPE, &one, sizeof(int)); -#endif - - return true; - } - - int Socket::_send( const char * data , int len ) { -#ifdef MONGO_SSL - if ( _ssl ) { - return SSL_write( _ssl , data , len ); - } -#endif - return ::send( _fd , data , len , portSendFlags ); - } - - // sends all data or throws an exception - void Socket::send( const char * data , int len, const char *context ) { - while( len > 0 ) { - int ret = _send( data , len ); - if ( ret == -1 ) { - -#ifdef MONGO_SSL - if ( _ssl ) { - log() << "SSL Error ret: " << ret << " err: " << SSL_get_error( _ssl , ret ) - << " " << ERR_error_string(ERR_get_error(), NULL) - << endl; - } -#endif - -#if defined(_WIN32) - if ( WSAGetLastError() == WSAETIMEDOUT && _timeout != 0 ) { -#else - if ( ( errno == EAGAIN || errno == EWOULDBLOCK ) && _timeout != 0 ) { -#endif - log(_logLevel) << "Socket " << context << " send() timed out " << _remote.toString() << endl; - throw SocketException( SocketException::SEND_TIMEOUT , remoteString() ); - } - else { - SocketException::Type t = SocketException::SEND_ERROR; - log(_logLevel) << "Socket " << context << " send() " - << errnoWithDescription() << ' ' << remoteString() << endl; - throw SocketException( t , remoteString() ); - } - } - else { - _bytesOut += ret; - - assert( ret <= len ); - len -= ret; - data += ret; - } - } - } - - void Socket::_send( const vector< pair< char *, int > > &data, const char *context ) { - for( vector< pair< char *, int > >::const_iterator i = data.begin(); i != data.end(); ++i ) { - char * data = i->first; - int len = i->second; - send( data, len, context ); - } - } - - // sends all data or throws an exception - void Socket::send( const vector< pair< char *, int > > &data, const char *context ) { - -#ifdef MONGO_SSL - if ( _ssl ) { - _send( data , context ); - return; - } -#endif - -#if defined(_WIN32) - // TODO use scatter/gather api - _send( data , context ); -#else - vector< struct iovec > d( data.size() ); - int i = 0; - for( vector< pair< char *, int > >::const_iterator j = data.begin(); j != data.end(); ++j ) { - if ( j->second > 0 ) { - d[ i ].iov_base = j->first; - d[ i ].iov_len = j->second; - ++i; - _bytesOut += j->second; - } - } - struct msghdr meta; - memset( &meta, 0, sizeof( meta ) ); - meta.msg_iov = &d[ 0 ]; - meta.msg_iovlen = d.size(); - - while( meta.msg_iovlen > 0 ) { - int ret = ::sendmsg( _fd , &meta , portSendFlags ); - if ( ret == -1 ) { - if ( errno != EAGAIN || _timeout == 0 ) { - log(_logLevel) << "Socket " << context << " send() " << errnoWithDescription() << ' ' << remoteString() << endl; - throw SocketException( SocketException::SEND_ERROR , remoteString() ); - } - else { - log(_logLevel) << "Socket " << context << " send() remote timeout " << remoteString() << endl; - throw SocketException( SocketException::SEND_TIMEOUT , remoteString() ); - } - } - else { - struct iovec *& i = meta.msg_iov; - while( ret > 0 ) { - if ( i->iov_len > unsigned( ret ) ) { - i->iov_len -= ret; - i->iov_base = (char*)(i->iov_base) + ret; - ret = 0; - } - else { - ret -= i->iov_len; - ++i; - --(meta.msg_iovlen); - } - } - } - } -#endif - } - - void Socket::recv( char * buf , int len ) { - unsigned retries = 0; - while( len > 0 ) { - int ret = unsafe_recv( buf , len ); - if ( ret > 0 ) { - if ( len <= 4 && ret != len ) - log(_logLevel) << "Socket recv() got " << ret << " bytes wanted len=" << len << endl; - assert( ret <= len ); - len -= ret; - buf += ret; - } - else if ( ret == 0 ) { - log(3) << "Socket recv() conn closed? " << remoteString() << endl; - throw SocketException( SocketException::CLOSED , remoteString() ); - } - else { /* ret < 0 */ -#if defined(_WIN32) - int e = WSAGetLastError(); -#else - int e = errno; -# if defined(EINTR) - if( e == EINTR ) { - if( ++retries == 1 ) { - log() << "EINTR retry" << endl; - continue; - } - } -# endif -#endif - if ( ( e == EAGAIN -#if defined(_WIN32) - || e == WSAETIMEDOUT -#endif - ) && _timeout > 0 ) - { - // this is a timeout - log(_logLevel) << "Socket recv() timeout " << remoteString() <<endl; - throw SocketException( SocketException::RECV_TIMEOUT, remoteString() ); - } - - log(_logLevel) << "Socket recv() " << errnoWithDescription(e) << " " << remoteString() <<endl; - throw SocketException( SocketException::RECV_ERROR , remoteString() ); - } - } - } - - int Socket::unsafe_recv( char *buf, int max ) { - int x = _recv( buf , max ); - _bytesIn += x; - return x; - } - - - int Socket::_recv( char *buf, int max ) { -#ifdef MONGO_SSL - if ( _ssl ){ - return SSL_read( _ssl , buf , max ); - } -#endif - return ::recv( _fd , buf , max , portRecvFlags ); - } - - void Socket::setTimeout( double secs ) { - setSockTimeouts( _fd, secs ); - } - -#if defined(_WIN32) - struct WinsockInit { - WinsockInit() { - WSADATA d; - if ( WSAStartup(MAKEWORD(2,2), &d) != 0 ) { - out() << "ERROR: wsastartup failed " << errnoWithDescription() << endl; - problem() << "ERROR: wsastartup failed " << errnoWithDescription() << endl; - dbexit( EXIT_NTSERVICE_ERROR ); - } - } - } winsock_init; -#endif - -} // namespace mongo diff --git a/util/net/sock.h b/util/net/sock.h deleted file mode 100644 index f91c2881d23..00000000000 --- a/util/net/sock.h +++ /dev/null @@ -1,256 +0,0 @@ -// @file sock.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 - -#include "../../pch.h" - -#include <stdio.h> -#include <sstream> -#include "../goodies.h" -#include "../../db/cmdline.h" -#include "../mongoutils/str.h" - -#ifndef _WIN32 - -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <errno.h> - -#ifdef __openbsd__ -# include <sys/uio.h> -#endif - -#endif // _WIN32 - -#ifdef MONGO_SSL -#include <openssl/ssl.h> -#endif - -namespace mongo { - - const int SOCK_FAMILY_UNKNOWN_ERROR=13078; - - void disableNagle(int sock); - -#if defined(_WIN32) - - typedef short sa_family_t; - typedef int socklen_t; - - // This won't actually be used on windows - struct sockaddr_un { - short sun_family; - char sun_path[108]; // length from unix header - }; - -#else // _WIN32 - - inline void closesocket(int s) { close(s); } - const int INVALID_SOCKET = -1; - typedef int SOCKET; - -#endif // _WIN32 - - inline string makeUnixSockPath(int port) { - return mongoutils::str::stream() << cmdLine.socket << "/mongodb-" << port << ".sock"; - } - - // If an ip address is passed in, just return that. If a hostname is passed - // in, look up its ip and return that. Returns "" on failure. - string hostbyname(const char *hostname); - - void enableIPv6(bool state=true); - bool IPv6Enabled(); - void setSockTimeouts(int sock, double secs); - - /** - * wrapped around os representation of network address - */ - struct SockAddr { - SockAddr() { - addressSize = sizeof(sa); - memset(&sa, 0, sizeof(sa)); - sa.ss_family = AF_UNSPEC; - } - SockAddr(int sourcePort); /* listener side */ - SockAddr(const char *ip, int port); /* EndPoint (remote) side, or if you want to specify which interface locally */ - - template <typename T> T& as() { return *(T*)(&sa); } - template <typename T> const T& as() const { return *(const T*)(&sa); } - - string toString(bool includePort=true) const; - - /** - * @return one of AF_INET, AF_INET6, or AF_UNIX - */ - sa_family_t getType() const; - - unsigned getPort() const; - - string getAddr() const; - - bool isLocalHost() const; - - bool operator==(const SockAddr& r) const; - - bool operator!=(const SockAddr& r) const; - - bool operator<(const SockAddr& r) const; - - const sockaddr* raw() const {return (sockaddr*)&sa;} - sockaddr* raw() {return (sockaddr*)&sa;} - - socklen_t addressSize; - private: - struct sockaddr_storage sa; - }; - - extern SockAddr unknownAddress; // ( "0.0.0.0", 0 ) - - /** this is not cache and does a syscall */ - string getHostName(); - - /** this is cached, so if changes during the process lifetime - * will be stale */ - string getHostNameCached(); - - /** - * thrown by Socket and SockAddr - */ - class SocketException : public DBException { - public: - const enum Type { CLOSED , RECV_ERROR , SEND_ERROR, RECV_TIMEOUT, SEND_TIMEOUT, FAILED_STATE, CONNECT_ERROR } _type; - - SocketException( Type t , string server , int code = 9001 , string extra="" ) - : DBException( "socket exception" , code ) , _type(t) , _server(server), _extra(extra){ } - virtual ~SocketException() throw() {} - - bool shouldPrint() const { return _type != CLOSED; } - virtual string toString() const; - - private: - string _server; - string _extra; - }; - -#ifdef MONGO_SSL - class SSLManager : boost::noncopyable { - public: - SSLManager( bool client ); - - void setupPEM( const string& keyFile , const string& password ); - void setupPubPriv( const string& privateKeyFile , const string& publicKeyFile ); - - /** - * creates an SSL context to be used for this file descriptor - * caller should delete - */ - SSL * secure( int fd ); - - static int password_cb( char *buf,int num, int rwflag,void *userdata ); - - private: - bool _client; - SSL_CTX* _context; - string _password; - }; -#endif - - /** - * thin wrapped around file descriptor and system calls - * todo: ssl - */ - class Socket { - public: - Socket(int sock, const SockAddr& farEnd); - - /** In some cases the timeout will actually be 2x this value - eg we do a partial send, - then the timeout fires, then we try to send again, then the timeout fires again with - no data sent, then we detect that the other side is down. - - Generally you don't want a timeout, you should be very prepared for errors if you set one. - */ - Socket(double so_timeout = 0, int logLevel = 0 ); - - bool connect(SockAddr& farEnd); - void close(); - - void send( const char * data , int len, const char *context ); - void send( const vector< pair< char *, int > > &data, const char *context ); - - // recv len or throw SocketException - void recv( char * data , int len ); - int unsafe_recv( char *buf, int max ); - - int getLogLevel() const { return _logLevel; } - void setLogLevel( int ll ) { _logLevel = ll; } - - SockAddr remoteAddr() const { return _remote; } - string remoteString() const { return _remote.toString(); } - unsigned remotePort() const { return _remote.getPort(); } - - void clearCounters() { _bytesIn = 0; _bytesOut = 0; } - long long getBytesIn() const { return _bytesIn; } - long long getBytesOut() const { return _bytesOut; } - - void setTimeout( double secs ); - -#ifdef MONGO_SSL - /** secures inline */ - void secure( SSLManager * ssl ); - - void secureAccepted( SSLManager * ssl ); -#endif - - /** - * call this after a fork for server sockets - */ - void postFork(); - - private: - void _init(); - /** raw send, same semantics as ::send */ - int _send( const char * data , int len ); - - /** sends dumbly, just each buffer at a time */ - void _send( const vector< pair< char *, int > > &data, const char *context ); - - /** raw recv, same semantics as ::recv */ - int _recv( char * buf , int max ); - - int _fd; - SockAddr _remote; - double _timeout; - - long long _bytesIn; - long long _bytesOut; - -#ifdef MONGO_SSL - SSL* _ssl; - SSLManager * _sslAccepted; -#endif - - protected: - int _logLevel; // passed to log() when logging errors - - }; - - -} // namespace mongo diff --git a/util/ntservice.cpp b/util/ntservice.cpp deleted file mode 100644 index c9723a10d4f..00000000000 --- a/util/ntservice.cpp +++ /dev/null @@ -1,371 +0,0 @@ -// ntservice.cpp - -/* 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. - */ - -#include "pch.h" -#include "ntservice.h" -#include "../db/client.h" -#include "winutil.h" -#include "text.h" -#include <direct.h> - -#if defined(_WIN32) - -namespace mongo { - - void shutdownServer(); - - SERVICE_STATUS_HANDLE ServiceController::_statusHandle = NULL; - std::wstring ServiceController::_serviceName; - ServiceCallback ServiceController::_serviceCallback = NULL; - - ServiceController::ServiceController() {} - - bool initService(); - - // returns true if the service is started. - bool serviceParamsCheck( program_options::variables_map& params, const std::string dbpath, int argc, char* argv[] ) { - bool installService = false; - bool removeService = false; - bool reinstallService = false; - bool startService = false; - - std::wstring windowsServiceName = L"MongoDB"; - std::wstring windowsServiceDisplayName = L"Mongo DB"; - std::wstring windowsServiceDescription = L"Mongo DB Server"; - std::wstring windowsServiceUser = L""; - std::wstring windowsServicePassword = L""; - - if (params.count("install")) { - if ( ! params.count( "logpath" ) ) { - cerr << "--install has to be used with --logpath" << endl; - ::exit(-1); - } - installService = true; - } - if (params.count("reinstall")) { - if ( ! params.count( "logpath" ) ) { - cerr << "--reinstall has to be used with --logpath" << endl; - ::exit(-1); - } - reinstallService = true; - } - if (params.count("remove")) { - removeService = true; - } - if (params.count("service")) { - startService = true; - } - - if (params.count("serviceName")) { - string x = params["serviceName"].as<string>(); - windowsServiceName = wstring(x.size(),L' '); - for ( size_t i=0; i<x.size(); i++) { - windowsServiceName[i] = x[i]; - } - } - if (params.count("serviceDisplayName")) { - string x = params["serviceDisplayName"].as<string>(); - windowsServiceDisplayName = wstring(x.size(),L' '); - for ( size_t i=0; i<x.size(); i++) { - windowsServiceDisplayName[i] = x[i]; - } - } - if (params.count("serviceDescription")) { - string x = params["serviceDescription"].as<string>(); - windowsServiceDescription = wstring(x.size(),L' '); - for ( size_t i=0; i<x.size(); i++) { - windowsServiceDescription[i] = x[i]; - } - } - if (params.count("serviceUser")) { - string x = params["serviceUser"].as<string>(); - windowsServiceUser = wstring(x.size(),L' '); - for ( size_t i=0; i<x.size(); i++) { - windowsServiceUser[i] = x[i]; - } - } - if (params.count("servicePassword")) { - string x = params["servicePassword"].as<string>(); - windowsServicePassword = wstring(x.size(),L' '); - for ( size_t i=0; i<x.size(); i++) { - windowsServicePassword[i] = x[i]; - } - } - - if ( reinstallService ) { - ServiceController::removeService( windowsServiceName ); - } - if ( installService || reinstallService ) { - if ( !ServiceController::installService( windowsServiceName , windowsServiceDisplayName, windowsServiceDescription, windowsServiceUser, windowsServicePassword, dbpath, argc, argv ) ) - dbexit( EXIT_NTSERVICE_ERROR ); - dbexit( EXIT_CLEAN ); - } - else if ( removeService ) { - if ( !ServiceController::removeService( windowsServiceName ) ) - dbexit( EXIT_NTSERVICE_ERROR ); - dbexit( EXIT_CLEAN ); - } - else if ( startService ) { - if ( !ServiceController::startService( windowsServiceName , mongo::initService ) ) - dbexit( EXIT_NTSERVICE_ERROR ); - return true; - } - return false; - } - - bool ServiceController::installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, const std::wstring& serviceUser, const std::wstring& servicePassword, const std::string dbpath, int argc, char* argv[] ) { - assert(argc >= 1); - - stringstream commandLine; - - char exePath[1024]; - GetModuleFileNameA( NULL, exePath, sizeof exePath ); - commandLine << '"' << exePath << "\" "; - - for ( int i = 1; i < argc; i++ ) { - std::string arg( argv[ i ] ); - // replace install command to indicate process is being started as a service - if ( arg == "--install" || arg == "--reinstall" ) { - arg = "--service"; - } - else if ( arg == "--dbpath" && i + 1 < argc ) { - commandLine << arg << " \"" << dbpath << "\" "; - i++; - continue; - } - else if ( arg == "--logpath" && i + 1 < argc ) { - commandLine << arg << " \"" << argv[i+1] << "\" "; - i++; - continue; - } - else if ( arg.length() > 9 && arg.substr(0, 9) == "--service" ) { - // Strip off --service(Name|User|Password) arguments - i++; - continue; - } - commandLine << arg << " "; - } - - SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - if ( schSCManager == NULL ) { - DWORD err = ::GetLastError(); - cerr << "Error connecting to the Service Control Manager: " << GetWinErrMsg(err) << endl; - return false; - } - - // Make sure servise doesn't already exist. - // TODO: Check to see if service is in "Deleting" status, suggest the user close down Services MMC snap-ins. - SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS ); - if ( schService != NULL ) { - cerr << "There is already a service named " << toUtf8String(serviceName) << ". Aborting" << endl; - ::CloseServiceHandle( schService ); - ::CloseServiceHandle( schSCManager ); - return false; - } - std::basic_ostringstream< TCHAR > commandLineWide; - commandLineWide << commandLine.str().c_str(); - - cerr << "Creating service " << toUtf8String(serviceName) << "." << endl; - - // create new service - schService = ::CreateService( schSCManager, serviceName.c_str(), displayName.c_str(), - SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, - commandLineWide.str().c_str(), NULL, NULL, L"\0\0", NULL, NULL ); - if ( schService == NULL ) { - DWORD err = ::GetLastError(); - cerr << "Error creating service: " << GetWinErrMsg(err) << endl; - ::CloseServiceHandle( schSCManager ); - return false; - } - - cerr << "Service creation successful." << endl; - cerr << "Service can be started from the command line via 'net start \"" << toUtf8String(serviceName) << "\"'." << endl; - - bool serviceInstalled; - - // TODO: If neccessary grant user "Login as a Service" permission. - if ( !serviceUser.empty() ) { - std::wstring actualServiceUser; - if ( serviceUser.find(L"\\") == string::npos ) { - actualServiceUser = L".\\" + serviceUser; - } - else { - actualServiceUser = serviceUser; - } - - cerr << "Setting service login credentials. User: " << toUtf8String(actualServiceUser) << endl; - serviceInstalled = ::ChangeServiceConfig( schService, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, actualServiceUser.c_str(), servicePassword.c_str(), NULL ); - if ( !serviceInstalled ) { - cerr << "Setting service login failed. Service has 'LocalService' permissions." << endl; - } - } - - // set the service description - SERVICE_DESCRIPTION serviceDescription; - serviceDescription.lpDescription = (LPTSTR)serviceDesc.c_str(); - serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_DESCRIPTION, &serviceDescription ); - - - if ( serviceInstalled ) { - SC_ACTION aActions[ 3 ] = { { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 } }; - - SERVICE_FAILURE_ACTIONS serviceFailure; - ZeroMemory( &serviceFailure, sizeof( SERVICE_FAILURE_ACTIONS ) ); - serviceFailure.cActions = 3; - serviceFailure.lpsaActions = aActions; - - // set service recovery options - serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailure ); - - } - else { - cerr << "Could not set service description. Check the event log for more details." << endl; - } - - ::CloseServiceHandle( schService ); - ::CloseServiceHandle( schSCManager ); - - return serviceInstalled; - } - - bool ServiceController::removeService( const std::wstring& serviceName ) { - SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); - if ( schSCManager == NULL ) { - DWORD err = ::GetLastError(); - cerr << "Error connecting to the Service Control Manager: " << GetWinErrMsg(err) << endl; - return false; - } - - SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS ); - if ( schService == NULL ) { - cerr << "Could not find a service named " << toUtf8String(serviceName) << " to uninstall." << endl; - ::CloseServiceHandle( schSCManager ); - return false; - } - - SERVICE_STATUS serviceStatus; - - // stop service if its running - if ( ::ControlService( schService, SERVICE_CONTROL_STOP, &serviceStatus ) ) { - cerr << "Service " << toUtf8String(serviceName) << " is currently running. Stopping service." << endl; - while ( ::QueryServiceStatus( schService, &serviceStatus ) ) { - if ( serviceStatus.dwCurrentState == SERVICE_STOP_PENDING ) { - Sleep( 1000 ); - } - else { break; } - } - cerr << "Service stopped." << endl; - } - - cerr << "Deleting service " << toUtf8String(serviceName) << "." << endl; - bool serviceRemoved = ::DeleteService( schService ); - - ::CloseServiceHandle( schService ); - ::CloseServiceHandle( schSCManager ); - - if (serviceRemoved) { - cerr << "Service deleted successfully." << endl; - } - else { - cerr << "Failed to delete service." << endl; - } - - return serviceRemoved; - } - - bool ServiceController::startService( const std::wstring& serviceName, ServiceCallback startService ) { - _serviceName = serviceName; - _serviceCallback = startService; - - SERVICE_TABLE_ENTRY dispTable[] = { - { (LPTSTR)serviceName.c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceController::initService }, - { NULL, NULL } - }; - - return StartServiceCtrlDispatcher( dispTable ); - } - - bool ServiceController::reportStatus( DWORD reportState, DWORD waitHint ) { - if ( _statusHandle == NULL ) - return false; - - static DWORD checkPoint = 1; - - SERVICE_STATUS ssStatus; - - DWORD dwControlsAccepted; - switch ( reportState ) { - case SERVICE_START_PENDING: - case SERVICE_STOP_PENDING: - case SERVICE_STOPPED: - dwControlsAccepted = 0; - break; - default: - dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; - break; - } - - ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - ssStatus.dwServiceSpecificExitCode = 0; - ssStatus.dwControlsAccepted = dwControlsAccepted; - ssStatus.dwCurrentState = reportState; - ssStatus.dwWin32ExitCode = NO_ERROR; - ssStatus.dwWaitHint = waitHint; - ssStatus.dwCheckPoint = ( reportState == SERVICE_RUNNING || reportState == SERVICE_STOPPED ) ? 0 : checkPoint++; - - return SetServiceStatus( _statusHandle, &ssStatus ); - } - - void WINAPI ServiceController::initService( DWORD argc, LPTSTR *argv ) { - _statusHandle = RegisterServiceCtrlHandler( _serviceName.c_str(), serviceCtrl ); - if ( !_statusHandle ) - return; - - reportStatus( SERVICE_START_PENDING, 1000 ); - - _serviceCallback(); - dbexit( EXIT_CLEAN ); - - reportStatus( SERVICE_STOPPED ); - } - - static void serviceShutdown( const char* controlCodeName ) { - Client::initThread( "serviceShutdown" ); - log() << "got " << controlCodeName << " request from Windows Service Controller, " << - ( inShutdown() ? "already in shutdown" : "will terminate after current cmd ends" ) << endl; - ServiceController::reportStatus( SERVICE_STOP_PENDING ); - if ( ! inShutdown() ) { - exitCleanly( EXIT_WINDOWS_SERVICE_STOP ); - ServiceController::reportStatus( SERVICE_STOPPED ); - } - } - - void WINAPI ServiceController::serviceCtrl( DWORD ctrlCode ) { - switch ( ctrlCode ) { - case SERVICE_CONTROL_STOP: - serviceShutdown( "SERVICE_CONTROL_STOP" ); - break; - case SERVICE_CONTROL_SHUTDOWN: - serviceShutdown( "SERVICE_CONTROL_SHUTDOWN" ); - break; - } - } - -} // namespace mongo - -#endif diff --git a/util/ntservice.h b/util/ntservice.h deleted file mode 100644 index 4958d0395aa..00000000000 --- a/util/ntservice.h +++ /dev/null @@ -1,49 +0,0 @@ -// ntservice.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 - -#if defined(_WIN32) -#include <windows.h> - -namespace mongo { - - typedef bool ( *ServiceCallback )( void ); - bool serviceParamsCheck( program_options::variables_map& params, const std::string dbpath, int argc, char* argv[] ); - - class ServiceController { - public: - ServiceController(); - virtual ~ServiceController() {} - - static bool installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, const std::wstring& serviceUser, const std::wstring& servicePassword, const std::string dbpath, int argc, char* argv[] ); - static bool removeService( const std::wstring& serviceName ); - static bool startService( const std::wstring& serviceName, ServiceCallback startService ); - static bool reportStatus( DWORD reportState, DWORD waitHint = 0 ); - - static void WINAPI initService( DWORD argc, LPTSTR *argv ); - static void WINAPI serviceCtrl( DWORD ctrlCode ); - - protected: - static std::wstring _serviceName; - static SERVICE_STATUS_HANDLE _statusHandle; - static ServiceCallback _serviceCallback; - }; - -} // namespace mongo - -#endif diff --git a/util/optime.h b/util/optime.h deleted file mode 100644 index 9f78fda6d40..00000000000 --- a/util/optime.h +++ /dev/null @@ -1,152 +0,0 @@ -// optime.h - OpTime class - -/* 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 - -#include "../db/concurrency.h" - -namespace mongo { - void exitCleanly( ExitCode code ); - - struct ClockSkewException : public DBException { - ClockSkewException() : DBException( "clock skew exception" , 20001 ) {} - }; - - /* replsets used to use RSOpTime. - M/S uses OpTime. - But this is useable from both. - */ - typedef unsigned long long ReplTime; - - /* Operation sequence #. A combination of current second plus an ordinal value. - */ -#pragma pack(4) - class OpTime { - unsigned i; // ordinal comes first so we can do a single 64 bit compare on little endian - unsigned secs; - static OpTime last; - static OpTime skewed(); - public: - static void setLast(const Date_t &date) { - last = OpTime(date); - } - unsigned getSecs() const { - return secs; - } - unsigned getInc() const { - return i; - } - OpTime(Date_t date) { - reinterpret_cast<unsigned long long&>(*this) = date.millis; - dassert( (int)secs >= 0 ); - } - OpTime(ReplTime x) { - reinterpret_cast<unsigned long long&>(*this) = x; - dassert( (int)secs >= 0 ); - } - OpTime(unsigned a, unsigned b) { - secs = a; - i = b; - dassert( (int)secs >= 0 ); - } - OpTime( const OpTime& other ) { - secs = other.secs; - i = other.i; - dassert( (int)secs >= 0 ); - } - OpTime() { - secs = 0; - i = 0; - } - // it isn't generally safe to not be locked for this. so use now(). some tests use this. - static OpTime now_inlock() { - unsigned t = (unsigned) time(0); - if ( last.secs == t ) { - last.i++; - return last; - } - if ( t < last.secs ) { - return skewed(); // separate function to keep out of the hot code path - } - last = OpTime(t, 1); - return last; - } - static OpTime now() { - DEV dbMutex.assertWriteLocked(); - return now_inlock(); - } - - /* We store OpTime's in the database as BSON Date datatype -- we needed some sort of - 64 bit "container" for these values. While these are not really "Dates", that seems a - better choice for now than say, Number, which is floating point. Note the BinData type - is perhaps the cleanest choice, lacking a true unsigned64 datatype, but BinData has 5 - bytes of overhead. - */ - unsigned long long asDate() const { - return reinterpret_cast<const unsigned long long*>(&i)[0]; - } - long long asLL() const { - return reinterpret_cast<const long long*>(&i)[0]; - } - - bool isNull() const { return secs == 0; } - - string toStringLong() const { - char buf[64]; - time_t_to_String(secs, buf); - stringstream ss; - ss << time_t_to_String_short(secs) << ' '; - ss << hex << secs << ':' << i; - return ss.str(); - } - - string toStringPretty() const { - stringstream ss; - ss << time_t_to_String_short(secs) << ':' << hex << i; - return ss.str(); - } - - string toString() const { - stringstream ss; - ss << hex << secs << ':' << i; - return ss.str(); - } - - bool operator==(const OpTime& r) const { - return i == r.i && secs == r.secs; - } - bool operator!=(const OpTime& r) const { - return !(*this == r); - } - bool operator<(const OpTime& r) const { - if ( secs != r.secs ) - return secs < r.secs; - return i < r.i; - } - bool operator<=(const OpTime& r) const { - return *this < r || *this == r; - } - bool operator>(const OpTime& r) const { - return !(*this <= r); - } - bool operator>=(const OpTime& r) const { - return !(*this < r); - } - }; -#pragma pack() - -} // namespace mongo diff --git a/util/password.cpp b/util/password.cpp deleted file mode 100644 index 18164c3aa0a..00000000000 --- a/util/password.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2010 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. - */ - -#include "pch.h" -#include "password.h" -#include <iostream> - -#ifndef _WIN32 -#include <termios.h> -#endif - -using namespace std; - -namespace mongo { - - string askPassword() { - - std::string password; - cout << "Enter password: "; -#ifndef _WIN32 - const int stdinfd = 0; - termios termio; - tcflag_t old = 0; - if ( isatty( stdinfd ) ) { - int i = tcgetattr( stdinfd, &termio ); - if( i == -1 ) { - cerr << "Cannot get terminal attributes " << errnoWithDescription() << endl; - return string(); - } - old = termio.c_lflag; - termio.c_lflag &= ~ECHO; - i = tcsetattr( stdinfd, TCSANOW, &termio ); - if( i == -1 ) { - cerr << "Cannot set terminal attributes " << errnoWithDescription() << endl; - return string(); - } - } - - getline( cin, password ); - - if ( isatty( stdinfd ) ) { - termio.c_lflag = old; - int i = tcsetattr( stdinfd, TCSANOW, &termio ); - if( i == -1 ) { - cerr << "Cannot set terminal attributes " << errnoWithDescription() << endl; - return string(); - } - } -#else - HANDLE stdinh = GetStdHandle( STD_INPUT_HANDLE ); - if ( stdinh == INVALID_HANDLE_VALUE) { - cerr << "Cannot get stdin handle " << GetLastError() << "\n"; - return string(); - } - - DWORD old; - if ( !GetConsoleMode( stdinh, &old ) ) { - cerr << "Cannot get console mode " << GetLastError() << "\n"; - return string(); - } - - DWORD noecho = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; - if ( !SetConsoleMode( stdinh, noecho ) ) { - cerr << "Cannot set console mode " << GetLastError() << "\n"; - return string(); - } - - getline( cin, password ); - - if ( !SetConsoleMode( stdinh, old ) ) { - cerr << "Cannot set console mode " << GetLastError() << "\n"; - return string(); - } -#endif - cout << "\n"; - return password; - } -} diff --git a/util/password.h b/util/password.h deleted file mode 100644 index 519f712ee7e..00000000000 --- a/util/password.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2010 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 - -#include <boost/program_options.hpp> -#include <string> - -namespace mongo { - - struct PasswordValue : public boost::program_options::typed_value<std::string> { - - PasswordValue( std::string* val ) - : boost::program_options::typed_value<std::string>( val ) { } - - unsigned min_tokens() const { - return 0; - } - - unsigned max_tokens() const { - return 1; - } - - bool is_required() const { - return false; - } - - void xparse( boost::any& value_store, - const std::vector<std::string>& new_tokens ) const { - if ( !value_store.empty() ) -#if BOOST_VERSION >= 104200 - boost::throw_exception( boost::program_options::validation_error( boost::program_options::validation_error::multiple_values_not_allowed ) ); -#else - boost::throw_exception( boost::program_options::validation_error( "multiple values not allowed" ) ); -#endif - else if ( !new_tokens.empty() ) - boost::program_options::typed_value<std::string>::xparse - (value_store, new_tokens); - else - value_store = std::string(); - } - - }; - - std::string askPassword(); - -} diff --git a/util/paths.h b/util/paths.h deleted file mode 100644 index 2297a9a2f90..00000000000 --- a/util/paths.h +++ /dev/null @@ -1,117 +0,0 @@ -// @file paths.h -// file paths and directory handling - -/* Copyright 2010 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 - -#include "mongoutils/str.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -namespace mongo { - - using namespace mongoutils; - - extern string dbpath; - - /** this is very much like a boost::path. however, we define a new type to get some type - checking. if you want to say 'my param MUST be a relative path", use this. - */ - struct RelativePath { - string _p; - - bool empty() const { return _p.empty(); } - - static RelativePath fromRelativePath(string f) { - RelativePath rp; - rp._p = f; - return rp; - } - - /** from a full path */ - static RelativePath fromFullPath(path f) { - path dbp(dbpath); // normalizes / and backslash - string fullpath = f.string(); - string relative = str::after(fullpath, dbp.string()); - if( relative.empty() ) { - log() << "warning file is not under db path? " << fullpath << ' ' << dbp.string() << endl; - RelativePath rp; - rp._p = fullpath; - return rp; - } - /*uassert(13600, - str::stream() << "file path is not under the db path? " << fullpath << ' ' << dbpath, - relative != fullpath);*/ - if( str::startsWith(relative, "/") || str::startsWith(relative, "\\") ) { - relative.erase(0, 1); - } - RelativePath rp; - rp._p = relative; - return rp; - } - - string toString() const { return _p; } - - bool operator!=(const RelativePath& r) const { return _p != r._p; } - bool operator==(const RelativePath& r) const { return _p == r._p; } - bool operator<(const RelativePath& r) const { return _p < r._p; } - - string asFullPath() const { - path x(dbpath); - x /= _p; - return x.string(); - } - - }; - - inline dev_t getPartition(const string& path){ - struct stat stats; - - if (stat(path.c_str(), &stats) != 0){ - uasserted(13646, str::stream() << "stat() failed for file: " << path << " " << errnoWithDescription()); - } - - return stats.st_dev; - } - - inline bool onSamePartition(const string& path1, const string& path2){ - dev_t dev1 = getPartition(path1); - dev_t dev2 = getPartition(path2); - - return dev1 == dev2; - } - - inline void flushMyDirectory(const boost::filesystem::path& file){ -#ifdef __linux__ // this isn't needed elsewhere - massert(13652, str::stream() << "Couldn't find parent dir for file: " << file.string(), file.has_branch_path()); - boost::filesystem::path dir = file.branch_path(); // parent_path in new boosts - - log(1) << "flushing directory " << dir.string() << endl; - - int fd = ::open(dir.string().c_str(), O_RDONLY); // DO NOT THROW OR ASSERT BEFORE CLOSING - massert(13650, str::stream() << "Couldn't open directory '" << dir.string() << "' for flushing: " << errnoWithDescription(), fd >= 0); - if (fsync(fd) != 0){ - int e = errno; - close(fd); - massert(13651, str::stream() << "Couldn't fsync directory '" << dir.string() << "': " << errnoWithDescription(e), false); - } - close(fd); -#endif - } - -} diff --git a/util/processinfo.cpp b/util/processinfo.cpp deleted file mode 100644 index 2d5b6e3c3ad..00000000000 --- a/util/processinfo.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// processinfo.cpp - -/* 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. - */ - -#include "pch.h" -#include "processinfo.h" -#include "mmap.h" - -#include <iostream> -using namespace std; - -namespace mongo { - - class PidFileWiper { - public: - ~PidFileWiper() { - ofstream out( path.c_str() , ios_base::out ); - out.close(); - } - - void write( const string& p ) { - path = p; - ofstream out( path.c_str() , ios_base::out ); - out << getpid() << endl; - out.close(); - } - - string path; - } pidFileWiper; - - void writePidFile( const string& path ) { - pidFileWiper.write( path ); - } - - void printMemInfo( const char * where ) { - cout << "mem info: "; - if ( where ) - cout << where << " "; - ProcessInfo pi; - if ( ! pi.supported() ) { - cout << " not supported" << endl; - return; - } - - cout << "vsize: " << pi.getVirtualMemorySize() << " resident: " << pi.getResidentSize() << " mapped: " << ( MemoryMappedFile::totalMappedLength() / ( 1024 * 1024 ) ) << endl; - } - - -} diff --git a/util/processinfo.h b/util/processinfo.h deleted file mode 100644 index 5272831eb74..00000000000 --- a/util/processinfo.h +++ /dev/null @@ -1,67 +0,0 @@ -// processinfo.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 - -#include <sys/types.h> -#include <string> - -#ifndef _WIN32 -#include <unistd.h> -#else -typedef int pid_t; -int getpid(); -#endif - -namespace mongo { - - class BSONObjBuilder; - - class ProcessInfo { - public: - ProcessInfo( pid_t pid = getpid() ); - ~ProcessInfo(); - - /** - * @return mbytes - */ - int getVirtualMemorySize(); - - /** - * @return mbytes - */ - int getResidentSize(); - - /** - * Append platform-specific data to obj - */ - void getExtraInfo(BSONObjBuilder& info); - - bool supported(); - - static bool blockCheckSupported(); - static bool blockInMemory( char * start ); - - private: - pid_t _pid; - }; - - void writePidFile( const std::string& path ); - - void printMemInfo( const char * whereContextStr = 0 ); - -} diff --git a/util/processinfo_darwin.cpp b/util/processinfo_darwin.cpp deleted file mode 100644 index 9f73cbffd4f..00000000000 --- a/util/processinfo_darwin.cpp +++ /dev/null @@ -1,116 +0,0 @@ -// processinfo_darwin.cpp - -/* 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. - */ - -#include "../pch.h" -#include "processinfo.h" -#include "log.h" - -#include <mach/vm_statistics.h> -#include <mach/task_info.h> -#include <mach/mach_init.h> -#include <mach/mach_host.h> -#include <mach/mach_traps.h> -#include <mach/task.h> -#include <mach/vm_map.h> -#include <mach/shared_region.h> -#include <iostream> - -#include <sys/types.h> -#include <sys/mman.h> - -using namespace std; - -namespace mongo { - - ProcessInfo::ProcessInfo( pid_t pid ) : _pid( pid ) { - } - - ProcessInfo::~ProcessInfo() { - } - - bool ProcessInfo::supported() { - return true; - } - - int ProcessInfo::getVirtualMemorySize() { - task_t result; - - mach_port_t task; - - if ( ( result = task_for_pid( mach_task_self() , _pid , &task) ) != KERN_SUCCESS ) { - cout << "error getting task\n"; - return 0; - } - -#if !defined(__LP64__) - task_basic_info_32 ti; -#else - task_basic_info_64 ti; -#endif - mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; - if ( ( result = task_info( task , TASK_BASIC_INFO , (task_info_t)&ti, &count ) ) != KERN_SUCCESS ) { - cout << "error getting task_info: " << result << endl; - return 0; - } - return (int)((double)ti.virtual_size / (1024.0 * 1024 ) ); - } - - int ProcessInfo::getResidentSize() { - task_t result; - - mach_port_t task; - - if ( ( result = task_for_pid( mach_task_self() , _pid , &task) ) != KERN_SUCCESS ) { - cout << "error getting task\n"; - return 0; - } - - -#if !defined(__LP64__) - task_basic_info_32 ti; -#else - task_basic_info_64 ti; -#endif - mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT; - if ( ( result = task_info( task , TASK_BASIC_INFO , (task_info_t)&ti, &count ) ) != KERN_SUCCESS ) { - cout << "error getting task_info: " << result << endl; - return 0; - } - return (int)( ti.resident_size / (1024 * 1024 ) ); - } - - void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {} - - bool ProcessInfo::blockCheckSupported() { - return true; - } - - bool ProcessInfo::blockInMemory( char * start ) { - static long pageSize = 0; - if ( pageSize == 0 ) { - pageSize = sysconf( _SC_PAGESIZE ); - } - start = start - ( (unsigned long long)start % pageSize ); - char x = 0; - if ( mincore( start , 128 , &x ) ) { - log() << "mincore failed: " << errnoWithDescription() << endl; - return 1; - } - return x & 0x1; - } - -} diff --git a/util/processinfo_linux2.cpp b/util/processinfo_linux2.cpp deleted file mode 100644 index e82e2d154aa..00000000000 --- a/util/processinfo_linux2.cpp +++ /dev/null @@ -1,242 +0,0 @@ -// processinfo_linux2.cpp - -/* 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. - */ - -#include "processinfo.h" - -#include <iostream> -#include <stdio.h> -#include <malloc.h> -#include <db/jsobj.h> -#include <unistd.h> -#include <sys/mman.h> - -using namespace std; - -#define KLONG long -#define KLF "l" - -namespace mongo { - - class LinuxProc { - public: - LinuxProc( pid_t pid = getpid() ) { - char name[128]; - sprintf( name , "/proc/%d/stat" , pid ); - - FILE * f = fopen( name , "r"); - if ( ! f ) { - stringstream ss; - ss << "couldn't open [" << name << "] " << errnoWithDescription(); - string s = ss.str(); - // help the assert# control uasserted( 13538 , s.c_str() ); - msgassertedNoTrace( 13538 , s.c_str() ); - } - int found = fscanf(f, - "%d %s %c " - "%d %d %d %d %d " - "%lu %lu %lu %lu %lu " - "%lu %lu %ld %ld " /* utime stime cutime cstime */ - "%ld %ld " - "%ld " - "%ld " - "%lu " /* start_time */ - "%lu " - "%ld " // rss - "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u " - /* - "%*s %*s %*s %*s " - "%"KLF"u %*lu %*lu " - "%d %d " - "%lu %lu" - */ - - , - - &_pid, - _comm, - &_state, - &_ppid, &_pgrp, &_session, &_tty, &_tpgid, - &_flags, &_min_flt, &_cmin_flt, &_maj_flt, &_cmaj_flt, - &_utime, &_stime, &_cutime, &_cstime, - &_priority, &_nice, - &_alarm, - &_nlwp, - &_start_time, - &_vsize, - &_rss, - &_rss_rlim, &_start_code, &_end_code, &_start_stack, &_kstk_esp, &_kstk_eip - - /* - &_wchan, - &_exit_signal, &_processor, - &_rtprio, &_sched - */ - ); - if ( found == 0 ) { - cout << "system error: reading proc info" << endl; - } - fclose( f ); - } - - unsigned long getVirtualMemorySize() { - return _vsize; - } - - unsigned long getResidentSize() { - return (unsigned long)_rss * 4 * 1024; - } - - int _pid; - // The process ID. - - char _comm[128]; - // The filename of the executable, in parentheses. This is visible whether or not the executable is swapped out. - - char _state; - //One character from the string "RSDZTW" where R is running, S is sleeping in an interruptible wait, D is waiting in uninterruptible - // disk sleep, Z is zombie, T is traced or stopped (on a signal), and W is paging. - - int _ppid; - // The PID of the parent. - - int _pgrp; - // The process group ID of the process. - - int _session; - // The session ID of the process. - - int _tty; - // The tty the process uses. - - int _tpgid; - // The process group ID of the process which currently owns the tty that the process is connected to. - - unsigned long _flags; // %lu - // The kernel flags word of the process. For bit meanings, see the PF_* defines in <linux/sched.h>. Details depend on the kernel version. - - unsigned long _min_flt; // %lu - // The number of minor faults the process has made which have not required loading a memory page from disk. - - unsigned long _cmin_flt; // %lu - // The number of minor faults that the process - - unsigned long _maj_flt; // %lu - // The number of major faults the process has made which have required loading a memory page from disk. - - unsigned long _cmaj_flt; // %lu - // The number of major faults that the process - - unsigned long _utime; // %lu - // The number of jiffies that this process has been scheduled in user mode. - - unsigned long _stime; // %lu - // The number of jiffies that this process has been scheduled in kernel mode. - - long _cutime; // %ld - // The number of jiffies that this removed field. - - long _cstime; // %ld - - long _priority; - long _nice; - - long _nlwp; // %ld - // The time in jiffies before the next SIGALRM is sent to the process due to an interval timer. - - unsigned long _alarm; - - unsigned long _start_time; // %lu - // The time in jiffies the process started after system boot. - - unsigned long _vsize; // %lu - // Virtual memory size in bytes. - - long _rss; // %ld - // Resident Set Size: number of pages the process has in real memory, minus 3 for administrative purposes. This is just the pages which - // count towards text, data, or stack space. This does not include pages which have not been demand-loaded in, or which are swapped out - - unsigned long _rss_rlim; // %lu - // Current limit in bytes on the rss of the process (usually 4294967295 on i386). - - unsigned long _start_code; // %lu - // The address above which program text can run. - - unsigned long _end_code; // %lu - // The address below which program text can run. - - unsigned long _start_stack; // %lu - // The address of the start of the stack. - - unsigned long _kstk_esp; // %lu - // The current value of esp (stack pointer), as found in the kernel stack page for the process. - - unsigned long _kstk_eip; // %lu - // The current EIP (instruction pointer). - - - - }; - - - ProcessInfo::ProcessInfo( pid_t pid ) : _pid( pid ) { - } - - ProcessInfo::~ProcessInfo() { - } - - bool ProcessInfo::supported() { - return true; - } - - int ProcessInfo::getVirtualMemorySize() { - LinuxProc p(_pid); - return (int)( p.getVirtualMemorySize() / ( 1024.0 * 1024 ) ); - } - - int ProcessInfo::getResidentSize() { - LinuxProc p(_pid); - return (int)( p.getResidentSize() / ( 1024.0 * 1024 ) ); - } - - void ProcessInfo::getExtraInfo(BSONObjBuilder& info) { - struct mallinfo malloc_info = mallinfo(); // structure has same name as function that returns it. (see malloc.h) - info.append("heap_usage_bytes", malloc_info.uordblks); - - LinuxProc p(_pid); - info.append("page_faults", (int)p._maj_flt); - } - - bool ProcessInfo::blockCheckSupported() { - return true; - } - - bool ProcessInfo::blockInMemory( char * start ) { - static long pageSize = 0; - if ( pageSize == 0 ) { - pageSize = sysconf( _SC_PAGESIZE ); - } - start = start - ( (unsigned long long)start % pageSize ); - unsigned char x = 0; - if ( mincore( start , 128 , &x ) ) { - log() << "mincore failed: " << errnoWithDescription() << endl; - return 1; - } - return x & 0x1; - } - - -} diff --git a/util/processinfo_none.cpp b/util/processinfo_none.cpp deleted file mode 100644 index 7d1e84d377c..00000000000 --- a/util/processinfo_none.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// processinfo_none.cpp - -/* 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. - */ - -#include "pch.h" -#include "processinfo.h" - -#include <iostream> -using namespace std; - -namespace mongo { - - ProcessInfo::ProcessInfo( pid_t pid ) { - } - - ProcessInfo::~ProcessInfo() { - } - - bool ProcessInfo::supported() { - return false; - } - - int ProcessInfo::getVirtualMemorySize() { - return -1; - } - - int ProcessInfo::getResidentSize() { - return -1; - } - - void ProcessInfo::getExtraInfo(BSONObjBuilder& info) {} - - bool ProcessInfo::blockCheckSupported() { - return false; - } - - bool ProcessInfo::blockInMemory( char * start ) { - assert(0); - return true; - } - -} diff --git a/util/processinfo_win32.cpp b/util/processinfo_win32.cpp deleted file mode 100644 index fdd88d374ac..00000000000 --- a/util/processinfo_win32.cpp +++ /dev/null @@ -1,84 +0,0 @@ -// processinfo_win32.cpp - -/* 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. - */ - -#include "pch.h" -#include "processinfo.h" -#include <iostream> -#include <psapi.h> -#include "../bson/bsonobjbuilder.h" -using namespace std; - -int getpid() { - return GetCurrentProcessId(); -} - -namespace mongo { - - int _wconvertmtos( SIZE_T s ) { - return (int)( s / ( 1024 * 1024 ) ); - } - - ProcessInfo::ProcessInfo( pid_t pid ) { - } - - ProcessInfo::~ProcessInfo() { - } - - bool ProcessInfo::supported() { - return true; - } - - int ProcessInfo::getVirtualMemorySize() { - MEMORYSTATUSEX mse; - mse.dwLength = sizeof(mse); - assert( GlobalMemoryStatusEx( &mse ) ); - DWORDLONG x = (mse.ullTotalVirtual - mse.ullAvailVirtual) / (1024 * 1024) ; - assert( x <= 0x7fffffff ); - return (int) x; - } - - int ProcessInfo::getResidentSize() { - PROCESS_MEMORY_COUNTERS pmc; - assert( GetProcessMemoryInfo( GetCurrentProcess() , &pmc, sizeof(pmc) ) ); - return _wconvertmtos( pmc.WorkingSetSize ); - } - - void ProcessInfo::getExtraInfo(BSONObjBuilder& info) { - MEMORYSTATUSEX mse; - mse.dwLength = sizeof(mse); - PROCESS_MEMORY_COUNTERS pmc; - if( GetProcessMemoryInfo( GetCurrentProcess() , &pmc, sizeof(pmc) ) ) { - info.append("page_faults", static_cast<int>(pmc.PageFaultCount)); - info.append("usagePageFileMB", static_cast<int>(pmc.PagefileUsage / 1024 / 1024)); - } - if( GlobalMemoryStatusEx( &mse ) ) { - info.append("totalPageFileMB", static_cast<int>(mse.ullTotalPageFile / 1024 / 1024)); - info.append("availPageFileMB", static_cast<int>(mse.ullAvailPageFile / 1024 / 1024)); - info.append("ramMB", static_cast<int>(mse.ullTotalPhys / 1024 / 1024)); - } - } - - bool ProcessInfo::blockCheckSupported() { - return false; - } - - bool ProcessInfo::blockInMemory( char * start ) { - assert(0); - return true; - } - -} diff --git a/util/queue.h b/util/queue.h deleted file mode 100644 index 4223bd6c256..00000000000 --- a/util/queue.h +++ /dev/null @@ -1,106 +0,0 @@ -// @file queue.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 - -#include "../pch.h" - -#include <queue> - -#include "../util/timer.h" - -namespace mongo { - - /** - * simple blocking queue - */ - template<typename T> class BlockingQueue : boost::noncopyable { - public: - BlockingQueue() : _lock("BlockingQueue") { } - - void push(T const& t) { - scoped_lock l( _lock ); - _queue.push( t ); - _condition.notify_one(); - } - - bool empty() const { - scoped_lock l( _lock ); - return _queue.empty(); - } - - size_t size() const { - scoped_lock l( _lock ); - return _queue.size(); - } - - - bool tryPop( T & t ) { - scoped_lock l( _lock ); - if ( _queue.empty() ) - return false; - - t = _queue.front(); - _queue.pop(); - - return true; - } - - T blockingPop() { - - scoped_lock l( _lock ); - while( _queue.empty() ) - _condition.wait( l.boost() ); - - T t = _queue.front(); - _queue.pop(); - return t; - } - - - /** - * blocks waiting for an object until maxSecondsToWait passes - * if got one, return true and set in t - * otherwise return false and t won't be changed - */ - bool blockingPop( T& t , int maxSecondsToWait ) { - - Timer timer; - - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += maxSecondsToWait; - - scoped_lock l( _lock ); - while( _queue.empty() ) { - if ( ! _condition.timed_wait( l.boost() , xt ) ) - return false; - } - - t = _queue.front(); - _queue.pop(); - return true; - } - - private: - std::queue<T> _queue; - - mutable mongo::mutex _lock; - boost::condition _condition; - }; - -} diff --git a/util/ramlog.cpp b/util/ramlog.cpp deleted file mode 100644 index d7a839a3fff..00000000000 --- a/util/ramlog.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// ramlog.cpp - -/* 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. - */ - -#include "pch.h" -#include "log.h" -#include "ramlog.h" -#include "mongoutils/html.h" -#include "mongoutils/str.h" - -namespace mongo { - - using namespace mongoutils; - - RamLog::RamLog( string name ) : _name(name), _lastWrite(0) { - h = 0; n = 0; - for( int i = 0; i < N; i++ ) - lines[i][C-1] = 0; - - if ( name.size() ) { - - if ( ! _namedLock ) - _namedLock = new mongo::mutex("RamLog::_namedLock"); - - scoped_lock lk( *_namedLock ); - if ( ! _named ) - _named = new RM(); - (*_named)[name] = this; - } - - } - - RamLog::~RamLog() { - - } - - void RamLog::write(LogLevel ll, const string& str) { - _lastWrite = time(0); - - char *p = lines[(h+n)%N]; - - unsigned sz = str.size(); - if( sz < C ) { - if ( str.c_str()[sz-1] == '\n' ) { - memcpy(p, str.c_str(), sz-1); - p[sz-1] = 0; - } - else - strcpy(p, str.c_str()); - } - else { - memcpy(p, str.c_str(), C-1); - } - - if( n < N ) n++; - else h = (h+1) % N; - } - - void RamLog::get( vector<const char*>& v) const { - for( unsigned x=0, i=h; x++ < n; i=(i+1)%N ) - v.push_back(lines[i]); - } - - int RamLog::repeats(const vector<const char *>& v, int i) { - for( int j = i-1; j >= 0 && j+8 > i; j-- ) { - if( strcmp(v[i]+20,v[j]+20) == 0 ) { - for( int x = 1; ; x++ ) { - if( j+x == i ) return j; - if( i+x>=(int) v.size() ) return -1; - if( strcmp(v[i+x]+20,v[j+x]+20) ) return -1; - } - return -1; - } - } - return -1; - } - - - string RamLog::clean(const vector<const char *>& v, int i, string line ) { - if( line.empty() ) line = v[i]; - if( i > 0 && strncmp(v[i], v[i-1], 11) == 0 ) - return string(" ") + line.substr(11); - return v[i]; - } - - string RamLog::color(string line) { - string s = str::after(line, "replSet "); - if( str::startsWith(s, "warning") || startsWith(s, "error") ) - return html::red(line); - if( str::startsWith(s, "info") ) { - if( str::endsWith(s, " up\n") ) - return html::green(line); - else if( str::contains(s, " down ") || str::endsWith(s, " down\n") ) - return html::yellow(line); - return line; //html::blue(line); - } - - return line; - } - - /* turn http:... into an anchor */ - string RamLog::linkify(const char *s) { - const char *p = s; - const char *h = strstr(p, "http://"); - if( h == 0 ) return s; - - const char *sp = h + 7; - while( *sp && *sp != ' ' ) sp++; - - string url(h, sp-h); - stringstream ss; - ss << string(s, h-s) << "<a href=\"" << url << "\">" << url << "</a>" << sp; - return ss.str(); - } - - void RamLog::toHTML(stringstream& s) { - vector<const char*> v; - get( v ); - - s << "<pre>\n"; - for( int i = 0; i < (int)v.size(); i++ ) { - assert( strlen(v[i]) > 20 ); - int r = repeats(v, i); - if( r < 0 ) { - s << color( linkify( clean(v,i).c_str() ) ) << '\n'; - } - else { - stringstream x; - x << string(v[i], 0, 20); - int nr = (i-r); - int last = i+nr-1; - for( ; r < i ; r++ ) x << '.'; - if( 1 ) { - stringstream r; - if( nr == 1 ) r << "repeat last line"; - else r << "repeats last " << nr << " lines; ends " << string(v[last]+4,0,15); - s << html::a("", r.str(), clean(v,i,x.str())); - } - else s << x.str(); - s << '\n'; - i = last; - } - } - s << "</pre>\n"; - } - - // --------------- - // static things - // --------------- - - RamLog* RamLog::get( string name ) { - if ( ! _named ) - return 0; - - scoped_lock lk( *_namedLock ); - RM::iterator i = _named->find( name ); - if ( i == _named->end() ) - return 0; - return i->second; - } - - void RamLog::getNames( vector<string>& names ) { - if ( ! _named ) - return; - - scoped_lock lk( *_namedLock ); - for ( RM::iterator i=_named->begin(); i!=_named->end(); ++i ) { - if ( i->second->n ) - names.push_back( i->first ); - } - } - - mongo::mutex* RamLog::_namedLock; - RamLog::RM* RamLog::_named = 0; - - Tee* const warnings = new RamLog("warnings"); // Things put here go in serverStatus -} diff --git a/util/ramlog.h b/util/ramlog.h deleted file mode 100644 index d3d5c8fbb4e..00000000000 --- a/util/ramlog.h +++ /dev/null @@ -1,65 +0,0 @@ -// ramlog.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 - -#include "log.h" - -namespace mongo { - - class RamLog : public Tee { - public: - RamLog( string name ); - - virtual void write(LogLevel ll, const string& str); - - void get( vector<const char*>& v) const; - - void toHTML(stringstream& s); - - static RamLog* get( string name ); - static void getNames( vector<string>& names ); - - time_t lastWrite() { return _lastWrite; } // 0 if no writes - - protected: - static int repeats(const vector<const char *>& v, int i); - static string clean(const vector<const char *>& v, int i, string line=""); - static string color(string line); - - /* turn http:... into an anchor */ - static string linkify(const char *s); - - private: - ~RamLog(); // want this private as we want to leak so we can use them till the very end - - enum { - N = 128, // number of links - C = 256 // max size of line - }; - char lines[N][C]; - unsigned h; // current position - unsigned n; // numer of lines stores 0 o N - string _name; - - typedef map<string,RamLog*> RM; - static mongo::mutex* _namedLock; - static RM* _named; - time_t _lastWrite; - }; - -} diff --git a/util/scopeguard.h b/util/scopeguard.h deleted file mode 100644 index 8ced04f47fc..00000000000 --- a/util/scopeguard.h +++ /dev/null @@ -1,432 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// 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/signal_handlers.cpp b/util/signal_handlers.cpp deleted file mode 100644 index 0e9ec7a9b15..00000000000 --- a/util/signal_handlers.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// signal_handlers.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/>. -*/ - -#include "pch.h" - -#include <cstdarg> -#include <cstdio> -#include <cstdlib> - -#if !defined(_WIN32) // TODO: windows support -#include <unistd.h> -#endif - -#if !defined(_WIN32) && !defined(NOEXECINFO) -#include <execinfo.h> -#endif - -#include "log.h" -#include "signal_handlers.h" - -namespace mongo { - - /* - * WARNING: PLEASE READ BEFORE CHANGING THIS MODULE - * - * All code in this module should be singal-friendly. Before adding any system - * call or other dependency, please make sure the latter still holds. - * - */ - - static int rawWrite( int fd , char* c , int size ) { -#if !defined(_WIN32) - - int toWrite = size; - int writePos = 0; - int wrote; - while ( toWrite > 0 ) { - wrote = write( fd , &c[writePos] , toWrite ); - if ( wrote < 1 ) break; - toWrite -= wrote; - writePos += wrote; - } - return writePos; - -#else - - return -1; - -#endif - } - - static int formattedWrite( int fd , const char* format, ... ) { - const int MAX_ENTRY = 256; - static char entryBuf[MAX_ENTRY]; - - va_list ap; - va_start( ap , format ); - int entrySize = vsnprintf( entryBuf , MAX_ENTRY-1 , format , ap ); - if ( entrySize < 0 ) { - return -1; - } - - if ( rawWrite( fd , entryBuf , entrySize ) < 0 ) { - return -1; - } - - return 0; - } - - static void formattedBacktrace( int fd ) { - -#if !defined(_WIN32) && !defined(NOEXECINFO) - - int numFrames; - const int MAX_DEPTH = 20; - void* stackFrames[MAX_DEPTH]; - - numFrames = backtrace( stackFrames , 20 ); - for ( int i = 0; i < numFrames; i++ ) { - formattedWrite( fd , "%p " , stackFrames[i] ); - } - formattedWrite( fd , "\n" ); - - backtrace_symbols_fd( stackFrames , numFrames , fd ); - -#else - - formattedWrite( fd, "backtracing not implemented for this platform yet\n" ); - -#endif - - } - - void printStackAndExit( int signalNum ) { - int fd = Logstream::getLogDesc(); - - if ( fd >= 0 ) { - formattedWrite( fd , "Received signal %d\n" , signalNum ); - formattedWrite( fd , "Backtrace: " ); - formattedBacktrace( fd ); - formattedWrite( fd , "===\n" ); - } - - ::exit( EXIT_ABRUPT ); - } - -} // namespace mongo diff --git a/util/signal_handlers.h b/util/signal_handlers.h deleted file mode 100644 index 9d3a735a723..00000000000 --- a/util/signal_handlers.h +++ /dev/null @@ -1,34 +0,0 @@ -// signal_handlers.h - -/** -* 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/>. -*/ - -#pragma once - -#include "../pch.h" - -namespace mongo { - - /** - * Obtains the log file handler and writes the current thread's stack trace to - * it. This call issues an exit(). The function can safely be called from within a - * signal handler. - * - * @param signal that this hadler is called for - */ - void printStackAndExit( int signalNum ); - -} // namespace mongo diff --git a/util/stringutils.cpp b/util/stringutils.cpp deleted file mode 100644 index 229f57bb3cb..00000000000 --- a/util/stringutils.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// stringutils.cpp - -/** -* Copyright (C) 2008 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/>. -*/ - -#include "pch.h" - -namespace mongo { - - void splitStringDelim( const string& str , vector<string>* res , char delim ) { - if ( str.empty() ) - return; - - size_t beg = 0; - size_t pos = str.find( delim ); - while ( pos != string::npos ) { - res->push_back( str.substr( beg, pos - beg) ); - beg = ++pos; - pos = str.find( delim, beg ); - } - res->push_back( str.substr( beg ) ); - } - - void joinStringDelim( const vector<string>& strs , string* res , char delim ) { - for ( vector<string>::const_iterator it = strs.begin(); it != strs.end(); ++it ) { - if ( it !=strs.begin() ) res->push_back( delim ); - res->append( *it ); - } - } - -} // namespace mongo diff --git a/util/stringutils.h b/util/stringutils.h deleted file mode 100644 index 93598aa520b..00000000000 --- a/util/stringutils.h +++ /dev/null @@ -1,139 +0,0 @@ -// stringutils.h - -/* Copyright 2010 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 { - - // see also mongoutils/str.h - perhaps move these there? - // see also text.h - - void splitStringDelim( const string& str , vector<string>* res , char delim ); - - void joinStringDelim( const vector<string>& strs , string* res , char delim ); - - inline string tolowerString( const string& input ) { - string::size_type sz = input.size(); - - boost::scoped_array<char> line(new char[sz+1]); - char * copy = line.get(); - - for ( string::size_type i=0; i<sz; i++ ) { - char c = input[i]; - copy[i] = (char)tolower( (int)c ); - } - copy[sz] = 0; - return string(copy); - } - - /** - * Non numeric characters are compared lexicographically; numeric substrings - * are compared numerically; dots separate ordered comparable subunits. - * For convenience, character 255 is greater than anything else. - */ - inline int lexNumCmp( const char *s1, const char *s2 ) { - //cout << "START : " << s1 << "\t" << s2 << endl; - - bool startWord = true; - - while( *s1 && *s2 ) { - - bool d1 = ( *s1 == '.' ); - bool d2 = ( *s2 == '.' ); - if ( d1 && !d2 ) - return -1; - if ( d2 && !d1 ) - return 1; - if ( d1 && d2 ) { - ++s1; ++s2; - startWord = true; - continue; - } - - bool p1 = ( *s1 == (char)255 ); - bool p2 = ( *s2 == (char)255 ); - //cout << "\t\t " << p1 << "\t" << p2 << endl; - if ( p1 && !p2 ) - return 1; - if ( p2 && !p1 ) - return -1; - - bool n1 = isNumber( *s1 ); - bool n2 = isNumber( *s2 ); - - if ( n1 && n2 ) { - // get rid of leading 0s - if ( startWord ) { - while ( *s1 == '0' ) s1++; - while ( *s2 == '0' ) s2++; - } - - char * e1 = (char*)s1; - char * e2 = (char*)s2; - - // find length - // if end of string, will break immediately ('\0') - while ( isNumber (*e1) ) e1++; - while ( isNumber (*e2) ) e2++; - - int len1 = (int)(e1-s1); - int len2 = (int)(e2-s2); - - int result; - // if one is longer than the other, return - if ( len1 > len2 ) { - return 1; - } - else if ( len2 > len1 ) { - return -1; - } - // if the lengths are equal, just strcmp - else if ( (result = strncmp(s1, s2, len1)) != 0 ) { - return result; - } - - // otherwise, the numbers are equal - s1 = e1; - s2 = e2; - startWord = false; - continue; - } - - if ( n1 ) - return 1; - - if ( n2 ) - return -1; - - if ( *s1 > *s2 ) - return 1; - - if ( *s2 > *s1 ) - return -1; - - s1++; s2++; - startWord = false; - } - - if ( *s1 ) - return 1; - if ( *s2 ) - return -1; - return 0; - } - -} // namespace mongo diff --git a/util/text.cpp b/util/text.cpp deleted file mode 100644 index 51a2556afdc..00000000000 --- a/util/text.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// text.cpp - -/* 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. - */ - -#include "pch.h" -#include "text.h" -#include "unittest.h" - -namespace mongo { - - inline int leadingOnes(unsigned char c) { - if (c < 0x80) return 0; - static const char _leadingOnes[128] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 - 0x8F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 0x99 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xA0 - 0xA9 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xB0 - 0xB9 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xC0 - 0xC9 - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xD0 - 0xD9 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xE0 - 0xE9 - 4, 4, 4, 4, 4, 4, 4, 4, // 0xF0 - 0xF7 - 5, 5, 5, 5, // 0xF8 - 0xFB - 6, 6, // 0xFC - 0xFD - 7, // 0xFE - 8, // 0xFF - }; - return _leadingOnes[c & 0x7f]; - - } - - bool isValidUTF8(const char *s) { - int left = 0; // how many bytes are left in the current codepoint - while (*s) { - const unsigned char c = (unsigned char) *(s++); - const int ones = leadingOnes(c); - if (left) { - if (ones != 1) return false; // should be a continuation byte - left--; - } - else { - if (ones == 0) continue; // ASCII byte - if (ones == 1) return false; // unexpected continuation byte - if (c > 0xF4) return false; // codepoint too large (< 0x10FFFF) - if (c == 0xC0 || c == 0xC1) return false; // codepoints <= 0x7F shouldn't be 2 bytes - - // still valid - left = ones-1; - } - } - if (left!=0) return false; // string ended mid-codepoint - return true; - } - -#if defined(_WIN32) - - std::string toUtf8String(const std::wstring& wide) { - if (wide.size() > boost::integer_traits<int>::const_max) - throw std::length_error( - "Wide string cannot be more than INT_MAX characters long."); - if (wide.size() == 0) - return ""; - - // Calculate necessary buffer size - int len = ::WideCharToMultiByte( - CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), - NULL, 0, NULL, NULL); - - // Perform actual conversion - if (len > 0) { - std::vector<char> buffer(len); - len = ::WideCharToMultiByte( - CP_UTF8, 0, wide.c_str(), static_cast<int>(wide.size()), - &buffer[0], static_cast<int>(buffer.size()), NULL, NULL); - if (len > 0) { - assert(len == static_cast<int>(buffer.size())); - return std::string(&buffer[0], buffer.size()); - } - } - - throw boost::system::system_error( - ::GetLastError(), boost::system::system_category); - } - -#if defined(_UNICODE) - std::wstring toWideString(const char *s) { - std::basic_ostringstream<TCHAR> buf; - buf << s; - return buf.str(); - } -#endif - -#endif - - struct TextUnitTest : public UnitTest { - void run() { - assert( parseLL("123") == 123 ); - assert( parseLL("-123000000000") == -123000000000LL ); - } - } textUnitTest; - -} - diff --git a/util/text.h b/util/text.h deleted file mode 100644 index fc2da214097..00000000000 --- a/util/text.h +++ /dev/null @@ -1,148 +0,0 @@ -// text.h -/* - * Copyright 2010 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. - */ - -/* 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 { - - class StringSplitter { - public: - /** @param big the string to be split - @param splitter the delimiter - */ - StringSplitter( const char * big , const char * splitter ) - : _big( big ) , _splitter( splitter ) { - } - - /** @return true if more to be taken via next() */ - bool more() { - return _big[0]; - } - - /** get next split string fragment */ - string next() { - const char * foo = strstr( _big , _splitter ); - if ( foo ) { - string s( _big , foo - _big ); - _big = foo + 1; - while ( *_big && strstr( _big , _splitter ) == _big ) - _big++; - return s; - } - - string s = _big; - _big += strlen( _big ); - return s; - } - - void split( vector<string>& l ) { - while ( more() ) { - l.push_back( next() ); - } - } - - vector<string> split() { - vector<string> l; - split( l ); - return l; - } - - static vector<string> split( const string& big , const string& splitter ) { - StringSplitter ss( big.c_str() , splitter.c_str() ); - return ss.split(); - } - - static string join( vector<string>& l , const string& split ) { - stringstream ss; - for ( unsigned i=0; i<l.size(); i++ ) { - if ( i > 0 ) - ss << split; - ss << l[i]; - } - return ss.str(); - } - - private: - const char * _big; - const char * _splitter; - }; - - /* This doesn't defend against ALL bad UTF8, but it will guarantee that the - * string can be converted to sequence of codepoints. However, it doesn't - * guarantee that the codepoints are valid. - */ - bool isValidUTF8(const char *s); - inline bool isValidUTF8(string s) { return isValidUTF8(s.c_str()); } - -#if defined(_WIN32) - - std::string toUtf8String(const std::wstring& wide); - - std::wstring toWideString(const char *s); - - /* like toWideString but UNICODE macro sensitive */ -# if !defined(_UNICODE) -#error temp error - inline std::string toNativeString(const char *s) { return s; } -# else - inline std::wstring toNativeString(const char *s) { return toWideString(s); } -# endif - -#endif - - // expect that n contains a base ten number and nothing else after it - // NOTE win version hasn't been tested directly - inline long long parseLL( const char *n ) { - long long ret; - uassert( 13307, "cannot convert empty string to long long", *n != 0 ); -#if !defined(_WIN32) - char *endPtr = 0; - errno = 0; - ret = strtoll( n, &endPtr, 10 ); - uassert( 13305, "could not convert string to long long", *endPtr == 0 && errno == 0 ); -#elif _MSC_VER>=1600 // 1600 is VS2k10 1500 is VS2k8 - size_t endLen = 0; - try { - ret = stoll( n, &endLen, 10 ); - } - catch ( ... ) { - endLen = 0; - } - uassert( 13306, "could not convert string to long long", endLen != 0 && n[ endLen ] == 0 ); -#else // stoll() wasn't introduced until VS 2010. - char* endPtr = 0; - ret = _strtoi64( n, &endPtr, 10 ); - uassert( 13310, "could not convert string to long long", (*endPtr == 0) && (ret != _I64_MAX) && (ret != _I64_MIN) ); -#endif // !defined(_WIN32) - return ret; - } -} diff --git a/util/time_support.h b/util/time_support.h deleted file mode 100644 index ca17807ec96..00000000000 --- a/util/time_support.h +++ /dev/null @@ -1,253 +0,0 @@ -// @file time_support.h - -/* Copyright 2010 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 - -#include <cstdio> // sscanf -#include <ctime> -#include <boost/date_time/posix_time/posix_time.hpp> -#include <boost/thread/xtime.hpp> -#undef assert -#define assert MONGO_assert - -namespace mongo { - - inline void time_t_to_Struct(time_t t, struct tm * buf , bool local = false ) { -#if defined(_WIN32) - if ( local ) - localtime_s( buf , &t ); - else - gmtime_s(buf, &t); -#else - if ( local ) - localtime_r(&t, buf); - else - gmtime_r(&t, buf); -#endif - } - - // uses ISO 8601 dates without trailing Z - // colonsOk should be false when creating filenames - inline string terseCurrentTime(bool colonsOk=true) { - struct tm t; - time_t_to_Struct( time(0) , &t ); - - const char* fmt = (colonsOk ? "%Y-%m-%dT%H:%M:%S" : "%Y-%m-%dT%H-%M-%S"); - char buf[32]; - assert(strftime(buf, sizeof(buf), fmt, &t) == 19); - return buf; - } - - inline string timeToISOString(time_t time) { - struct tm t; - time_t_to_Struct( time, &t ); - - const char* fmt = "%Y-%m-%dT%H:%M:%SZ"; - char buf[32]; - assert(strftime(buf, sizeof(buf), fmt, &t) == 20); - return buf; - } - - inline boost::gregorian::date currentDate() { - boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); - return now.date(); - } - - // parses time of day in "hh:mm" format assuming 'hh' is 00-23 - inline bool toPointInTime( const string& str , boost::posix_time::ptime* timeOfDay ) { - int hh = 0; - int mm = 0; - if ( 2 != sscanf( str.c_str() , "%d:%d" , &hh , &mm ) ) { - return false; - } - - // verify that time is well formed - if ( ( hh / 24 ) || ( mm / 60 ) ) { - return false; - } - - boost::posix_time::ptime res( currentDate() , boost::posix_time::hours( hh ) + boost::posix_time::minutes( mm ) ); - *timeOfDay = res; - return true; - } - -#define MONGO_asctime _asctime_not_threadsafe_ -#define asctime MONGO_asctime -#define MONGO_gmtime _gmtime_not_threadsafe_ -#define gmtime MONGO_gmtime -#define MONGO_localtime _localtime_not_threadsafe_ -#define localtime MONGO_localtime -#define MONGO_ctime _ctime_is_not_threadsafe_ -#define ctime MONGO_ctime - -#if defined(_WIN32) - inline void sleepsecs(int s) { - Sleep(s*1000); - } - inline void sleepmillis(long long s) { - assert( s <= 0xffffffff ); - Sleep((DWORD) s); - } - inline void sleepmicros(long long s) { - if ( s <= 0 ) - return; - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += (int)( s / 1000000 ); - xt.nsec += (int)(( s % 1000000 ) * 1000); - if ( xt.nsec >= 1000000000 ) { - xt.nsec -= 1000000000; - xt.sec++; - } - boost::thread::sleep(xt); - } -#elif defined(__sunos__) - inline void sleepsecs(int s) { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += s; - boost::thread::sleep(xt); - } - inline void sleepmillis(long long s) { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += (int)( s / 1000 ); - xt.nsec += (int)(( s % 1000 ) * 1000000); - if ( xt.nsec >= 1000000000 ) { - xt.nsec -= 1000000000; - xt.sec++; - } - boost::thread::sleep(xt); - } - inline void sleepmicros(long long s) { - if ( s <= 0 ) - return; - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - xt.sec += (int)( s / 1000000 ); - xt.nsec += (int)(( s % 1000000 ) * 1000); - if ( xt.nsec >= 1000000000 ) { - xt.nsec -= 1000000000; - xt.sec++; - } - boost::thread::sleep(xt); - } -#else - inline void sleepsecs(int s) { - struct timespec t; - t.tv_sec = s; - t.tv_nsec = 0; - if ( nanosleep( &t , 0 ) ) { - cout << "nanosleep failed" << endl; - } - } - inline void sleepmicros(long long s) { - if ( s <= 0 ) - return; - struct timespec t; - t.tv_sec = (int)(s / 1000000); - t.tv_nsec = 1000 * ( s % 1000000 ); - struct timespec out; - if ( nanosleep( &t , &out ) ) { - cout << "nanosleep failed" << endl; - } - } - inline void sleepmillis(long long s) { - sleepmicros( s * 1000 ); - } -#endif - - extern long long jsTime_virtual_skew; - extern boost::thread_specific_ptr<long long> jsTime_virtual_thread_skew; - - // DO NOT TOUCH except for testing - inline void jsTimeVirtualSkew( long long skew ){ - jsTime_virtual_skew = skew; - } - inline long long getJSTimeVirtualSkew(){ - return jsTime_virtual_skew; - } - - inline void jsTimeVirtualThreadSkew( long long skew ){ - jsTime_virtual_thread_skew.reset(new long long(skew)); - } - inline long long getJSTimeVirtualThreadSkew(){ - if(jsTime_virtual_thread_skew.get()){ - return *(jsTime_virtual_thread_skew.get()); - } - else return 0; - } - - /** Date_t is milliseconds since epoch */ - inline Date_t jsTime(); - - /** warning this will wrap */ - inline unsigned curTimeMicros(); - - inline unsigned long long curTimeMicros64(); -#ifdef _WIN32 // no gettimeofday on windows - inline unsigned long long curTimeMillis64() { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - return ((unsigned long long)xt.sec) * 1000 + xt.nsec / 1000000; - } - inline Date_t jsTime() { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - unsigned long long t = xt.nsec / 1000000; - return ((unsigned long long) xt.sec * 1000) + t + getJSTimeVirtualSkew() + getJSTimeVirtualThreadSkew(); - } - inline unsigned long long curTimeMicros64() { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - unsigned long long t = xt.nsec / 1000; - return (((unsigned long long) xt.sec) * 1000000) + t; - } - inline unsigned curTimeMicros() { - boost::xtime xt; - boost::xtime_get(&xt, boost::TIME_UTC); - unsigned t = xt.nsec / 1000; - unsigned secs = xt.sec % 1024; - return secs*1000000 + t; - } -#else -# include <sys/time.h> - inline unsigned long long curTimeMillis64() { - timeval tv; - gettimeofday(&tv, NULL); - return ((unsigned long long)tv.tv_sec) * 1000 + tv.tv_usec / 1000; - } - inline Date_t jsTime() { - timeval tv; - gettimeofday(&tv, NULL); - unsigned long long t = tv.tv_usec / 1000; - return ((unsigned long long) tv.tv_sec * 1000) + t + getJSTimeVirtualSkew() + getJSTimeVirtualThreadSkew(); - } - inline unsigned long long curTimeMicros64() { - timeval tv; - gettimeofday(&tv, NULL); - return (((unsigned long long) tv.tv_sec) * 1000*1000) + tv.tv_usec; - } - inline unsigned curTimeMicros() { - timeval tv; - gettimeofday(&tv, NULL); - unsigned secs = tv.tv_sec % 1024; - return secs*1000*1000 + tv.tv_usec; - } -#endif - -} // namespace mongo diff --git a/util/timer.h b/util/timer.h deleted file mode 100644 index cbfe859ef5c..00000000000 --- a/util/timer.h +++ /dev/null @@ -1,104 +0,0 @@ -// @file timer.h - -/* Copyright 2010 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 - -#include "time_support.h" - -namespace mongo { - - /** - * simple scoped timer - */ - class Timer /*copyable*/ { - public: - Timer() { reset(); } - Timer( unsigned long long startMicros ) { old = startMicros; } - int seconds() const { return (int)(micros() / 1000000); } - int millis() const { return (int)(micros() / 1000); } - int minutes() const { return seconds() / 60; } - - - /** gets time interval and resets at the same time. this way we can call curTimeMicros - once instead of twice if one wanted millis() and then reset(). - @return time in millis - */ - int millisReset() { - unsigned long long now = curTimeMicros64(); - int m = (int)((now-old)/1000); - old = now; - return m; - } - - // note: dubious that the resolution is as anywhere near as high as ethod name implies! - unsigned long long micros() const { - unsigned long long n = curTimeMicros64(); - return n - old; - } - unsigned long long micros(unsigned long long & n) const { // returns cur time in addition to timer result - n = curTimeMicros64(); - return n - old; - } - - unsigned long long startTime() const { return old; } - void reset() { old = curTimeMicros64(); } - private: - unsigned long long old; - }; - -#if 1 - class DevTimer { - public: - class scoped { - public: - scoped(DevTimer& dt) { } - ~scoped() { } - }; - DevTimer(string) { } - ~DevTimer() { } - }; -#elif defined(_WIN32) - class DevTimer { - const string _name; - public: - unsigned long long _ticks; - class scoped { - DevTimer& _dt; - unsigned long long _start; - public: - scoped(DevTimer& dt) : _dt(dt) { - LARGE_INTEGER i; - QueryPerformanceCounter(&i); - _start = i.QuadPart; - } - ~scoped() { - LARGE_INTEGER i; - QueryPerformanceCounter(&i); - _dt._ticks += (i.QuadPart - _start); - } - }; - DevTimer(string name) : _name(name), _ticks(0) { - } - ~DevTimer() { - LARGE_INTEGER freq; - assert( QueryPerformanceFrequency(&freq) );
- cout << "devtimer\t" << _name << '\t' << _ticks*1000.0/freq.QuadPart << "ms" << endl; - } - }; -#endif - -} // namespace mongo diff --git a/util/unittest.h b/util/unittest.h deleted file mode 100644 index 94be444363f..00000000000 --- a/util/unittest.h +++ /dev/null @@ -1,62 +0,0 @@ -// unittest.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 idea here is to let all initialization of global variables (classes inheriting from UnitTest) - complete before we run the tests -- otherwise order of initilization being arbitrary may mess - us up. The app's main() function should call runTests(). - - To define a unit test, inherit from this and implement run. instantiate one object for the new class - as a global. - - These tests are ran on *every* startup of mongod, so they have to be very lightweight. But it is a - good quick check for a bad build. - */ - struct UnitTest { - UnitTest() { - registerTest(this); - } - virtual ~UnitTest() {} - - // assert if fails - virtual void run() = 0; - - static bool testsInProgress() { return running; } - private: - static vector<UnitTest*> *tests; - static bool running; - public: - static void registerTest(UnitTest *t) { - if ( tests == 0 ) - tests = new vector<UnitTest*>(); - tests->push_back(t); - } - - static void runTests() { - running = true; - for ( vector<UnitTest*>::iterator i = tests->begin(); i != tests->end(); i++ ) { - (*i)->run(); - } - running = false; - } - }; - - -} // namespace mongo diff --git a/util/util.cpp b/util/util.cpp deleted file mode 100644 index 4528e300813..00000000000 --- a/util/util.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// @file util.cpp - -/* 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. - */ - -#include "pch.h" -#include "goodies.h" -#include "unittest.h" -#include "file_allocator.h" -#include "optime.h" -#include "time_support.h" -#include "mongoutils/str.h" - -namespace mongo { - - string hexdump(const char *data, unsigned len) { - assert( len < 1000000 ); - const unsigned char *p = (const unsigned char *) data; - stringstream ss; - for( unsigned i = 0; i < 4 && i < len; i++ ) { - ss << std::hex << setw(2) << setfill('0'); - unsigned n = p[i]; - ss << n; - ss << ' '; - } - string s = ss.str(); - return s; - } - - boost::thread_specific_ptr<string> _threadName; - - unsigned _setThreadName( const char * name ) { - if ( ! name ) name = "NONE"; - - static unsigned N = 0; - - if ( strcmp( name , "conn" ) == 0 ) { - string* x = _threadName.get(); - if ( x && mongoutils::str::startsWith( *x , "conn" ) ) { - int n = atoi( x->c_str() + 4 ); - if ( n > 0 ) - return n; - warning() << "unexpected thread name [" << *x << "] parsed to " << n << endl; - } - unsigned n = ++N; - stringstream ss; - ss << name << n; - _threadName.reset( new string( ss.str() ) ); - return n; - } - - _threadName.reset( new string(name) ); - return 0; - } - -#if defined(_WIN32) -#define MS_VC_EXCEPTION 0x406D1388 -#pragma pack(push,8) - typedef struct tagTHREADNAME_INFO { - DWORD dwType; // Must be 0x1000. - LPCSTR szName; // Pointer to name (in user addr space). - DWORD dwThreadID; // Thread ID (-1=caller thread). - DWORD dwFlags; // Reserved for future use, must be zero. - } THREADNAME_INFO; -#pragma pack(pop) - - void setWinThreadName(const char *name) { - /* is the sleep here necessary??? - Sleep(10); - */ - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = -1; - info.dwFlags = 0; - __try { - RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info ); - } - __except(EXCEPTION_EXECUTE_HANDLER) { - } - } - - unsigned setThreadName(const char *name) { - unsigned n = _setThreadName( name ); -#if !defined(_DEBUG) - // naming might be expensive so don't do "conn*" over and over - if( string("conn") == name ) - return n; -#endif - setWinThreadName(name); - return n; - } - -#else - - unsigned setThreadName(const char * name ) { - return _setThreadName( name ); - } - -#endif - - string getThreadName() { - string * s = _threadName.get(); - if ( s ) - return *s; - return ""; - } - - vector<UnitTest*> *UnitTest::tests = 0; - bool UnitTest::running = false; - - const char *default_getcurns() { return ""; } - const char * (*getcurns)() = default_getcurns; - - int logLevel = 0; - int tlogLevel = 0; - mongo::mutex Logstream::mutex("Logstream"); - int Logstream::doneSetup = Logstream::magicNumber(); - - bool isPrime(int n) { - int z = 2; - while ( 1 ) { - if ( z*z > n ) - break; - if ( n % z == 0 ) - return false; - z++; - } - return true; - } - - int nextPrime(int n) { - n |= 1; // 2 goes to 3...don't care... - while ( !isPrime(n) ) - n += 2; - return n; - } - - struct UtilTest : public UnitTest { - void run() { - assert( isPrime(3) ); - assert( isPrime(2) ); - assert( isPrime(13) ); - assert( isPrime(17) ); - assert( !isPrime(9) ); - assert( !isPrime(6) ); - assert( nextPrime(4) == 5 ); - assert( nextPrime(8) == 11 ); - - assert( endsWith("abcde", "de") ); - assert( !endsWith("abcde", "dasdfasdfashkfde") ); - - assert( swapEndian(0x01020304) == 0x04030201 ); - - } - } utilTest; - - OpTime OpTime::last(0, 0); - - /* this is a good place to set a breakpoint when debugging, as lots of warning things - (assert, wassert) call it. - */ - void sayDbContext(const char *errmsg) { - if ( errmsg ) { - problem() << errmsg << endl; - } - printStackTrace(); - } - - /* note: can't use malloc herein - may be in signal handler. - logLockless() likely does not comply and should still be fixed todo - likewise class string? - */ - void rawOut( const string &s ) { - if( s.empty() ) return; - - char buf[64]; - time_t_to_String( time(0) , buf ); - /* truncate / don't show the year: */ - buf[19] = ' '; - buf[20] = 0; - - Logstream::logLockless(buf); - Logstream::logLockless(s); - Logstream::logLockless("\n"); - } - - ostream& operator<<( ostream &s, const ThreadSafeString &o ) { - s << o.toString(); - return s; - } - - bool StaticObserver::_destroyingStatics = false; - -} // namespace mongo diff --git a/util/version.cpp b/util/version.cpp deleted file mode 100644 index 58e910dc397..00000000000 --- a/util/version.cpp +++ /dev/null @@ -1,284 +0,0 @@ -// @file version.cpp - -/* 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. - */ - -#include "pch.h" -#include <cstdlib> -#include <iostream> -#include <iomanip> -#include <sstream> -#include <string> -#include "unittest.h" -#include "version.h" -#include "stringutils.h" -#include "../db/jsobj.h" -#include "file.h" -#include "ramlog.h" -#include "../db/cmdline.h" - -namespace mongo { - - /* Approved formats for versionString: - * 1.2.3 - * 1.2.3-pre- - * 1.2.3-rc4 (up to rc9) - * 1.2.3-rc4-pre- - * If you really need to do something else you'll need to fix _versionArray() - */ - const char versionString[] = "2.0.7"; - - // See unit test for example outputs - static BSONArray _versionArray(const char* version){ - // this is inefficient, but cached so it doesn't matter - BSONArrayBuilder b; - string curPart; - const char* c = version; - int finalPart = 0; // 0 = final release, -100 = pre, -10 to -1 = -10 + X for rcX - do { //walks versionString including NUL byte - if (!(*c == '.' || *c == '-' || *c == '\0')){ - curPart += *c; - continue; - } - - try { - unsigned num = stringToNum(curPart.c_str()); - b.append((int) num); - } - catch (...){ // not a number - if (curPart.empty()){ - assert(*c == '\0'); - break; - } - else if (startsWith(curPart, "rc")){ - finalPart = -10 + stringToNum(curPart.c_str()+2); - break; - } - else if (curPart == "pre"){ - finalPart = -100; - break; - } - } - - curPart = ""; - } while (*c++); - - b.append(finalPart); - return b.arr(); - } - - const BSONArray versionArray = _versionArray(versionString); - - string mongodVersion() { - stringstream ss; - ss << "db version v" << versionString << ", pdfile version " << VERSION << "." << VERSION_MINOR; - return ss.str(); - } - -#ifndef _SCONS - // only works in scons - const char * gitVersion() { return "not-scons"; } -#endif - - void printGitVersion() { log() << "git version: " << gitVersion() << endl; } - -#ifndef _SCONS -#if defined(_WIN32) - string sysInfo() { - stringstream ss; - ss << "not-scons win"; - ss << " mscver:" << _MSC_FULL_VER << " built:" << __DATE__; - ss << " boostver:" << BOOST_VERSION; -#if( !defined(_MT) ) -#error _MT is not defined -#endif - ss << (sizeof(char *) == 8) ? " 64bit" : " 32bit"; - return ss.str(); - } -#else - string sysInfo() { return ""; } -#endif -#endif - - void printSysInfo() { - log() << "build info: " << sysInfo() << endl; - } - - - static Tee * startupWarningsLog = new RamLog("startupWarnings"); //intentionally leaked - - // - // system warnings - // - void show_warnings() { - // each message adds a leading and a trailing newline - - bool warned = false; - { - const char * foo = strchr( versionString , '.' ) + 1; - int bar = atoi( foo ); - if ( ( 2 * ( bar / 2 ) ) != bar ) { - log() << startupWarningsLog; - log() << "** NOTE: This is a development version (" << versionString << ") of MongoDB." << startupWarningsLog; - log() << "** Not recommended for production." << startupWarningsLog; - warned = true; - } - } - - if ( sizeof(int*) == 4 ) { - log() << startupWarningsLog; - log() << "** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data" << startupWarningsLog; - log() << "** see http://blog.mongodb.org/post/137788967/32-bit-limitations" << startupWarningsLog; - log() << "** with --journal, the limit is lower" << startupWarningsLog; - warned = true; - } - -#ifdef __linux__ - if (boost::filesystem::exists("/proc/vz") && !boost::filesystem::exists("/proc/bc")) { - log() << startupWarningsLog; - log() << "** WARNING: You are running in OpenVZ. This is known to be broken!!!" << startupWarningsLog; - warned = true; - } - - if (boost::filesystem::exists("/sys/devices/system/node/node1")){ - // We are on a box with a NUMA enabled kernel and more than 1 numa node (they start at node0) - // Now we look at the first line of /proc/self/numa_maps - // - // Bad example: - // $ cat /proc/self/numa_maps - // 00400000 default file=/bin/cat mapped=6 N4=6 - // - // Good example: - // $ numactl --interleave=all cat /proc/self/numa_maps - // 00400000 interleave:0-7 file=/bin/cat mapped=6 N4=6 - - File f; - f.open("/proc/self/numa_maps", /*read_only*/true); - if ( f.is_open() && ! f.bad() ) { - char line[100]; //we only need the first line - assert( read(f.fd, line, sizeof(line)) <= 100 ); - - // just in case... - line[98] = ' '; - line[99] = '\0'; - - // skip over pointer - const char* space = strchr(line, ' '); - - if ( ! space ) { - log() << startupWarningsLog; - log() << "** WARNING: cannot parse numa_maps" << startupWarningsLog; - warned = true; - } - else if ( ! startsWith(space+1, "interleave") ) { - log() << startupWarningsLog; - log() << "** WARNING: You are running on a NUMA machine." << startupWarningsLog; - log() << "** We suggest launching mongod like this to avoid performance problems:" << startupWarningsLog; - log() << "** numactl --interleave=all mongod [other options]" << startupWarningsLog; - warned = true; - } - } - } - - if (cmdLine.dur){ - fstream f ("/proc/sys/vm/overcommit_memory", ios_base::in); - unsigned val; - f >> val; - - if (val == 2) { - log() << startupWarningsLog; - log() << "** WARNING: /proc/sys/vm/overcommit_memory is " << val << startupWarningsLog; - log() << "** Journaling works best with it set to 0 or 1" << startupWarningsLog; - } - } - - if (boost::filesystem::exists("/proc/sys/vm/zone_reclaim_mode")){ - fstream f ("/proc/sys/vm/zone_reclaim_mode", ios_base::in); - unsigned val; - f >> val; - - if (val != 0) { - log() << startupWarningsLog; - log() << "** WARNING: /proc/sys/vm/zone_reclaim_mode is " << val << startupWarningsLog; - log() << "** We suggest setting it to 0" << startupWarningsLog; - log() << "** http://www.kernel.org/doc/Documentation/sysctl/vm.txt" << startupWarningsLog; - } - } -#endif - - if (warned) { - log() << startupWarningsLog; - } - } - - int versionCmp(StringData rhs, StringData lhs) { - if (strcmp(rhs.data(),lhs.data()) == 0) - return 0; - - // handle "1.2.3-" and "1.2.3-pre" - if (rhs.size() < lhs.size()) { - if (strncmp(rhs.data(), lhs.data(), rhs.size()) == 0 && lhs.data()[rhs.size()] == '-') - return +1; - } - else if (rhs.size() > lhs.size()) { - if (strncmp(rhs.data(), lhs.data(), lhs.size()) == 0 && rhs.data()[lhs.size()] == '-') - return -1; - } - - return lexNumCmp(rhs.data(), lhs.data()); - } - - class VersionCmpTest : public UnitTest { - public: - void run() { - assert( versionCmp("1.2.3", "1.2.3") == 0 ); - assert( versionCmp("1.2.3", "1.2.4") < 0 ); - assert( versionCmp("1.2.3", "1.2.20") < 0 ); - assert( versionCmp("1.2.3", "1.20.3") < 0 ); - assert( versionCmp("2.2.3", "10.2.3") < 0 ); - assert( versionCmp("1.2.3", "1.2.3-") > 0 ); - assert( versionCmp("1.2.3", "1.2.3-pre") > 0 ); - assert( versionCmp("1.2.3", "1.2.4-") < 0 ); - assert( versionCmp("1.2.3-", "1.2.3") < 0 ); - assert( versionCmp("1.2.3-pre", "1.2.3") < 0 ); - - log(1) << "versionCmpTest passed" << endl; - } - } versionCmpTest; - - class VersionArrayTest : public UnitTest { - public: - void run() { - assert( _versionArray("1.2.3") == BSON_ARRAY(1 << 2 << 3 << 0) ); - assert( _versionArray("1.2.0") == BSON_ARRAY(1 << 2 << 0 << 0) ); - assert( _versionArray("2.0.0") == BSON_ARRAY(2 << 0 << 0 << 0) ); - - assert( _versionArray("1.2.3-pre-") == BSON_ARRAY(1 << 2 << 3 << -100) ); - assert( _versionArray("1.2.0-pre-") == BSON_ARRAY(1 << 2 << 0 << -100) ); - assert( _versionArray("2.0.0-pre-") == BSON_ARRAY(2 << 0 << 0 << -100) ); - - assert( _versionArray("1.2.3-rc0") == BSON_ARRAY(1 << 2 << 3 << -10) ); - assert( _versionArray("1.2.0-rc1") == BSON_ARRAY(1 << 2 << 0 << -9) ); - assert( _versionArray("2.0.0-rc2") == BSON_ARRAY(2 << 0 << 0 << -8) ); - - // Note that the pre of an rc is the same as the rc itself - assert( _versionArray("1.2.3-rc3-pre-") == BSON_ARRAY(1 << 2 << 3 << -7) ); - assert( _versionArray("1.2.0-rc4-pre-") == BSON_ARRAY(1 << 2 << 0 << -6) ); - assert( _versionArray("2.0.0-rc5-pre-") == BSON_ARRAY(2 << 0 << 0 << -5) ); - - log(1) << "versionArrayTest passed" << endl; - } - } versionArrayTest; -} diff --git a/util/version.h b/util/version.h deleted file mode 100644 index 64f8b140fd5..00000000000 --- a/util/version.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef UTIL_VERSION_HEADER -#define UTIL_VERSION_HEADER - -#include <string> - -namespace mongo { - struct BSONArray; - - using std::string; - - // mongo version - extern const char versionString[]; - extern const BSONArray versionArray; - string mongodVersion(); - int versionCmp(StringData rhs, StringData lhs); // like strcmp - - const char * gitVersion(); - void printGitVersion(); - - string sysInfo(); - void printSysInfo(); - - void show_warnings(); - -} // namespace mongo - -#endif // UTIL_VERSION_HEADER diff --git a/util/winutil.h b/util/winutil.h deleted file mode 100644 index b69b69a630d..00000000000 --- a/util/winutil.h +++ /dev/null @@ -1,44 +0,0 @@ -// @file winutil.cpp : Windows related utility functions -// -// /** -// * Copyright (C) 2008 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/>. -// */ -// -// #include "pch.h" - -#pragma once - -#if defined(_WIN32) -#include <windows.h> -#include "text.h" - -namespace mongo { - - inline string GetWinErrMsg(DWORD err) { - LPTSTR errMsg; - ::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, (LPTSTR)&errMsg, 0, NULL ); - std::string errMsgStr = toUtf8String( errMsg ); - ::LocalFree( errMsg ); - // FormatMessage() appends a newline to the end of error messages, we trim it because endl flushes the buffer. - errMsgStr = errMsgStr.erase( errMsgStr.length() - 2 ); - std::ostringstream output; - output << errMsgStr << " (" << err << ")"; - - return output.str(); - } -} - -#endif - |
