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