bes  Updated for version 3.20.13
BESRequestHandlerList.cc
1 // BESRequestHandlerList.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 "config.h"
34 #include <mutex>
35 
36 #include "BESLog.h"
37 #include "BESRequestHandlerList.h"
38 #include "BESRequestHandler.h"
39 #include "BESInternalError.h"
40 
41 using std::endl;
42 using std::ostream;
43 using std::string;
44 
45 BESRequestHandlerList *BESRequestHandlerList::d_instance = nullptr;
46 static std::once_flag d_euc_init_once;
47 
48 BESRequestHandlerList::BESRequestHandlerList() {}
49 
50 BESRequestHandlerList::~BESRequestHandlerList() {}
51 
61 bool BESRequestHandlerList::add_handler(const string &handler_name, BESRequestHandler *handler_object)
62 {
63  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
64 
65  if (find_handler(handler_name) == 0) {
66  _handler_list[handler_name] = handler_object;
67  return true;
68  }
69  return false;
70 }
71 
85 BESRequestHandlerList::remove_handler(const string &handler_name)
86 {
87  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
88 
89  BESRequestHandler *ret = 0;
90  BESRequestHandlerList::Handler_iter i;
91  i = _handler_list.find(handler_name);
92  if (i != _handler_list.end()) {
93  ret = (*i).second;
94  _handler_list.erase(i);
95  }
96  return ret;
97 }
98 
106 BESRequestHandlerList::find_handler(const string &handler_name)
107 {
108  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
109 
110  BESRequestHandlerList::Handler_citer i;
111  i = _handler_list.find(handler_name);
112  if (i != _handler_list.end()) {
113  return (*i).second;
114  }
115  return 0;
116 }
117 
125 BESRequestHandlerList::Handler_citer BESRequestHandlerList::get_first_handler()
126 {
127  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
128 
129  return _handler_list.begin();
130 }
131 
137 BESRequestHandlerList::Handler_citer BESRequestHandlerList::get_last_handler()
138 {
139  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
140 
141  return _handler_list.end();
142 }
143 
152 {
153  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
154 
155  string ret = "";
156  bool first_name = true;
157  BESRequestHandlerList::Handler_citer i = _handler_list.begin();
158  for (; i != _handler_list.end(); i++) {
159  if (!first_name) ret += ", ";
160  ret += (*i).first;
161  first_name = false;
162  }
163  return ret;
164 }
165 
187 {
188  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
189 
190  dhi.first_container();
191  while (dhi.container) {
192  execute_current(dhi);
193  dhi.next_container();
194  }
195 }
196 
216 {
217  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
218 
219  BESRequestHandlerList::Handler_citer i = get_first_handler();
220  BESRequestHandlerList::Handler_citer ie = get_last_handler();
221  for (; i != ie; i++) {
222  BESRequestHandler *rh = (*i).second;
223  p_request_handler_method p = rh->find_method(dhi.action);
224  if (p) {
225  p(dhi);
226  }
227  }
228 }
229 
230 #if 0
251 void BESRequestHandlerList::execute_once(BESDataHandlerInterface &dhi)
252 {
253  dhi.first_container();
254  execute_current(dhi);
255 }
256 #endif
257 
278 {
279  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
280 
281  if (dhi.container) {
282  // Patrick's comment: This needs to happen here, but really should be done
283  // in the get_container_type method in the container class if it
284  // needs to happen.
285  //
286  // This call will, for BESFileContainer, decompress and cache compressed files,
287  // changing their extensions from, e.g., '.gz' to '.h5' and enabling the
288  // get_container_type() method to function correctly. jhrg 5/31/18
289  dhi.container->access();
290 
291  // Given the kind of thing in the DHI's container (netcdf file, ...) find the
292  // RequestHandler that understands that and then find the method in that handler
293  // that can process the DHI's action.
295  if (!rh)
296  throw BESInternalError(string("The data handler '") + dhi.container->get_container_type() + "' does not exist",
297  __FILE__, __LINE__);
298 
299  p_request_handler_method request_handler_method = rh->find_method(dhi.action);
300  if (!request_handler_method) {
301  throw BESInternalError(string("Request handler for '") + dhi.container->get_container_type()
302  + "' does not handle the response type '" + dhi.action + "'", __FILE__, __LINE__);
303  }
304 
305  VERBOSE("Found handler '" << rh->get_name() << "' for item '" << dhi.container->get_symbolic_name() << "'." << endl);
306 
307  request_handler_method(dhi); // This is where the request handler method is called
308  }
309 }
310 
318 void BESRequestHandlerList::dump(ostream &strm) const
319 {
320  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
321 
322  strm << BESIndent::LMarg << "BESRequestHandlerList::dump - (" << (void *) this << ")" << endl;
323  BESIndent::Indent();
324  if (_handler_list.size()) {
325  strm << BESIndent::LMarg << "registered handlers:" << endl;
326  BESIndent::Indent();
327  BESRequestHandlerList::Handler_citer i = _handler_list.begin();
328  BESRequestHandlerList::Handler_citer ie = _handler_list.end();
329  for (; i != ie; i++) {
330  BESRequestHandler *rh = (*i).second;
331  rh->dump(strm);
332  }
333  BESIndent::UnIndent();
334  }
335  else {
336  strm << BESIndent::LMarg << "registered handlers: none" << endl;
337  }
338  BESIndent::UnIndent();
339 }
340 
342 BESRequestHandlerList::TheList()
343 {
344  std::call_once(d_euc_init_once,BESRequestHandlerList::initialize_instance);
345  return d_instance;
346 }
347 
348 void BESRequestHandlerList::initialize_instance() {
349  d_instance = new BESRequestHandlerList;
350 #ifdef HAVE_ATEXIT
351  atexit(delete_instance);
352 #endif
353 }
354 
355 void BESRequestHandlerList::delete_instance() {
356  delete d_instance;
357  d_instance = 0;
358 }
359 
360 
361 
std::string get_symbolic_name() const
retrieve the symbolic name for this container
Definition: BESContainer.h:221
virtual std::string access()=0
returns the true name of this container
std::string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Definition: BESContainer.h:232
Structure storing information used by the BES to handle the request.
std::string action
the response object requested, e.g. das, dds
void first_container()
set the container pointer to the first container in the containers list
BESContainer * container
pointer to current container in this interface
void next_container()
set the container pointer to the next * container in the list, null if at the end or no containers in...
exception thrown if internal error encountered
The list of registered request handlers for this server; a singleton.
virtual void execute_all(BESDataHandlerInterface &dhi)
for all of the registered request handlers, execute the given request
virtual std::string get_handler_names()
Returns a comma separated string of request handlers registered with the server.
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual bool add_handler(const std::string &handler_name, BESRequestHandler *handler)
add a request handler to the list of registered handlers for this server
virtual BESRequestHandler * remove_handler(const std::string &handler_name)
remove and return the specified request handler
virtual Handler_citer get_last_handler()
return a constant iterator pointing to the end of the list
virtual void execute_current(BESDataHandlerInterface &dhi)
Execute a single method for the current container that will fill in the response object rather than i...
virtual void execute_each(BESDataHandlerInterface &dhi)
for each container in the given data handler interface, execute the given request
virtual Handler_citer get_first_handler()
return an iterator pointing to the first request handler in the list
virtual BESRequestHandler * find_handler(const std::string &handler_name)
find and return the specified request handler
Represents a specific data type request handler.
virtual p_request_handler_method find_method(const std::string &name)
find the method that can handle the specified response object type
virtual void dump(std::ostream &strm) const
dumps information about this object