bes  Updated for version 3.20.10
BESServiceRegistry.cc
1 // BESServiceRegistry.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 <mutex>
34 
35 #include "BESServiceRegistry.h"
36 #include "BESInfo.h"
37 #include "BESInternalError.h"
38 
39 using std::endl;
40 using std::ostream;
41 using std::string;
42 using std::map;
43 using std::list;
44 
45 BESServiceRegistry *BESServiceRegistry::d_instance = nullptr ;
46 static std::once_flag d_euc_init_once;
47 
48 BESServiceRegistry::BESServiceRegistry() {}
49 
50 BESServiceRegistry::~BESServiceRegistry() {}
51 
57 void
58 BESServiceRegistry::add_service( const string &name )
59 {
60  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
61 
62  map<string,map<string,service_cmd> >::iterator i = _services.find( name ) ;
63  if( i == _services.end() )
64  {
65  map<string,service_cmd> cmds ;
66  _services[name] = cmds ;
67  }
68  else
69  {
70  string err = (string)"The service " + name
71  + " has already been registered" ;
72  throw BESInternalError( err, __FILE__, __LINE__ ) ;
73  }
74 }
75 
90 void
91 BESServiceRegistry::add_to_service( const string &service,
92  const string &cmd,
93  const string &cmd_descript,
94  const string &format )
95 {
96  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
97 
98  map<string,map<string,service_cmd> >::iterator si ;
99  si = _services.find( service ) ;
100  if( si != _services.end() )
101  {
102  map<string,service_cmd>::const_iterator ci ;
103  ci = (*si).second.find( cmd ) ;
104  if( ci != (*si).second.end() )
105  {
106  string err = (string)"Attempting to add command "
107  + (*ci).first + " to the service "
108  + service + ", command alrady exists" ;
109  throw BESInternalError( err, __FILE__, __LINE__ ) ;
110  }
111  service_cmd sc ;
112  sc._description = cmd_descript ;
113  sc._formats[format] = format ;
114  (*si).second[cmd] = sc ;
115  }
116  else
117  {
118  string err = (string)"Attempting to add commands to the service "
119  + service + " that has not yet been registered" ;
120  throw BESInternalError( err, __FILE__, __LINE__ ) ;
121  }
122 }
123 
132 void
133 BESServiceRegistry::add_format( const string &service,
134  const string &cmd,
135  const string &format )
136 {
137  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
138 
139  map<string,map<string,service_cmd> >::iterator si ;
140  si = _services.find( service ) ;
141  if( si != _services.end() )
142  {
143  map<string,service_cmd>::iterator ci = (*si).second.find( cmd ) ;
144  if( ci != (*si).second.end() )
145  {
146  map<string,string>::iterator fi ;
147  fi = (*ci).second._formats.find( format ) ;
148  if( fi == (*ci).second._formats.end() )
149  {
150  (*ci).second._formats[format] = format ;
151  }
152  else
153  {
154  string err = (string)"Attempting to add format "
155  + format + " to command " + cmd
156  + " for service " + service
157  + " where the format has already been registered" ;
158  throw BESInternalError( err, __FILE__, __LINE__ ) ;
159  }
160  }
161  else
162  {
163  string err = (string)"Attempting to add a format " + format
164  + " to command " + cmd + " for service " + service
165  + " where the command has not been registered" ;
166  throw BESInternalError( err, __FILE__, __LINE__ ) ;
167  }
168  }
169  else
170  {
171  string err = (string)"Attempting to add a format " + format
172  + " to command " + cmd + " for a service " + service
173  + " that has not been registered" ;
174  throw BESInternalError( err, __FILE__, __LINE__ ) ;
175  }
176 }
177 
186 void
187 BESServiceRegistry::remove_service( const string &service )
188 {
189  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
190 
191  map<string,map<string,service_cmd> >::iterator i ;
192  i = _services.find( service ) ;
193  if( i != _services.end() )
194  {
195  // erase the service from the registry
196  _services.erase( i ) ;
197 
198  // remove the service from the _handles list as well, so that if
199  // asked, the handlers no longer handler the service because it no
200  // longer exists.
201  map<string,map<string,string> >::iterator hi = _handles.begin() ;
202  map<string,map<string,string> >::iterator he = _handles.end() ;
203  for( ; hi != he; hi++ )
204  {
205  map<string,string>::iterator hsi = (*hi).second.find( service ) ;
206  if( hsi != (*hi).second.end() )
207  {
208  (*hi).second.erase( hsi ) ;
209  }
210  }
211  }
212 }
213 
228 bool
230  const string &cmd,
231  const string &format )
232 {
233  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
234 
235  bool isit = false ;
236  map<string,map<string,service_cmd> >::iterator si ;
237  si = _services.find( service ) ;
238  if( si != _services.end() )
239  {
240  if( !cmd.empty() )
241  {
242  map<string,service_cmd>::iterator ci = (*si).second.find( cmd ) ;
243  if( ci != (*si).second.end() )
244  {
245  if( !format.empty() )
246  {
247  map<string,string>::iterator fi ;
248  fi = (*ci).second._formats.find( format ) ;
249  if( fi != (*ci).second._formats.end() )
250  {
251  isit = true ;
252  }
253  }
254  else
255  {
256  isit = true ;
257  }
258  }
259  }
260  else
261  {
262  isit = true ;
263  }
264  }
265  return isit ;
266 }
267 
279 void
280 BESServiceRegistry::handles_service( const string &handler,
281  const string &service )
282 {
283  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
284 
285  map<string,map<string,service_cmd> >::iterator si ;
286  si = _services.find( service ) ;
287  if( si == _services.end() )
288  {
289  string err = (string)"Registering a handler to handle service "
290  + service + " that has not yet been registered" ;
291  throw BESInternalError( err, __FILE__, __LINE__ ) ;
292  }
293 
294  map<string,map<string,string> >::iterator hi = _handles.find( handler ) ;
295  if( hi == _handles.end() )
296  {
297  map<string,string> services ;
298  services[service] = service ;
299  _handles[handler] = services ;
300  }
301  else
302  {
303  map<string,string>::iterator ci = (*hi).second.find( service ) ;
304  if( ci == (*hi).second.end() )
305  {
306  (*hi).second[service] = service ;
307  }
308  }
309 }
310 
319 bool
321  const string &service )
322 {
323  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
324 
325  bool handled = false ;
326  map<string,map<string,string> >::iterator hi = _handles.find( handler ) ;
327  if( hi != _handles.end() )
328  {
329  map<string,string>::iterator si = (*hi).second.find( service ) ;
330  if( si != (*hi).second.end() )
331  {
332  handled = true ;
333  }
334  }
335  return handled ;
336 }
337 
346 void
348  list<string> &services )
349 {
350  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
351 
352  map<string,map<string,string> >::iterator hi = _handles.find( handler ) ;
353  if( hi != _handles.end() )
354  {
355  map<string,string>::const_iterator si = (*hi).second.begin() ;
356  map<string,string>::const_iterator se = (*hi).second.end() ;
357  for( ; si != se; si++ )
358  {
359  services.push_back( (*si).second ) ;
360  }
361  }
362 }
363 
372 void
374 {
375  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
376 
377  map<string,map<string,service_cmd> >::iterator si = _services.begin() ;
378  map<string,map<string,service_cmd> >::iterator se = _services.end() ;
379  for( ; si != se; si++ )
380  {
381  map<string,string> props ;
382  props["name"] = (*si).first ;
383  info.begin_tag( "serviceDescription", &props ) ;
384  map<string,service_cmd>::iterator ci = (*si).second.begin() ;
385  map<string,service_cmd>::iterator ce = (*si).second.end() ;
386  for( ; ci != ce; ci++ )
387  {
388  map<string,string> cprops ;
389  cprops["name"] = (*ci).first ;
390  info.begin_tag( "command", &cprops ) ;
391  info.add_tag( "description", (*ci).second._description ) ;
392  map<string,string>::iterator fi = (*ci).second._formats.begin() ;
393  map<string,string>::iterator fe = (*ci).second._formats.end() ;
394  for( ; fi != fe; fi++ )
395  {
396  map<string,string> fprops ;
397  fprops["name"] = (*fi).first ;
398  info.add_tag( "format", "", &fprops ) ;
399  }
400  info.end_tag( "command" ) ;
401  }
402  info.end_tag( "serviceDescription" ) ;
403  }
404 }
405 
413 void
414 BESServiceRegistry::dump( ostream &strm ) const
415 {
416  std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
417 
418  strm << BESIndent::LMarg << "BESServiceRegistry::dump - ("
419  << (void *)this << ")" << endl ;
420  BESIndent::Indent() ;
421  strm << BESIndent::LMarg << "registered services" << endl ;
422  BESIndent::Indent() ;
423  map<string,map<string,service_cmd> >::const_iterator si ;
424  si = _services.begin() ;
425  map<string,map<string,service_cmd> >::const_iterator se ;
426  se = _services.end() ;
427  for( ; si != se; si++ )
428  {
429  strm << BESIndent::LMarg << (*si).first << endl ;
430  BESIndent::Indent() ;
431  map<string,service_cmd>::const_iterator ci = (*si).second.begin() ;
432  map<string,service_cmd>::const_iterator ce = (*si).second.end() ;
433  for( ; ci != ce; ci++ )
434  {
435  strm << BESIndent::LMarg << (*ci).first << endl ;
436  BESIndent::Indent() ;
437  strm << BESIndent::LMarg << "description: "
438  << (*ci).second._description << endl ;
439  strm << BESIndent::LMarg << "formats:" << endl ;
440  BESIndent::Indent() ;
441  map<string,string>::const_iterator fi ;
442  fi = (*ci).second._formats.begin() ;
443  map<string,string>::const_iterator fe ;
444  fe = (*ci).second._formats.end() ;
445  for( ; fi != fe; fi++ )
446  {
447  strm << BESIndent::LMarg << (*fi).first << endl ;
448  }
449  BESIndent::UnIndent() ;
450  BESIndent::UnIndent() ;
451  }
452  BESIndent::UnIndent() ;
453  }
454  BESIndent::UnIndent() ;
455  strm << BESIndent::LMarg << "services provided by handler" << endl ;
456  BESIndent::Indent() ;
457  map<string,map<string,string> >::const_iterator hi = _handles.begin() ;
458  map<string,map<string,string> >::const_iterator he = _handles.end() ;
459  for( ; hi != he; hi++ )
460  {
461  strm << BESIndent::LMarg << (*hi).first ;
462  map<string,string>::const_iterator hsi = (*hi).second.begin() ;
463  map<string,string>::const_iterator hse = (*hi).second.end() ;
464  bool isfirst = true ;
465  for( ; hsi != hse; hsi++ )
466  {
467  if( !isfirst ) strm << ", " ;
468  else strm << ": " ;
469  strm << (*hsi).first ;
470  isfirst = false ;
471  }
472  strm << endl ;
473  }
474  BESIndent::UnIndent() ;
475  BESIndent::UnIndent() ;
476 }
477 
479 BESServiceRegistry::TheRegistry()
480 {
481  std::call_once(d_euc_init_once,BESServiceRegistry::initialize_instance);
482  return d_instance;
483 }
484 
485 void BESServiceRegistry::initialize_instance() {
486  d_instance = new BESServiceRegistry;
487 #ifdef HAVE_ATEXIT
488  atexit(delete_instance);
489 #endif
490 }
491 
492 void BESServiceRegistry::delete_instance() {
493  delete d_instance;
494  d_instance = 0;
495 }
496 
informational response object
Definition: BESInfo.h:63
exception thrown if internal error encountered
The service registry allows modules to register services with the BES that they provide.
virtual bool does_handle_service(const std::string &handler, const std::string &service)
Asks if the specified handler can handle the specified service.
virtual void services_handled(const std::string &handler, std::list< std::string > &services)
returns the list of servies provided by the handler in question
virtual bool service_available(const std::string &name, const std::string &cmd="", const std::string &format="")
Determines if a service and, optionally, a command and a return format, is available.
virtual void add_service(const std::string &name)
Add a service to the BES.
virtual void add_to_service(const std::string &service, const std::string &cmd, const std::string &cmd_descript, const std::string &format)
This function allows callers to add to a service that already exists.
virtual void show_services(BESInfo &info)
fills in the response object for the <showService /> request
virtual void handles_service(const std::string &handler, const std::string &service)
The specified handler can handle the specified service.
virtual void add_format(const std::string &service, const std::string &cmd, const std::string &format)
add a format response to a command of a service
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void remove_service(const std::string &name)
remove a service from the BES