(file) Return to disp.c CVS log (file) (dir) Up to [OMI] / omi / disp

   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, &reg );
 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           }

ViewCVS 0.9.2