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-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             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 = "cannot determine memory keys."  ;
00070                 line += (string)"Please set values for"
00071                      + " BES.Memory.GlobalArea.EmergencyPoolSize,"
00072                      + " BES.Memory.GlobalArea.MaxiumumHeapSize,"
00073                      + " BES.Memory.GlobalArea.Verbose, and"
00074                      + " BES.Memory.GlobalArea.ControlHeap" ;
00075                 throw BESInternalFatalError( line, __FILE__, __LINE__ ) ;
00076             }
00077             else
00078             {
00079                 if( verbose=="no" )
00080                     BESLog::TheLog()->suspend();
00081 
00082                 unsigned int emergency=atol(eps.c_str());
00083 
00084                 if( control_heap == "yes" )
00085                 {
00086                     unsigned int max = atol(mhs.c_str());
00087                     BESDEBUG( "bes", "Initializing emergency heap to "
00088                               << (long int)emergency << " MB" << endl )
00089                     BESDEBUG( "bes", "Initializing max heap size to "
00090                               << (long int)(max+1) << " MB" << endl )
00091                     (*BESLog::TheLog()) << "Initialize emergency heap size to "
00092                                         << (long int)emergency
00093                                         << " and heap size to ";
00094                     (*BESLog::TheLog()) << (long int)(max+1)
00095                                         << " megabytes" << endl ;
00096                     if( emergency > max )
00097                     {
00098                         string s = string ( "BES: " )
00099                                    + "unable to start since the emergency "
00100                                    + "pool is larger than the maximum size of "
00101                                    + "the heap.\n" ;
00102                         (*BESLog::TheLog()) << s ;
00103                         throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00104                     }
00105                     log_limits( "before setting limits: " ) ;
00106                     limit.rlim_cur = megabytes( max + 1 ) ;
00107                     limit.rlim_max = megabytes( max + 1 ) ;
00108                     /* repetative
00109                     (*BESLog::TheLog()) << "BES: Trying limits soft to "
00110                                         << (long int)limit.rlim_cur ;
00111                     (*BESLog::TheLog()) << " and hard to "
00112                                         << (long int)limit.rlim_max
00113                                         << endl ;
00114                     */
00115                     if( setrlimit( RLIMIT_DATA, &limit ) < 0 )
00116                     {
00117                         string s = string( "BES: " )
00118                                    + "Could not set limit for the heap "
00119                                    + "because " + strerror(errno) + "\n" ;
00120                         if( errno == EPERM )
00121                         {
00122                             s = s + "Attempting to increase the soft/hard "
00123                                   + "limit above the current hard limit, "
00124                                   + "must be superuser\n" ;
00125                         }
00126                         (*BESLog::TheLog()) << s ;
00127                         throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00128                     }
00129                     log_limits( "after setting limits: " ) ;
00130                     _buffer = 0 ;
00131                     _buffer = malloc( megabytes( max ) ) ;
00132                     if( !_buffer )
00133                     {
00134                         string s = string( "BES: " ) 
00135                                    + "cannot get heap of size "
00136                                    + mhs + " to start running" ;
00137                         (*BESLog::TheLog()) << s ;
00138                         throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00139                     }
00140                     free( _buffer ) ;
00141                 }
00142                 else
00143                 {
00144                     if( emergency > 10 )
00145                     {
00146                         string s = "Emergency pool is larger than 10 Megabytes";
00147                         throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00148                     }
00149                 }
00150 
00151                 _size = megabytes( emergency ) ;
00152                 _buffer = 0 ;
00153                 _buffer = malloc( _size ) ;
00154                 if( !_buffer )
00155                 {
00156                     string s = (string)"BES: cannot expand heap to "
00157                                + eps + " to start running" ;
00158                     (*BESLog::TheLog()) << s << endl ;
00159                     throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
00160                 }
00161                 /* repetative
00162                 else
00163                 {
00164                     if( BESLog::TheLog()->is_verbose() )
00165                     {
00166                         (*BESLog::TheLog()) << "BES: Memory emergency area "
00167                                       << "initialized with size " 
00168                                       << _size << " megabytes" << endl;
00169                     }
00170                 }
00171                 */
00172             }
00173         }
00174         catch( BESError &ex )
00175         {
00176             cerr << "BES: unable to start properly because "
00177                  << ex.get_message()
00178                  << endl ;
00179             exit(1) ;
00180         }
00181         catch(...)
00182         {
00183             cerr << "BES: unable to start: undefined exception happened\n" ;
00184             exit(1) ;
00185         }
00186     }
00187     BESLog::TheLog()->resume();
00188 }
00189 
00190 BESMemoryGlobalArea::~BESMemoryGlobalArea()
00191 {
00192     if (--_counter == 0)
00193     {
00194         if (_buffer)
00195             free( _buffer ) ;
00196         _buffer = 0 ;
00197     }
00198 }
00199 
00200 inline void
00201 BESMemoryGlobalArea::log_limits( const string &msg )
00202 {
00203     if( getrlimit( RLIMIT_DATA, &limit ) < 0 )
00204     {
00205         (*BESLog::TheLog()) << msg << "Could not get limits because "
00206                             << strerror( errno ) << endl ;
00207         _counter-- ;
00208         throw BESInternalFatalError( strerror( errno ), __FILE__, __LINE__ ) ;
00209     }
00210     if( limit.rlim_cur == RLIM_INFINITY )
00211         (*BESLog::TheLog()) << msg << "heap size soft limit is infinte"
00212                             << endl ;
00213     else
00214         (*BESLog::TheLog()) << msg << "heap size soft limit is "
00215                       << (long int)limit.rlim_cur 
00216                       << " bytes ("
00217                       << (long int)(limit.rlim_cur)/(MEGABYTE)
00218                       << " MB - may be rounded up)" << endl ;
00219     if( limit.rlim_max == RLIM_INFINITY )
00220         (*BESLog::TheLog()) << msg << "heap size hard limit is infinite"
00221                             << endl ;
00222     else
00223         (*BESLog::TheLog()) << msg << "heap size hard limit is "
00224                             << (long int)limit.rlim_max 
00225                             << " bytes ("
00226                             << (long int)(limit.rlim_cur)/(MEGABYTE)
00227                             << " MB - may be rounded up)" << endl ;
00228 }
00229 
00230 void
00231 BESMemoryGlobalArea::release_memory()
00232 {
00233     if( _buffer )
00234     {
00235         free( _buffer ) ;
00236         _buffer = 0 ;
00237     }
00238 }
00239 
00240 bool
00241 BESMemoryGlobalArea::reclaim_memory()
00242 {
00243     if( !_buffer )
00244         _buffer = malloc( _size ) ;
00245     if( _buffer )
00246         return true ;
00247     else
00248         return false ;
00249 }
00250 
00258 void
00259 BESMemoryGlobalArea::dump( ostream &strm ) const
00260 {
00261     strm << BESIndent::LMarg << "BESMemoryGlobalArea::dump - ("
00262                              << (void *)this << ")" << endl ;
00263     BESIndent::Indent() ;
00264     strm << BESIndent::LMarg << "area set? " << _counter << endl ;
00265     strm << BESIndent::LMarg << "emergency buffer: "
00266                              << (void *)_buffer << endl ;
00267     strm << BESIndent::LMarg << "buffer size: " << _size << endl ;
00268     strm << BESIndent::LMarg << "rlimit current: " << limit.rlim_cur << endl ;
00269     strm << BESIndent::LMarg << "rlimit max: " << limit.rlim_max << endl ;
00270     BESIndent::UnIndent() ;
00271 }
00272 

Generated on 27 Oct 2009 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.6.1