00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <iostream>
00034 #include <cstdlib>
00035 #include <cstring>
00036 #include <cerrno>
00037
00038 using std::cerr ;
00039 using std::endl ;
00040
00041 #include "BESMemoryGlobalArea.h"
00042 #include "BESInternalFatalError.h"
00043 #include "BESDebug.h"
00044 #include "BESLog.h"
00045 #include "TheBESKeys.h"
00046
00047 int BESMemoryGlobalArea::_counter = 0 ;
00048 unsigned long BESMemoryGlobalArea::_size = 0 ;
00049 void* BESMemoryGlobalArea::_buffer = 0 ;
00050
00051 BESMemoryGlobalArea::BESMemoryGlobalArea()
00052 {
00053 if( _counter++ == 0 )
00054 {
00055 try
00056 {
00057 bool fnd = false ;
00058 string key = "BES.Memory.GlobalArea." ;
00059 string eps =
00060 TheBESKeys::TheKeys()->get_key( key + "EmergencyPoolSize", fnd);
00061 string mhs =
00062 TheBESKeys::TheKeys()->get_key( key + "MaximumHeapSize", fnd ) ;
00063 string verbose =
00064 TheBESKeys::TheKeys()->get_key( key + "Verbose", fnd ) ;
00065 string control_heap =
00066 TheBESKeys::TheKeys()->get_key( key + "ControlHeap", fnd ) ;
00067 if( (eps=="") || (mhs=="") || (verbose=="") || (control_heap=="") )
00068 {
00069 string line = "can not determine memory keys.\n" ;
00070 throw BESInternalFatalError( line, __FILE__, __LINE__ ) ;
00071 }
00072 else
00073 {
00074 if( verbose=="no" )
00075 BESLog::TheLog()->suspend();
00076
00077 unsigned int emergency=atol(eps.c_str());
00078
00079 if( control_heap == "yes" )
00080 {
00081 unsigned int max = atol(mhs.c_str());
00082 BESDEBUG( "bes", "Initializing emergency heap to "
00083 << (long int)emergency << " MB" << endl )
00084 BESDEBUG( "bes", "Initializing max heap size to "
00085 << (long int)(max+1) << " MB" << endl )
00086 (*BESLog::TheLog()) << "Initialize emergency heap size to "
00087 << (long int)emergency
00088 << " and heap size to ";
00089 (*BESLog::TheLog()) << (long int)(max+1)
00090 << " megabytes" << endl ;
00091 if( emergency > max )
00092 {
00093 string s = string ( "BES: " )
00094 + "unable to start since the emergency "
00095 + "pool is larger than the maximum size of "
00096 + "the heap.\n" ;
00097 (*BESLog::TheLog()) << s ;
00098 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00099 }
00100 log_limits( "before setting limits: " ) ;
00101 limit.rlim_cur = megabytes( max + 1 ) ;
00102 limit.rlim_max = megabytes( max + 1 ) ;
00103
00104
00105
00106
00107
00108
00109
00110 if( setrlimit( RLIMIT_DATA, &limit ) < 0 )
00111 {
00112 string s = string( "BES: " )
00113 + "Could not set limit for the heap "
00114 + "because " + strerror(errno) + "\n" ;
00115 if( errno == EPERM )
00116 {
00117 s = s + "Attempting to increase the soft/hard "
00118 + "limit above the current hard limit, "
00119 + "must be superuser\n" ;
00120 }
00121 (*BESLog::TheLog()) << s ;
00122 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00123 }
00124 log_limits( "after setting limits: " ) ;
00125 _buffer = 0 ;
00126 _buffer = malloc( megabytes( max ) ) ;
00127 if( !_buffer )
00128 {
00129 string s = string( "BES: " )
00130 + "can not get heap of size "
00131 + mhs + " to start running" ;
00132 (*BESLog::TheLog()) << s ;
00133 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00134 }
00135 free( _buffer ) ;
00136 }
00137 else
00138 {
00139 if( emergency > 10 )
00140 {
00141 string s = "Emergency pool is larger than 10 Megabytes";
00142 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00143 }
00144 }
00145
00146 _size = megabytes( emergency ) ;
00147 _buffer = 0 ;
00148 _buffer = malloc( _size ) ;
00149 if( !_buffer )
00150 {
00151 string s = (string)"BES: can not expand heap to "
00152 + eps + " to start running" ;
00153 (*BESLog::TheLog()) << s << endl ;
00154 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 }
00168 }
00169 catch( BESError &ex )
00170 {
00171 cerr << "BES: unable to start properly because "
00172 << ex.get_message()
00173 << endl ;
00174 exit(1) ;
00175 }
00176 catch(...)
00177 {
00178 cerr << "BES: unable to start: undefined exception happened\n" ;
00179 exit(1) ;
00180 }
00181 }
00182 BESLog::TheLog()->resume();
00183 }
00184
00185 BESMemoryGlobalArea::~BESMemoryGlobalArea()
00186 {
00187 if (--_counter == 0)
00188 {
00189 if (_buffer)
00190 free( _buffer ) ;
00191 _buffer = 0 ;
00192 }
00193 }
00194
00195 inline void
00196 BESMemoryGlobalArea::log_limits( const string &msg )
00197 {
00198 if( getrlimit( RLIMIT_DATA, &limit ) < 0 )
00199 {
00200 (*BESLog::TheLog()) << msg << "Could not get limits because "
00201 << strerror( errno ) << endl ;
00202 _counter-- ;
00203 throw BESInternalFatalError( strerror( errno ), __FILE__, __LINE__ ) ;
00204 }
00205 if( limit.rlim_cur == RLIM_INFINITY )
00206 (*BESLog::TheLog()) << msg << "heap size soft limit is infinte"
00207 << endl ;
00208 else
00209 (*BESLog::TheLog()) << msg << "heap size soft limit is "
00210 << (long int)limit.rlim_cur
00211 << " bytes ("
00212 << (long int)(limit.rlim_cur)/(MEGABYTE)
00213 << " MB - may be rounded up)" << endl ;
00214 if( limit.rlim_max == RLIM_INFINITY )
00215 (*BESLog::TheLog()) << msg << "heap size hard limit is infinite"
00216 << endl ;
00217 else
00218 (*BESLog::TheLog()) << msg << "heap size hard limit is "
00219 << (long int)limit.rlim_max
00220 << " bytes ("
00221 << (long int)(limit.rlim_cur)/(MEGABYTE)
00222 << " MB - may be rounded up)" << endl ;
00223 }
00224
00225 void
00226 BESMemoryGlobalArea::release_memory()
00227 {
00228 if( _buffer )
00229 {
00230 free( _buffer ) ;
00231 _buffer = 0 ;
00232 }
00233 }
00234
00235 bool
00236 BESMemoryGlobalArea::reclaim_memory()
00237 {
00238 if( !_buffer )
00239 _buffer = malloc( _size ) ;
00240 if( _buffer )
00241 return true ;
00242 else
00243 return false ;
00244 }
00245
00253 void
00254 BESMemoryGlobalArea::dump( ostream &strm ) const
00255 {
00256 strm << BESIndent::LMarg << "BESMemoryGlobalArea::dump - ("
00257 << (void *)this << ")" << endl ;
00258 BESIndent::Indent() ;
00259 strm << BESIndent::LMarg << "area set? " << _counter << endl ;
00260 strm << BESIndent::LMarg << "emergency buffer: "
00261 << (void *)_buffer << endl ;
00262 strm << BESIndent::LMarg << "buffer size: " << _size << endl ;
00263 strm << BESIndent::LMarg << "rlimit current: " << limit.rlim_cur << endl ;
00264 strm << BESIndent::LMarg << "rlimit max: " << limit.rlim_max << endl ;
00265 BESIndent::UnIndent() ;
00266 }
00267