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 Atmostpheric 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 <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                     /* repetative
00102                     (*BESLog::TheLog()) << "BES: Trying limits soft to "
00103                                         << (long int)limit.rlim_cur ;
00104                     (*BESLog::TheLog()) << " and hard to "
00105                                         << (long int)limit.rlim_max
00106                                         << endl ;
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                 /* repetative
00155                 else
00156                 {
00157                     if( BESLog::TheLog()->is_verbose() )
00158                     {
00159                         (*BESLog::TheLog()) << "BES: Memory emergency area "
00160                                       << "initialized with size " 
00161                                       << _size << " megabytes" << endl;
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 

Generated on Wed Aug 29 03:14:16 2007 for OPeNDAP Back End Server (BES) by  doxygen 1.5.2