1 mike 1.2 //%///////////-*-c++-*-//////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
4 //
|
5 mike 1.5 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 mike 1.2 // of this software and associated documentation files (the "Software"), to
7 // deal in the Software without restriction, including without limitation the
8 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 // sell copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
14 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
16 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 //
21 //==============================================================================
22 //
23 // Author: Mike Day (mdday@us.ibm.com)
24 //
25 // Modified By:
26 //
27 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
28
29
30 #ifndef Pegasus_AsyncOpNode_h
31 #define Pegasus_AsyncOpNode_h
32
33 #include <Pegasus/Common/Config.h>
34 #include <Pegasus/Common/Message.h>
35 #include <Pegasus/Common/OperationContext.h>
36 #include <Pegasus/Common/internal_dq.h>
37 #include <Pegasus/Common/IPC.h>
38
39 PEGASUS_NAMESPACE_BEGIN
|
40 mike 1.5
|
41 mday 1.15 // ATTN usage of flags and state is inconsistent
|
42 mday 1.14 // << Wed Jan 16 17:41:57 2002 mdd >>
|
43 mday 1.17 // resolved mdd
44
|
45 mike 1.2
46 #define ASYNC_OPFLAGS_UNKNOWN 0x00000000
47 #define ASYNC_OPFLAGS_INTERVAL_REPEAT 0x00000010
48 #define ASYNC_OPFLAGS_INDICATION 0x00000020
49 #define ASYNC_OPFLAGS_REMOTE 0x00000040
50 #define ASYNC_OPFLAGS_LOCAL_OUT_OF_PROC 0x00000080
51 #define ASYNC_OPFLAGS_PHASED 0x00000001
52 #define ASYNC_OPFLAGS_PARTIAL 0x00000002
53 #define ASYNC_OPFLAGS_NORMAL 0x00000000
54 #define ASYNC_OPFLAGS_SINGLE 0x00000008
55 #define ASYNC_OPFLAGS_MULTIPLE 0x00000010
56 #define ASYNC_OPFLAGS_TOTAL 0x00000020
|
57 mday 1.13 #define ASYNC_OPFLAGS_META_DISPATCHER 0x00000040
|
58 mday 1.17 #define ASYNC_OPFLAGS_FIRE_AND_FORGET 0x00000080
59 #define ASYNC_OPFLAGS_SIMPLE_STATUS 0x00000100
60 #define ASYNC_OPFLAGS_CALLBACK 0x00000200
|
61 mday 1.20 #define ASYNC_OPFLAGS_FORWARD 0x00000400
|
62 mike 1.2
63 #define ASYNC_OPSTATE_UNKNOWN 0x00000000
64 #define ASYNC_OPSTATE_OFFERED 0x00000001
65 #define ASYNC_OPSTATE_DECLINED 0x00000002
66 #define ASYNC_OPSTATE_STARTED 0x00000004
67 #define ASYNC_OPSTATE_PROCESSING 0x00000008
68 #define ASYNC_OPSTATE_DELIVER 0x00000010
69 #define ASYNC_OPSTATE_RESERVE 0x00000020
70 #define ASYNC_OPSTATE_COMPLETE 0x00000040
71 #define ASYNC_OPSTATE_TIMEOUT 0x00000080
72 #define ASYNC_OPSTATE_CANCELLED 0x00000100
73 #define ASYNC_OPSTATE_PAUSED 0x00000200
|
74 mday 1.12 #define ASYNC_OPSTATE_SUSPENDED 0x00000400
|
75 mday 1.3 #define ASYNC_OPSTATE_RESUMED 0x00000800
|
76 mday 1.8 #define ASYNC_OPSTATE_ORPHANED 0x00001000
|
77 mday 1.12 #define ASYNC_OPSTATE_RELEASED 0x00002000
|
78 mike 1.2
|
79 mday 1.8 class Cimom;
|
80 mday 1.23 class Thread;
|
81 mday 1.13
|
82 mike 1.2 class PEGASUS_COMMON_LINKAGE AsyncOpNode
83 {
84 public:
85
86 AsyncOpNode(void);
87 ~AsyncOpNode(void);
88
89 Boolean operator == (const void *key) const;
90 Boolean operator == (const AsyncOpNode & node) const;
|
91 mday 1.9
|
92 mday 1.12 void get_timeout_interval(struct timeval *buffer) ;
|
93 mday 1.9 void set_timeout_interval(const struct timeval *interval);
94
|
95 mike 1.2 Boolean timeout(void) ;
96
97 OperationContext & get_context(void) ;
98
|
99 mday 1.4 void put_request(const Message *request) ;
|
100 mday 1.13 Message *get_request(void) ;
|
101 mike 1.2
|
102 mday 1.4 void put_response(const Message *response) ;
|
103 mday 1.13 Message *get_response(void) ;
|
104 mike 1.2
105 Uint32 read_state(void) ;
106 void write_state(Uint32) ;
|
107 mday 1.11
|
108 mike 1.2 Uint32 read_flags(void);
109 void write_flags(Uint32);
110
111 void lock(void) throw(IPCException);
112 void unlock(void) throw(IPCException);
113 void udpate(void) throw(IPCException);
114 void deliver(const Uint32 count) throw(IPCException);
115 void reserve(const Uint32 size) throw(IPCException);
116 void processing(void) throw(IPCException) ;
117 void processing(OperationContext *context) throw(IPCException);
118 void complete(void) throw(IPCException) ;
119 void complete(OperationContext *context) throw(IPCException);
|
120 mday 1.12 void release(void);
|
121 mday 1.10 void wait(void);
122
|
123 mike 1.2
124 private:
125 Semaphore _client_sem;
126 Mutex _mut;
|
127 mday 1.16 unlocked_dq<Message> _request;
128 unlocked_dq<Message> _response;
|
129 mday 1.15
|
130 mike 1.2 OperationContext _operation_list;
131 Uint32 _state;
132 Uint32 _flags;
133 Uint32 _offered_count;
134 Uint32 _total_ops;
135 Uint32 _completed_ops;
|
136 mday 1.15 Uint32 _user_data;
|
137 mday 1.17 Uint32 _completion_code;
|
138 mday 1.19 MessageQueue *_op_dest;
|
139 mday 1.17
|
140 mike 1.2 struct timeval _start;
141 struct timeval _lifetime;
142 struct timeval _updated;
143 struct timeval _timeout_interval;
144
145 AsyncOpNode *_parent;
146 unlocked_dq<AsyncOpNode> _children;
147
148 void _reset(unlocked_dq<AsyncOpNode> *dst_q);
149
|
150 mday 1.9 // the lifetime member is for cache management by the cimom
|
151 mike 1.2 void _set_lifetime(struct timeval *lifetime) ;
|
152 mday 1.12 Boolean _check_lifetime(void) ;
|
153 mike 1.2
154 Boolean _is_child(void) ;
155 Uint32 _is_parent(void) ;
156 Boolean _is_my_child(const AsyncOpNode & caller) const;
157 void _make_orphan( AsyncOpNode & parent) ;
158 void _adopt_child(AsyncOpNode *child) ;
159 void _disown_child(AsyncOpNode *child) ;
|
160 mday 1.18 void (*_async_callback)(AsyncOpNode *,
|
161 mday 1.19 MessageQueue *,
|
162 mday 1.18 void *);
|
163 mday 1.23 // << Tue Mar 12 14:44:51 2002 mdd >>
164 // pointers for async callbacks - don't use
|
165 mday 1.19 AsyncOpNode *_callback_node;
|
166 mday 1.21 MessageQueue *_callback_response_q;
|
167 mday 1.19 void *_callback_ptr;
|
168 mday 1.22 MessageQueue *_callback_request_q;
|
169 mday 1.23 // << Tue Mar 12 14:44:53 2002 mdd >>
170 // pointers to help static class message handlers - don't use
171 MessageQueue *_service_ptr;
172 Thread *_thread_ptr;
173
|
174 mday 1.8 friend class cimom;
|
175 mday 1.10 friend class MessageQueueService;
176
|
177 mike 1.2 };
178
179
180 inline Boolean AsyncOpNode::operator == (const void *key) const
181 {
182 if (key == (void *)this)
183 return true;
184 return false;
185 }
186
187 inline Boolean AsyncOpNode::operator == (const AsyncOpNode & node) const
188 {
189 return AsyncOpNode::operator==((const void *)&node);
190 }
191
|
192 mday 1.9
|
193 mday 1.12 inline void AsyncOpNode::get_timeout_interval(struct timeval *buffer)
|
194 mday 1.9 {
195 if(buffer != 0)
196 {
|
197 mday 1.12 _mut.lock( pegasus_thread_self() );
|
198 mday 1.9 buffer->tv_sec = _timeout_interval.tv_sec;
199 buffer->tv_usec = _timeout_interval.tv_usec;
|
200 mday 1.12 _mut.unlock();
|
201 mday 1.9 }
202 return;
203 }
204
205 inline void AsyncOpNode::set_timeout_interval(const struct timeval *interval)
206 {
207 if(interval != 0)
208 {
|
209 mday 1.12 _mut.lock(pegasus_thread_self());
|
210 mday 1.9 _timeout_interval.tv_sec = interval->tv_sec;
211 _timeout_interval.tv_usec = interval->tv_usec;
|
212 mday 1.12 gettimeofday(&_updated, NULL);
213 _mut.unlock();
|
214 mday 1.9 }
215 }
216
217
|
218 mike 1.2 inline Boolean AsyncOpNode::timeout(void)
219 {
220 struct timeval now;
221 gettimeofday(&now, NULL);
|
222 mday 1.12 Boolean ret = false;
223 _mut.lock(pegasus_thread_self());
|
224 mday 1.15 if((_updated.tv_sec + _timeout_interval.tv_sec ) < now.tv_sec)
225 if((_updated.tv_usec + _timeout_interval.tv_usec ) < now.tv_usec)
|
226 mday 1.12 ret = true;
227 _mut.unlock();
228 return ret;
|
229 mike 1.2 }
230
|
231 mday 1.4 // context is now a locked list
|
232 mday 1.3 inline OperationContext & AsyncOpNode::get_context(void)
|
233 mike 1.2 {
|
234 mday 1.9 gettimeofday(&_updated, NULL);
|
235 mike 1.2 return _operation_list;
236 }
237
|
238 mday 1.16
|
239 mday 1.4 inline void AsyncOpNode::put_request(const Message *request)
|
240 mike 1.2 {
|
241 mday 1.12 _mut.lock(pegasus_thread_self());
|
242 mday 1.9 gettimeofday(&_updated, NULL);
|
243 mday 1.21 if( false == _request.exists(reinterpret_cast<void *>(const_cast<Message *>(request))) )
|
244 mday 1.16 _request.insert_last( const_cast<Message *>(request) ) ;
|
245 mday 1.15
|
246 mday 1.16 // _request = const_cast<Message *>(request);
|
247 mday 1.15
|
248 mday 1.12 _mut.unlock();
|
249 mike 1.2 }
250
|
251 mday 1.13 inline Message * AsyncOpNode::get_request(void)
|
252 mike 1.2 {
|
253 mday 1.12 Message *ret;
254 _mut.lock(pegasus_thread_self());
|
255 mday 1.9 gettimeofday(&_updated, NULL);
|
256 mday 1.16 ret = _request.remove_first() ;
257 // ret = _request;
|
258 mday 1.15
|
259 mday 1.12 _mut.unlock();
260 return ret;
|
261 mike 1.2 }
262
|
263 mday 1.4 inline void AsyncOpNode::put_response(const Message *response)
|
264 mike 1.2 {
|
265 mday 1.12 _mut.lock(pegasus_thread_self());
|
266 mday 1.9 gettimeofday(&_updated, NULL);
|
267 mday 1.21 if (false == _response.exists(reinterpret_cast<void *>(const_cast<Message *>(response))))
|
268 mday 1.16 _response.insert_last( const_cast<Message *>(response) );
|
269 mday 1.15
|
270 mday 1.16 // _response = const_cast<Message *>(response);
|
271 mday 1.15
|
272 mday 1.12 _mut.unlock();
|
273 mike 1.2 }
274
|
275 mday 1.13 inline Message * AsyncOpNode::get_response(void)
|
276 mike 1.2 {
|
277 mday 1.12 Message *ret;
278
279 _mut.lock(pegasus_thread_self());
|
280 mday 1.15 // gettimeofday(&_updated, NULL);
|
281 mday 1.16 ret = _response.remove_first();
282 // ret = _response;
|
283 mday 1.15
|
284 mday 1.12 _mut.unlock();
285 return ret;
|
286 mike 1.2 }
287
288 inline Uint32 AsyncOpNode::read_state(void)
289 {
|
290 mday 1.12 _mut.lock(pegasus_thread_self());
|
291 mday 1.9 gettimeofday(&_updated, NULL);
|
292 mday 1.12 Uint32 ret = _state;
293 _mut.unlock();
294 return ret;
295
|
296 mike 1.2 }
297
298 inline void AsyncOpNode::write_state(Uint32 state)
299 {
|
300 mday 1.12 _mut.lock(pegasus_thread_self());
|
301 mday 1.9 gettimeofday(&_updated, NULL);
|
302 mike 1.2 _state = state;
|
303 mday 1.12 _mut.unlock();
|
304 mike 1.2 }
305
306 inline Uint32 AsyncOpNode::read_flags(void)
307 {
|
308 mday 1.12 _mut.lock(pegasus_thread_self());
|
309 mday 1.9 gettimeofday(&_updated, NULL);
|
310 mday 1.12 Uint32 ret = _flags;
311 _mut.unlock();
312 return ret;
|
313 mike 1.2 }
314
315 inline void AsyncOpNode::write_flags(Uint32 flags)
|
316 mday 1.9 {
|
317 mday 1.12 _mut.lock(pegasus_thread_self());
|
318 mday 1.9 gettimeofday(&_updated, NULL);
|
319 mike 1.2 _flags = flags;
|
320 mday 1.12 _mut.unlock();
|
321 mike 1.2 }
322
323
324 inline void AsyncOpNode::lock(void)
325 throw(IPCException)
326 {
327 _mut.lock(pegasus_thread_self());
328 }
329
330 inline void AsyncOpNode::unlock(void)
331 throw(IPCException)
332 {
333 _mut.unlock();
334 }
335
336 inline void AsyncOpNode::udpate(void)
337 throw(IPCException)
338 {
339 _mut.lock(pegasus_thread_self());
340 gettimeofday(&_updated, NULL);
341 _mut.unlock();
342 mike 1.2 return;
343 }
344
345 inline void AsyncOpNode::deliver(const Uint32 count)
346 throw(IPCException)
347 {
348 _mut.lock(pegasus_thread_self());
349 _completed_ops = count;
|
350 mday 1.15 _state |= ASYNC_OPSTATE_DELIVER;
|
351 mike 1.2 gettimeofday(&_updated, NULL);
352 _mut.unlock();
353 return;
354 }
355
356 inline void AsyncOpNode::reserve(const Uint32 size)
357 throw(IPCException)
358 {
359 _mut.lock(pegasus_thread_self());
360 _total_ops = size;
|
361 mday 1.15 _state |= ASYNC_OPSTATE_RESERVE;
|
362 mike 1.2 gettimeofday(&_updated, NULL);
363 _mut.unlock();
364 return;
365 }
366
367 inline void AsyncOpNode::processing(void)
368 throw(IPCException)
369 {
370 _mut.lock(pegasus_thread_self());
|
371 mday 1.15 _state |= ASYNC_OPSTATE_PROCESSING;
|
372 mike 1.2 gettimeofday(&_updated, NULL);
373 _mut.unlock();
374 return;
375 }
376
377 // con will be empty upon return of this member function
378 inline void AsyncOpNode::processing(OperationContext *con)
379 throw(IPCException)
380 {
381 _mut.lock(pegasus_thread_self());
|
382 mday 1.15 _state |= ASYNC_OPSTATE_PROCESSING;
|
383 mike 1.2 gettimeofday(&_updated, NULL);
384
385 context *c = con->remove_context();
386 while(c != 0)
387 {
388 _operation_list.add_context(c);
389 c = con->remove_context();
390 }
391 _mut.unlock();
392 return;
393 }
394
395 inline void AsyncOpNode::complete(void)
396 throw(IPCException)
397 {
398 _mut.lock(pegasus_thread_self());
|
399 mday 1.15 _state |= ASYNC_OPSTATE_COMPLETE;
|
400 mike 1.2 gettimeofday(&_updated, NULL);
401 _mut.unlock();
|
402 mday 1.12
|
403 mike 1.2 return;
404 }
405
406 inline void AsyncOpNode::complete(OperationContext *con)
407 throw(IPCException)
408 {
409 _mut.lock(pegasus_thread_self());
|
410 mday 1.15 _state |= ASYNC_OPSTATE_COMPLETE;
|
411 mike 1.2 gettimeofday(&_updated, NULL);
412 context *c = con->remove_context();
413 while(c != 0)
414 {
415 _operation_list.add_context(c);
416 c = con->remove_context();
417 }
418 _mut.unlock();
|
419 mday 1.10 }
420
421 inline void AsyncOpNode::wait(void)
422 {
423 _client_sem.wait();
|
424 mike 1.2 }
425
|
426 mday 1.12 inline void AsyncOpNode::release(void)
427 {
428 _mut.lock(pegasus_thread_self());
429 _state |= ASYNC_OPSTATE_RELEASED;
430 _mut.unlock();
431 }
432
|
433 mike 1.2 inline void AsyncOpNode::_set_lifetime(struct timeval *lifetime)
434 {
|
435 mday 1.12 _mut.lock(pegasus_thread_self());
|
436 mike 1.2 _lifetime.tv_sec = lifetime->tv_sec;
437 _lifetime.tv_usec = lifetime->tv_usec;
|
438 mday 1.12 _mut.unlock();
|
439 mike 1.2 }
440
|
441 mday 1.12 inline Boolean AsyncOpNode::_check_lifetime(void)
|
442 mike 1.2 {
443 struct timeval now;
|
444 mday 1.12
|
445 mike 1.2 gettimeofday(&now, NULL);
446 if((_start.tv_sec + _lifetime.tv_sec ) >= now.tv_sec)
447 if((_start.tv_usec + _lifetime.tv_usec ) >= now.tv_usec)
448 return true;
449 return false;
450 }
451
452 inline Boolean AsyncOpNode::_is_child(void)
453 {
454 if (_parent != 0)
455 return true;
456 return false;
457 }
458
459 inline Uint32 AsyncOpNode::_is_parent(void)
460 {
461 return _children.count();
462 }
463
464 inline Boolean AsyncOpNode::_is_my_child(const AsyncOpNode & caller) const
465 {
466 mike 1.2 if ( _parent == &caller )
467 return true;
468 return false;
469 }
470
471 inline void AsyncOpNode::_make_orphan( AsyncOpNode & parent)
472 {
473 if( _parent == &parent )
474 {
475 _parent = NULL;
476 parent._children.remove(this);
477 }
478 else
479 throw Permission(pegasus_thread_self());
480 }
481
482 inline void AsyncOpNode::_adopt_child(AsyncOpNode *child)
483 {
484 if(child == NULL)
485 throw NullPointer();
486 if(true == child->_is_child())
487 mike 1.2 throw Permission(pegasus_thread_self());
488 child->_parent = this;
489 _children.insert_last(child);
490 }
491
492 inline void AsyncOpNode::_disown_child(AsyncOpNode *child)
493 {
494 if(child == NULL)
495 throw NullPointer();
496 if( false == child->_is_child() || false == child->_is_my_child( *this ))
497 throw Permission(pegasus_thread_self());
498 child->_make_orphan( *this );
499 _children.remove(child);
500 }
501
502 PEGASUS_NAMESPACE_END
503
504 #endif //Pegasus_AsyncOpNode_h
|