1 martin 1.37 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.38 //
|
3 martin 1.37 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.38 //
|
10 martin 1.37 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.38 //
|
17 martin 1.37 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.38 //
|
20 martin 1.37 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.38 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.37 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.38 //
|
28 martin 1.37 //////////////////////////////////////////////////////////////////////////
|
29 schuur 1.1 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include "WQLOperationRequestDispatcher.h"
|
33 a.arora 1.2 #include <Pegasus/Common/AutoPtr.h>
|
34 kumpf 1.20 #include <Pegasus/Common/StatisticalData.h>
|
35 schuur 1.1
36 PEGASUS_NAMESPACE_BEGIN
37
38 PEGASUS_USING_STD;
39
40 void WQLOperationRequestDispatcher::applyQueryToEnumeration(
|
41 kumpf 1.24 CIMResponseMessage* msg,
42 QueryExpressionRep* query)
|
43 schuur 1.1 {
|
44 kumpf 1.24 CIMEnumerateInstancesResponseMessage* enr =
45 (CIMEnumerateInstancesResponseMessage*) msg;
46 WQLSelectStatement* qs = ((WQLQueryExpressionRep*)query)->_stmt;
|
47 schuur 1.1
|
48 mike 1.36 Array<CIMInstance>& a = enr->getNamedInstances();
49
50 for (int i = a.size() - 1; i >= 0; i--)
|
51 kumpf 1.24 {
|
52 mike 1.36 WQLInstancePropertySource ips(a[i]);
|
53 kumpf 1.24 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 mike 1.36 qs->applyProjection(a[i], true);
|
62 kumpf 1.24 }
|
63 mike 1.36 else a.remove(i);
|
64 kumpf 1.24 }
65 catch (...)
66 {
|
67 mike 1.36 a.remove(i);
|
68 kumpf 1.24 }
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 kumpf 1.39
|
80 marek 1.30 PEG_TRACE((
81 TRC_DISPATCHER,
|
82 marek 1.32 Tracer::LEVEL4,
|
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 mike 1.36 Array<CIMInstance>& a = fromResponse->getNamedInstances();
132 for (Uint32 j = 0, m = a.size();
|
133 kumpf 1.24 j < m; j++)
134 {
|
135 mike 1.36 CIMObject co=CIMObject(a[j]);
|
136 kumpf 1.24 CIMObjectPath op=co.getPath();
137 const Array<CIMKeyBinding>& kbs=op.getKeyBindings();
138 if (kbs.size() == 0)
139 { // no path set why ?
140 if (clsRead == false)
141 {
142 cimClass = _repository->getClass(
143 poA->_nameSpace, op.getClassName(),
144 false,true,false, CIMPropertyList());
145 clsRead=true;
146 }
|
147 mike 1.36 op = a[j].buildPath(cimClass);
|
148 kumpf 1.24 }
149 op.setNameSpace(poA->_nameSpace);
150 op.setHost(System::getHostName());
151 co.setPath(op);
152 if (manyResponses)
153 toResponse->cimObjects.append(co);
154 }
155 }
156 else
157 {
158 CIMExecQueryResponseMessage* fromResponse =
159 (CIMExecQueryResponseMessage*) response;
160 CIMClass cimClass;
161 Boolean clsRead=false;
162 for (Uint32 j = 0, m = fromResponse->cimObjects.size(); j < m; j++)
163 {
164 CIMObject co=fromResponse->cimObjects[j];
165 CIMObjectPath op=co.getPath();
166 const Array<CIMKeyBinding>& kbs=op.getKeyBindings();
167 if (kbs.size()==0)
168 { // no path set why ?
169 kumpf 1.24 if (clsRead==false)
170 {
171 cimClass = _repository->getClass(
172 poA->_nameSpace,op.getClassName(),
173 false,true,false, CIMPropertyList());
174 clsRead=true;
175 }
176 op = CIMInstance(fromResponse->cimObjects[j]).buildPath(
177 cimClass);
178 }
179 op.setNameSpace(poA->_nameSpace);
180 op.setHost(System::getHostName());
181 co.setPath(op);
182 if (manyResponses)
183 toResponse->cimObjects.append(co);
184 }
185 }
186
187 if (manyResponses)
188 poA->deleteResponse(i);
189
190 kumpf 1.24 if (i == 0)
191 break;
192 } // for all responses in response list
193
194 // if we started with an enumerateInstances repsonse, then add it to overall
195 if ((startIndex == 0) && manyResponses)
196 poA->appendResponse(toResponse);
|
197 schuur 1.1
|
198 kumpf 1.24 PEG_METHOD_EXIT();
199 }
|
200 schuur 1.1
201 void WQLOperationRequestDispatcher::handleQueryRequest(
|
202 kumpf 1.24 CIMExecQueryRequestMessage* request)
|
203 schuur 1.1 {
|
204 kumpf 1.21 PEG_METHOD_ENTER(TRC_DISPATCHER,
|
205 kumpf 1.28 "WQLOperationRequestDispatcher::handleQueryRequest");
|
206 kumpf 1.21
|
207 kumpf 1.24 Boolean exception=false;
208 AutoPtr<WQLSelectStatement> selectStatement(new WQLSelectStatement());
209 AutoPtr<WQLQueryExpressionRep> qx;
210 CIMException cimException;
211 CIMName className;
212
213 if (request->queryLanguage!="WQL")
214 {
215 cimException = PEGASUS_CIM_EXCEPTION(
216 CIM_ERR_QUERY_LANGUAGE_NOT_SUPPORTED, request->queryLanguage);
217 exception=true;
218 }
219 else
220 {
221 try
222 {
223 WQLParser::parse(request->query, *selectStatement.get());
224 className = selectStatement->getClassName();
225 qx.reset(new WQLQueryExpressionRep("WQL", selectStatement.get()));
226 selectStatement.release();
227 }
228 kumpf 1.24 catch (ParseError&)
229 {
230 cimException =
231 PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_QUERY, request->query);
232 exception=true;
233 }
234 catch (MissingNullTerminator&)
235 {
236 cimException =
237 PEGASUS_CIM_EXCEPTION(CIM_ERR_INVALID_QUERY, request->query);
238 exception = true;
239 }
240
241 if (exception == false)
242 {
|
243 kumpf 1.27 if (!_checkExistenceOfClass(request->nameSpace, className))
244 {
245 cimException = PEGASUS_CIM_EXCEPTION(
246 CIM_ERR_INVALID_CLASS, className.getString());
|
247 kumpf 1.24 exception = true;
|
248 kumpf 1.27 }
|
249 kumpf 1.24 }
250 }
|
251 schuur 1.1
|
252 kumpf 1.21 if (exception)
253 {
254 CIMResponseMessage* response = request->buildResponse();
255 response->cimException = cimException;
|
256 schuur 1.1
|
257 kumpf 1.21 _enqueueResponse(request, response);
|
258 schuur 1.1 PEG_METHOD_EXIT();
259 return;
260 }
261
262 //
263 // Get names of descendent classes:
264 //
265 Array<ProviderInfo> providerInfos;
266
267 // This gets set by _lookupAllInstanceProviders()
268 Uint32 providerCount;
269
|
270 kumpf 1.24 try
271 {
|
272 chip 1.12 providerInfos =
273 _lookupAllInstanceProviders(
274 request->nameSpace,
275 className,
276 providerCount);
|
277 schuur 1.1 }
|
278 kumpf 1.33 catch (CIMException& e)
|
279 kumpf 1.24 {
|
280 schuur 1.1 // Return exception response if exception from getSubClasses
|
281 kumpf 1.21 CIMResponseMessage* response = request->buildResponse();
|
282 kumpf 1.33 response->cimException = e;
|
283 schuur 1.1
|
284 kumpf 1.21 _enqueueResponse(request, response);
|
285 schuur 1.1 PEG_METHOD_EXIT();
286 return;
287 }
288
289 // Test for "enumerate too Broad" and if so, execute exception.
290 // This limits the number of provider invocations, not the number
291 // of instances returned.
|
292 kumpf 1.24 if (providerCount > _maximumEnumerateBreadth)
|
293 schuur 1.1 {
|
294 marek 1.31 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL1,
|
295 kumpf 1.25 "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 thilo.boehm 1.34 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL2,
317 "CIM_ERROR_NOT_SUPPORTED for %s",
318 (const char*)request->className.getString().getCString()));
|
319 schuur 1.1
|
320 kumpf 1.21 CIMResponseMessage* response = request->buildResponse();
321 response->cimException =
322 PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, String::EMPTY);
|
323 schuur 1.1
|
324 kumpf 1.21 _enqueueResponse(request, response);
325 PEG_METHOD_EXIT();
|
326 schuur 1.1 return;
327 }
328
329 // We have instances for Providers and possibly repository.
330 // Set up an aggregate object and save a copy of the original request.
331
|
332 kumpf 1.24 OperationAggregate* poA= new OperationAggregate(
|
333 schuur 1.1 new CIMExecQueryRequestMessage(*request),
|
334 kumpf 1.24 request->getType(),
335 request->messageId,
336 request->queueIds.top(),
337 className, CIMNamespaceName(),
338 qx.release(),
339 "WQL");
|
340 schuur 1.1
341 // Set the number of expected responses in the OperationAggregate
342 Uint32 numClasses = providerInfos.size();
343 poA->_aggregationSN = cimOperationAggregationSN++;
344 poA->_nameSpace=request->nameSpace;
345
346 if (_repository->isDefaultInstanceProvider())
|
347 brian.campbell 1.10 {
|
348 kumpf 1.24 // Loop through providerInfos, forwarding requests to repository
349 for (Uint32 i = 0; i < numClasses; i++)
350 {
351 ProviderInfo& providerInfo = providerInfos[i];
352
353 // this class is registered to a provider - skip
354 if (providerInfo.hasProvider)
355 continue;
356
357 // If this class does not have a provider
358
|
359 kumpf 1.25 PEG_TRACE((TRC_DISPATCHER, Tracer::LEVEL4,
360 "Routing ExecQuery request for class %s to the "
361 "repository. Class # %u of %u, aggregation SN %u.",
362 (const char*)providerInfo.className.getString().getCString(),
|
363 mike 1.26 (unsigned int)(i + 1),
364 (unsigned int)(numClasses),
365 (unsigned int)(poA->_aggregationSN)));
|
366 kumpf 1.24
|
367 kumpf 1.29 // Create an EnumerateInstances response from an ExecQuery request
|
368 kumpf 1.24 AutoPtr<CIMEnumerateInstancesResponseMessage> response(
369 new CIMEnumerateInstancesResponseMessage(
370 request->messageId,
371 CIMException(),
|
372 mike 1.36 request->queueIds.copyAndPop()));
|
373 kumpf 1.24 response->syncAttributes(request);
374
375 try
376 {
377 // Enumerate instances only for this class
|
378 mike 1.36 response->setNamedInstances(
|
379 kumpf 1.24 _repository->enumerateInstancesForClass(
380 request->nameSpace,
|
381 mike 1.36 providerInfo.className));
|
382 kumpf 1.24 }
|
383 kumpf 1.33 catch (CIMException& e)
|
384 kumpf 1.24 {
|
385 kumpf 1.33 response->cimException = e;
|
386 kumpf 1.24 }
|
387 kumpf 1.33 catch (Exception& e)
|
388 kumpf 1.24 {
389 response->cimException = PEGASUS_CIM_EXCEPTION(
|
390 kumpf 1.33 CIM_ERR_FAILED, e.getMessage());
|
391 kumpf 1.24 }
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 _forwardRequestForAggregation(
|
410 venkat.puvvada 1.35 getQueueId(),
|
411 kumpf 1.24 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 venkat.puvvada 1.35 lookup(providerInfo.serviceId)->getQueueName(),
|
438 kumpf 1.25 (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 kumpf 1.40 false,false,false,
|
460 kumpf 1.24 CIMPropertyList(),
461 request->queueIds,
462 request->authType,
463 identityContainer.getUserName()));
464
465 context = &enumReq->operationContext;
466 if (providerIdContainer)
467 context->insert(*providerIdContainer);
468 context->insert(identityContainer);
469 _forwardRequestForAggregation(
|
470 venkat.puvvada 1.35 providerInfo.serviceId,
|
471 kumpf 1.24 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 requestCopy->className = providerInfo.className;
485
486 _forwardRequestForAggregation(
|
487 venkat.puvvada 1.35 providerInfo.serviceId,
|
488 kumpf 1.24 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
|