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