OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BESMemoryGlobalArea.cc
Go to the documentation of this file.
1 // BESMemoryGlobalArea.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <iostream>
34 #include <cstdlib>
35 #include <cstring>
36 #include <cerrno>
37 
38 using std::cerr ;
39 using std::endl ;
40 
41 #include "BESMemoryGlobalArea.h"
42 #include "BESInternalFatalError.h"
43 #include "BESDebug.h"
44 #include "BESLog.h"
45 #include "TheBESKeys.h"
46 
47 int BESMemoryGlobalArea::_counter = 0 ;
48 unsigned long BESMemoryGlobalArea::_size = 0 ;
49 void* BESMemoryGlobalArea::_buffer = 0 ;
50 
52 {
53  if( _counter++ == 0 )
54  {
55  try
56  {
57  bool fnd = false ;
58  string key = "BES.Memory.GlobalArea." ;
59 
60  string eps ;
61  TheBESKeys::TheKeys()->get_value( key + "EmergencyPoolSize",
62  eps, fnd ) ;
63 
64  string mhs ;
65  TheBESKeys::TheKeys()->get_value( key + "MaximumHeapSize",
66  mhs, fnd ) ;
67 
68  string verbose ;
69  TheBESKeys::TheKeys()->get_value( key + "Verbose",
70  verbose, fnd ) ;
71 
72  string control_heap ;
73  TheBESKeys::TheKeys()->get_value( key + "ControlHeap",
74  control_heap, fnd ) ;
75 
76  if( (eps=="") || (mhs=="") || (verbose=="") || (control_heap=="") )
77  {
78  string line = "cannot determine memory keys." ;
79  line += (string)"Please set values for"
80  + " BES.Memory.GlobalArea.EmergencyPoolSize,"
81  + " BES.Memory.GlobalArea.MaxiumumHeapSize,"
82  + " BES.Memory.GlobalArea.Verbose, and"
83  + " BES.Memory.GlobalArea.ControlHeap"
84  + " in the BES configuration file." ;
85  throw BESInternalFatalError( line, __FILE__, __LINE__ ) ;
86  }
87  else
88  {
89  if( verbose=="no" )
91 
92  unsigned int emergency=atol(eps.c_str());
93 
94  if( control_heap == "yes" )
95  {
96  unsigned int max = atol(mhs.c_str());
97  BESDEBUG( "bes", "Initializing emergency heap to "
98  << (long int)emergency << " MB" << endl ) ;
99  BESDEBUG( "bes", "Initializing max heap size to "
100  << (long int)(max+1) << " MB" << endl ) ;
101  (*BESLog::TheLog()) << "Initialize emergency heap size to "
102  << (long int)emergency
103  << " and heap size to " ;
104  (*BESLog::TheLog()) << (long int)(max+1)
105  << " megabytes" << endl ;
106  if( emergency > max )
107  {
108  string s = string ( "BES: " )
109  + "unable to start since the emergency "
110  + "pool is larger than the maximum size of "
111  + "the heap.\n" ;
112  (*BESLog::TheLog()) << s ;
113  throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
114  }
115  log_limits( "before setting limits: " ) ;
116  limit.rlim_cur = megabytes( max + 1 ) ;
117  limit.rlim_max = megabytes( max + 1 ) ;
118  /* repetative
119  (*BESLog::TheLog()) << "BES: Trying limits soft to "
120  << (long int)limit.rlim_cur ;
121  (*BESLog::TheLog()) << " and hard to "
122  << (long int)limit.rlim_max
123  << endl ;
124  */
125  if( setrlimit( RLIMIT_DATA, &limit ) < 0 )
126  {
127  string s = string( "BES: " )
128  + "Could not set limit for the heap "
129  + "because " + strerror(errno) + "\n" ;
130  if( errno == EPERM )
131  {
132  s = s + "Attempting to increase the soft/hard "
133  + "limit above the current hard limit, "
134  + "must be superuser\n" ;
135  }
136  (*BESLog::TheLog()) << s ;
137  throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
138  }
139  log_limits( "after setting limits: " ) ;
140  _buffer = 0 ;
141  _buffer = malloc( megabytes( max ) ) ;
142  if( !_buffer )
143  {
144  string s = string( "BES: " )
145  + "cannot get heap of size "
146  + mhs + " to start running" ;
147  (*BESLog::TheLog()) << s ;
148  throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
149  }
150  free( _buffer ) ;
151  }
152  else
153  {
154  if( emergency > 10 )
155  {
156  string s = "Emergency pool is larger than 10 Megabytes";
157  throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
158  }
159  }
160 
161  _size = megabytes( emergency ) ;
162  _buffer = 0 ;
163  _buffer = malloc( _size ) ;
164  if( !_buffer )
165  {
166  string s = (string)"BES: cannot expand heap to "
167  + eps + " to start running" ;
168  (*BESLog::TheLog()) << s << endl ;
169  throw BESInternalFatalError( s, __FILE__, __LINE__ ) ;
170  }
171  /* repetative
172  else
173  {
174  if( BESLog::TheLog()->is_verbose() )
175  {
176  (*BESLog::TheLog()) << "BES: Memory emergency area "
177  << "initialized with size "
178  << _size << " megabytes" << endl;
179  }
180  }
181  */
182  }
183  }
184  catch( BESError &ex )
185  {
186  cerr << "BES: unable to start properly because "
187  << ex.get_message()
188  << endl ;
189  exit(1) ;
190  }
191  catch(...)
192  {
193  cerr << "BES: unable to start: undefined exception happened\n" ;
194  exit(1) ;
195  }
196  }
197  BESLog::TheLog()->resume();
198 }
199 
201 {
202  if (--_counter == 0)
203  {
204  if (_buffer)
205  free( _buffer ) ;
206  _buffer = 0 ;
207  }
208 }
209 
210 inline void
211 BESMemoryGlobalArea::log_limits( const string &msg )
212 {
213  if( getrlimit( RLIMIT_DATA, &limit ) < 0 )
214  {
215  (*BESLog::TheLog()) << msg << "Could not get limits because "
216  << strerror( errno ) << endl ;
217  _counter-- ;
218  throw BESInternalFatalError( strerror( errno ), __FILE__, __LINE__ ) ;
219  }
220  if( limit.rlim_cur == RLIM_INFINITY )
221  (*BESLog::TheLog()) << msg << "heap size soft limit is infinte"
222  << endl ;
223  else
224  (*BESLog::TheLog()) << msg << "heap size soft limit is "
225  << (long int)limit.rlim_cur
226  << " bytes ("
227  << (long int)(limit.rlim_cur)/(MEGABYTE)
228  << " MB - may be rounded up)" << endl ;
229  if( limit.rlim_max == RLIM_INFINITY )
230  (*BESLog::TheLog()) << msg << "heap size hard limit is infinite"
231  << endl ;
232  else
233  (*BESLog::TheLog()) << msg << "heap size hard limit is "
234  << (long int)limit.rlim_max
235  << " bytes ("
236  << (long int)(limit.rlim_cur)/(MEGABYTE)
237  << " MB - may be rounded up)" << endl ;
238 }
239 
240 void
242 {
243  if( _buffer )
244  {
245  free( _buffer ) ;
246  _buffer = 0 ;
247  }
248 }
249 
250 bool
252 {
253  if( !_buffer )
254  _buffer = malloc( _size ) ;
255  if( _buffer )
256  return true ;
257  else
258  return false ;
259 }
260 
268 void
269 BESMemoryGlobalArea::dump( ostream &strm ) const
270 {
271  strm << BESIndent::LMarg << "BESMemoryGlobalArea::dump - ("
272  << (void *)this << ")" << endl ;
274  strm << BESIndent::LMarg << "area set? " << _counter << endl ;
275  strm << BESIndent::LMarg << "emergency buffer: "
276  << (void *)_buffer << endl ;
277  strm << BESIndent::LMarg << "buffer size: " << _size << endl ;
278  strm << BESIndent::LMarg << "rlimit current: " << limit.rlim_cur << endl ;
279  strm << BESIndent::LMarg << "rlimit max: " << limit.rlim_max << endl ;
281 }
282 
exception thrown if an internal error is found and is fatal to the BES
void resume()
Resumes logging after being suspended.
Definition: BESLog.h:121
static void Indent()
Definition: BESIndent.cc:38
virtual string get_message()
get the error message for this exception
Definition: BESError.h:91
virtual void dump(ostream &strm) const
dumps information about this object
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
void suspend()
Suspend logging of any information until resumed.
Definition: BESLog.h:111
#define MEGABYTE
static ostream & LMarg(ostream &strm)
Definition: BESIndent.cc:73
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:453
static BESLog * TheLog()
Definition: BESLog.cc:347
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
static void UnIndent()
Definition: BESIndent.cc:44
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:48