bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
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
39using std::endl;
40using std::ostream;
41using std::string;
42using std::map;
43using std::list;
44
45BESServiceRegistry *BESServiceRegistry::d_instance = nullptr ;
46static std::once_flag d_euc_init_once;
47
48BESServiceRegistry::BESServiceRegistry() {}
49
50BESServiceRegistry::~BESServiceRegistry() {}
51
57void
58BESServiceRegistry::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
90void
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 {
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
132void
133BESServiceRegistry::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 {
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
186void
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
228bool
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 {
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
279void
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
319bool
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
346void
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
372void
374{
375 std::lock_guard<std::recursive_mutex> lock_me(d_cache_lock_mutex);
376
377 auto si = _services.begin() ;
378 auto se = _services.end() ;
379 for( ; si != se; si++ )
380 {
381 map<string, string, std::less<>> props ;
382 props["name"] = (*si).first ;
383 info.begin_tag( "serviceDescription", &props ) ;
384 auto ci = (*si).second.begin() ;
385 auto ce = (*si).second.end() ;
386 for( ; ci != ce; ci++ )
387 {
388 map<string, string, std::less<>> cprops ;
389 cprops["name"] = (*ci).first ;
390 info.begin_tag( "command", &cprops ) ;
391 info.add_tag( "description", (*ci).second._description ) ;
392 auto fi = (*ci).second._formats.begin() ;
393 auto fe = (*ci).second._formats.end() ;
394 for( ; fi != fe; fi++ )
395 {
396 map<string, string, std::less<>> 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
413void
414BESServiceRegistry::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() ;
442 fi = (*ci).second._formats.begin() ;
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
479BESServiceRegistry::TheRegistry()
480{
481 std::call_once(d_euc_init_once,BESServiceRegistry::initialize_instance);
482 return d_instance;
483}
484
485void BESServiceRegistry::initialize_instance() {
486 d_instance = new BESServiceRegistry;
487#ifdef HAVE_ATEXIT
488 atexit(delete_instance);
489#endif
490}
491
492void 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
STL iterator class.
STL iterator class.