1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <base/strings.h>
26 #include <base/messages.h>
27 #include <base/log.h>
28 #include <base/strings.h>
29 #include <base/paths.h>
30 #include <base/io.h>
31 #include <wql/wql.h>
32 #include "disp.h"
33
34 #define T MI_T
35
36 /*
37 **==============================================================================
38 **
39 ** Data structures
40 **
41 **==============================================================================
42 */
43 mike 1.1
44 /*
45 subscription item - represents single subscription;
46 */
47 typedef struct _DispSubscriptionItem
48 {
49 struct _DispSubscriptionItem* next;
50 struct _DispSubscriptionItem* prev;
51
52 /* The batch this context was allocated from */
53 Batch batch;
54
55 /* filter */
56 MI_ConstString filter;
57 MI_ConstString language;
58
59 /* unique id of the sub */
60 MI_Uint64 subscriptionID;
61
62 /* Client identifier if supported */
63 MI_Uint64 clientID;
64 mike 1.1
65 }
66 DispSubscriptionItem;
67
68
69 /* subscriptions context -
70 used to track indicaiton providers
71 and store indications for 'pull' operation
72 one context per ns/cn pair
73 */
74 typedef struct _DispIndicationContext
75 {
76 struct _DispIndicationContext* next;
77 struct _DispIndicationContext* prev;
78
79 /* The batch this context was allocated from */
80 Batch batch;
81
82 /* namespace/cn */
83 MI_ConstString nameSpace;
84 MI_ConstString className;
85 mike 1.1
86 /* unique id of the context (used by ProvMgr) */
87 MI_Uint64 ctxID;
88
89 /* provider info */
90 const ProvRegEntry* provEntry;
91
92 /* exisitng subscriptions */
93 DispSubscriptionItem* headSubscriptions;
94 DispSubscriptionItem* tailSubscriptions;
95 }
96 DispIndicationContext;
97
98
99 /*
100 **==============================================================================
101 **
102 ** Local definitions
103 **
104 **==============================================================================
105 */
106 mike 1.1 static MI_Result _SendErrorResponse(
107 Message* req,
108 MI_Result r);
109
110 static DispIndicationContext* _FindIndCtxByNScn(
111 Disp* self,
112 MI_ConstString nameSpace,
113 MI_ConstString className)
114 {
115 DispIndicationContext* current = (DispIndicationContext*)self->headIndCtx;
116
117 while (current)
118 {
119 if (0 == Zcasecmp(nameSpace, current->nameSpace) &&
120 0 == Zcasecmp(className, current->className))
121 break;
122
123 current = current->next;
124 }
125 return current;
126 }
127 mike 1.1
128 static DispIndicationContext* _FindIndCtxByID(
129 Disp* self,
130 MI_Uint64 id)
131 {
132 DispIndicationContext* current = (DispIndicationContext*)self->headIndCtx;
133
134 while (current)
135 {
136 if (id == current->ctxID)
137 break;
138
139 current = current->next;
140 }
141 return current;
142 }
143
144 static DispSubscriptionItem* _FindSubscriptionItem(
145 DispIndicationContext* ctx,
146 MI_Uint64 subscriptionID)
147 {
148 mike 1.1 DispSubscriptionItem* item = ctx->headSubscriptions;
149
150 while (item)
151 {
152 if (item->subscriptionID == subscriptionID)
153 break;
154
155 item = item->next;
156 }
157 return item;
158 }
159
160
161 static void _DestroySubscriptionItem(
162 DispSubscriptionItem* item)
163 {
164 Batch_Destroy(&item->batch);
165 }
166 static void _DestroyIndCtx(
167 DispIndicationContext* ctx)
168 {
169 mike 1.1 DispSubscriptionItem* item = ctx->headSubscriptions;
170
171 while (item)
172 {
173 DispSubscriptionItem* next = item->next;
174
175 _DestroySubscriptionItem(item);
176 item = next;
177 }
178 Batch_Destroy(&ctx->batch);
179 }
180
181
182 static MI_Result _FindCreateIndCtx(
183 Disp* self,
184 SubscribeReq* req,
185 ProvRegEntry const** reg)
186 {
187 /* look for exisiting first */
188 DispIndicationContext* ctx = _FindIndCtxByNScn( self, req->nameSpace, req->className );
189
190 mike 1.1 if (!ctx)
191 {
192 Batch batch = BATCH_INITIALIZER;
193
194 /* Allocate heap space for message */
195 ctx = (DispIndicationContext*) Batch_GetClear(&batch, sizeof(DispIndicationContext) );
196
197 if (!ctx)
198 return MI_RESULT_FAILED;
199
200 /* Copy batch into context (released by _Destroy method) */
201 memcpy(&ctx->batch, &batch, sizeof(batch));
202
203 ctx->className = Batch_Zdup(&batch, req->className);
204 ctx->nameSpace = Batch_Zdup(&batch, req->nameSpace);
205
206 if (!ctx->className || !ctx->nameSpace)
207 {
208 _DestroyIndCtx(ctx);
209 return MI_RESULT_FAILED;
210 }
211 mike 1.1 ctx->ctxID = ++self->nextID;
212
213 /* Look for provider info */
214 ctx->provEntry = ProvReg_FindProviderForClass(&self->provreg,
215 req->nameSpace, req->className);
216
217 if (!ctx->provEntry)
218 {
219 _DestroyIndCtx(ctx);
220 return MI_RESULT_INVALID_NAMESPACE;
221 }
222
223 /* add context to the list */
224 List_Append(&self->headIndCtx, &self->tailIndCtx, (ListElem*)ctx);
225 }
226
227 /* Update request with correct IDs */
228 req->ctxID = ctx->ctxID;
229 req->subscriptionID = ++self->nextID;
230
231 /* Set out parameter */
232 mike 1.1 *reg = ctx->provEntry;
233
234 return MI_RESULT_OK;
235 }
236
237 static MI_Result _UpdateIndicationCtxWithSub(
238 Disp* self,
239 SubscribeReq* dispReq)
240 {
241 DispIndicationContext* ctx;
242 DispSubscriptionItem* subItem;
243
244 ctx = _FindIndCtxByID( self, dispReq->ctxID );
245
246 /* unlikely, but it can be removed by other operation */
247 if (!ctx)
248 return MI_RESULT_FAILED;
249
250 /* */
251 subItem = _FindSubscriptionItem(ctx, dispReq->subscriptionID);
252
253 mike 1.1 if (subItem)
254 return MI_RESULT_ALREADY_EXISTS;
255
256 {
257 Batch batch = BATCH_INITIALIZER;
258
259 /* Allocate heap space for message */
260 subItem = (DispSubscriptionItem*) Batch_GetClear(&batch, sizeof(DispSubscriptionItem) );
261
262 if (!subItem)
263 return MI_RESULT_FAILED;
264
265 /* Copy batch into context (released by _Destroy method) */
266 memcpy(&subItem->batch, &batch, sizeof(batch));
267
268 subItem->filter = Batch_Zdup(&batch, dispReq->filter);
269 subItem->language = Batch_Zdup(&batch, dispReq->language);
270
271 if (!subItem->filter || !subItem->language)
272 {
273 _DestroySubscriptionItem(subItem);
274 mike 1.1 return MI_RESULT_FAILED;
275 }
276 subItem->subscriptionID = dispReq->subscriptionID;
277 subItem->clientID = dispReq->base.request->clientID;
278
279 /* add item to the context */
280 List_Append(
281 (ListElem**)&ctx->headSubscriptions,
282 (ListElem**)&ctx->tailSubscriptions,
283 (ListElem*)subItem);
284 }
285
286 return MI_RESULT_OK;
287 }
288
289 static void _ProcessSubscribeResponse(
290 Disp* self,
291 PostResultMsg* rsp)
292 {
293 MI_Result r;
294 SubscribeReq* dispReq = (SubscribeReq*)rsp->base.request;
295 mike 1.1
296
297 /* Find context, create subscription struct */
298 Mutex_Lock(&self->mt);
299
300 r = _UpdateIndicationCtxWithSub( self, dispReq );
301
302 Mutex_Unlock(&self->mt);
303
304 /* check if error was detected */
305 if (MI_RESULT_OK != r)
306 {
307 _SendErrorResponse(rsp->base.request->request, r);
308 }
309
310 /* send subscription response */
311 {
312 SubscribeRes* resp;
313 char s[50];
314
315 resp = SubscribeRes_New( rsp->base.request->request->msgID );
316 mike 1.1
317 if (!resp)
318 return ;
319
320 Snprintf(s, MI_COUNT(s), UINT64_FMT "," UINT64_FMT,
321 dispReq->ctxID,
322 dispReq->subscriptionID);
323
324 resp->subscriptionID = Batch_Strdup2(resp->base.batch, s);
325
326 Message_SetRequest(&resp->base,rsp->base.request->request);
327 (*rsp->base.request->request->callback)(&resp->base, rsp->base.request->request->callbackData);
328
329 SubscribeRes_Release(resp);
330 }
331
332 }
333
334 static void _ProviderToDispatcherCallback(
335 Message* msg,
336 void* callbackData)
337 mike 1.1 {
338 switch ( msg->tag )
339 {
340 case PostResultMsgTag:
341 {
342 PostResultMsg* rsp = (PostResultMsg*)msg;
343
344 if (msg->request && msg->request->request && msg->request->request->tag == DispResultMsgTag)
345 {
346 DispResultMsg* dispStateMsg = (DispResultMsg*)msg->request->request;
347
348 if (rsp->result != MI_RESULT_OK && dispStateMsg->result == MI_RESULT_OK)
349 {
350 dispStateMsg->result = rsp->result;
351 }
352
353 if ( AtomicDec(&dispStateMsg->requestCounter) )
354 { /* last result - forward it to the net stack */
355 rsp->result = dispStateMsg->result;
356 }
357 else /* not the last result - skip it */
358 mike 1.1 return;
359
360 }
361 else if (msg->request && msg->request->tag == SubscribeReqTag)
362 {
363 /* process subscription response */
364 if (MI_RESULT_OK != rsp->result )
365 break;
366
367 /*
368 validate parameter msg->request->request is a parameter received from network transport;
369 msg->request is a message created by disp for provmgr
370 */
371 if (msg->request->request)
372 {
373 _ProcessSubscribeResponse((Disp*)callbackData, rsp);
374 return;
375 }
376 }
377 }
378 break;
379 mike 1.1
380 default:
381 break;
382 }
383
384 /* forward message to the other side */
385 if (msg->request && msg->request->request)
386 {
387 /* delegate message to protocol stack */
388 msg->clientID = msg->request->request->clientID;
389 (*msg->request->request->callback)(msg, msg->request->request->callbackData);
390 }
391 else if (msg->request)
392 {
393 /* delegate message to protocol stack */
394 msg->clientID = msg->request->clientID;
395 (*msg->request->callback)(msg, msg->request->callbackData);
396 }
397 else
398 {
399 (*msg->callback)(msg, msg->callbackData);
400 mike 1.1 }
401 }
402
403 static MI_Boolean _DispatchEnumerateInstancesReq(
404 Disp* self,
405 const MI_Char* className,
406 const EnumerateInstancesReq* req,
407 DispResultMsg* dispStateMsg)
408 {
409 const ProvRegEntry* entry;
410 EnumerateInstancesReq* msg;
411 MI_Result r;
412
413 /* Attempt to find a provider for this class */
414 {
415 entry = ProvReg_FindProviderForClass(&self->provreg,
416 req->nameSpace, className);
417
418 if (!entry)
419 return MI_FALSE;
420 }
421 mike 1.1
422 /* Create new request to send to provider */
423 msg = EnumerateInstancesReq_New(req->base.msgID, req->base.flags);
424 msg->base.clientID = req->base.clientID;
425 msg->base.uid = req->base.uid;
426 msg->base.gid = req->base.gid;
427 msg->nameSpace = Batch_Zdup(msg->base.batch, req->nameSpace);
428 msg->className = Batch_Zdup(msg->base.batch, className);
429
430 /* Clone the query fields (if any) */
431 if (req->queryLanguage)
432 msg->queryLanguage = Batch_Zdup(msg->base.batch, req->queryLanguage);
433
434 if (req->queryExpression)
435 msg->queryExpression = Batch_Zdup(msg->base.batch,req->queryExpression);
436
437 if (req->wql)
438 msg->wql = WQL_Clone(req->wql, msg->base.batch);
439
440 /* Save request's class name to allow porvmgr pack back only base properties */
441 if (req->basePropertiesOnly)
442 mike 1.1 msg->requestClassName = Batch_Zdup(msg->base.batch, req->className);
443
444 AtomicInc(&dispStateMsg->requestCounter);
445 Message_SetRequest(&msg->base, &dispStateMsg->base);
446
447 /* Setup callback */
448 msg->base.callback = _ProviderToDispatcherCallback;
449 msg->base.callbackData = self;
450
451 /* Send the request to provider manager */
452 r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, entry);
453
454 /* Release the original message */
455 EnumerateInstancesReq_Release(msg);
456
457 /* Log failure */
458 if (r != MI_RESULT_OK)
459 {
460 LOGW((T("AgentMgr_HandleRequest() failed: %u: %s"), r,
461 Result_ToString(r)));
462
463 mike 1.1 AtomicDec(&dispStateMsg->requestCounter);
464 return MI_FALSE;
465 }
466
467
468 return MI_TRUE;
469 }
470
471 static MI_Boolean _DispatchAssocReq(
472 Disp* self,
473 const MI_Char* className,
474 const AssociatorsOfReq* req,
475 DispResultMsg* dispStateMsg)
476 {
477 const ProvRegEntry* entry;
478 AssociatorsOfReq* msg;
479 MI_Result r;
480
481 /* Attempt to find a provider for this class */
482 {
483 entry = ProvReg_FindProviderForClass(&self->provreg,
484 mike 1.1 req->nameSpace, className);
485
486 if (!entry)
487 return MI_FALSE;
488 }
489
490 /* Create new request to send to provider */
491 msg = AssociatorsOfReq_New(req->base.msgID, req->base.flags);
492 msg->base.clientID = req->base.clientID;
493 msg->base.uid = req->base.uid;
494 msg->base.gid = req->base.gid;
495 /* original request will be kept for the request duration, so perform shallow copy only */
496 /*ATTN! perform full copy*/
497 msg->nameSpace = req->nameSpace;
498 msg->assocClass = req->assocClass;
499 msg->resultClass = req->resultClass;
500 msg->role = req->role;
501 msg->resultRole = req->resultRole;
502 msg->instance = req->instance;
503 msg->packedInstancePtr = req->packedInstancePtr;
504 msg->packedInstanceSize = req->packedInstanceSize;
505 mike 1.1
506 msg->className = className;
507
508 AtomicInc(&dispStateMsg->requestCounter);
509 Message_SetRequest(&msg->base, &dispStateMsg->base);
510
511 /* Setup callback */
512 msg->base.callback = _ProviderToDispatcherCallback;
513 msg->base.callbackData = self;
514
515 /* Send the request to provider manager */
516 r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, entry);
517
518 /* Release the original message */
519 AssociatorsOfReq_Release(msg);
520
521 /* Log failure */
522 if (r != MI_RESULT_OK)
523 {
524 LOGW((T("AgentMgr_HandleRequest() failed: %u: %s"), r,
525 Result_ToString(r)));
526 mike 1.1
527 AtomicDec(&dispStateMsg->requestCounter);
528 return MI_FALSE;
529 }
530
531 return MI_TRUE;
532 }
533
534 static MI_Boolean _DispatchRefReq(
535 Disp* self,
536 const MI_Char* className,
537 const ReferencesOfReq* req,
538 DispResultMsg* dispStateMsg)
539 {
540 const ProvRegEntry* entry;
541 ReferencesOfReq* msg;
542 MI_Result r;
543
544 /* Attempt to find a provider for this class */
545 {
546 entry = ProvReg_FindProviderForClass(&self->provreg,
547 mike 1.1 req->nameSpace, className);
548
549 if (!entry)
550 return MI_FALSE;
551 }
552
553 /* Create new request to send to provider */
554 msg = ReferencesOfReq_New(req->base.msgID, req->base.flags);
555 msg->base.clientID = req->base.clientID;
556 msg->base.uid = req->base.uid;
557 msg->base.gid = req->base.gid;
558 /* original request will be kept for the request duration, so perform shallow copy only */
559 /*ATTN! perform full copy*/
560 msg->nameSpace = req->nameSpace;
561 msg->assocClass = req->assocClass;
562 msg->role = req->role;
563 msg->instance = req->instance;
564 msg->packedInstancePtr = req->packedInstancePtr;
565 msg->packedInstanceSize = req->packedInstanceSize;
566
567 msg->className = className;
568 mike 1.1
569 AtomicInc(&dispStateMsg->requestCounter);
570 Message_SetRequest(&msg->base, &dispStateMsg->base);
571
572 /* Setup callback */
573 msg->base.callback = _ProviderToDispatcherCallback;
574 msg->base.callbackData = self;
575
576 /* Send the request to provider manager */
577 r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, entry);
578
579 /* Release the original message */
580 ReferencesOfReq_Release(msg);
581
582 /* Log failure */
583 if (r != MI_RESULT_OK)
584 {
585 LOGW((T("AgentMgr_HandleRequest() failed: %u: %s"), r,
586 Result_ToString(r)));
587
588 AtomicDec(&dispStateMsg->requestCounter);
589 mike 1.1 return MI_FALSE;
590 }
591
592 return MI_TRUE;
593 }
594
595 static MI_Result _SendErrorResponse(
596 Message* req,
597 MI_Result r
598 )
599 {
600 PostResultMsg* resp;
601
602 resp = PostResultMsg_New( req->msgID );
603
604 if (!resp)
605 return MI_RESULT_FAILED;
606
607 resp->result = r;
608 Message_SetRequest(&resp->base,req);
609 (*req->callback)(&resp->base, req->callbackData);
610 mike 1.1
611 PostResultMsg_Release(resp);
612
613 return MI_RESULT_OK;
614 }
615
616 static MI_Result _HandleEnumerateInstancesReq(
617 Disp* self,
618 EnumerateInstancesReq* req)
619 {
620 ProvRegPosition pos;
621 MI_Result r;
622 MI_Boolean sentOk = MI_FALSE;
623 DispResultMsg* dispStateMsg;
624
625 /* Validate input parameters */
626 if (!req->className || !req->nameSpace)
627 return MI_RESULT_INVALID_PARAMETER;
628
629 /* create a state message that will keep track of results from providers */
630 dispStateMsg = DispResultMsg_New(req->base.msgID);
631 mike 1.1 if (!dispStateMsg)
632 return MI_RESULT_FAILED;
633
634 /* add one for sending thread so first 'fast' provider will not send its response all the way */
635 AtomicInc(&dispStateMsg->requestCounter);
636
637 dispStateMsg->base.clientID = req->base.clientID;
638 /* Setup callback */
639 dispStateMsg->base.callback = req->base.callback;
640 dispStateMsg->base.callbackData = req->base.callbackData;
641
642 /* Precompile the query */
643 if (req->queryLanguage || req->queryExpression)
644 {
645 /* Fail if either query language or expression is missing */
646 if (!req->queryLanguage || !req->queryExpression)
647 {
648 LOGW((T("queryLanguage or queryExpression is missing")));
649 r = MI_RESULT_INVALID_QUERY;
650 goto sendErrorBack;
651 }
652 mike 1.1
653 /* Reject non-WQL queries */
654 if (Zcmp(req->queryLanguage, T("WQL")) != 0)
655 {
656 LOGW((T("unknown query language: %s"), req->queryLanguage));
657 r = MI_RESULT_QUERY_LANGUAGE_NOT_SUPPORTED;
658 goto sendErrorBack;
659 }
660
661 /* Compile the query */
662 {
663 req->wql = WQL_Parse(req->queryExpression, req->base.batch);
664
665 if (!req->wql)
666 {
667 LOGW((T("invalid query expression: %s"), req->queryExpression));
668 r = MI_RESULT_INVALID_QUERY;
669 goto sendErrorBack;
670 }
671 }
672
673 mike 1.1 /* Verify that the query classname matches the enumeration classname */
674 if (Zcmp(req->wql->className, req->className) != 0)
675 {
676 LOGW((T("query/enumeration class name mismatch: %s/%s"),
677 req->className, req->className));
678 r = MI_RESULT_INVALID_QUERY;
679 goto sendErrorBack;
680 }
681 }
682
683 /* Send to direct name */
684 if (_DispatchEnumerateInstancesReq(self, req->className, req, dispStateMsg))
685 sentOk = MI_TRUE;
686
687 if (req->deepInheritance)
688 {
689 /* Begin enumeration of classes for this request */
690 {
691 r = ProvReg_BeginClasses(&self->provreg, req->nameSpace,
692 req->className, MI_TRUE, &pos);
693
694 mike 1.1 if (MI_RESULT_OK != r)
695 {
696 LOGD((T("ProvReg_BeginClasses() failed: %u: %s"),
697 r, Result_ToString(r)));
698
699 LOGI((T("unknown class in enumerate request: %s:%s"),
700 req->nameSpace, req->className));
701
702 /* send error back to caller */
703 goto sendErrorBack;
704 }
705 }
706
707 /* While more classes */
708 for (;;)
709 {
710 const MI_Char* derived = NULL;
711 MI_Boolean done;
712
713 r = ProvReg_NextClass(&pos, &derived, &done);
714
715 mike 1.1 if (done)
716 break;
717
718 if (MI_RESULT_OK != r)
719 {
720 LOGD((T("ProvReg_NextClass() failed: %u: %s"),
721 r, Result_ToString(r)));
722
723 LOGI((T("unknown class in enumerate request: %s:%s"),
724 req->nameSpace, req->className));
725
726 /* send error back to caller */
727 goto sendErrorBack;
728 }
729
730 if (_DispatchEnumerateInstancesReq(self, derived, req, dispStateMsg))
731 sentOk = MI_TRUE;
732 }
733
734 /* Finalize enumeration */
735 {
736 mike 1.1 r = ProvReg_EndClasses(&pos);
737
738 if (MI_RESULT_OK != r)
739 {
740 LOGD((T("ProvReg_EndClasses() failed: %u: %s"),
741 r, Result_ToString(r)));
742 /* send error back to caller */
743 goto sendErrorBack;
744 }
745 }
746 } /* if deep*/
747
748 /* Fail if no provider was found for request */
749 if (!sentOk)
750 {
751 LOGD((T("found no providers for class: %s"), MI_GET_SAFE_PRINTF_STRING(req->className)));
752 r = MI_RESULT_NOT_FOUND;
753 goto sendErrorBack;
754 }
755
756 if ( AtomicDec(&dispStateMsg->requestCounter) )
757 mike 1.1 { /* last result - forward it to the net stack */
758 r = dispStateMsg->result;
759 goto sendErrorBack;
760 }
761
762 DispResultMsg_Release(dispStateMsg);
763 return MI_RESULT_OK;
764
765 sendErrorBack:
766 DispResultMsg_Release(dispStateMsg);
767 return _SendErrorResponse(&req->base,r);
768 }
769
770
771 static MI_Result _HandleGetInstanceReq(
772 Disp* self,
773 GetInstanceReq* req)
774 {
775 MI_Result r;
776 const ProvRegEntry* reg;
777
778 mike 1.1 /* Validate input parameters */
779 if (!req->instanceName || !req->nameSpace)
780 return MI_RESULT_INVALID_PARAMETER;
781
782 // Find a provider for this class.
783 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
784 req->instanceName->classDecl->name );
785
786 if (!reg)
787 {
788 r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/
789 LOGD((T("cannot find provider for class: %s/%s"),
790 MI_GET_SAFE_PRINTF_STRING(req->nameSpace),
791 MI_GET_SAFE_PRINTF_STRING(req->instanceName->classDecl->name)));
792 goto sendErrorBack;
793 }
794
795 // Send the request to provider manager.
796 r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);
797
798 if (r != MI_RESULT_OK)
799 mike 1.1 {
800 LOGD((T("AgentMgr_HandleRequest for namespace: %s"),
801 MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));
802 goto sendErrorBack;
803 }
804
805 return MI_RESULT_OK;
806
807 sendErrorBack:
808 return _SendErrorResponse(&req->base,r);
809 }
810
811 static MI_Result _HandleCreateInstanceReq(
812 Disp* self,
813 CreateInstanceReq* req)
814 {
815 MI_Result r;
816 const ProvRegEntry* reg;
817
818 /* Validate input parameters */
819 if (!req->instance || !req->nameSpace)
820 mike 1.1 return MI_RESULT_INVALID_PARAMETER;
821
822 // Find a provider for this class.
823 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
824 req->instance->classDecl->name );
825
826 if (!reg)
827 {
828 r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/
829 LOGD((T("cannot find provider for class: %s/%s"),
830 MI_GET_SAFE_PRINTF_STRING(req->nameSpace),
831 MI_GET_SAFE_PRINTF_STRING(req->instance->classDecl->name)));
832 goto sendErrorBack;
833 }
834
835 // Send the request to provider manager.
836 r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);
837
838 if (r != MI_RESULT_OK)
839 {
840 LOGD((T("AgentMgr_HandleRequest for namespace: %s"),
841 mike 1.1 MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));
842 goto sendErrorBack;
843 }
844
845 return MI_RESULT_OK;
846
847 sendErrorBack:
848 return _SendErrorResponse(&req->base,r);
849 }
850
851 static MI_Result _HandleModifyInstanceReq(
852 Disp* self,
853 ModifyInstanceReq* req)
854 {
855 MI_Result r;
856 const ProvRegEntry* reg;
857
858 /* Validate input parameters */
859 if (!req->instance || !req->nameSpace)
860 return MI_RESULT_INVALID_PARAMETER;
861
862 mike 1.1 // Find a provider for this class.
863 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
864 req->instance->classDecl->name );
865
866 if (!reg)
867 {
868 r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/
869 LOGD((T("cannot find provider for class: %s/%s"),
870 MI_GET_SAFE_PRINTF_STRING(req->nameSpace),
871 MI_GET_SAFE_PRINTF_STRING(req->instance->classDecl->name)));
872 goto sendErrorBack;
873 }
874
875 // Send the request to provider manager.
876 r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);
877
878 if (r != MI_RESULT_OK)
879 {
880 LOGD((T("AgentMgr_HandleRequest for namespace: %s"),
881 MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));
882 goto sendErrorBack;
883 mike 1.1 }
884
885 return MI_RESULT_OK;
886
887 sendErrorBack:
888 return _SendErrorResponse(&req->base,r);
889 }
890
891 static MI_Result _HandleDeleteInstanceReq(
892 Disp* self,
893 DeleteInstanceReq* req)
894 {
895 MI_Result r;
896 const ProvRegEntry* reg;
897
898 /* Validate input parameters */
899 if (!req->instanceName || !req->nameSpace)
900 return MI_RESULT_INVALID_PARAMETER;
901
902 // Find a provider for this class.
903 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace,
904 mike 1.1 req->instanceName->classDecl->name);
905
906 if (!reg)
907 {
908 r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/
909 LOGD((T("cannot find provider for class: %s/%s"),
910 MI_GET_SAFE_PRINTF_STRING(req->nameSpace),
911 MI_GET_SAFE_PRINTF_STRING(req->instanceName->classDecl->name)));
912 goto sendErrorBack;
913 }
914
915 // Send the request to provider manager.
916 r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);
917
918 if (r != MI_RESULT_OK)
919 {
920 LOGD((T("AgentMgr_HandleRequest for namespace: %s"),
921 MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));
922 goto sendErrorBack;
923 }
924
925 mike 1.1 return MI_RESULT_OK;
926
927 sendErrorBack:
928 return _SendErrorResponse(&req->base,r);
929 }
930
931 static MI_Result _HandleSubscribeReq(
932 Disp* self,
933 SubscribeReq* req)
934 {
935 MI_Result r;
936 const ProvRegEntry* reg = 0;
937 SubscribeReq* msg = 0;
938
939 /* Validate input parameters */
940 if (!req->className || !req->nameSpace || !req->language || !req->filter)
941 return MI_RESULT_INVALID_PARAMETER;
942
943 // Duplicate incoming request to substitute callback pointer
944 msg = SubscribeReq_New(req->base.msgID, req->base.flags);
945
946 mike 1.1 msg->base.uid = req->base.uid;
947 msg->base.gid = req->base.gid;
948 msg->nameSpace = Batch_Zdup(msg->base.batch, req->nameSpace);
949 msg->className = Batch_Zdup(msg->base.batch, req->className);
950 msg->filter = Batch_Zdup(msg->base.batch, req->filter);
951 msg->language = Batch_Zdup(msg->base.batch, req->language);
952
953 msg->base.clientID = req->base.clientID;
954
955 Message_SetRequest(&msg->base, &req->base);
956
957 /* Setup callback */
958 msg->base.callback = _ProviderToDispatcherCallback;
959 msg->base.callbackData = self;
960
961 // Find a indication context by ns/cn
962 Mutex_Lock(&self->mt);
963
964 r = _FindCreateIndCtx( self, msg, ® );
965
966 Mutex_Unlock(&self->mt);
967 mike 1.1
968 /* check if error was detected */
969 if (MI_RESULT_OK != r)
970 goto sendErrorBack;
971
972 /* empty reg with OK means context is being initialized;
973 sub command will be processed later, once EnableIndicaitons is processed */
974 if (!reg)
975 return MI_RESULT_OK;
976
977 // Send the request to provider manager.
978 r = AgentMgr_HandleRequest(&self->agentmgr, &msg->base, reg);
979
980 if (r != MI_RESULT_OK)
981 {
982 LOGD((T("AgentMgr_HandleRequest for namespace: %s"), MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));
983 goto sendErrorBack;
984 }
985
986 if (msg)
987 SubscribeReq_Release(msg);
988 mike 1.1
989 return MI_RESULT_OK;
990
991 sendErrorBack:
992 if (msg)
993 SubscribeReq_Release(msg);
994
995 return _SendErrorResponse(&req->base,r);
996 }
997
998 static MI_Result _HandleInvokeReq(
999 Disp* self,
1000 InvokeReq* req)
1001 {
1002 MI_Result r;
1003 const ProvRegEntry* reg;
1004 MI_ConstString cn = 0;
1005
1006 /* Validate input parameters */
1007 if (!req->nameSpace)
1008 return MI_RESULT_INVALID_PARAMETER;
1009 mike 1.1
1010 if (req->className)
1011 cn = req->className;
1012 else if (req->instance)
1013 cn = req->instance->classDecl->name;
1014
1015 if (!cn)
1016 {
1017 r = MI_RESULT_INVALID_CLASS;
1018 LOGD((T("class name is expected for invoke\n")));
1019 goto sendErrorBack;
1020 }
1021
1022
1023 // Find a provider for this class.
1024 reg = ProvReg_FindProviderForClass(&self->provreg, req->nameSpace, cn);
1025
1026 if (!reg)
1027 {
1028 r = MI_RESULT_INVALID_NAMESPACE; /*ATTN! or class?*/
1029 LOGD((T("cannot find provider for class: %s"), MI_GET_SAFE_PRINTF_STRING(cn)));
1030 mike 1.1 goto sendErrorBack;
1031 }
1032
1033 // Send the request to provider manager.
1034 r = AgentMgr_HandleRequest(&self->agentmgr, &req->base, reg);
1035
1036 if (r != MI_RESULT_OK)
1037 {
1038 LOGD((T("AgentMgr_HandleRequest for namespace: %s"), MI_GET_SAFE_PRINTF_STRING(req->nameSpace)));
1039 goto sendErrorBack;
1040 }
1041
1042 return MI_RESULT_OK;
1043
1044 sendErrorBack:
1045 return _SendErrorResponse(&req->base,r);
1046 }
1047
1048
1049 static MI_Result _HandleAssociatorsOfReq(
1050 Disp* self,
1051 mike 1.1 AssociatorsOfReq* req)
1052 {
1053 MI_Result r;
1054 MI_ConstString cn = 0;
1055 DispResultMsg* dispStateMsg;
1056 ProvRegAssocPosition pos;
1057 MI_Boolean sentOk = MI_FALSE;
1058
1059 /* Validate input parameters */
1060 if (!req->instance || !req->nameSpace)
1061 return MI_RESULT_INVALID_PARAMETER;
1062
1063 /* create a state message that will keep track of results from providers */
1064 dispStateMsg = DispResultMsg_New(req->base.msgID);
1065 if (!dispStateMsg)
1066 return MI_RESULT_FAILED;
1067
1068 /* add one for sending thread so first 'fast' provider will not send its response all the way */
1069 AtomicInc(&dispStateMsg->requestCounter);
1070
1071 dispStateMsg->base.clientID = req->base.clientID;
1072 mike 1.1 /* Setup callback */
1073 dispStateMsg->base.callback = req->base.callback;
1074 dispStateMsg->base.callbackData = req->base.callbackData;
1075 Message_SetRequest(&dispStateMsg->base, &req->base);
1076
1077 r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,
1078 req->instance->classDecl->name,
1079 req->assocClass, req->resultClass, &pos);
1080
1081 if (MI_RESULT_OK != r)
1082 {
1083 LOGD((T("ProvReg_BeginAssocClasses() failed: %u: %s"),
1084 r, Result_ToString(r)));
1085
1086 /* send error back to caller */
1087 goto sendErrorBack;
1088 }
1089
1090 /* While more classes */
1091 for (;;)
1092 {
1093 mike 1.1 MI_Boolean done;
1094 r = ProvReg_NextAssocClass(&pos, &cn, &done);
1095
1096 if (done)
1097 break;
1098
1099 if (MI_RESULT_OK != r)
1100 {
1101 LOGD((T("ProvReg_NextAssocClass() failed: %u: %s"),
1102 r, Result_ToString(r)));
1103 /* send error back to caller */
1104 goto sendErrorBack;
1105 }
1106
1107 if (_DispatchAssocReq(self, cn, req, dispStateMsg))
1108 sentOk = MI_TRUE;
1109 }
1110
1111 /* Finalize enumeration */
1112 {
1113 r = ProvReg_EndAssocClasses(&pos);
1114 mike 1.1
1115 if (MI_RESULT_OK != r)
1116 {
1117 LOGD((T("ProvReg_EndAssocClasses() failed: %u: %s"),
1118 r, Result_ToString(r)));
1119 /* send error back to caller */
1120 goto sendErrorBack;
1121 }
1122 }
1123
1124 /* Fail if no provider was found for request */
1125 if (!sentOk)
1126 {
1127 LOGD((T("found no providers for class: %s"), req->instance->classDecl->name));
1128 r = MI_RESULT_NOT_FOUND;
1129 goto sendErrorBack;
1130 }
1131
1132 if ( AtomicDec(&dispStateMsg->requestCounter) )
1133 { /* last result - forward it to the net stack */
1134 r = dispStateMsg->result;
1135 mike 1.1 goto sendErrorBack;
1136 }
1137
1138 DispResultMsg_Release(dispStateMsg);
1139 return MI_RESULT_OK;
1140
1141 sendErrorBack:
1142 DispResultMsg_Release(dispStateMsg);
1143 return _SendErrorResponse(&req->base,r);
1144 }
1145
1146 static MI_Result _HandleReferencesOfReq(
1147 Disp* self,
1148 ReferencesOfReq* req)
1149 {
1150 MI_Result r;
1151 MI_ConstString cn = 0;
1152 DispResultMsg* dispStateMsg;
1153 ProvRegAssocPosition pos;
1154 MI_Boolean sentOk = MI_FALSE;
1155
1156 mike 1.1 /* Validate input parameters */
1157 if (!req->instance || !req->nameSpace)
1158 return MI_RESULT_INVALID_PARAMETER;
1159
1160 /* create a state message that will keep track of results from providers */
1161 dispStateMsg = DispResultMsg_New(req->base.msgID);
1162 if (!dispStateMsg)
1163 return MI_RESULT_FAILED;
1164
1165 /* add one for sending thread so first 'fast' provider will not send its response all the way */
1166 AtomicInc(&dispStateMsg->requestCounter);
1167
1168 dispStateMsg->base.clientID = req->base.clientID;
1169 /* Setup callback */
1170 dispStateMsg->base.callback = req->base.callback;
1171 dispStateMsg->base.callbackData = req->base.callbackData;
1172 Message_SetRequest(&dispStateMsg->base, &req->base);
1173
1174 r = ProvReg_BeginAssocClasses(&self->provreg, req->nameSpace,
1175 req->instance->classDecl->name,
1176 req->assocClass, 0, &pos);
1177 mike 1.1
1178 if (MI_RESULT_OK != r)
1179 {
1180 LOGD((T("ProvReg_BeginAssocClasses() failed: %u: %s"),
1181 r, Result_ToString(r)));
1182
1183 /* send error back to caller */
1184 goto sendErrorBack;
1185 }
1186
1187 /* While more classes */
1188 for (;;)
1189 {
1190 MI_Boolean done;
1191 r = ProvReg_NextAssocClass(&pos, &cn, &done);
1192
1193 if (done)
1194 break;
1195
1196 if (MI_RESULT_OK != r)
1197 {
1198 mike 1.1 LOGD((T("ProvReg_NextAssocClass() failed: %u: %s"),
1199 r, Result_ToString(r)));
1200 /* send error back to caller */
1201 goto sendErrorBack;
1202 }
1203
1204 if (_DispatchRefReq(self, cn, req, dispStateMsg))
1205 sentOk = MI_TRUE;
1206 }
1207
1208 /* Finalize enumeration */
1209 {
1210 r = ProvReg_EndAssocClasses(&pos);
1211
1212 if (MI_RESULT_OK != r)
1213 {
1214 LOGD((T("ProvReg_EndAssocClasses() failed: %u: %s"),
1215 r, Result_ToString(r)));
1216 /* send error back to caller */
1217 goto sendErrorBack;
1218 }
1219 mike 1.1 }
1220
1221 /* Fail if no provider was found for request */
1222 if (!sentOk)
1223 {
1224 LOGD((T("found no providers for class: %s"), req->instance->classDecl->name));
1225 r = MI_RESULT_NOT_FOUND;
1226 goto sendErrorBack;
1227 }
1228
1229 if ( AtomicDec(&dispStateMsg->requestCounter) )
1230 { /* last result - forward it to the net stack */
1231 r = dispStateMsg->result;
1232 goto sendErrorBack;
1233 }
1234
1235 DispResultMsg_Release(dispStateMsg);
1236 return MI_RESULT_OK;
1237
1238 sendErrorBack:
1239 DispResultMsg_Release(dispStateMsg);
1240 mike 1.1 return _SendErrorResponse(&req->base,r);
1241 }
1242
1243 /*
1244 **==============================================================================
1245 **
1246 ** Public definitions
1247 **
1248 **==============================================================================
1249 */
1250
1251 MI_Result Disp_Init(Disp* self, Selector* selector)
1252 {
1253 /* Check parameters */
1254 if (!self)
1255 return MI_RESULT_INVALID_PARAMETER;
1256
1257 memset(self, 0, sizeof(Disp));
1258
1259 #if 0
1260 /* Initialize the provider registry */
1261 mike 1.1 MI_RETURN_ERR(ProvReg_Init(&self->provreg, GetPath(ID_REGISTERFILE)));
1262 #else
1263 MI_RETURN_ERR(ProvReg_Init2(&self->provreg));
1264 #endif
1265
1266 /* Initialize the provider manager */
1267 MI_RETURN_ERR(AgentMgr_Init(&self->agentmgr, selector));
1268
1269 /* Initialize indications part */
1270 MI_RETURN_ERR(Mutex_Init(&self->mt));
1271
1272 return MI_RESULT_OK;
1273 }
1274
1275 MI_Result Disp_Destroy(Disp* self)
1276 {
1277 MI_RETURN_ERR(AgentMgr_Destroy(&self->agentmgr));
1278 ProvReg_Destroy(&self->provreg);
1279
1280 /*ATTN! remove indication contexts! */
1281 Mutex_Destroy(&self->mt);
1282 mike 1.1 return MI_RESULT_OK;
1283 }
1284
1285 MI_Result Disp_HandleRequest(
1286 Disp* self,
1287 Message* msg)
1288 {
1289 switch (msg->tag)
1290 {
1291 case EnumerateInstancesReqTag:
1292 {
1293 EnumerateInstancesReq* req = (EnumerateInstancesReq*)msg;
1294 return _HandleEnumerateInstancesReq(self, req);
1295 }
1296
1297 case GetInstanceReqTag:
1298 {
1299 GetInstanceReq* req = (GetInstanceReq*)msg;
1300 return _HandleGetInstanceReq(self, req);
1301 }
1302
1303 mike 1.1 case CreateInstanceReqTag:
1304 {
1305 CreateInstanceReq* req = (CreateInstanceReq*)msg;
1306 return _HandleCreateInstanceReq(self, req);
1307 }
1308
1309 case ModifyInstanceReqTag:
1310 {
1311 ModifyInstanceReq* req = (ModifyInstanceReq*)msg;
1312 return _HandleModifyInstanceReq(self, req);
1313 }
1314
1315 case DeleteInstanceReqTag:
1316 {
1317 DeleteInstanceReq* req = (DeleteInstanceReq*)msg;
1318 return _HandleDeleteInstanceReq(self, req);
1319 }
1320
1321 case InvokeReqTag:
1322 {
1323 InvokeReq* req = (InvokeReq*)msg;
1324 mike 1.1 return _HandleInvokeReq(self, req);
1325 }
1326
1327 case AssociatorsOfReqTag:
1328 {
1329 AssociatorsOfReq* req = (AssociatorsOfReq*)msg;
1330 return _HandleAssociatorsOfReq(self, req);
1331 }
1332
1333 case ReferencesOfReqTag:
1334 {
1335 ReferencesOfReq* req = (ReferencesOfReq*)msg;
1336 return _HandleReferencesOfReq(self, req);
1337 }
1338
1339 case SubscribeReqTag:
1340 {
1341 SubscribeReq* req = (SubscribeReq*)msg;
1342 return _HandleSubscribeReq(self, req);
1343 }
1344
1345 mike 1.1 default:
1346 {
1347 /* Unsupported mesage type */
1348 return _SendErrorResponse(msg,MI_RESULT_NOT_SUPPORTED);
1349 }
1350 }
1351 }
|