1 karl 1.47 //%2005////////////////////////////////////////////////////////////////////////
|
2 mday 1.1 //
|
3 karl 1.45 // 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 karl 1.41 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.45 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.47 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mday 1.1 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
|
18 david.dillard 1.51 //
|
19 mday 1.1 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Mike Day (mdday@us.ibm.com) << Tue Mar 19 13:19:24 2002 mdd >>
31 //
|
32 a.arora 1.44 // Modified By: Amit K Arora, IBM (amita@in.ibm.com) for PEP101 and Bug#1090
|
33 david.dillard 1.51 // David Dillard, VERITAS Software Corp.
34 // (david.dillard@veritas.com)
|
35 mday 1.1 //
36 //%/////////////////////////////////////////////////////////////////////////////
37
38 #include "ModuleController.h"
|
39 humberto 1.39 #include <Pegasus/Common/MessageLoader.h> //l10n
|
40 konrad.r 1.52 #include <Pegasus/Common/Tracer.h>
|
41 mday 1.1 PEGASUS_NAMESPACE_BEGIN
42
43 PEGASUS_USING_STD;
|
44 david.dillard 1.51
|
45 mday 1.27 ModuleController::callback_handle * ModuleController::callback_handle::_head;
46 const int ModuleController::callback_handle::BLOCK_SIZE = 20;
47 Mutex ModuleController::callback_handle::_alloc_mut;
48
|
49 mday 1.40
|
50 mday 1.27 void * ModuleController::callback_handle::operator new(size_t size)
51 {
52 if( size != sizeof(callback_handle))
53 return ::operator new(size);
|
54 a.arora 1.44 AutoMutex autoMut(_alloc_mut);
|
55 mday 1.27 callback_handle *node = _head;
56 if(node)
57 _head = reinterpret_cast<callback_handle *>(node->_parm);
58 else
59 {
|
60 david.dillard 1.51 callback_handle *block =
|
61 mday 1.27 reinterpret_cast<callback_handle *>(::operator new(BLOCK_SIZE * sizeof(callback_handle)));
62 int i;
63 for(i = 1; i < BLOCK_SIZE - 1; ++i)
64 block[i]._parm = & block[i + 1];
65 block[BLOCK_SIZE - 1]._parm = NULL;
66 node = block;
67 _head = &block[1];
68 }
69 return node;
70 }
71
72
73 void ModuleController::callback_handle::operator delete(void *dead, size_t size)
74 {
75 if(dead == 0)
76 return;
77 if(size != sizeof(callback_handle))
78 {
79 ::operator delete(dead);
80 return;
81 }
82 mday 1.27 callback_handle *node = reinterpret_cast<callback_handle *>(dead);
|
83 a.arora 1.44 AutoMutex autoMut(_alloc_mut);
|
84 mday 1.27 node->_parm = _head;
85 _head = node;
86 }
87
|
88 mday 1.6
|
89 david.dillard 1.51 pegasus_module::module_rep::module_rep(ModuleController *controller,
|
90 mday 1.6 const String & name,
|
91 david.dillard 1.51 void *module_address,
|
92 mday 1.8 Message * (*receive_message)(Message *, void *),
93 void (*async_callback)(Uint32, Message *, void *),
94 void (*shutdown_notify)(Uint32 code, void *))
|
95 mday 1.15 : Base ( pegasus_internal_identity(peg_credential_types::MODULE) ),
96 _thread_safety(),
|
97 david.dillard 1.51 _controller(controller),
98 _name(name),
99 _reference_count(1),
|
100 mday 1.6 _shutting_down(0),
101 _module_address(module_address)
|
102 mday 1.15
|
103 mday 1.6 {
104 if(receive_message != NULL)
105 _receive_message = receive_message;
106 else
107 _receive_message = default_receive_message;
108 if(async_callback != NULL)
109 _async_callback = async_callback;
110 else
111 _async_callback = default_async_callback;
112 if(shutdown_notify != NULL)
113 _shutdown_notify = shutdown_notify;
114 else
115 _shutdown_notify = default_shutdown_notify;
116 }
117
118
|
119 david.dillard 1.51 pegasus_module::module_rep::~module_rep()
|
120 mday 1.6 {
121 _send_shutdown_notify();
122 }
123
124 Message * pegasus_module::module_rep::module_receive_message(Message *msg)
125 {
126 Message * ret;
|
127 kumpf 1.49 // ATTN: This Mutex serializes requests to this Module (Control Provider)
128 //AutoMutex autoMut(_thread_safety);
|
129 a.arora 1.44 ret = _receive_message(msg, _module_address);
|
130 mday 1.6 return ret;
131 }
132
|
133 mday 1.16 void pegasus_module::module_rep::_send_async_callback(Uint32 msg_handle, Message *msg, void *parm)
|
134 mday 1.6 {
|
135 a.arora 1.44 AutoMutex autoMut(_thread_safety);
136 _async_callback(msg_handle, msg, parm);
|
137 mday 1.6 }
|
138 david.dillard 1.51
139 void pegasus_module::module_rep::_send_shutdown_notify()
|
140 mday 1.6 {
|
141 a.arora 1.44 AutoMutex autoMut(_thread_safety);
|
142 mday 1.6 if(_reference_count.value() == 0 )
143 {
144 if( _shutting_down == 0 )
145 {
146 _shutting_down++;
|
147 mday 1.8 _shutdown_notify(_reference_count.value(), _module_address);
|
148 mday 1.6 _async_callback = closed_async_callback;
149 _receive_message = closed_receive_message;
150 }
151 }
152 }
153
|
154 mday 1.15
155 Boolean pegasus_module::module_rep::authorized()
156 {
157 return true;
158 }
159
160 Boolean pegasus_module::module_rep::authorized(Uint32 operation)
161 {
162 return true;
163 }
164
165 Boolean pegasus_module::module_rep::authorized(Uint32 index, Uint32 operation)
166 {
167 return true;
168 }
169
170
|
171 david.dillard 1.51 pegasus_module::pegasus_module(ModuleController *controller,
172 const String &id,
|
173 mday 1.3 void *module_address,
|
174 mday 1.8 Message * (*receive_message)(Message *, void *),
175 void (*async_callback)(Uint32, Message *, void *),
|
176 a.arora 1.43 void (*shutdown_notify)(Uint32 code, void *)) :
177 _rep(new module_rep(controller, id, module_address,
178 receive_message, async_callback, shutdown_notify))
|
179 mday 1.2 {
|
180 a.arora 1.43 _allowed_operations = ModuleController::GET_CLIENT_HANDLE |
|
181 mday 1.12 ModuleController::REGISTER_MODULE |
|
182 david.dillard 1.51 ModuleController::DEREGISTER_MODULE |
|
183 mday 1.12 ModuleController::FIND_SERVICE |
|
184 david.dillard 1.51 ModuleController::FIND_MODULE_IN_SERVICE |
185 ModuleController::GET_MODULE_REFERENCE |
186 ModuleController::MODULE_SEND_WAIT |
187 ModuleController::MODULE_SEND_WAIT_MODULE |
188 ModuleController::MODULE_SEND_ASYNC |
189 ModuleController::MODULE_SEND_ASYNC_MODULE |
190 ModuleController::BLOCKING_THREAD_EXEC |
|
191 mday 1.12 ModuleController::ASYNC_THREAD_EXEC;
|
192 mday 1.2 }
193
194 pegasus_module::pegasus_module(const pegasus_module & mod)
195 {
196 mod._rep->reference();
|
197 a.arora 1.43 _rep.reset(mod._rep.get());
|
198 mday 1.2 }
|
199 mday 1.1
|
200 david.dillard 1.51 pegasus_module::~pegasus_module()
|
201 mday 1.6 {
202 _rep->dereference();
203 _send_shutdown_notify();
204 if( 0 == _rep->reference_count())
|
205 a.arora 1.43 _rep.reset();
|
206 mday 1.6 }
207
|
208 mday 1.15 Boolean pegasus_module::authorized(Uint32 operation)
|
209 mday 1.12 {
210 return true;
211 }
212
|
213 mday 1.15 Boolean pegasus_module::authorized()
|
214 mday 1.12 {
215 return true;
216 }
217
218
|
219 mday 1.2 pegasus_module & pegasus_module::operator= (const pegasus_module & mod)
|
220 david.dillard 1.51 {
|
221 mday 1.12 if( this != &mod)
222 {
223 if ( _rep->reference_count() == 0 )
|
224 a.arora 1.43 _rep.reset();
225 _rep.reset(mod._rep.get());
|
226 mday 1.12 }
|
227 mday 1.2 return *this;
228 }
|
229 mday 1.12
|
230 david.dillard 1.51 Boolean pegasus_module::operator== (const pegasus_module & mod) const
|
231 mday 1.1 {
|
232 david.dillard 1.51 if( mod._rep.get() == _rep.get() )
|
233 mday 1.2 return true;
234 return false;
|
235 david.dillard 1.51
|
236 mday 1.1 }
|
237 david.dillard 1.51
|
238 mday 1.6 Boolean pegasus_module::operator == (const String & mod) const
|
239 mday 1.2 {
240 if(_rep->get_name() == mod)
|
241 david.dillard 1.51 return true;
|
242 mday 1.2 return false;
243 }
244
245
246 Boolean pegasus_module::operator == (const void *mod) const
247 {
|
248 a.arora 1.43 if ( (reinterpret_cast<const pegasus_module *>(mod))->_rep.get() == _rep.get())
|
249 mday 1.2 return true;
250 return false;
251 }
252
|
253 david.dillard 1.51 const String & pegasus_module::get_name() const
|
254 mday 1.2 {
255 return _rep->get_name();
256 }
|
257 mday 1.1
|
258 mday 1.2
|
259 david.dillard 1.51 Boolean pegasus_module::query_interface(const String & class_id,
260 void **object_ptr) const
|
261 mday 1.2 {
262 PEGASUS_ASSERT(object_ptr != NULL);
263 if( class_id == _rep->get_name())
264 {
265 *object_ptr = _rep->get_module_address();
266 return true;
267 }
268 *object_ptr = NULL;
269 return false;
270 }
|
271 mday 1.3
|
272 mday 1.6 Message * pegasus_module::_receive_message(Message *msg)
273 {
274 return _rep->module_receive_message(msg);
275 }
276
|
277 david.dillard 1.51 void pegasus_module::_send_async_callback(Uint32 msg_handle, Message *msg, void *parm)
|
278 mday 1.6 {
|
279 mday 1.16 _rep->_send_async_callback(msg_handle, msg, parm);
|
280 mday 1.6 }
281
|
282 david.dillard 1.51 void pegasus_module::_send_shutdown_notify()
|
283 mday 1.6 {
284 _rep->_send_shutdown_notify();
285 }
286
|
287 david.dillard 1.51 Boolean pegasus_module::_shutdown()
|
288 mday 1.6 {
|
289 david.dillard 1.51 _send_shutdown_notify();
290 return true;
291 }
|
292 mday 1.6
293
|
294 mday 1.11
295 const Uint32 ModuleController::GET_CLIENT_HANDLE = 0x00000001;
296 const Uint32 ModuleController::REGISTER_MODULE = 0x00000002;
297 const Uint32 ModuleController::DEREGISTER_MODULE = 0x00000004;
298 const Uint32 ModuleController::FIND_SERVICE = 0x00000008;
299 const Uint32 ModuleController::FIND_MODULE_IN_SERVICE = 0x00000010;
300 const Uint32 ModuleController::GET_MODULE_REFERENCE = 0x00000020;
301 const Uint32 ModuleController::MODULE_SEND_WAIT = 0x00000040;
302 const Uint32 ModuleController::MODULE_SEND_WAIT_MODULE = 0x00000040;
303 const Uint32 ModuleController::MODULE_SEND_ASYNC = 0x00000080;
304 const Uint32 ModuleController::MODULE_SEND_ASYNC_MODULE = 0x00000080;
305 const Uint32 ModuleController::BLOCKING_THREAD_EXEC = 0x00000100;
306 const Uint32 ModuleController::ASYNC_THREAD_EXEC = 0x00000200;
307 const Uint32 ModuleController::CLIENT_SEND_WAIT = 0x00000400;
308 const Uint32 ModuleController::CLIENT_SEND_WAIT_MODULE = 0x00000400;
309 const Uint32 ModuleController::CLIENT_SEND_ASYNC = 0x00000800;
310 const Uint32 ModuleController::CLIENT_SEND_ASYNC_MODULE = 0x00000800;
311 const Uint32 ModuleController::CLIENT_BLOCKING_THREAD_EXEC =0x00001000;
312 const Uint32 ModuleController::CLIENT_ASYNC_THREAD_EXEC = 0x00001000;
|
313 mday 1.19 const Uint32 ModuleController::CLIENT_SEND_FORGET = 0x00002000;
314 const Uint32 ModuleController::CLIENT_SEND_FORGET_MODULE = 0x00002000;
315 const Uint32 ModuleController::MODULE_SEND_FORGET = 0x00004000;
316 const Uint32 ModuleController::MODULE_SEND_FORGET_MODULE = 0x00004000;
|
317 mday 1.11
318
|
319 mday 1.15 Boolean ModuleController::client_handle::authorized()
320 {
321 return true;
322 }
323
|
324 mday 1.12 Boolean ModuleController::client_handle::authorized(Uint32 operation)
325 {
326 return true;
327 }
|
328 david.dillard 1.51
|
329 mday 1.15
330 Boolean ModuleController::client_handle::authorized(Uint32 index, Uint32 operation)
|
331 kumpf 1.14 {
332 return true;
333 }
|
334 david.dillard 1.51
|
335 mday 1.12
|
336 kumpf 1.10 // NOTE: "destroy" is defined in <memory> on HP-UX and must not be redefined
337 static struct timeval createTime = {0, 50000};
338 static struct timeval destroyTime = {15, 0};
|
339 mday 1.3
340 ModuleController::ModuleController(const char *name )
|
341 david.dillard 1.51 :Base(name, MessageQueue::getNextQueueId(),
|
342 mday 1.4 module_capabilities::module_controller |
343 module_capabilities::async),
|
344 konrad.r 1.50 _modules(true)
|
345 david.dillard 1.51 {
|
346 mday 1.3
347 }
348
|
349 mday 1.32 // ModuleController::ModuleController(const char *name ,
|
350 david.dillard 1.51 // Sint16 min_threads,
|
351 mday 1.32 // Sint16 max_threads,
352 // struct timeval & create_thread,
|
353 kumpf 1.48 // struct timeval & destroy_thread)
|
354 mday 1.32 // :Base(name, MessageQueue::getNextQueueId(),
355 // module_capabilities::module_controller |
356 // module_capabilities::async),
357 // _modules(true),
|
358 david.dillard 1.51 // _thread_pool(min_threads + 1,
359 // name, min_threads,
360 // max_threads,
361 // create_thread,
|
362 kumpf 1.48 // destroy_thread)
|
363 david.dillard 1.51 // {
|
364 mday 1.3
|
365 mday 1.32 // }
|
366 mday 1.3
|
367 kumpf 1.5 ModuleController::~ModuleController()
368 {
369
|
370 mday 1.6 pegasus_module *module;
|
371 mday 1.40
|
372 david.dillard 1.51 try
|
373 mday 1.40 {
374 module = _modules.remove_first();
375 while(module)
376 {
377 delete module;
378 module = _modules.remove_first();
379 }
380
381 }
382 catch(...)
|
383 mday 1.6 {
384 }
|
385 kumpf 1.5 }
|
386 mday 1.3
|
387 david.dillard 1.51 // called by a module to register itself, returns a handle to the controller
|
388 mday 1.6 ModuleController & ModuleController::register_module(const String & controller_name,
|
389 david.dillard 1.51 const String & module_name,
390 void *module_address,
|
391 mday 1.8 Message * (*receive_message)(Message *, void *),
392 void (*async_callback)(Uint32, Message *, void *),
393 void (*shutdown_notify)(Uint32, void *),
|
394 david.dillard 1.51 pegasus_module **instance)
|
395 mday 1.3 {
|
396 mday 1.4
397 pegasus_module *module ;
|
398 mday 1.6 ModuleController *controller;
|
399 david.dillard 1.51
|
400 mday 1.6
401 Array<Uint32> services;
|
402 david.dillard 1.51
|
403 kumpf 1.37 MessageQueue *message_queue = MessageQueue::lookup(controller_name.getCString());
|
404 david.dillard 1.51
|
405 mday 1.6 if ((message_queue == NULL) || ( false == message_queue->isAsync() ))
406 {
|
407 kumpf 1.36 throw IncompatibleTypesException();
|
408 mday 1.6 }
409
410 MessageQueueService *service = static_cast<MessageQueueService *>(message_queue);
411 if( (service == NULL) || ! ( service->get_capabilities() & module_capabilities::module_controller ))
|
412 kumpf 1.7 {
|
413 kumpf 1.36 throw IncompatibleTypesException();
|
414 kumpf 1.7 }
|
415 mday 1.6
|
416 kumpf 1.7 controller = static_cast<ModuleController *>(service);
|
417 david.dillard 1.51
|
418 mday 1.40 {
|
419 david.dillard 1.51
|
420 mday 1.4 // see if the module already exists in this controller.
|
421 mday 1.40 _module_lock lock(&(controller->_modules));
|
422 david.dillard 1.51
|
423 mday 1.6 module = controller->_modules.next(0);
|
424 mday 1.4 while(module != NULL )
425 {
426 if(module->get_name() == module_name )
427 {
|
428 humberto 1.39 //l10n
429 //throw AlreadyExistsException("module \"" + module_name + "\"");
430 MessageLoaderParms parms("Common.ModuleController.MODULE",
431 "module \"$0\"",
432 module_name);
433 throw AlreadyExistsException(parms);
|
434 mday 1.4 }
|
435 mday 1.6 module = controller->_modules.next(module);
|
436 mday 1.4 }
|
437 david.dillard 1.51
|
438 mday 1.40 }
|
439 david.dillard 1.51
|
440 mday 1.4 // now reserve this module name with the meta dispatcher
441
442 Uint32 result = 0 ;
|
443 a.arora 1.43 AutoPtr<RegisteredModule> request(new RegisteredModule(controller->get_next_xid(),
|
444 david.dillard 1.51 0,
445 true,
|
446 mday 1.25 controller->getQueueId(),
|
447 a.arora 1.43 module_name));
|
448 mday 1.21
449 request->dest = CIMOM_Q_ID;
|
450 david.dillard 1.51
|
451 a.arora 1.43 AutoPtr<AsyncReply> response(controller->SendWait(request.get()));
|
452 david.dillard 1.51 if( response.get() != NULL)
|
453 mday 1.4 result = response->result;
|
454 david.dillard 1.51
|
455 a.arora 1.43 request.reset();
456 response.reset();
|
457 humberto 1.39 if ( result == async_results::MODULE_ALREADY_REGISTERED){
458 //l10n
459 //throw AlreadyExistsException("module \"" + module_name + "\"");
460 MessageLoaderParms parms("Common.ModuleController.MODULE",
461 "module \"$0\"",
462 module_name);
463 throw AlreadyExistsException(parms);
|
464 david.dillard 1.51
|
465 humberto 1.39 }
|
466 david.dillard 1.51
467 // the module does not exist, go ahead and create it.
468 module = new pegasus_module(controller,
469 module_name,
470 module_address,
471 receive_message,
472 async_callback,
|
473 mday 1.4 shutdown_notify);
|
474 david.dillard 1.51
|
475 mday 1.6 controller->_modules.insert_last(module);
|
476 david.dillard 1.51
|
477 mday 1.8 if(instance != NULL)
478 *instance = module;
|
479 david.dillard 1.51
|
480 mday 1.6 return *controller;
|
481 mday 1.3 }
482
|
483 mday 1.4
484 Boolean ModuleController::deregister_module(const String & module_name)
485 {
|
486 a.arora 1.43 AutoPtr<DeRegisteredModule> request(new DeRegisteredModule(get_next_xid(),
|
487 mday 1.4 0,
488 true,
489 getQueueId(),
|
490 a.arora 1.43 module_name));
|
491 mday 1.4 request->dest = _meta_dispatcher->getQueueId();
|
492 david.dillard 1.51
|
493 a.arora 1.43 AutoPtr<AsyncReply> response(SendWait(request.get()));
|
494 mday 1.4
|
495 a.arora 1.43 request.reset();
496 response.reset();
|
497 david.dillard 1.51
|
498 mday 1.4 pegasus_module *module;
|
499 mday 1.40
500 _module_lock lock(&_modules);
|
501 mday 1.4 module = _modules.next(0);
502 while(module != NULL )
503 {
504 if( module->get_name() == module_name)
505 {
|
506 mday 1.22 _modules.remove_no_lock(module);
|
507 mday 1.40 return true;
|
508 mday 1.4 }
|
509 kumpf 1.23 module = _modules.next(module);
|
510 mday 1.4 }
|
511 mday 1.40 return false;
|
512 mday 1.4 }
513
514 Boolean ModuleController::verify_handle(pegasus_module *handle)
515 {
516 pegasus_module *module;
|
517 david.dillard 1.51
|
518 mday 1.16 // ATTN change to use authorization and the pegasus_id class
519 // << Fri Apr 5 12:43:19 2002 mdd >>
520 if( handle->_rep->_module_address == (void *)this)
521 return true;
|
522 david.dillard 1.51
|
523 mday 1.40 _module_lock lock(&_modules);
|
524 david.dillard 1.51
|
525 mday 1.4 module = _modules.next(0);
526 while(module != NULL)
527 {
528 if ( module == handle)
529 {
|
530 mday 1.40 return true;
|
531 mday 1.4 }
532 module = _modules.next(module);
533 }
|
534 mday 1.40 return false;
|
535 mday 1.4 }
536
537 // given a name, find a service's queue id
|
538 david.dillard 1.51 Uint32 ModuleController::find_service(const pegasus_module & handle,
539 const String & name)
|
540 mday 1.4 {
541
|
542 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)) )
|
543 mday 1.4 throw Permission(pegasus_thread_self());
544 Array<Uint32> services;
545 Base::find_services(name, 0, 0, &services);
546 return( services[0]);
547 }
548
549
|
550 david.dillard 1.51 // returns the queue ID of the service hosting the named module,
|
551 mday 1.4 // zero otherwise
552
|
553 david.dillard 1.51 Uint32 ModuleController::find_module_in_service(const pegasus_module & handle,
|
554 mday 1.4 const String & name)
555 {
|
556 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
557 mday 1.4 throw(Permission(pegasus_thread_self()));
|
558 david.dillard 1.51
|
559 mday 1.4 Uint32 result = 0 ;
560
|
561 a.arora 1.43 AutoPtr<FindModuleInService> request(new FindModuleInService(get_next_xid(),
|
562 david.dillard 1.51 0,
563 true,
|
564 mday 1.4 _meta_dispatcher->getQueueId(),
|
565 david.dillard 1.51 name));
|
566 mday 1.4 request->dest = _meta_dispatcher->getQueueId();
|
567 a.arora 1.43 AutoPtr<FindModuleInServiceResponse>
568 response(static_cast<FindModuleInServiceResponse *>(SendWait(request.get())));
569 if( response.get() != NULL)
|
570 mday 1.4 result = response->_module_service_queue;
571
572 return result;
573 }
574
575
|
576 david.dillard 1.51 pegasus_module * ModuleController::get_module_reference(const pegasus_module & my_handle,
|
577 mday 1.4 const String & module_name)
578 {
|
579 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&my_handle)))
|
580 mday 1.4 throw(Permission(pegasus_thread_self()));
581
582 pegasus_module *module, *ref = NULL;
|
583 mday 1.40 _module_lock lock(&_modules);
|
584 mday 1.4 module = _modules.next(0);
585 while(module != NULL)
586 {
587 if(module->get_name() == module_name)
588 {
589 ref = new pegasus_module(*module);
590 break;
591 }
592 module = _modules.next(module);
593 }
594 return ref;
595 }
596
597
|
598 david.dillard 1.51 AsyncReply *ModuleController::_send_wait(Uint32 destination_q,
|
599 mday 1.16 AsyncRequest *request)
600 {
601 request->dest = destination_q;
602 AsyncReply *reply = Base::SendWait(request);
603 return reply;
604 }
605
606
|
607 mday 1.4 // sendwait to another service
|
608 david.dillard 1.51 AsyncReply * ModuleController::ModuleSendWait(const pegasus_module & handle,
|
609 mday 1.4 Uint32 destination_q,
610 AsyncRequest *request)
611 {
|
612 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
613 mday 1.4 throw(Permission(pegasus_thread_self()));
614
|
615 mday 1.16 return _send_wait(destination_q, request);
|
616 mday 1.4 }
617
|
618 david.dillard 1.51 AsyncReply *ModuleController::_send_wait(Uint32 destination_q,
619 const String & destination_module,
|
620 mday 1.16 AsyncRequest *message)
|
621 mday 1.4 {
|
622 a.arora 1.43 AutoPtr<AsyncModuleOperationStart> request(new AsyncModuleOperationStart(get_next_xid(),
|
623 david.dillard 1.51 0,
|
624 mday 1.4 destination_q,
625 getQueueId(),
|
626 david.dillard 1.51 true,
|
627 mday 1.4 destination_module,
|
628 a.arora 1.43 message));
|
629 david.dillard 1.51
|
630 mday 1.4 request->dest = destination_q;
|
631 david.dillard 1.51 AutoPtr<AsyncModuleOperationResult>
|
632 a.arora 1.43 response(static_cast<AsyncModuleOperationResult *>(SendWait(request.get())));
633
|
634 mday 1.4 AsyncReply *ret = 0;
|
635 david.dillard 1.51
|
636 a.arora 1.43 if (response.get() != NULL && response->getType() == async_messages::ASYNC_MODULE_OP_RESULT )
|
637 mday 1.4 {
638 ret = static_cast<AsyncReply *>(response->get_result());
639 //clear the request out of the envelope so it can be deleted by the module
640 }
|
641 mday 1.26 request->get_action();
|
642 mday 1.4 return ret;
643 }
644
|
645 mday 1.16
|
646 david.dillard 1.51 // sendwait to another module controlled by another service.
|
647 mday 1.16 // throws Deadlock() if destination_q is this->queue_id
|
648 david.dillard 1.51 AsyncReply * ModuleController::ModuleSendWait(const pegasus_module & handle,
649 Uint32 destination_q,
|
650 mday 1.19 const String & destination_module,
|
651 mday 1.16 AsyncRequest *message)
652 {
|
653 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
654 mday 1.16 throw(Permission(pegasus_thread_self()));
|
655 david.dillard 1.51
|
656 mday 1.16 return _send_wait(destination_q, destination_module, message);
657 }
658
|
659 david.dillard 1.51 void ModuleController::_async_handleEnqueue(AsyncOpNode *op,
660 MessageQueue *q,
|
661 mday 1.4 void *parm)
662 {
|
663 david.dillard 1.51
|
664 mday 1.4 ModuleController *myself = static_cast<ModuleController *>(q);
665 Message *request = op->get_request();
666 Message *response = op->get_response();
|
667 mday 1.16
|
668 mday 1.26 if( request && (! (request->getMask() & message_mask::ha_async)))
|
669 kumpf 1.36 throw TypeMismatchException();
|
670 mday 1.26
671 if( response && (! (response->getMask() & message_mask::ha_async) ))
|
672 kumpf 1.36 throw TypeMismatchException();
|
673 david.dillard 1.51
|
674 mday 1.17 op->release();
|
675 mday 1.6 myself->return_op(op);
|
676 david.dillard 1.51
|
677 w.otsuka 1.46 Uint32 routing=0;
|
678 david.dillard 1.51
679 // get rid of the module wrapper
|
680 mday 1.26 if( request && request->getType() == async_messages::ASYNC_MODULE_OP_START )
|
681 mday 1.6 {
|
682 mday 1.26 (static_cast<AsyncMessage *>(request))->op = NULL;
|
683 mday 1.6 AsyncModuleOperationStart *rq = static_cast<AsyncModuleOperationStart *>(request);
684 request = rq->get_action();
|
685 mday 1.26 request->setRouting(routing = rq->getRouting());
|
686 mday 1.6 delete rq;
687 }
|
688 david.dillard 1.51
689 // get rid of the module wrapper
|
690 mday 1.26 if(response && response->getType() == async_messages::ASYNC_MODULE_OP_RESULT )
|
691 mday 1.6 {
|
692 mday 1.26 (static_cast<AsyncMessage *>(response))->op = NULL;
|
693 mday 1.6 AsyncModuleOperationResult *rp = static_cast<AsyncModuleOperationResult *>(response);
694 response = rp->get_result();
|
695 mday 1.26 response->setRouting(routing = rp->getRouting());
|
696 mday 1.6 delete rp;
697 }
|
698 david.dillard 1.51
|
699 mday 1.16 callback_handle *cb = reinterpret_cast<callback_handle *>(parm);
|
700 david.dillard 1.51
701 cb->_module->_send_async_callback(routing, response, cb->_parm);
|
702 mday 1.16 delete cb;
|
703 david.dillard 1.51
|
704 mday 1.4 return;
705 }
706
707
708 // send an async message to a service asynchronously
|
709 mday 1.19 Boolean ModuleController::ModuleSendAsync(const pegasus_module & handle,
|
710 david.dillard 1.51 Uint32 msg_handle,
711 Uint32 destination_q,
712 AsyncRequest *message,
713 void *callback_parm)
|
714 mday 1.4 {
|
715 kumpf 1.30 //printf("verifying handle %p, controller at %p \n", &handle, this);
|
716 david.dillard 1.51
|
717 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
718 mday 1.4 throw(Permission(pegasus_thread_self()));
|
719 mday 1.6
720 if (message->op == NULL)
721 {
722 message->op = get_op();
723 message->op->put_request(message);
724 }
725
|
726 mday 1.24
|
727 david.dillard 1.51 callback_handle *cb = new callback_handle(const_cast<pegasus_module *>(&handle),
|
728 mday 1.19 callback_parm);
|
729 david.dillard 1.51
|
730 mday 1.6 message->setRouting(msg_handle);
731 message->resp = getQueueId();
732 message->block = false;
733 message->dest = destination_q;
|
734 david.dillard 1.51 return SendAsync(message->op,
|
735 mday 1.4 destination_q,
736 _async_handleEnqueue,
737 this,
|
738 mday 1.16 cb);
|
739 mday 1.4 }
740
|
741 david.dillard 1.51 // send a message to a module within another service asynchronously
|
742 mday 1.19 Boolean ModuleController::ModuleSendAsync(const pegasus_module & handle,
|
743 david.dillard 1.51 Uint32 msg_handle,
744 Uint32 destination_q,
|
745 mday 1.19 const String & destination_module,
|
746 david.dillard 1.51 AsyncRequest *message,
747 void *callback_parm)
|
748 mday 1.4 {
|
749 david.dillard 1.51
|
750 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
751 mday 1.4 throw(Permission(pegasus_thread_self()));
|
752 mday 1.19
|
753 mday 1.4 AsyncOpNode *op = get_op();
|
754 david.dillard 1.51 AsyncModuleOperationStart *request =
|
755 mday 1.6 new AsyncModuleOperationStart(msg_handle,
|
756 mday 1.4 op,
757 destination_q,
758 getQueueId(),
|
759 david.dillard 1.51 true,
|
760 mday 1.4 destination_module,
761 message);
762 request->dest = destination_q;
|
763 david.dillard 1.51 callback_handle *cb = new callback_handle(const_cast<pegasus_module *>(&handle), callback_parm);
764 return SendAsync(op,
|
765 mday 1.4 destination_q,
766 _async_handleEnqueue,
767 this,
|
768 mday 1.26 cb);
|
769 mday 1.4 }
770
|
771 mday 1.19
772 Boolean ModuleController::_send_forget(Uint32 destination_q, AsyncRequest *message)
773 {
774 message->dest = destination_q;
775 return SendForget(message);
776 }
777
|
778 david.dillard 1.51 Boolean ModuleController::_send_forget(Uint32 destination_q,
779 const String & destination_module,
|
780 mday 1.19 AsyncRequest *message)
781 {
782 AsyncOpNode *op = get_op();
783 message->dest = destination_q;
|
784 david.dillard 1.51 AsyncModuleOperationStart *request =
|
785 mday 1.19 new AsyncModuleOperationStart(0,
786 op,
787 destination_q,
788 getQueueId(),
|
789 david.dillard 1.51 true,
|
790 mday 1.19 destination_module,
791 message);
792 return SendForget(request);
793 }
794
795
796
|
797 david.dillard 1.51 Boolean ModuleController::ModuleSendForget(const pegasus_module & handle,
798 Uint32 destination_q,
|
799 mday 1.19 AsyncRequest *message)
800 {
801 if(false == verify_handle(const_cast<pegasus_module *>( &handle)))
802 throw(Permission(pegasus_thread_self()));
|
803 david.dillard 1.51
|
804 mday 1.19 return _send_forget(destination_q, message);
805 }
|
806 david.dillard 1.51
807 Boolean ModuleController::ModuleSendForget(const pegasus_module & handle,
808 Uint32 destination_q,
809 const String & destination_module,
|
810 mday 1.19 AsyncRequest *message)
811 {
812 if(false == verify_handle(const_cast<pegasus_module *>( &handle)))
813 throw(Permission(pegasus_thread_self()));
|
814 david.dillard 1.51 return _send_forget(destination_q,
815 destination_module,
|
816 mday 1.19 message);
817 }
818
819
820
|
821 mday 1.16 void ModuleController::_blocking_thread_exec(
|
822 david.dillard 1.51 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *thread_func)(void *),
823 void *parm)
|
824 mday 1.4 {
|
825 a.arora 1.43 AutoPtr<Semaphore> blocking_sem(new Semaphore(0));
|
826 konrad.r 1.52 ThreadStatus rc = PEGASUS_THREAD_OK;
827 while ((rc=_thread_pool->allocate_and_awaken(parm, thread_func, blocking_sem.get())) != PEGASUS_THREAD_OK)
|
828 kumpf 1.42 {
|
829 konrad.r 1.52 if (rc == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
830 pegasus_yield();
831 else
832 {
833 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
834 "Not enough threads for the client's blocking thread function.");
835 // ATTN: There is no category for the 'ModuleController' trace.
836 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
837 "Could not allocate for %s a client's blocking thread.",
838 getQueueName());
839 break;
840 }
|
841 kumpf 1.42 }
|
842 mday 1.4 blocking_sem->wait();
|
843 mday 1.16 }
844
845
846 void ModuleController::blocking_thread_exec(
|
847 david.dillard 1.51 const pegasus_module & handle,
848 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *thread_func)(void *),
849 void *parm)
|
850 mday 1.16 {
|
851 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
852 mday 1.16 throw(Permission(pegasus_thread_self()));
853 _blocking_thread_exec(thread_func, parm);
|
854 david.dillard 1.51
|
855 mday 1.16 }
856
857
858 void ModuleController::_async_thread_exec(
|
859 david.dillard 1.51 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *thread_func)(void *),
860 void *parm)
|
861 mday 1.16 {
|
862 konrad.r 1.52 ThreadStatus rc = PEGASUS_THREAD_OK;
863 while ((rc=_thread_pool->allocate_and_awaken(parm, thread_func)) != PEGASUS_THREAD_OK)
|
864 kumpf 1.42 {
|
865 konrad.r 1.52 if (rc == PEGASUS_THREAD_INSUFFICIENT_RESOURCES)
866 pegasus_yield();
867 else
868 {
869 Logger::put(Logger::STANDARD_LOG, System::CIMSERVER, Logger::TRACE,
870 "Not enough threads for the client's asynchronous thread function.");
871 // ATTN:There is no category for 'ModuleController' traceing.
872 Tracer::trace(TRC_DISCARDED_DATA, Tracer::LEVEL2,
873 "Could not allocate for %s a client's asynchronous thread.",
874 getQueueName());
875 break;
876 }
|
877 kumpf 1.42 }
|
878 mday 1.4 }
879
|
880 mday 1.16
881
|
882 david.dillard 1.51 void ModuleController::async_thread_exec(const pegasus_module & handle,
883 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *thread_func)(void *),
884 void *parm)
|
885 mday 1.4 {
|
886 mday 1.19 if ( false == verify_handle(const_cast<pegasus_module *>(&handle)))
|
887 mday 1.4 throw(Permission(pegasus_thread_self()));
|
888 mday 1.16 _async_thread_exec(thread_func, parm);
|
889 mday 1.4 }
|
890 mday 1.3
|
891 mday 1.6 void ModuleController::_handle_async_request(AsyncRequest *rq)
892 {
893
894 if( rq->getType() == async_messages::ASYNC_MODULE_OP_START)
895 {
896 // find the target module
897 pegasus_module *target;
898 Message *module_result = NULL;
|
899 kumpf 1.49
|
900 mday 1.6 {
|
901 mday 1.40 _module_lock lock(&_modules);
902 target = _modules.next(0);
903 while(target != NULL)
|
904 mday 1.6 {
|
905 mday 1.40 if(target->get_name() == static_cast<AsyncModuleOperationStart *>(rq)->_target_module)
906 {
907 break;
908 }
|
909 david.dillard 1.51
|
910 mday 1.40 target = _modules.next(target);
|
911 mday 1.6 }
|
912 kumpf 1.49 }
913
914 if (target)
915 {
916 // ATTN: This statement was taken out of the _module_lock block
917 // above because that caused all requests to control providers to
918 // be serialized. There is now a risk that the control provider
919 // module may be deleted after the lookup and before this call.
920 // See Bugzilla 3120.
921 module_result = target->_receive_message(
922 static_cast<AsyncModuleOperationStart *>(rq)->_act);
|
923 mday 1.6 }
|
924 david.dillard 1.51
|
925 mday 1.6 if(module_result == NULL)
926 {
|
927 david.dillard 1.51 module_result = new AsyncReply(async_messages::REPLY,
|
928 mday 1.6 static_cast<AsyncModuleOperationStart *>(rq)->_act->getKey(),
929 static_cast<AsyncModuleOperationStart *>(rq)->_act->getRouting(),
930 message_mask::ha_async | message_mask::ha_reply,
931 rq->op,
932 async_results::CIM_NAK,
933 rq->resp,
934 false);
935 }
|
936 david.dillard 1.51
937 AsyncModuleOperationResult *result =
|
938 mday 1.6 new AsyncModuleOperationResult(rq->getKey(),
939 rq->getRouting(),
940 rq->op,
941 async_results::OK,
942 static_cast<AsyncModuleOperationStart *>(rq)->resp,
|
943 david.dillard 1.51 false,
|
944 mday 1.6 static_cast<AsyncModuleOperationStart *>(rq)->_target_module,
945 module_result);
946 _complete_op_node(rq->op, 0, 0, 0);
947 }
948 else
949 Base::_handle_async_request(rq);
950 }
951
952 void ModuleController::_handle_async_callback(AsyncOpNode *op)
953 {
954 Base::_handle_async_callback(op);
|
955 david.dillard 1.51
|
956 mday 1.6 }
|
957 mday 1.12
|
958 mday 1.25 ModuleController & ModuleController::get_client_handle(const pegasus_identity & id,
959 client_handle **handle)
960 {
961 return get_client_handle(PEGASUS_QUEUENAME_CONTROLSERVICE,
|
962 david.dillard 1.51 id,
|
963 mday 1.25 handle);
964 }
965
|
966 mday 1.12
|
967 mday 1.16 // called by a non-module client to get the interface and authorization to use the controller
968
|
969 kumpf 1.31 ModuleController & ModuleController::get_client_handle(const char *controller,
|
970 david.dillard 1.51 const pegasus_identity & id,
971 client_handle **handle)
|
972 mday 1.16 {
|
973 david.dillard 1.51
|
974 mday 1.16 if(handle == NULL)
975 throw NullPointer();
|
976 david.dillard 1.51
|
977 mday 1.16 Array<Uint32> services;
|
978 mday 1.25 MessageQueue *message_queue = MessageQueue::lookup(controller);
|
979 david.dillard 1.51
|
980 mday 1.16 if ((message_queue == NULL) || ( false == message_queue->isAsync() ))
981 {
|
982 kumpf 1.36 throw IncompatibleTypesException();
|
983 mday 1.16 }
984
985 MessageQueueService *service = static_cast<MessageQueueService *>(message_queue);
986 if( (service == NULL) || ! ( service->get_capabilities() & module_capabilities::module_controller ))
987 {
|
988 kumpf 1.36 throw IncompatibleTypesException();
|
989 mday 1.16 }
990
|
991 mday 1.25 ModuleController *_controller = static_cast<ModuleController *>(service);
|
992 mday 1.16 if(true == const_cast<pegasus_identity &>(id).authenticate())
993 *handle = new client_handle(id);
994 else
995 *handle = NULL;
|
996 david.dillard 1.51
|
997 mday 1.25 return *_controller;
|
998 mday 1.16 }
999
1000
1001 void ModuleController::return_client_handle(client_handle *handle)
1002 {
|
1003 mday 1.38 if( true == handle->reference_count.DecAndTestIfZero())
|
1004 mday 1.34 delete handle;
|
1005 mday 1.16 }
1006
1007
1008 // send a message to another service
1009 AsyncReply *ModuleController::ClientSendWait(const client_handle & handle,
|
1010 david.dillard 1.51 Uint32 destination_q,
1011 AsyncRequest *request)
|
1012 mday 1.16 {
|
1013 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_SEND_WAIT))
|
1014 mday 1.16 throw Permission(pegasus_thread_self());
1015 return _send_wait(destination_q, request);
1016 }
1017
1018
1019 // send a message to another module via another service
1020 AsyncReply *ModuleController::ClientSendWait(const client_handle & handle,
1021 Uint32 destination_q,
1022 String & destination_module,
|
1023 david.dillard 1.51 AsyncRequest *request)
|
1024 mday 1.16 {
|
1025 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_SEND_WAIT_MODULE))
|
1026 mday 1.16 throw Permission(pegasus_thread_self());
1027 return _send_wait(destination_q, destination_module, request);
1028 }
1029
1030
1031 // send an async message to another service
1032 Boolean ModuleController::ClientSendAsync(const client_handle & handle,
|
1033 david.dillard 1.51 Uint32 msg_handle,
1034 Uint32 destination_q,
|
1035 mday 1.16 AsyncRequest *message,
1036 void (*async_callback)(Uint32, Message *, void *) ,
1037 void *callback_parm)
1038 {
|
1039 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_SEND_ASYNC))
|
1040 mday 1.16 throw Permission(pegasus_thread_self());
|
1041 david.dillard 1.51
1042 pegasus_module *temp = new pegasus_module(this,
|
1043 kumpf 1.18 String(PEGASUS_MODULENAME_TEMP),
|
1044 david.dillard 1.51 this,
1045 0,
1046 async_callback,
|
1047 mday 1.16 0);
|
1048 david.dillard 1.51 return ModuleSendAsync( *temp,
1049 msg_handle,
1050 destination_q,
1051 message,
|
1052 mday 1.16 callback_parm);
1053 }
1054
1055
1056 // send an async message to another module via another service
1057 Boolean ModuleController::ClientSendAsync(const client_handle & handle,
|
1058 david.dillard 1.51 Uint32 msg_handle,
1059 Uint32 destination_q,
|
1060 mday 1.27 const String & destination_module,
|
1061 david.dillard 1.51 AsyncRequest *message,
|
1062 mday 1.16 void (*async_callback)(Uint32, Message *, void *),
1063 void *callback_parm)
1064 {
|
1065 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_SEND_ASYNC_MODULE))
|
1066 mday 1.16 throw Permission(pegasus_thread_self());
|
1067 david.dillard 1.51
1068 pegasus_module *temp = new pegasus_module(this,
|
1069 kumpf 1.18 String(PEGASUS_MODULENAME_TEMP),
|
1070 david.dillard 1.51 this,
1071 0,
1072 async_callback,
|
1073 mday 1.16 0);
|
1074 david.dillard 1.51 return ModuleSendAsync(*temp,
1075 msg_handle,
1076 destination_q,
|
1077 mday 1.16 destination_module,
1078 message,
1079 callback_parm);
1080 }
1081
1082
|
1083 mday 1.19
|
1084 david.dillard 1.51 Boolean ModuleController::ClientSendForget(const client_handle & handle,
1085 Uint32 destination_q,
|
1086 mday 1.19 AsyncRequest *message)
1087 {
|
1088 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_SEND_FORGET))
|
1089 mday 1.19 throw Permission(pegasus_thread_self());
1090
1091 return _send_forget(destination_q, message);
1092 }
1093
1094
|
1095 david.dillard 1.51 Boolean ModuleController::ClientSendForget(const client_handle & handle,
1096 Uint32 destination_q,
1097 const String & destination_module,
|
1098 mday 1.19 AsyncRequest *message)
1099 {
|
1100 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_SEND_FORGET_MODULE))
|
1101 mday 1.19 throw Permission(pegasus_thread_self());
1102
1103 return _send_forget(destination_q, destination_module, message);
1104 }
1105
|
1106 david.dillard 1.51 void ModuleController::client_blocking_thread_exec(
|
1107 mday 1.16 const client_handle & handle,
|
1108 david.dillard 1.51 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *thread_func)(void *),
1109 void *parm)
|
1110 mday 1.16 {
|
1111 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_BLOCKING_THREAD_EXEC))
|
1112 mday 1.16 throw Permission(pegasus_thread_self());
1113 _blocking_thread_exec(thread_func, parm);
|
1114 david.dillard 1.51
|
1115 mday 1.16 }
1116
1117 void ModuleController::client_async_thread_exec(
|
1118 david.dillard 1.51 const client_handle & handle,
1119 PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *thread_func)(void *),
1120 void *parm)
|
1121 mday 1.16 {
1122
|
1123 david.dillard 1.51 if( false == const_cast<client_handle &>(handle).authorized(CLIENT_ASYNC_THREAD_EXEC))
|
1124 mday 1.16 throw Permission(pegasus_thread_self());
1125 _async_thread_exec(thread_func, parm);
1126 }
|
1127 mday 1.1
1128
1129 PEGASUS_NAMESPACE_END
|