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.13
|
81 mike 1.2 class PEGASUS_COMMON_LINKAGE AsyncOpNode
82 {
83 public:
84
85 AsyncOpNode(void);
86 ~AsyncOpNode(void);
87
88 Boolean operator == (const void *key) const;
89 Boolean operator == (const AsyncOpNode & node) const;
|
90 mday 1.9
|
91 mday 1.12 void get_timeout_interval(struct timeval *buffer) ;
|
92 mday 1.9 void set_timeout_interval(const struct timeval *interval);
93
|
94 mike 1.2 Boolean timeout(void) ;
95
96 OperationContext & get_context(void) ;
97
|
98 mday 1.4 void put_request(const Message *request) ;
|
99 mday 1.13 Message *get_request(void) ;
|
100 mike 1.2
|
101 mday 1.4 void put_response(const Message *response) ;
|
102 mday 1.13 Message *get_response(void) ;
|
103 mike 1.2
104 Uint32 read_state(void) ;
105 void write_state(Uint32) ;
|
106 mday 1.11
|
107 mike 1.2 Uint32 read_flags(void);
108 void write_flags(Uint32);
109
110 void lock(void) throw(IPCException);
111 void unlock(void) throw(IPCException);
112 void udpate(void) throw(IPCException);
113 void deliver(const Uint32 count) throw(IPCException);
114 void reserve(const Uint32 size) throw(IPCException);
115 void processing(void) throw(IPCException) ;
116 void processing(OperationContext *context) throw(IPCException);
117 void complete(void) throw(IPCException) ;
118 void complete(OperationContext *context) throw(IPCException);
|
119 mday 1.12 void release(void);
|
120 mday 1.10 void wait(void);
121
|
122 mike 1.2
123 private:
124 Semaphore _client_sem;
125 Mutex _mut;
|
126 mday 1.16 unlocked_dq<Message> _request;
127 unlocked_dq<Message> _response;
|
128 mday 1.15
|
129 mike 1.2 OperationContext _operation_list;
130 Uint32 _state;
131 Uint32 _flags;
132 Uint32 _offered_count;
133 Uint32 _total_ops;
134 Uint32 _completed_ops;
|
135 mday 1.15 Uint32 _user_data;
|
136 mday 1.17 Uint32 _completion_code;
|
137 mday 1.19 MessageQueue *_op_dest;
|
138 mday 1.17
|
139 mike 1.2 struct timeval _start;
140 struct timeval _lifetime;
141 struct timeval _updated;
142 struct timeval _timeout_interval;
143
144 AsyncOpNode *_parent;
145 unlocked_dq<AsyncOpNode> _children;
146
147 void _reset(unlocked_dq<AsyncOpNode> *dst_q);
148
|
149 mday 1.9 // the lifetime member is for cache management by the cimom
|
150 mike 1.2 void _set_lifetime(struct timeval *lifetime) ;
|
151 mday 1.12 Boolean _check_lifetime(void) ;
|
152 mike 1.2
153 Boolean _is_child(void) ;
154 Uint32 _is_parent(void) ;
155 Boolean _is_my_child(const AsyncOpNode & caller) const;
156 void _make_orphan( AsyncOpNode & parent) ;
157 void _adopt_child(AsyncOpNode *child) ;
158 void _disown_child(AsyncOpNode *child) ;
|
159 mday 1.18 void (*_async_callback)(AsyncOpNode *,
|
160 mday 1.19 MessageQueue *,
|
161 mday 1.18 void *);
|
162 mday 1.19 AsyncOpNode *_callback_node;
|
163 mday 1.21 MessageQueue *_callback_response_q;
|
164 mday 1.19 void *_callback_ptr;
|
165 mday 1.22 MessageQueue *_callback_request_q;
|
166 mday 1.19
|
167 mday 1.8 friend class cimom;
|
168 mday 1.10 friend class MessageQueueService;
169
|
170 mike 1.2 };
171
172
173 inline Boolean AsyncOpNode::operator == (const void *key) const
174 {
175 if (key == (void *)this)
176 return true;
177 return false;
178 }
179
180 inline Boolean AsyncOpNode::operator == (const AsyncOpNode & node) const
181 {
182 return AsyncOpNode::operator==((const void *)&node);
183 }
184
|
185 mday 1.9
|
186 mday 1.12 inline void AsyncOpNode::get_timeout_interval(struct timeval *buffer)
|
187 mday 1.9 {
188 if(buffer != 0)
189 {
|
190 mday 1.12 _mut.lock( pegasus_thread_self() );
|
191 mday 1.9 buffer->tv_sec = _timeout_interval.tv_sec;
192 buffer->tv_usec = _timeout_interval.tv_usec;
|
193 mday 1.12 _mut.unlock();
|
194 mday 1.9 }
195 return;
196 }
197
198 inline void AsyncOpNode::set_timeout_interval(const struct timeval *interval)
199 {
200 if(interval != 0)
201 {
|
202 mday 1.12 _mut.lock(pegasus_thread_self());
|
203 mday 1.9 _timeout_interval.tv_sec = interval->tv_sec;
204 _timeout_interval.tv_usec = interval->tv_usec;
|
205 mday 1.12 gettimeofday(&_updated, NULL);
206 _mut.unlock();
|
207 mday 1.9 }
208 }
209
210
|
211 mike 1.2 inline Boolean AsyncOpNode::timeout(void)
212 {
213 struct timeval now;
214 gettimeofday(&now, NULL);
|
215 mday 1.12 Boolean ret = false;
216 _mut.lock(pegasus_thread_self());
|
217 mday 1.15 if((_updated.tv_sec + _timeout_interval.tv_sec ) < now.tv_sec)
218 if((_updated.tv_usec + _timeout_interval.tv_usec ) < now.tv_usec)
|
219 mday 1.12 ret = true;
220 _mut.unlock();
221 return ret;
|
222 mike 1.2 }
223
|
224 mday 1.4 // context is now a locked list
|
225 mday 1.3 inline OperationContext & AsyncOpNode::get_context(void)
|
226 mike 1.2 {
|
227 mday 1.9 gettimeofday(&_updated, NULL);
|
228 mike 1.2 return _operation_list;
229 }
230
|
231 mday 1.16
|
232 mday 1.4 inline void AsyncOpNode::put_request(const Message *request)
|
233 mike 1.2 {
|
234 mday 1.12 _mut.lock(pegasus_thread_self());
|
235 mday 1.9 gettimeofday(&_updated, NULL);
|
236 mday 1.21 if( false == _request.exists(reinterpret_cast<void *>(const_cast<Message *>(request))) )
|
237 mday 1.16 _request.insert_last( const_cast<Message *>(request) ) ;
|
238 mday 1.15
|
239 mday 1.16 // _request = const_cast<Message *>(request);
|
240 mday 1.15
|
241 mday 1.12 _mut.unlock();
|
242 mike 1.2 }
243
|
244 mday 1.13 inline Message * AsyncOpNode::get_request(void)
|
245 mike 1.2 {
|
246 mday 1.12 Message *ret;
247 _mut.lock(pegasus_thread_self());
|
248 mday 1.9 gettimeofday(&_updated, NULL);
|
249 mday 1.16 ret = _request.remove_first() ;
250 // ret = _request;
|
251 mday 1.15
|
252 mday 1.12 _mut.unlock();
253 return ret;
|
254 mike 1.2 }
255
|
256 mday 1.4 inline void AsyncOpNode::put_response(const Message *response)
|
257 mike 1.2 {
|
258 mday 1.12 _mut.lock(pegasus_thread_self());
|
259 mday 1.9 gettimeofday(&_updated, NULL);
|
260 mday 1.21 if (false == _response.exists(reinterpret_cast<void *>(const_cast<Message *>(response))))
|
261 mday 1.16 _response.insert_last( const_cast<Message *>(response) );
|
262 mday 1.15
|
263 mday 1.16 // _response = const_cast<Message *>(response);
|
264 mday 1.15
|
265 mday 1.12 _mut.unlock();
|
266 mike 1.2 }
267
|
268 mday 1.13 inline Message * AsyncOpNode::get_response(void)
|
269 mike 1.2 {
|
270 mday 1.12 Message *ret;
271
272 _mut.lock(pegasus_thread_self());
|
273 mday 1.15 // gettimeofday(&_updated, NULL);
|
274 mday 1.16 ret = _response.remove_first();
275 // ret = _response;
|
276 mday 1.15
|
277 mday 1.12 _mut.unlock();
278 return ret;
|
279 mike 1.2 }
280
281 inline Uint32 AsyncOpNode::read_state(void)
282 {
|
283 mday 1.12 _mut.lock(pegasus_thread_self());
|
284 mday 1.9 gettimeofday(&_updated, NULL);
|
285 mday 1.12 Uint32 ret = _state;
286 _mut.unlock();
287 return ret;
288
|
289 mike 1.2 }
290
291 inline void AsyncOpNode::write_state(Uint32 state)
292 {
|
293 mday 1.12 _mut.lock(pegasus_thread_self());
|
294 mday 1.9 gettimeofday(&_updated, NULL);
|
295 mike 1.2 _state = state;
|
296 mday 1.12 _mut.unlock();
|
297 mike 1.2 }
298
299 inline Uint32 AsyncOpNode::read_flags(void)
300 {
|
301 mday 1.12 _mut.lock(pegasus_thread_self());
|
302 mday 1.9 gettimeofday(&_updated, NULL);
|
303 mday 1.12 Uint32 ret = _flags;
304 _mut.unlock();
305 return ret;
|
306 mike 1.2 }
307
308 inline void AsyncOpNode::write_flags(Uint32 flags)
|
309 mday 1.9 {
|
310 mday 1.12 _mut.lock(pegasus_thread_self());
|
311 mday 1.9 gettimeofday(&_updated, NULL);
|
312 mike 1.2 _flags = flags;
|
313 mday 1.12 _mut.unlock();
|
314 mike 1.2 }
315
316
317 inline void AsyncOpNode::lock(void)
318 throw(IPCException)
319 {
320 _mut.lock(pegasus_thread_self());
321 }
322
323 inline void AsyncOpNode::unlock(void)
324 throw(IPCException)
325 {
326 _mut.unlock();
327 }
328
329 inline void AsyncOpNode::udpate(void)
330 throw(IPCException)
331 {
332 _mut.lock(pegasus_thread_self());
333 gettimeofday(&_updated, NULL);
334 _mut.unlock();
335 mike 1.2 return;
336 }
337
338 inline void AsyncOpNode::deliver(const Uint32 count)
339 throw(IPCException)
340 {
341 _mut.lock(pegasus_thread_self());
342 _completed_ops = count;
|
343 mday 1.15 _state |= ASYNC_OPSTATE_DELIVER;
|
344 mike 1.2 gettimeofday(&_updated, NULL);
345 _mut.unlock();
346 return;
347 }
348
349 inline void AsyncOpNode::reserve(const Uint32 size)
350 throw(IPCException)
351 {
352 _mut.lock(pegasus_thread_self());
353 _total_ops = size;
|
354 mday 1.15 _state |= ASYNC_OPSTATE_RESERVE;
|
355 mike 1.2 gettimeofday(&_updated, NULL);
356 _mut.unlock();
357 return;
358 }
359
360 inline void AsyncOpNode::processing(void)
361 throw(IPCException)
362 {
363 _mut.lock(pegasus_thread_self());
|
364 mday 1.15 _state |= ASYNC_OPSTATE_PROCESSING;
|
365 mike 1.2 gettimeofday(&_updated, NULL);
366 _mut.unlock();
367 return;
368 }
369
370 // con will be empty upon return of this member function
371 inline void AsyncOpNode::processing(OperationContext *con)
372 throw(IPCException)
373 {
374 _mut.lock(pegasus_thread_self());
|
375 mday 1.15 _state |= ASYNC_OPSTATE_PROCESSING;
|
376 mike 1.2 gettimeofday(&_updated, NULL);
377
378 context *c = con->remove_context();
379 while(c != 0)
380 {
381 _operation_list.add_context(c);
382 c = con->remove_context();
383 }
384 _mut.unlock();
385 return;
386 }
387
388 inline void AsyncOpNode::complete(void)
389 throw(IPCException)
390 {
391 _mut.lock(pegasus_thread_self());
|
392 mday 1.15 _state |= ASYNC_OPSTATE_COMPLETE;
|
393 mike 1.2 gettimeofday(&_updated, NULL);
394 _mut.unlock();
|
395 mday 1.12
|
396 mike 1.2 return;
397 }
398
399 inline void AsyncOpNode::complete(OperationContext *con)
400 throw(IPCException)
401 {
402 _mut.lock(pegasus_thread_self());
|
403 mday 1.15 _state |= ASYNC_OPSTATE_COMPLETE;
|
404 mike 1.2 gettimeofday(&_updated, NULL);
405 context *c = con->remove_context();
406 while(c != 0)
407 {
408 _operation_list.add_context(c);
409 c = con->remove_context();
410 }
411 _mut.unlock();
|
412 mday 1.10 }
413
414 inline void AsyncOpNode::wait(void)
415 {
416 _client_sem.wait();
|
417 mike 1.2 }
418
|
419 mday 1.12 inline void AsyncOpNode::release(void)
420 {
421 _mut.lock(pegasus_thread_self());
422 _state |= ASYNC_OPSTATE_RELEASED;
423 _mut.unlock();
424 }
425
|
426 mike 1.2 inline void AsyncOpNode::_set_lifetime(struct timeval *lifetime)
427 {
|
428 mday 1.12 _mut.lock(pegasus_thread_self());
|
429 mike 1.2 _lifetime.tv_sec = lifetime->tv_sec;
430 _lifetime.tv_usec = lifetime->tv_usec;
|
431 mday 1.12 _mut.unlock();
|
432 mike 1.2 }
433
|
434 mday 1.12 inline Boolean AsyncOpNode::_check_lifetime(void)
|
435 mike 1.2 {
436 struct timeval now;
|
437 mday 1.12
|
438 mike 1.2 gettimeofday(&now, NULL);
439 if((_start.tv_sec + _lifetime.tv_sec ) >= now.tv_sec)
440 if((_start.tv_usec + _lifetime.tv_usec ) >= now.tv_usec)
441 return true;
442 return false;
443 }
444
445 inline Boolean AsyncOpNode::_is_child(void)
446 {
447 if (_parent != 0)
448 return true;
449 return false;
450 }
451
452 inline Uint32 AsyncOpNode::_is_parent(void)
453 {
454 return _children.count();
455 }
456
457 inline Boolean AsyncOpNode::_is_my_child(const AsyncOpNode & caller) const
458 {
459 mike 1.2 if ( _parent == &caller )
460 return true;
461 return false;
462 }
463
464 inline void AsyncOpNode::_make_orphan( AsyncOpNode & parent)
465 {
466 if( _parent == &parent )
467 {
468 _parent = NULL;
469 parent._children.remove(this);
470 }
471 else
472 throw Permission(pegasus_thread_self());
473 }
474
475 inline void AsyncOpNode::_adopt_child(AsyncOpNode *child)
476 {
477 if(child == NULL)
478 throw NullPointer();
479 if(true == child->_is_child())
480 mike 1.2 throw Permission(pegasus_thread_self());
481 child->_parent = this;
482 _children.insert_last(child);
483 }
484
485 inline void AsyncOpNode::_disown_child(AsyncOpNode *child)
486 {
487 if(child == NULL)
488 throw NullPointer();
489 if( false == child->_is_child() || false == child->_is_my_child( *this ))
490 throw Permission(pegasus_thread_self());
491 child->_make_orphan( *this );
492 _children.remove(child);
493 }
494
495 PEGASUS_NAMESPACE_END
496
497 #endif //Pegasus_AsyncOpNode_h
|