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