1 karl 1.19 //%2006////////////////////////////////////////////////////////////////////////
|
2 schuur 1.1 //
|
3 karl 1.8 // 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 schuur 1.1 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.8 // 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.11 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.19 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 schuur 1.1 //
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:
|
20 karl 1.19 //
|
21 schuur 1.1 // 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.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include "WQLOperationRequestDispatcher.h"
|
35 a.arora 1.2 #include <Pegasus/Common/AutoPtr.h>
|
36 kumpf 1.20 #include <Pegasus/Common/StatisticalData.h>
|
37 schuur 1.1
38 PEGASUS_NAMESPACE_BEGIN
39
40 PEGASUS_USING_STD;
41
42 void WQLOperationRequestDispatcher::applyQueryToEnumeration(
|
43 kumpf 1.24 CIMResponseMessage* msg,
44 QueryExpressionRep* query)
|
45 schuur 1.1 {
|
46 kumpf 1.24 CIMEnumerateInstancesResponseMessage* enr =
47 (CIMEnumerateInstancesResponseMessage*) msg;
48 WQLSelectStatement* qs = ((WQLQueryExpressionRep*)query)->_stmt;
|
49 schuur 1.1
|
50 mike 1.36 Array<CIMInstance>& a = enr->getNamedInstances();
51
52 for (int i = a.size() - 1; i >= 0; i--)
|
53 kumpf 1.24 {
|
54 mike 1.36 WQLInstancePropertySource ips(a[i]);
|
55 kumpf 1.24 try
56 {
57 if (qs->evaluateWhereClause(&ips))
58 {
59 //
60 // Specify that missing requested project properties are
61 // allowed to be consistent with clarification from DMTF
62 //
|
63 mike 1.36 qs->applyProjection(a[i], true);
|
64 kumpf 1.24 }
|
65 mike 1.36 else a.remove(i);
|
66 kumpf 1.24 }
67 catch (...)
68 {
|
69 mike 1.36 a.remove(i);
|
70 kumpf 1.24 }
71 }
|
72 schuur 1.1 }
73
74 void WQLOperationRequestDispatcher::handleQueryResponseAggregation(
|
75 kumpf 1.24 OperationAggregate* poA)
|
76 schuur 1.1 {
|
77 kumpf 1.24 PEG_METHOD_ENTER(TRC_DISPATCHER,
|
78 kumpf 1.28 "WQLOperationRequestDispatcher::handleQueryResponseAggregation");
|
79 kumpf 1.24
80 Uint32 numberResponses = poA->numberResponses();
|
81 marek 1.30
82 PEG_TRACE((
83 TRC_DISPATCHER,
|
84 marek 1.32 Tracer::LEVEL4,
|
85 kumpf 1.28 "WQLOperationRequestDispatcher::ExecQuery Response - "
|
86 marek 1.30 "Name Space: %s Class name: %s Response Count: %u",
87 (const char*) poA->_nameSpace.getString().getCString(),
88 (const char*) poA->_className.getString().getCString(),
89 numberResponses));
|
90 kumpf 1.24
91 if (numberResponses == 0)
92 return;
|
93 schuur 1.1
|
94 kumpf 1.24 CIMResponseMessage* response = poA->getResponse(0);
95 CIMExecQueryResponseMessage* toResponse = 0;
96 Uint32 startIndex = 0;
97 Uint32 endIndex = numberResponses - 1;
98 Boolean manyResponses = true;
99 if (response->getType() == CIM_ENUMERATE_INSTANCES_RESPONSE_MESSAGE)
100 {
|
101 kumpf 1.29 // Create an ExecQuery response from an EnumerateInstances request
|
102 kumpf 1.24 CIMRequestMessage* request = poA->getRequest();
103 AutoPtr<CIMExecQueryResponseMessage> query(
104 new CIMExecQueryResponseMessage(
105 request->messageId,
106 CIMException(),
107 request->queueIds.copyAndPop(),
108 Array<CIMObject>()));
109 query->syncAttributes(request);
|
110 aruran.ms 1.17 toResponse = query.release();
|
111 kumpf 1.24 }
112 else
113 {
114 toResponse = (CIMExecQueryResponseMessage*) response;
115 manyResponses = false;
116 }
|
117 brian.campbell 1.10
|
118 kumpf 1.24 // Work backward and delete each response off the end of the array
119 for (Uint32 i = endIndex; i >= startIndex; i--)
120 {
121 if (manyResponses)
122 response = poA->getResponse(i);
|
123 schuur 1.1
|
124 kumpf 1.24 if (response->getType() == CIM_ENUMERATE_INSTANCES_RESPONSE_MESSAGE)
125 {
126 // convert enumerate instances responses to exec query responses
127 applyQueryToEnumeration(response, poA->_query);
128 CIMEnumerateInstancesResponseMessage* fromResponse =
129 (CIMEnumerateInstancesResponseMessage*) response;
130 CIMClass cimClass;
131
132 Boolean clsRead=false;
|
133 mike 1.36 Array<CIMInstance>& a = fromResponse->getNamedInstances();
134 for (Uint32 j = 0, m = a.size();
|
135 kumpf 1.24 j < m; j++)
136 {
|
137 mike 1.36 CIMObject co=CIMObject(a[j]);
|
138 kumpf 1.24 CIMObjectPath op=co.getPath();
139 const Array<CIMKeyBinding>& kbs=op.getKeyBindings();
140 if (kbs.size() == 0)
141 { // no path set why ?
142 if (clsRead == false)
143 {
144 cimClass = _repository->getClass(
145 poA->_nameSpace, op.getClassName(),
146 false,true,false, CIMPropertyList());
147 clsRead=true;
148 }
|
149 mike 1.36 op = a[j].buildPath(cimClass);
|
150 kumpf 1.24 }
151 op.setNameSpace(poA->_nameSpace);
152 op.setHost(System::getHostName());
153 co.setPath(op);
154 if (manyResponses)
155 toResponse->cimObjects.append(co);
156 }
157 }
158 else
159 {
160 CIMExecQueryResponseMessage* fromResponse =
161 (CIMExecQueryResponseMessage*) response;
162 CIMClass cimClass;
163 Boolean clsRead=false;
164 for (Uint32 j = 0, m = fromResponse->cimObjects.size(); j < m; j++)
165 {
166 CIMObject co=fromResponse->cimObjects[j];
167 CIMObjectPath op=co.getPath();
168 const Array<CIMKeyBinding>& kbs=op.getKeyBindings();
169 if (kbs.size()==0)
170 { // no path set why ?
171 kumpf 1.24 if (clsRead==false)
172 {
173 cimClass = _repository->getClass(
174 poA->_nameSpace,op.getClassName(),
175 false,true,false, CIMPropertyList());
176 clsRead=true;
177 }
178 op = CIMInstance(fromResponse->cimObjects[j]).buildPath(
179 cimClass);
180 }
181 op.setNameSpace(poA->_nameSpace);
182 op.setHost(System::getHostName());
183 co.setPath(op);
184 if (manyResponses)
185 toResponse->cimObjects.append(co);
186 }
187 }
188
189 if (manyResponses)
190 poA->deleteResponse(i);
191
192 kumpf 1.24 if (i == 0)
193 break;
194 } // for all responses in response list
195
196 // if we started with an enumerateInstances repsonse, then add it to overall
197 if ((startIndex == 0) && manyResponses)
198 poA->appendResponse(toResponse);
|
199 schuur 1.1
|
200 kumpf 1.24 PEG_METHOD_EXIT();
201 }
|
202 schuur 1.1
203 void WQLOperationRequestDispatcher::handleQueryRequest(
|
204 kumpf 1.24 CIMExecQueryRequestMessage* request)
|
205 schuur 1.1 {
|
206 kumpf 1.21 PEG_METHOD_ENTER(TRC_DISPATCHER,
|
207 kumpf 1.28 "WQLOperationRequestDispatcher::handleQueryRequest");
|
208 kumpf 1.21
|
209 kumpf 1.24 Boolean exception=false;
210 AutoPtr<WQLSelectStatement> selectStatement(new WQLSelectStatement());
211 AutoPtr<WQLQueryExpressionRep> qx;
212 CIMException cimException;
213 CIMName className;
214
215 if (request->queryLanguage!="WQL")
216 {
217 cimException = PEGASUS_CIM_EXCEPTION(
218 CIM_ERR_QUERY_LANGUAGE_NOT_SUPPORTED, request->queryLanguage);
219 exception=true;
220 }
221 else
222 {
223 try
224 {
225 WQLParser::parse(request->query, *selectStatement.get());
226 className = selectStatement->getClassName();
227 qx.reset(new WQLQueryExpressionRep("WQL", selectStatement.get()));
228 selectStatement.release();
229 }
230 kumpf 1.24 catch (ParseError&)
231 {
232 cimException =
233 PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_QUERY, request->query);
234 exception=true;
235 }
236 catch (MissingNullTerminator&)
237 {
238 cimException =
239 PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_QUERY, request->query);
240 exception = true;
241 }
242
243 if (exception == false)
244 {
|
245 kumpf 1.27 if (!_checkExistenceOfClass(request->nameSpace, className))
246 {
247 cimException = PEGASUS_CIM_EXCEPTION(
248 CIM_ERR_INVALID_CLASS, className.getString());
|
249 kumpf 1.24 exception = true;
|
250 kumpf 1.27 }
|
251 kumpf 1.24 }
252 }
|
253 schuur 1.1
|
254 kumpf 1.21 if (exception)
255 {
256 CIMResponseMessage* response = request->buildResponse();
257 response->cimException = cimException;
|
258 schuur 1.1
|
259 kumpf 1.21 _enqueueResponse(request, response);
|
260 schuur 1.1 PEG_METHOD_EXIT();
261 return;
262 }
263
264 //
265 // Get names of descendent classes:
266 //
267 Array<ProviderInfo> providerInfos;
268
269 // This gets set by _lookupAllInstanceProviders()
270 Uint32 providerCount;
271
|
272 kumpf 1.24 try
273 {
|
274 chip 1.12 providerInfos =
275 _lookupAllInstanceProviders(
276 request->nameSpace,
277 className,
278 providerCount);
|
279 schuur 1.1 }
|
280 kumpf 1.33 catch (CIMException& e)
|
281 kumpf 1.24 {
|
282 schuur 1.1 // Return exception response if exception from getSubClasses
|
283 kumpf 1.21 CIMResponseMessage* response = request->buildResponse();
|
284 kumpf 1.33 response->cimException = e;
|
285 schuur 1.1
|
286 kumpf 1.21 _enqueueResponse(request, response);
|
287 schuur 1.1 PEG_METHOD_EXIT();
288 return;
289 }
290
291 // Test for "enumerate too Broad" and if so, execute exception.
292 // This limits the number of provider invocations, not the number
293 // of instances returned.
|
294 kumpf 1.24 if (providerCount > _maximumEnumerateBreadth)
|
295 schuur 1.1 {
|
296 marek 1.31 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL1,
|
297 kumpf 1.25 "ERROR: Enumerate operation too broad for class %s. "
298 "Limit = %u, providerCount = %u",
299 (const char*)request->className.getString().getCString(),
300 _maximumEnumerateBreadth,
301 providerCount));
|
302 schuur 1.1
|
303 kumpf 1.21 CIMResponseMessage* response = request->buildResponse();
304 response->cimException =
305 PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED, MessageLoaderParms(
|
306 kumpf 1.28 "Server.WQLOperationRequestDispatcher.QUERY_REQ_TOO_BROAD",
307 "The query request is too broad."));
|
308 schuur 1.1
|
309 kumpf 1.21 _enqueueResponse(request, response);
|
310 schuur 1.1 PEG_METHOD_EXIT();
311 return;
312 }
313
314 // If no provider is registered and the repository isn't the default,
315 // return CIM_ERR_NOT_SUPPORTED
316 if ((providerCount == 0) && !(_repository->isDefaultInstanceProvider()))
317 {
|
318 thilo.boehm 1.34 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL2,
319 "CIM_ERROR_NOT_SUPPORTED for %s",
320 (const char*)request->className.getString().getCString()));
|
321 schuur 1.1
|
322 kumpf 1.21 CIMResponseMessage* response = request->buildResponse();
323 response->cimException =
324 PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
|
325 schuur 1.1
|
326 kumpf 1.21 _enqueueResponse(request, response);
327 PEG_METHOD_EXIT();
|
328 schuur 1.1 return;
329 }
330
331 // We have instances for Providers and possibly repository.
332 // Set up an aggregate object and save a copy of the original request.
333
|
334 kumpf 1.24 OperationAggregate* poA= new OperationAggregate(
|
335 schuur 1.1 new CIMExecQueryRequestMessage(*request),
|
336 kumpf 1.24 request->getType(),
337 request->messageId,
338 request->queueIds.top(),
339 className, CIMNamespaceName(),
340 qx.release(),
341 "WQL");
|
342 schuur 1.1
343 // Set the number of expected responses in the OperationAggregate
344 Uint32 numClasses = providerInfos.size();
345 poA->_aggregationSN = cimOperationAggregationSN++;
346 poA->_nameSpace=request->nameSpace;
347
348 if (_repository->isDefaultInstanceProvider())
|
349 brian.campbell 1.10 {
|
350 kumpf 1.24 // Loop through providerInfos, forwarding requests to repository
351 for (Uint32 i = 0; i < numClasses; i++)
352 {
353 ProviderInfo& providerInfo = providerInfos[i];
354
355 // this class is registered to a provider - skip
356 if (providerInfo.hasProvider)
357 continue;
358
359 // If this class does not have a provider
360
|
361 kumpf 1.25 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL4,
362 "Routing ExecQuery request for class %s to the "
363 "repository. Class # %u of %u, aggregation SN %u.",
364 (const char*)providerInfo.className.getString().getCString(),
|
365 mike 1.26 (unsigned int)(i + 1),
366 (unsigned int)(numClasses),
367 (unsigned int)(poA->_aggregationSN)));
|
368 kumpf 1.24
|
369 kumpf 1.29 // Create an EnumerateInstances response from an ExecQuery request
|
370 kumpf 1.24 AutoPtr<CIMEnumerateInstancesResponseMessage> response(
371 new CIMEnumerateInstancesResponseMessage(
372 request->messageId,
373 CIMException(),
|
374 mike 1.36 request->queueIds.copyAndPop()));
|
375 kumpf 1.24 response->syncAttributes(request);
376
377 try
378 {
379 // Enumerate instances only for this class
|
380 mike 1.36 response->setNamedInstances(
|
381 kumpf 1.24 _repository->enumerateInstancesForClass(
382 request->nameSpace,
|
383 mike 1.36 providerInfo.className));
|
384 kumpf 1.24 }
|
385 kumpf 1.33 catch (CIMException& e)
|
386 kumpf 1.24 {
|
387 kumpf 1.33 response->cimException = e;
|
388 kumpf 1.24 }
|
389 kumpf 1.33 catch (Exception& e)
|
390 kumpf 1.24 {
391 response->cimException = PEGASUS_CIM_EXCEPTION(
|
392 kumpf 1.33 CIM_ERR_FAILED, e.getMessage());
|
393 kumpf 1.24 }
394 catch (...)
395 {
396 response->cimException = PEGASUS_CIM_EXCEPTION(
397 CIM_ERR_FAILED, String::EMPTY);
398 }
399
400 poA->appendResponse(response.release());
401 } // for all classes and derived classes
402
403 Uint32 numberResponses = poA->numberResponses();
404 Uint32 totalIssued = providerCount + (numberResponses > 0 ? 1 : 0);
405 poA->setTotalIssued(totalIssued);
406
407 if (numberResponses > 0)
408 {
409 handleEnumerateInstancesResponseAggregation(poA);
410 CIMResponseMessage* response = poA->removeResponse(0);
411 _forwardRequestForAggregation(
|
412 venkat.puvvada 1.35 getQueueId(),
|
413 kumpf 1.24 String(),
414 new CIMExecQueryRequestMessage(*request),
415 poA, response);
416 }
|
417 brian.campbell 1.10 } // if isDefaultInstanceProvider
|
418 kumpf 1.24 else
419 {
420 // Set the number of expected responses in the OperationAggregate
421 poA->setTotalIssued(providerCount);
422 }
|
423 schuur 1.1
424 // Loop through providerInfos, forwarding requests to providers
425 for (Uint32 i = 0; i < numClasses; i++)
426 {
427 // If this class has a provider
|
428 kumpf 1.24 ProviderInfo& providerInfo = providerInfos[i];
|
429 schuur 1.1
|
430 kumpf 1.24 // this class is NOT registered to a provider - skip
431 if (!providerInfo.hasProvider)
432 continue;
|
433 chip 1.12
|
434 kumpf 1.25 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL4,
435 "Routing ExecQuery request for class %s to "
436 "service \"%s\" for control provider \"%s\". "
437 "Class # %u of %u, aggregation SN %u.",
438 (const char*)providerInfo.className.getString().getCString(),
|
439 venkat.puvvada 1.35 lookup(providerInfo.serviceId)->getQueueName(),
|
440 kumpf 1.25 (const char*)providerInfo.controlProviderName.getCString(),
|
441 mike 1.26 (unsigned int)(i + 1),
442 (unsigned int)numClasses,
443 (unsigned int)(poA->_aggregationSN)));
|
444 kumpf 1.24
445 ProviderIdContainer* providerIdContainer =
446 providerInfo.providerIdContainer.get();
447
448 if (providerInfo.hasNoQuery)
449 {
450 OperationContext* context = &request->operationContext;
451 const OperationContext::Container* container = 0;
452 container = &context->get(IdentityContainer::NAME);
453 const IdentityContainer& identityContainer =
454 dynamic_cast<const IdentityContainer&>(*container);
455
456 AutoPtr<CIMEnumerateInstancesRequestMessage> enumReq(
457 new CIMEnumerateInstancesRequestMessage(
458 request->messageId,
459 request->nameSpace,
460 providerInfo.className,
461 false,false,false,false,
462 CIMPropertyList(),
463 request->queueIds,
464 request->authType,
465 kumpf 1.24 identityContainer.getUserName()));
466
467 context = &enumReq->operationContext;
468 if (providerIdContainer)
469 context->insert(*providerIdContainer);
470 context->insert(identityContainer);
471 _forwardRequestForAggregation(
|
472 venkat.puvvada 1.35 providerInfo.serviceId,
|
473 kumpf 1.24 providerInfo.controlProviderName,
474 enumReq.release(), poA);
475 }
476 else
477 {
478 AutoPtr<CIMExecQueryRequestMessage> requestCopy(
479 new CIMExecQueryRequestMessage(*request));
480
481 OperationContext* context = &request->operationContext;
482 if (providerIdContainer)
483 context->insert(*providerIdContainer);
484
485 requestCopy->operationContext = *context;
486 requestCopy->className = providerInfo.className;
487
488 _forwardRequestForAggregation(
|
489 venkat.puvvada 1.35 providerInfo.serviceId,
|
490 kumpf 1.24 providerInfo.controlProviderName,
491 requestCopy.release(), poA);
492 }
|
493 brian.campbell 1.10 } // for all classes and derived classes
|
494 schuur 1.1
|
495 kumpf 1.24 PEG_METHOD_EXIT();
|
496 schuur 1.1 }
497
498 PEGASUS_NAMESPACE_END
|