1 //%2006////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //==============================================================================
32 //%/////////////////////////////////////////////////////////////////////////////
34 #include "ModuleController.h"
35 #include <Pegasus/Common/MessageLoader.h>
36 #include <Pegasus/Common/InternalException.h>
38 PEGASUS_NAMESPACE_BEGIN
42 RegisteredModuleHandle::RegisteredModuleHandle(
45 Message* (*receive_message)(Message *, void *),
46 void (*async_callback)(Uint32, Message *, void *))
48 _module_address(module_address),
49 _module_receive_message(receive_message),
50 _async_callback(async_callback)
52 PEGASUS_ASSERT(_module_receive_message != 0);
55 RegisteredModuleHandle::~RegisteredModuleHandle()
59 const String & RegisteredModuleHandle::get_name() const
64 Message* RegisteredModuleHandle::_receive_message(Message* msg)
66 return _module_receive_message(msg, _module_address);
69 void RegisteredModuleHandle::_send_async_callback(
74 // ATTN: Assert this condition?
75 if (_async_callback == 0)
77 throw NotImplemented("Module Async Receive");
80 _async_callback(msg_handle, msg, parm);
84 ModuleController::ModuleController(const char* name)
85 : Base(name, MessageQueue::getNextQueueId(),
86 module_capabilities::module_controller |
87 module_capabilities::async),
92 ModuleController::~ModuleController()
94 RegisteredModuleHandle* module;
98 module = _modules.remove_front();
102 module = _modules.remove_front();
110 // called by a module to register itself, returns a handle to the controller
111 ModuleController& ModuleController::register_module(
112 const String& controller_name,
113 const String& module_name,
114 void* module_address,
115 Message* (*receive_message)(Message *, void *),
116 void (*async_callback)(Uint32, Message *, void *),
117 RegisteredModuleHandle** instance)
119 RegisteredModuleHandle *module;
120 ModuleController *controller;
122 Array<Uint32> services;
124 MessageQueue *message_queue =
125 MessageQueue::lookup(controller_name.getCString());
127 if ((message_queue == NULL) || (!message_queue->isAsync()))
129 throw IncompatibleTypesException();
132 MessageQueueService *service =
133 static_cast<MessageQueueService *>(message_queue);
134 if ((service == NULL) ||
135 !(service->get_capabilities() & module_capabilities::module_controller))
137 throw IncompatibleTypesException();
140 controller = static_cast<ModuleController *>(service);
144 // see if the module already exists in this controller.
145 _module_lock lock(&(controller->_modules));
147 module = controller->_modules.front();
148 while (module != NULL)
150 if (module->get_name() == module_name)
152 MessageLoaderParms parms(
153 "Common.ModuleController.MODULE",
156 throw AlreadyExistsException(parms);
158 module = controller->_modules.next_of(module);
162 // now reserve this module name with the meta dispatcher
165 AutoPtr<RegisteredModule> request(new RegisteredModule(
168 controller->getQueueId(),
171 request->dest = CIMOM_Q_ID;
173 AutoPtr<AsyncReply> response(controller->SendWait(request.get()));
174 if (response.get() != NULL)
175 result = response->result;
179 if (result == async_results::MODULE_ALREADY_REGISTERED)
181 MessageLoaderParms parms(
182 "Common.ModuleController.MODULE",
183 "module \"$0\"", module_name);
184 throw AlreadyExistsException(parms);
187 // the module does not exist, go ahead and create it.
188 module = new RegisteredModuleHandle(
194 controller->_modules.insert_back(module);
196 if (instance != NULL)
203 Boolean ModuleController::deregister_module(const String& module_name)
205 AutoPtr<DeRegisteredModule> request(new DeRegisteredModule(
210 request->dest = _meta_dispatcher->getQueueId();
212 AutoPtr<AsyncReply> response(SendWait(request.get()));
217 RegisteredModuleHandle* module;
219 _module_lock lock(&_modules);
220 module = _modules.front();
221 while (module != NULL)
223 if (module->get_name() == module_name)
225 _modules.remove(module);
228 module = _modules.next_of(module);
233 Boolean ModuleController::verify_handle(RegisteredModuleHandle* handle)
235 RegisteredModuleHandle *module;
237 if (handle->_module_address == (void *)this)
240 _module_lock lock(&_modules);
242 module = _modules.front();
243 while (module != NULL)
245 if ( module == handle)
249 module = _modules.next_of(module);
254 // given a name, find a service's queue id
255 Uint32 ModuleController::find_service(
256 const RegisteredModuleHandle& handle,
259 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
260 throw Permission(Threads::self());
261 Array<Uint32> services;
262 Base::find_services(name, 0, 0, &services);
267 // returns the queue ID of the service hosting the named module,
270 Uint32 ModuleController::find_module_in_service(
271 const RegisteredModuleHandle& handle,
274 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
275 throw(Permission(Threads::self()));
279 AutoPtr<FindModuleInService> request(new FindModuleInService(
282 _meta_dispatcher->getQueueId(),
284 request->dest = _meta_dispatcher->getQueueId();
285 AutoPtr<FindModuleInServiceResponse> response(
286 static_cast<FindModuleInServiceResponse *>(SendWait(request.get())));
287 if (response.get() != NULL)
288 result = response->_module_service_queue;
294 AsyncReply* ModuleController::_send_wait(
295 Uint32 destination_q,
296 AsyncRequest* request)
298 request->dest = destination_q;
299 AsyncReply* reply = Base::SendWait(request);
304 // sendwait to another service
305 AsyncReply* ModuleController::ModuleSendWait(
306 const RegisteredModuleHandle& handle,
307 Uint32 destination_q,
308 AsyncRequest* request)
310 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
311 throw(Permission(Threads::self()));
313 return _send_wait(destination_q, request);
316 AsyncReply* ModuleController::_send_wait(
317 Uint32 destination_q,
318 const String& destination_module,
319 AsyncRequest* message)
321 AutoPtr<AsyncModuleOperationStart> request(new AsyncModuleOperationStart(
329 request->dest = destination_q;
330 AutoPtr<AsyncModuleOperationResult> response(
331 static_cast<AsyncModuleOperationResult *>(SendWait(request.get())));
335 if (response.get() != NULL &&
336 response->getType() == async_messages::ASYNC_MODULE_OP_RESULT)
338 // clear the request out of the envelope so it can be deleted by the
340 ret = static_cast<AsyncReply *>(response->get_result());
342 request->get_action();
347 // sendwait to another module controlled by another service.
348 // throws Deadlock() if destination_q is this->queue_id
349 AsyncReply* ModuleController::ModuleSendWait(
350 const RegisteredModuleHandle& handle,
351 Uint32 destination_q,
352 const String& destination_module,
353 AsyncRequest* message)
355 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
356 throw(Permission(Threads::self()));
358 return _send_wait(destination_q, destination_module, message);
361 void ModuleController::_async_handleEnqueue(
366 ModuleController* myself = static_cast<ModuleController *>(q);
367 Message* request = op->removeRequest();
368 Message* response = op->removeResponse();
370 if (request && (!(request->getMask() & MessageMask::ha_async)))
371 throw TypeMismatchException();
373 if (response && (!(response->getMask() & MessageMask::ha_async)))
374 throw TypeMismatchException();
377 myself->return_op(op);
379 // get rid of the module wrapper
380 if (request && request->getType() == async_messages::ASYNC_MODULE_OP_START)
382 (static_cast<AsyncMessage *>(request))->op = NULL;
383 AsyncModuleOperationStart *rq =
384 static_cast<AsyncModuleOperationStart *>(request);
385 request = rq->get_action();
389 // get rid of the module wrapper
391 response->getType() == async_messages::ASYNC_MODULE_OP_RESULT)
393 (static_cast<AsyncMessage *>(response))->op = NULL;
394 AsyncModuleOperationResult *rp =
395 static_cast<AsyncModuleOperationResult *>(response);
396 response = rp->get_result();
400 callback_handle *cb = reinterpret_cast<callback_handle *>(parm);
402 cb->_module->_send_async_callback(0, response, cb->_parm);
407 // send an async message to a service asynchronously
408 Boolean ModuleController::ModuleSendAsync(
409 const RegisteredModuleHandle& handle,
411 Uint32 destination_q,
412 AsyncRequest* message,
415 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
416 throw(Permission(Threads::self()));
418 if (message->op == NULL)
420 message->op = get_op();
421 message->op->setRequest(message);
425 callback_handle *cb = new callback_handle(
426 const_cast<RegisteredModuleHandle *>(&handle),
429 message->resp = getQueueId();
430 message->block = false;
431 message->dest = destination_q;
435 _async_handleEnqueue,
440 // send a message to a module within another service asynchronously
441 Boolean ModuleController::ModuleSendAsync(
442 const RegisteredModuleHandle& handle,
444 Uint32 destination_q,
445 const String& destination_module,
446 AsyncRequest* message,
449 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
450 throw(Permission(Threads::self()));
452 AsyncOpNode *op = get_op();
453 AsyncModuleOperationStart *request = new AsyncModuleOperationStart(
460 request->dest = destination_q;
461 callback_handle* cb = new callback_handle(
462 const_cast<RegisteredModuleHandle *>(&handle),
467 _async_handleEnqueue,
473 Boolean ModuleController::_send_forget(
474 Uint32 destination_q,
475 AsyncRequest *message)
477 message->dest = destination_q;
478 return SendForget(message);
481 Boolean ModuleController::_send_forget(
482 Uint32 destination_q,
483 const String& destination_module,
484 AsyncRequest* message)
486 AsyncOpNode* op = get_op();
487 message->dest = destination_q;
488 AsyncModuleOperationStart* request = new AsyncModuleOperationStart(
495 return SendForget(request);
499 Boolean ModuleController::ModuleSendForget(
500 const RegisteredModuleHandle& handle,
501 Uint32 destination_q,
502 AsyncRequest* message)
504 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
505 throw(Permission(Threads::self()));
507 return _send_forget(destination_q, message);
510 Boolean ModuleController::ModuleSendForget(
511 const RegisteredModuleHandle& handle,
512 Uint32 destination_q,
513 const String& destination_module,
514 AsyncRequest* message)
516 if (false == verify_handle(const_cast<RegisteredModuleHandle *>(&handle)))
517 throw(Permission(Threads::self()));
518 return _send_forget(destination_q, destination_module, message);
522 void ModuleController::_handle_async_request(AsyncRequest* rq)
524 if (rq->getType() == async_messages::ASYNC_MODULE_OP_START)
526 // find the target module
527 RegisteredModuleHandle* target;
528 Message* module_result = NULL;
531 _module_lock lock(&_modules);
532 target = _modules.front();
533 while (target != NULL)
535 if (target->get_name() ==
536 static_cast<AsyncModuleOperationStart *>(rq)->
542 target = _modules.next_of(target);
548 // ATTN: This statement was taken out of the _module_lock block
549 // above because that caused all requests to control providers to
550 // be serialized. There is now a risk that the control provider
551 // module may be deleted after the lookup and before this call.
552 // See Bugzilla 3120.
553 module_result = target->_receive_message(
554 static_cast<AsyncModuleOperationStart *>(rq)->_act);
557 if (module_result == NULL)
559 module_result = new AsyncReply(
560 async_messages::REPLY,
561 MessageMask::ha_async | MessageMask::ha_reply,
563 async_results::CIM_NAK,
568 AsyncModuleOperationResult *result = new AsyncModuleOperationResult(
571 static_cast<AsyncModuleOperationStart *>(rq)->resp,
573 static_cast<AsyncModuleOperationStart *>(rq)->_target_module,
575 _complete_op_node(rq->op, 0, 0, 0);
578 Base::_handle_async_request(rq);
581 void ModuleController::_handle_async_callback(AsyncOpNode* op)
583 Base::_handle_async_callback(op);
586 ModuleController* ModuleController::getModuleController()
588 MessageQueue* messageQueue =
589 MessageQueue::lookup(PEGASUS_QUEUENAME_CONTROLSERVICE);
590 PEGASUS_ASSERT(messageQueue != 0);
591 PEGASUS_ASSERT(messageQueue->isAsync());
593 MessageQueueService* service =
594 dynamic_cast<MessageQueueService*>(messageQueue);
595 PEGASUS_ASSERT(service != 0);
597 service->get_capabilities() & module_capabilities::module_controller);
599 return static_cast<ModuleController*>(service);
603 // send a message to another service
604 AsyncReply* ModuleController::ClientSendWait(
605 Uint32 destination_q,
606 AsyncRequest* request)
608 return _send_wait(destination_q, request);
612 // send a message to another module via another service
613 AsyncReply *ModuleController::ClientSendWait(
614 Uint32 destination_q,
615 String& destination_module,
616 AsyncRequest* request)
618 return _send_wait(destination_q, destination_module, request);
622 // send an async message to another service
623 Boolean ModuleController::ClientSendAsync(
625 Uint32 destination_q,
626 AsyncRequest* message,
627 void (*async_callback)(Uint32, Message *, void *),
630 RegisteredModuleHandle* temp = new RegisteredModuleHandle(
631 String(PEGASUS_MODULENAME_TEMP),
635 return ModuleSendAsync(
644 // send an async message to another module via another service
645 Boolean ModuleController::ClientSendAsync(
647 Uint32 destination_q,
648 const String& destination_module,
649 AsyncRequest* message,
650 void (*async_callback)(Uint32, Message *, void *),
653 RegisteredModuleHandle* temp = new RegisteredModuleHandle(
654 String(PEGASUS_MODULENAME_TEMP),
658 return ModuleSendAsync(
668 Boolean ModuleController::ClientSendForget(
669 Uint32 destination_q,
670 AsyncRequest* message)
672 return _send_forget(destination_q, message);
676 Boolean ModuleController::ClientSendForget(
677 Uint32 destination_q,
678 const String& destination_module,
679 AsyncRequest* message)
681 return _send_forget(destination_q, destination_module, message);
684 PEGASUS_NAMESPACE_END