1 karl 1.40 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.4 //
|
3 karl 1.39 // 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.36 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.39 // 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.40 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.4 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 chip 1.8 // 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 mike 1.4 // 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.43 //
|
19 chip 1.8 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.4 // 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 chip 1.8 // 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 mike 1.4 // 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 Brasher (mbrasher@bmc.com)
31 //
|
32 a.arora 1.38 // Modified By: Amit K Arora, IBM (amita@in.ibm.com) for Bug#1090
|
33 joyce.j 1.41 // Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2076
|
34 david.dillard 1.43 // David Dillard, VERITAS Software Corp.
35 // (david.dillard@veritas.com)
|
36 aruran.ms 1.46 // Aruran, IBM (ashanmug@in.ibm.com) for Bug# 3475
|
37 mike 1.4 //
38 //%/////////////////////////////////////////////////////////////////////////////
39
|
40 mike 1.5 #include <Pegasus/Common/HashTable.h>
|
41 mike 1.7 #include <Pegasus/Common/IPC.h>
|
42 kumpf 1.19 #include <Pegasus/Common/Tracer.h>
|
43 aruran.ms 1.46 #include "Stack.h"
|
44 mike 1.4 #include "MessageQueue.h"
|
45 mday 1.24 #include "MessageQueueService.h"
|
46 mike 1.4 PEGASUS_USING_STD;
47
48 PEGASUS_NAMESPACE_BEGIN
49
|
50 mike 1.5 typedef HashTable<Uint32, MessageQueue*, EqualFunc<Uint32>, HashFunc<Uint32> >
51 QueueTable;
52
|
53 mday 1.33 static QueueTable _queueTable(256);
|
54 mday 1.28 static Mutex q_table_mut ;
|
55 mike 1.5
|
56 mday 1.35 void MessageQueue::remove_myself(Uint32 qid)
57 {
|
58 david.dillard 1.43 AutoMutex autoMut(q_table_mut);
59 _queueTable.remove(qid);
|
60 mday 1.35 }
61
|
62 aruran.ms 1.46 static Stack<Uint32> _qid_stack;
63 static Uint32 _qid_next = CIMOM_Q_ID + 1;
64 static Mutex _qid_mutex;
|
65 mday 1.35
|
66 david.dillard 1.43 Uint32 MessageQueue::getNextQueueId()
|
67 mike 1.5 {
|
68 aruran.ms 1.46 // If _qid_stack is empty, return _qid_next (and then increment _qid_next).
69 // Else return the top of the stack.
|
70 mike 1.16
|
71 aruran.ms 1.46 AutoMutex autoMutex(_qid_mutex);
|
72 chip 1.8
|
73 aruran.ms 1.46 if (_qid_stack.isEmpty())
74 return _qid_next++;
|
75 chip 1.8
|
76 aruran.ms 1.46 Uint32 queueId = _qid_stack.top();
77 _qid_stack.pop();
78 return queueId;
79 }
|
80 chip 1.8
|
81 aruran.ms 1.46 void MessageQueue::putQueueId(Uint32 queueId)
82 {
83 // Put the queueId on the top of the stack.
|
84 mike 1.7
|
85 aruran.ms 1.46 AutoMutex autoMutex(_qid_mutex);
86 // Ignore an attempt to return the well-known queue id (CIMOM_Q_ID).
87 // This id is reserved for the CIMOM queue.
|
88 mday 1.12
|
89 aruran.ms 1.46 if (queueId == CIMOM_Q_ID)
90 return;
|
91 mday 1.24
|
92 aruran.ms 1.46 _qid_stack.push(queueId);
93 }
|
94 mday 1.24
|
95 mike 1.16 MessageQueue::MessageQueue(
|
96 david.dillard 1.43 const char* name,
|
97 mike 1.16 Boolean async,
98 Uint32 queueId)
|
99 mday 1.24 : _queueId(queueId), _capabilities(0), _count(0), _front(0), _back(0), _async(async)
|
100 mike 1.5 {
|
101 mike 1.16 //
102 // Copy the name:
103 //
104
|
105 david.dillard 1.43 PEG_METHOD_ENTER(TRC_MESSAGEQUEUESERVICE,"MessageQueue::MessageQueue()");
|
106 kumpf 1.19
|
107 mike 1.16 if (!name)
|
108 david.dillard 1.43 name = "";
|
109 mike 1.16
110 _name = new char[strlen(name) + 1];
111 strcpy(_name, name);
112
|
113 kumpf 1.25 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL3,
|
114 kumpf 1.42 "MessageQueue::MessageQueue name = %s, queueId = %u", name, queueId);
|
115 kumpf 1.19
|
116 mike 1.16 //
117 // Insert into queue table:
118 //
|
119 a.arora 1.38 AutoMutex autoMut(q_table_mut);
|
120 david.dillard 1.43 while (!_queueTable.insert(_queueId, this))
121 ;
|
122 chip 1.8
|
123 david.dillard 1.43 PEG_METHOD_EXIT();
|
124 mike 1.5 }
125
126 MessageQueue::~MessageQueue()
127 {
128 // ATTN-A: thread safety!
|
129 kumpf 1.25 PEG_METHOD_ENTER(TRC_MESSAGEQUEUESERVICE,"MessageQueue::~MessageQueue()");
130 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL3,
|
131 kumpf 1.19 "MessageQueue::~MessageQueue queueId = %i, name = %s", _queueId, _name);
132
|
133 a.arora 1.38 {
|
134 david.dillard 1.43 AutoMutex autoMut(q_table_mut);
135 _queueTable.remove(_queueId);
|
136 a.arora 1.38 } // mutex unlocks here
|
137 david.dillard 1.43
|
138 mike 1.16 // Free the name:
|
139 david.dillard 1.43
|
140 mike 1.16 delete [] _name;
|
141 kumpf 1.19
|
142 david.dillard 1.43 while(_front)
|
143 joyce.j 1.41 {
144 Message* tmp = _front;
145 _front = _front->_next;
146 delete tmp;
147 }
|
148 aruran.ms 1.46
149 // Return the queue id.
150
151 putQueueId(_queueId);
|
152 joyce.j 1.41
|
153 kumpf 1.25 PEG_METHOD_EXIT();
|
154 chip 1.8 }
155
|
156 kumpf 1.37 void MessageQueue::enqueue(Message* message)
|
157 mike 1.4 {
|
158 kumpf 1.25 PEG_METHOD_ENTER(TRC_MESSAGEQUEUESERVICE,"MessageQueue::enqueue()");
|
159 kumpf 1.19
|
160 david.dillard 1.43 if (!message)
|
161 kumpf 1.19 {
|
162 david.dillard 1.43 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL3,
163 "MessageQueue::enqueue failure");
164 PEG_METHOD_EXIT();
165 throw NullPointer();
|
166 kumpf 1.19 }
|
167 mike 1.7
|
168 david.dillard 1.43 PEG_TRACE_STRING( TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL3,
|
169 kumpf 1.31 String("Queue name: ") + getQueueName() ) ;
|
170 david.dillard 1.43 Tracer::trace ( TRC_MESSAGEQUEUESERVICE,
|
171 kumpf 1.31 Tracer::LEVEL3,
|
172 david.dillard 1.43 "Message: [%s, %d]",
173 MessageTypeToString(message->getType()),
|
174 kumpf 1.31 message->getKey() );
|
175 david.dillard 1.43
|
176 a.arora 1.38 {
177 AutoMutex autoMut(_mut);
|
178 mike 1.4 if (_back)
179 {
|
180 david.dillard 1.43 _back->_next = message;
181 message->_prev = _back;
182 message->_next = 0;
183 _back = message;
|
184 mike 1.4 }
185 else
186 {
|
187 david.dillard 1.43 _front = message;
188 _back = message;
189 message->_prev = 0;
190 message->_next = 0;
|
191 mike 1.4 }
192 message->_owner = this;
|
193 david.dillard 1.43
|
194 mike 1.4 _count++;
|
195 kumpf 1.25 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL4,
|
196 david.dillard 1.43 "MessageQueue::enqueue _queueId = %d, _count = %d", _queueId, _count);
197
|
198 a.arora 1.38 } // mutex unlocks here
|
199 david.dillard 1.43
|
200 mday 1.22 handleEnqueue();
|
201 kumpf 1.25 PEG_METHOD_EXIT();
|
202 mday 1.15 }
203
|
204 david.dillard 1.43 Message* MessageQueue::dequeue()
|
205 mike 1.4 {
|
206 kumpf 1.25 PEG_METHOD_ENTER(TRC_MESSAGEQUEUESERVICE,"MessageQueue::dequeue()");
207
|
208 a.arora 1.38 AutoMutex autoMut(_mut);
|
209 mike 1.4 if (_front)
210 {
|
211 david.dillard 1.43 Message* message = _front;
212 _front = _front->_next;
213 if (_front)
214 _front->_prev = 0;
|
215 mike 1.4
|
216 david.dillard 1.43 if (_back == message)
217 _back = 0;
|
218 kumpf 1.25
|
219 david.dillard 1.43 _count--;
|
220 kumpf 1.25 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL4,
|
221 david.dillard 1.43 "MessageQueue::dequeue _queueId = %d, _count = %d",
|
222 kumpf 1.26 _queueId, _count);
|
223 kumpf 1.25
|
224 david.dillard 1.43 message->_next = 0;
225 message->_prev = 0;
226 message->_owner = 0;
|
227 kumpf 1.25
228 PEG_METHOD_EXIT();
|
229 david.dillard 1.43 return message;
|
230 mike 1.4 }
|
231 kumpf 1.25
232 PEG_METHOD_EXIT();
|
233 mike 1.4 return 0;
234 }
|
235 mday 1.23
|
236 mike 1.4
|
237 david.dillard 1.43
238 void MessageQueue::remove(Message* message)
|
239 mike 1.4 {
|
240 kumpf 1.25 PEG_METHOD_ENTER(TRC_MESSAGEQUEUESERVICE,"MessageQueue::remove()");
241
|
242 mike 1.4 if (!message)
|
243 kumpf 1.25 {
244 PEG_METHOD_EXIT();
|
245 david.dillard 1.43 throw NullPointer();
|
246 kumpf 1.25 }
|
247 mike 1.4
248 if (message->_owner != this)
|
249 kumpf 1.25 {
250 PEG_METHOD_EXIT();
|
251 david.dillard 1.43 throw NoSuchMessageOnQueue();
|
252 kumpf 1.25 }
|
253 mike 1.4
|
254 a.arora 1.38 {
255 AutoMutex autoMut(_mut);
|
256 chip 1.8
|
257 mike 1.4 if (message->_next)
|
258 david.dillard 1.43 message->_next->_prev = message->_prev;
|
259 mike 1.4 else
|
260 david.dillard 1.43 _back = message->_prev;
|
261 mike 1.4
262 if (message->_prev)
|
263 david.dillard 1.43 message->_prev->_next = message->_next;
|
264 mike 1.4 else
|
265 david.dillard 1.43 _front = message->_next;
|
266 mike 1.4
|
267 mike 1.7 _count--;
|
268 kumpf 1.25 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL4,
269 "MessageQueue::remove _count = %d", _count);
270
|
271 a.arora 1.38 } // mutex unlocks here
|
272 chip 1.8
|
273 mike 1.4 message->_prev = 0;
274 message->_next = 0;
275 message->_owner = 0;
|
276 kumpf 1.25
277 PEG_METHOD_EXIT();
|
278 mike 1.4 }
279
|
280 david.dillard 1.43 Message* MessageQueue::findByType(Uint32 type)
|
281 mike 1.4 {
|
282 david.dillard 1.43 AutoMutex autoMut(_mut);
|
283 chip 1.8
|
284 mike 1.4 for (Message* m = front(); m; m = m->getNext())
285 {
|
286 david.dillard 1.43 if (m->getType() == type)
287 {
288 return m;
289 }
|
290 mike 1.4 }
|
291 david.dillard 1.43
|
292 mike 1.4 return 0;
293 }
294
|
295 david.dillard 1.43 Message* MessageQueue::findByKey(Uint32 key)
|
296 mike 1.4 {
|
297 david.dillard 1.43 AutoMutex autoMut(_mut);
|
298 chip 1.8
|
299 mike 1.4 for (Message* m = front(); m; m = m->getNext())
300 {
|
301 mike 1.7 if (m->getKey() == key)
302 {
|
303 a.arora 1.38 return m;
|
304 mike 1.7 }
|
305 chip 1.8
|
306 mike 1.4 }
|
307 david.dillard 1.43
|
308 mike 1.4 return 0;
309 }
310
|
311 joyce.j 1.44 #ifdef PEGASUS_DEBUG
|
312 david.dillard 1.43 void MessageQueue::print(ostream& os) const
|
313 mike 1.4 {
|
314 david.dillard 1.43 AutoMutex autoMut(const_cast<MessageQueue *>(this)->_mut);
|
315 chip 1.8
|
316 david.dillard 1.43 for (const Message* m = front(); m; m = m->getNext())
317 m->print(os);
|
318 mike 1.4 }
|
319 joyce.j 1.44 #endif
|
320 mike 1.4
|
321 david.dillard 1.43 Message* MessageQueue::find(Uint32 type, Uint32 key)
|
322 mike 1.4 {
|
323 david.dillard 1.43 AutoMutex autoMut(_mut);
|
324 chip 1.8
|
325 mike 1.4 for (Message* m = front(); m; m = m->getNext())
326 {
|
327 david.dillard 1.43 if (m->getType() == type && m->getKey() == key)
328 {
329 return m;
330 }
|
331 mike 1.4 }
332
|
333 mike 1.5 return 0;
334 }
335
|
336 mike 1.7 const char* MessageQueue::getQueueName() const
|
337 mike 1.5 {
|
338 david.dillard 1.43 return _name;
|
339 mike 1.5 }
340
|
341 david.dillard 1.43 MessageQueue* MessageQueue::lookup(Uint32 queueId)
|
342 mike 1.5 {
|
343 kumpf 1.19
|
344 mike 1.5 MessageQueue* queue = 0;
|
345 a.arora 1.38 AutoMutex autoMut(q_table_mut);
|
346 chip 1.8
|
347 mike 1.5 if (_queueTable.lookup(queueId, queue))
|
348 mike 1.7 {
|
349 david.dillard 1.43 return queue;
|
350 mike 1.7 }
|
351 chip 1.8
|
352 mike 1.7 // Not found!
|
353 mike 1.5
|
354 kumpf 1.25 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL3,
|
355 kumpf 1.42 "MessageQueue::lookup failure queueId = %u", queueId);
|
356 kumpf 1.19
|
357 mike 1.4 return 0;
|
358 mike 1.6 }
|
359 mike 1.7
360
|
361 david.dillard 1.43 MessageQueue* MessageQueue::lookup(const char *name)
|
362 mike 1.7 {
|
363 kumpf 1.19
|
364 david.dillard 1.43 if(name == NULL)
365 throw NullPointer();
|
366 chip 1.8
|
367 david.dillard 1.43 AutoMutex autoMut(q_table_mut);
|
368 mike 1.7 for(QueueTable::Iterator i = _queueTable.start(); i; i++)
369 {
370 // ATTN: Need to decide how many characters to compare in queue names
|
371 david.dillard 1.43 if(! strcmp( ((MessageQueue *)i.value())->getQueueName(), name) )
372 {
373 return( (MessageQueue *)i.value());
374 }
375 }
|
376 chip 1.8
|
377 david.dillard 1.43 Tracer::trace(TRC_MESSAGEQUEUESERVICE, Tracer::LEVEL3,
378 "MessageQueue::lookup failure - name = %s", name);
|
379 kumpf 1.19
|
380 david.dillard 1.43 return 0;
|
381 mike 1.7 }
382
|
383 mike 1.6
384 void MessageQueue::handleEnqueue()
385 {
386
|
387 mike 1.4 }
388
389 PEGASUS_NAMESPACE_END
|