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 
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 

Generated on Thu Sep 16 15:20:30 2010 for OPeNDAP Hyrax Back End Server (BES) by  doxygen 1.4.7