OPeNDAP Hyrax Back End Server (BES)
Updated for version 3.8.3
|
00001 // BESMemoryGlobalArea.cc 00002 00003 // This file is part of bes, A C++ back-end server implementation framework 00004 // for the OPeNDAP Data Access Protocol. 00005 00006 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research 00007 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu> 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Lesser General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2.1 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Lesser General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Lesser General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 // 00023 // You can contact University Corporation for Atmospheric Research at 00024 // 3080 Center Green Drive, Boulder, CO 80301 00025 00026 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005 00027 // Please read the full copyright statement in the file COPYRIGHT_UCAR. 00028 // 00029 // Authors: 00030 // pwest Patrick West <pwest@ucar.edu> 00031 // jgarcia Jose Garcia <jgarcia@ucar.edu> 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 00060 string eps ; 00061 TheBESKeys::TheKeys()->get_value( key + "EmergencyPoolSize", 00062 eps, fnd ) ; 00063 00064 string mhs ; 00065 TheBESKeys::TheKeys()->get_value( key + "MaximumHeapSize", 00066 mhs, fnd ) ; 00067 00068 string verbose ; 00069 TheBESKeys::TheKeys()->get_value( key + "Verbose", 00070 verbose, fnd ) ; 00071 00072 string control_heap ; 00073 TheBESKeys::TheKeys()->get_value( key + "ControlHeap", 00074 control_heap, fnd ) ; 00075 00076 if( (eps=="") || (mhs=="") || (verbose=="") || (control_heap=="") ) 00077 { 00078 string line = "cannot determine memory keys." ; 00079 line += (string)"Please set values for" 00080 + " BES.Memory.GlobalArea.EmergencyPoolSize," 00081 + " BES.Memory.GlobalArea.MaxiumumHeapSize," 00082 + " BES.Memory.GlobalArea.Verbose, and" 00083 + " BES.Memory.GlobalArea.ControlHeap" 00084 + " in the BES configuration file." ; 00085 throw BESInternalFatalError( line, __FILE__, __LINE__ ) ; 00086 } 00087 else 00088 { 00089 if( verbose=="no" ) 00090 BESLog::TheLog()->suspend(); 00091 00092 unsigned int emergency=atol(eps.c_str()); 00093 00094 if( control_heap == "yes" ) 00095 { 00096 unsigned int max = atol(mhs.c_str()); 00097 BESDEBUG( "bes", "Initializing emergency heap to " 00098 << (long int)emergency << " MB" << endl ) ; 00099 BESDEBUG( "bes", "Initializing max heap size to " 00100 << (long int)(max+1) << " MB" << endl ) ; 00101 (*BESLog::TheLog()) << "Initialize emergency heap size to " 00102 << (long int)emergency 00103 << " and heap size to " ; 00104 (*BESLog::TheLog()) << (long int)(max+1) 00105 << " megabytes" << endl ; 00106 if( emergency > max ) 00107 { 00108 string s = string ( "BES: " ) 00109 + "unable to start since the emergency " 00110 + "pool is larger than the maximum size of " 00111 + "the heap.\n" ; 00112 (*BESLog::TheLog()) << s ; 00113 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ; 00114 } 00115 log_limits( "before setting limits: " ) ; 00116 limit.rlim_cur = megabytes( max + 1 ) ; 00117 limit.rlim_max = megabytes( max + 1 ) ; 00118 /* repetative 00119 (*BESLog::TheLog()) << "BES: Trying limits soft to " 00120 << (long int)limit.rlim_cur ; 00121 (*BESLog::TheLog()) << " and hard to " 00122 << (long int)limit.rlim_max 00123 << endl ; 00124 */ 00125 if( setrlimit( RLIMIT_DATA, &limit ) < 0 ) 00126 { 00127 string s = string( "BES: " ) 00128 + "Could not set limit for the heap " 00129 + "because " + strerror(errno) + "\n" ; 00130 if( errno == EPERM ) 00131 { 00132 s = s + "Attempting to increase the soft/hard " 00133 + "limit above the current hard limit, " 00134 + "must be superuser\n" ; 00135 } 00136 (*BESLog::TheLog()) << s ; 00137 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ; 00138 } 00139 log_limits( "after setting limits: " ) ; 00140 _buffer = 0 ; 00141 _buffer = malloc( megabytes( max ) ) ; 00142 if( !_buffer ) 00143 { 00144 string s = string( "BES: " ) 00145 + "cannot get heap of size " 00146 + mhs + " to start running" ; 00147 (*BESLog::TheLog()) << s ; 00148 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ; 00149 } 00150 free( _buffer ) ; 00151 } 00152 else 00153 { 00154 if( emergency > 10 ) 00155 { 00156 string s = "Emergency pool is larger than 10 Megabytes"; 00157 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ; 00158 } 00159 } 00160 00161 _size = megabytes( emergency ) ; 00162 _buffer = 0 ; 00163 _buffer = malloc( _size ) ; 00164 if( !_buffer ) 00165 { 00166 string s = (string)"BES: cannot expand heap to " 00167 + eps + " to start running" ; 00168 (*BESLog::TheLog()) << s << endl ; 00169 throw BESInternalFatalError( s, __FILE__, __LINE__ ) ; 00170 } 00171 /* repetative 00172 else 00173 { 00174 if( BESLog::TheLog()->is_verbose() ) 00175 { 00176 (*BESLog::TheLog()) << "BES: Memory emergency area " 00177 << "initialized with size " 00178 << _size << " megabytes" << endl; 00179 } 00180 } 00181 */ 00182 } 00183 } 00184 catch( BESError &ex ) 00185 { 00186 cerr << "BES: unable to start properly because " 00187 << ex.get_message() 00188 << endl ; 00189 exit(1) ; 00190 } 00191 catch(...) 00192 { 00193 cerr << "BES: unable to start: undefined exception happened\n" ; 00194 exit(1) ; 00195 } 00196 } 00197 BESLog::TheLog()->resume(); 00198 } 00199 00200 BESMemoryGlobalArea::~BESMemoryGlobalArea() 00201 { 00202 if (--_counter == 0) 00203 { 00204 if (_buffer) 00205 free( _buffer ) ; 00206 _buffer = 0 ; 00207 } 00208 } 00209 00210 inline void 00211 BESMemoryGlobalArea::log_limits( const string &msg ) 00212 { 00213 if( getrlimit( RLIMIT_DATA, &limit ) < 0 ) 00214 { 00215 (*BESLog::TheLog()) << msg << "Could not get limits because " 00216 << strerror( errno ) << endl ; 00217 _counter-- ; 00218 throw BESInternalFatalError( strerror( errno ), __FILE__, __LINE__ ) ; 00219 } 00220 if( limit.rlim_cur == RLIM_INFINITY ) 00221 (*BESLog::TheLog()) << msg << "heap size soft limit is infinte" 00222 << endl ; 00223 else 00224 (*BESLog::TheLog()) << msg << "heap size soft limit is " 00225 << (long int)limit.rlim_cur 00226 << " bytes (" 00227 << (long int)(limit.rlim_cur)/(MEGABYTE) 00228 << " MB - may be rounded up)" << endl ; 00229 if( limit.rlim_max == RLIM_INFINITY ) 00230 (*BESLog::TheLog()) << msg << "heap size hard limit is infinite" 00231 << endl ; 00232 else 00233 (*BESLog::TheLog()) << msg << "heap size hard limit is " 00234 << (long int)limit.rlim_max 00235 << " bytes (" 00236 << (long int)(limit.rlim_cur)/(MEGABYTE) 00237 << " MB - may be rounded up)" << endl ; 00238 } 00239 00240 void 00241 BESMemoryGlobalArea::release_memory() 00242 { 00243 if( _buffer ) 00244 { 00245 free( _buffer ) ; 00246 _buffer = 0 ; 00247 } 00248 } 00249 00250 bool 00251 BESMemoryGlobalArea::reclaim_memory() 00252 { 00253 if( !_buffer ) 00254 _buffer = malloc( _size ) ; 00255 if( _buffer ) 00256 return true ; 00257 else 00258 return false ; 00259 } 00260 00268 void 00269 BESMemoryGlobalArea::dump( ostream &strm ) const 00270 { 00271 strm << BESIndent::LMarg << "BESMemoryGlobalArea::dump - (" 00272 << (void *)this << ")" << endl ; 00273 BESIndent::Indent() ; 00274 strm << BESIndent::LMarg << "area set? " << _counter << endl ; 00275 strm << BESIndent::LMarg << "emergency buffer: " 00276 << (void *)_buffer << endl ; 00277 strm << BESIndent::LMarg << "buffer size: " << _size << endl ; 00278 strm << BESIndent::LMarg << "rlimit current: " << limit.rlim_cur << endl ; 00279 strm << BESIndent::LMarg << "rlimit max: " << limit.rlim_max << endl ; 00280 BESIndent::UnIndent() ; 00281 } 00282