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