BESMemoryGlobalArea.cc

Go to the documentation of this file.
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,2005 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             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                     /* repetative
00104                     (*BESLog::TheLog()) << "BES: Trying limits soft to "
00105                                         << (long int)limit.rlim_cur ;
00106                     (*BESLog::TheLog()) << " and hard to "
00107                                         << (long int)limit.rlim_max
00108                                         << endl ;
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                 /* repetative
00157                 else
00158                 {
00159                     if( BESLog::TheLog()->is_verbose() )
00160                     {
00161                         (*BESLog::TheLog()) << "BES: Memory emergency area "
00162                                       << "initialized with size " 
00163                                       << _size << " megabytes" << endl;
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 

Generated on Tue Mar 4 23:13:35 2008 for OPeNDAP Back End Server (BES) by  doxygen 1.5.1