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

Diff for /omi/provmgr/provmgr.c between version 1.3 and 1.4

version 1.3, 2015/04/20 18:10:13 version 1.4, 2015/04/20 18:19:56
Line 24 
Line 24 
  
 #include "provmgr.h" #include "provmgr.h"
 #include "context.h" #include "context.h"
   #include "AggregationContext.h"
   #include "LifecycleContext.h"
   #include "SubMgr.h"
   #include "nioproc.h"
 #include <base/log.h> #include <base/log.h>
 #include <base/strings.h>  #include <pal/strings.h>
 #include <base/atomic.h>  #include <pal/atomic.h>
 #include <base/paths.h> #include <base/paths.h>
 #include <base/time.h>  #include <pal/sleep.h>
   #include <base/class.h>
 #include <wql/wql.h> #include <wql/wql.h>
   #include <wsman/wsbuf.h>
   #include <pal/format.h>
   #include <indication/common/indilog.h>
   #include <indication/common/indicommon.h>
   #include <omi_error/errorutil.h>
   #include <provreg/provreg.h>
  
 #if defined(CONFIG_POSIX) #if defined(CONFIG_POSIX)
 # include <unistd.h> # include <unistd.h>
Line 39 
Line 50 
 /* ATTN: implement module provider Unload() methods */ /* ATTN: implement module provider Unload() methods */
 /* ATTN: implement propertySet */ /* ATTN: implement propertySet */
  
 /* Suppress casat error from 'void*' to 'MI_Main' */  /* Suppress cast error from 'void*' to 'MI_Main' */
 #if defined(_MSC_VER) #if defined(_MSC_VER)
 # pragma warning(disable : 4055) # pragma warning(disable : 4055)
 #endif #endif
  
 #define T MI_T  
   
 /* /*
 **============================================================================= **=============================================================================
 ** **
Line 54 
Line 63 
 **============================================================================= **=============================================================================
 */ */
  
 typedef MI_Module* (*MI_Main)(MI_Server* server);  
   
 extern MI_ContextFT __mi_contextFT; extern MI_ContextFT __mi_contextFT;
  
 static MI_Result MI_CALL _Server_GetVersion(MI_Uint32* version) static MI_Result MI_CALL _Server_GetVersion(MI_Uint32* version)
Line 67 
Line 74 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
 static MI_Result MI_CALL _Server_GetSystemName(const MI_Char** systemName)  static MI_Result MI_CALL _Server_GetSystemName(const ZChar** systemName)
 { {
 #if defined(CONFIG_OS_WINDOWS) #if defined(CONFIG_OS_WINDOWS)
     *systemName = MI_T("unknown");     *systemName = MI_T("unknown");
Line 81 
Line 88 
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
     }     }
  
   #if (MI_CHAR_TYPE == 1)
     *systemName = buf;     *systemName = buf;
   #else
       {
           static ZChar wbuf[sizeof(buf)];
           TcsStrlcpy(wbuf, buf, MI_COUNT(wbuf));
           *systemName = wbuf;
       }
   #endif
   
     return MI_RESULT_OK;     return MI_RESULT_OK;
 #endif #endif
 } }
Line 108 
Line 124 
  
 static void* _FindSymbol(const char* name) static void* _FindSymbol(const char* name)
 { {
     if (strcmp(name, "GetPath") == 0)      if (strcmp(name, "OMI_GetPath") == 0)
         return (void*)&GetPath;          return (void*)&OMI_GetPath;
  
     /* Not found */     /* Not found */
     return NULL;     return NULL;
Line 133 
Line 149 
     NULL, /* MI_FilterFT */     NULL, /* MI_FilterFT */
 }; };
  
 typedef struct _Library Library;  /*
    * Try to find specific library and open it if not found,
 struct _Provider   * this function is not thread-safely operate the library list
 {   */
     struct _Provider* next;  static Library* MI_CALL _OpenLibraryInternal(
     struct _Provider* prev;  
   
     const MI_ClassDecl* classDecl;  
     void* self;  
   
     /* number of outstanding requests */  
     AtomicInt   refCounter;  
   
     /* time when last outstanding request was handled */  
     MI_Uint64   idleSince;  
   
     /* indicator if Provider refused idle-unload */  
     MI_Boolean  refusedUnload;  
   
     /* pointer to lib object */  
     Library* lib;  
   
     /* indications support */  
     Context ctxIndications;  
   
 };  
   
 struct _Library  
 {  
     struct _Library* next;  
     struct _Library* prev;  
     char libraryName[MAX_PATH_SIZE];  
     void* handle;  
     const MI_Module* module;  
     MI_Module_Self* self;  
     struct _Provider* head;  
     struct _Provider* tail;  
     ProvMgr* provmgr;  
 };  
   
 static Library* _OpenLibrary(  
     ProvMgr* self,     ProvMgr* self,
     const char* libraryName)      _In_ const ProvRegEntry* proventry)
 { {
     Library* p;     Library* p;
  
     /* Search cache first */     /* Search cache first */
     for (p = self->head; p; p = p->next)     for (p = self->head; p; p = p->next)
     {     {
         if (strcmp(p->libraryName, libraryName) == 0)          if (strcmp(p->libraryName, proventry->libraryName) == 0)
         {         {
             return p;             return p;
         }         }
     }     }
  
     /* Allocate new libray object */     /* Allocate new libray object */
     p = (Library*)calloc(1, sizeof(Library));      p = (Library*)PAL_Calloc(1, sizeof(Library));
  
     if (!p)     if (!p)
         return NULL;         return NULL;
  
     /* Library.refs */     /* Library.refs */
     p->provmgr = self;     p->provmgr = self;
   
     /* Open the library */     /* Open the library */
     {     {
         char path[MAX_PATH_SIZE];          TChar path[PAL_MAX_PATH_SIZE];
         Lib_Format(path, self->providerDir, libraryName);          path[0] = '\0';
         p->handle = Lib_Open(path);          Shlib_Format(path, self->providerDir, proventry->libraryName);
           p->handle = Shlib_Open(path);
  
         if (!p->handle)         if (!p->handle)
         {         {
             /* ATTN: one more attempt */              TChar Tpath[PAL_MAX_PATH_SIZE];
             p->handle = Lib_Open(libraryName);  
               if (TcsStrlcpy(Tpath, proventry->libraryName, PAL_MAX_PATH_SIZE) >= PAL_MAX_PATH_SIZE)
               {
                   trace_SharedLib_CannotOpen(scs(proventry->libraryName));
                   PAL_Free(p);
                   return NULL;
         }         }
  
               trace_SharedLib_CannotOpenFirstTry(tcs(path), tcs(Shlib_Err()));
   
               // here we are ignoring error from Shlib_Open on first attempt
               NitsIgnoringError();
   
               /* Try again */
   
               p->handle = Shlib_Open(Tpath);
   
         if (!p->handle)         if (!p->handle)
         {         {
             free(p);                  trace_SharedLib_CannotOpenSecondTry(scs(proventry->libraryName), tcs(Shlib_Err()));
                   PAL_Free(p);
             return NULL;             return NULL;
         }         }
     }     }
       }
  
     /* Lib_Open.libraryName */     /* Lib_Open.libraryName */
     Strlcpy(p->libraryName, libraryName, sizeof(p->libraryName));      Strlcpy(p->libraryName, proventry->libraryName, sizeof(p->libraryName));
       p->instanceLifetimeContext = proventry->instanceLifetimeContext;
  
     /* Invoke MI_Main() entry point */     /* Invoke MI_Main() entry point */
     {     {
         MI_Main statikMain;          MI_MainFunction statikMain;
  
         /* Lookup symbol */         /* Lookup symbol */
         {         {
             void* ptr = Lib_Sym(p->handle, "MI_Main");              void* ptr = Shlib_Sym(p->handle, "MI_Main");
  
             statikMain = (MI_Main)ptr;              statikMain = (MI_MainFunction)ptr;
  
             if (!statikMain)             if (!statikMain)
             {             {
                 free(p);                  PAL_Free(p);
                   trace_SharedLibrary_CannotFindSymbol(scs(proventry->libraryName), scs("MI_Main"));
                 return NULL;                 return NULL;
             }             }
         }         }
Line 239 
Line 237 
         /* Call MI_Main */         /* Call MI_Main */
         {         {
             p->module = (*statikMain)(&_server);             p->module = (*statikMain)(&_server);
               if (!p->module)
               {
                   PAL_Free(p);
                   trace_Provmgr_NullModulePointer(scs(proventry->libraryName), scs("MI_Main"));
                   return NULL;
               }
               if (p->module->version > MI_VERSION)
               {
                   MI_Uint32 v =  p->module->version;
                   PAL_Free(p);
                   trace_Provmgr_FailedToLoadProvider(scs(proventry->libraryName), MI_VERSION_GET_MAJOR(v), MI_VERSION_GET_MINOR(v), MI_VERSION_GET_REVISION(v), MI_MAJOR, MI_MINOR, MI_REVISION);
                   return NULL;
               }
         }         }
     }     }
  
Line 246 
Line 257 
     if (p->module->Load)     if (p->module->Load)
     {     {
         Context ctx;         Context ctx;
         Context_Init(&ctx, 0);          MI_Result r = MI_RESULT_OK;
   
           Context_Init(&ctx, NULL, NULL);
           ctx.result = &r;
   
         (p->module->Load)(&p->self, (MI_Context*)&ctx);         (p->module->Load)(&p->self, (MI_Context*)&ctx);
         Context_Destroy(&ctx);  
           if (ctx.magic != 0xFFFFFFFF)
           {
               trace_ModuleLoad_FailedPostResult();
     }     }
  
           if (MI_RESULT_OK != r)
           {
               trace_FailedCallModuleLoad(r, scs(proventry->libraryName));
               return NULL;
           }
       }
   
       Lock_Init( &p->provlock );
   
     /* Add library to the list */     /* Add library to the list */
     List_Prepend(     List_Prepend(
         (ListElem**)&self->head,         (ListElem**)&self->head,
Line 260 
Line 287 
     return p;     return p;
 } }
  
 static Provider* _OpenProvider(  /*
    * Try to find specific library and open it if not found,
    * this function ensure thread-safe use of the library list
    */
   static Library* MI_CALL _OpenLibrary(
       ProvMgr* self,
       _In_ const ProvRegEntry* proventry)
   {
       Library* lib;
       Lock_Acquire( & self->liblock );
       lib = _OpenLibraryInternal( self, proventry );
       Lock_Release( & self->liblock );
       return lib;
   }
   
   /*
    * Try to find specific provider (class) and open it if not found,
    * this function is NOT thread-safe
    */
   static Provider* MI_CALL _OpenProviderInternal(
     Library* self,     Library* self,
     const MI_Char* className)      const ZChar* className,
       Message* request)
 { {
     Provider* p;     Provider* p;
       size_t psize = sizeof(Provider);
  
     /* Search cache first */     /* Search cache first */
     for (p = self->head; p; p = p->next)     for (p = self->head; p; p = p->next)
     {     {
         if (Zcasecmp(p->classDecl->name, className) == 0)          if (Tcscasecmp(p->classDecl->name, className) == 0)
         {         {
             AtomicInc(&p->refCounter);              Provider_Addref(p);
             return p;             return p;
         }         }
     }     }
  
   #ifndef DISABLE_INDICATION
       /* Allocate SubscriptionManager along with Provider */
       psize += sizeof( SubscriptionManager );
   #endif
   
     /* New Provider */     /* New Provider */
     p = (Provider*)calloc(1, sizeof(Provider));      p = (Provider*)PAL_Calloc(1, psize);
  
     if (!p)     if (!p)
     {     {
           LOGD_ALLOC_OOM;
         return NULL;         return NULL;
     }     }
  
Line 293 
Line 347 
         p->classDecl = SchemaDecl_FindClassDecl(self->module->schemaDecl,         p->classDecl = SchemaDecl_FindClassDecl(self->module->schemaDecl,
             className);             className);
  
         if (!p->classDecl)          if (!p->classDecl || (request->tag != GetClassReqTag && !p->classDecl->providerFT))
         {         {
             free(p);              PAL_Free(p);
             return NULL;             return NULL;
         }         }
     }     }
  
     /* Initialize context - used for indication providers */  #ifndef DISABLE_INDICATION
     Context_Init(&p->ctxIndications, 0);      /*
     p->ctxIndications.chainType = CTX_TYPE_IND_NOTINITIALIZED;       * Following picture explains memory layout of provider,
        * provider and submgr are sitting side by side, while
        * provider.submgr sets to the submgr's memory address
        *
        * |---------|
        * | Provider|
        * | ...     |
        * | submgr* |---|
        * |---------|<--|
        * | submgr  |
        * |         |
        * |---------|
        */
       p->subMgr = (SubscriptionManager*)(p + 1);
       SubMgr_Init(p->subMgr, p);
   #endif
  
       if(p->classDecl->providerFT)
       {
     /* Call provider Load() method */     /* Call provider Load() method */
     if (p->classDecl->providerFT->Load)     if (p->classDecl->providerFT->Load)
     {     {
         Context ctx;         Context ctx;
         MI_Result r = MI_RESULT_OK;         MI_Result r = MI_RESULT_OK;
  
         Context_Init(&ctx, p);              Context_Init(&ctx, p, NULL);
         ctx.result = &r;         ctx.result = &r;
               ctx.loadRequest = request;
               Message_AddRef(ctx.loadRequest);
  
         (*p->classDecl->providerFT->Load)(&p->self, self->self, &ctx.base);         (*p->classDecl->providerFT->Load)(&p->self, self->self, &ctx.base);
  
         DEBUG_ASSERT(ctx.magic == (MI_Uint32)-1);              if (ctx.magic != 0xFFFFFFFF)
               {
                   trace_ProviderLoad_DidnotPostResult();
               }
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
         {         {
             LOGW((T("failed to call provider's load with result %d; class: %s"), (int)r, className));                  trace_FailedProviderLoad(r, tcs(className));
             free(p);                  PAL_Free(p);
             return NULL;             return NULL;
         }         }
     }     }
       }
  
     /* Prepend to list */     /* Prepend to list */
     List_Prepend(     List_Prepend(
Line 334 
Line 411 
     return p;     return p;
 } }
  
 static MI_Result _GetProviderByClassName(  /*
     ProvMgr* self,   * Try to find specific provider (class) and open it if not found,
     const char* libraryName,   * this function is thread-safely operate the provider list
     MI_ConstString cn,   */
     Provider** provOut  static Provider* MI_CALL _OpenProvider(
     )      Library* self,
       const ZChar* className,
       Message* request)
   {
       Provider* prov;
       Lock_Acquire( & self->provlock );
       prov = _OpenProviderInternal( self, className, request );
       Lock_Release( & self->provlock );
       return prov;
   }
   
   static MI_Result MI_CALL _GetProviderByClassName(
       _In_ ProvMgr* self,
       _In_ const ProvRegEntry* proventry,
       _In_ MI_ConstString cn,
       _In_ Message* request,
       _Out_ Provider** provOut)
 { {
     Library* lib;     Library* lib;
     Provider* prov;     Provider* prov;
  
       trace_GetProviderByClassName(tcs(cn));
   
     /* Open the library */     /* Open the library */
     {     {
         lib = _OpenLibrary(self, libraryName);          lib = _OpenLibrary(self, proventry);
  
         if (!lib)         if (!lib)
         {         {
             LOGW_CHAR(("failed to open provider library: %s", libraryName));              trace_OpenProviderLib_Failed(scs(proventry->libraryName));
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
     }     }
  
     /* Open the provider */     /* Open the provider */
     {     {
         prov = _OpenProvider(lib, cn);          prov = _OpenProvider(lib, cn, request);
  
         if (!prov)         if (!prov)
         {         {
             LOGW_CHAR(("failed to open the provider %s for class %s",              trace_OpenProvider_FailedForClass(proventry->libraryName, tcs(cn));
                 libraryName, cn));  
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
     }     }
Line 378 
Line 472 
     MI_Instance* inst_in,     MI_Instance* inst_in,
     MI_Boolean keys_only,     MI_Boolean keys_only,
     MI_Boolean allow_keyless_inst,     MI_Boolean allow_keyless_inst,
     MI_Instance** instOut      MI_Instance** instOut,
       MI_Uint32 flags
     )     )
 { {
     MI_Instance* inst;     MI_Instance* inst;
Line 391 
Line 486 
  
     if (!inst)     if (!inst)
     {     {
         LOGF((T("allocation failed")));          trace_ProvMgr_AllocFailed();
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
 #if 0      /* Convert instance name to provider's format (borrow storage) */
     if (inst_in)      r = Instance_InitConvert(inst, cd, inst_in, keys_only, allow_keyless_inst, MI_FALSE,
           batch, flags);
   
       if (r != MI_RESULT_OK)
       {
           trace_InstanceConversionFailed(tcs(cd->name), r);
           return r;
       }
   
       *instOut = inst;
       return MI_RESULT_OK;
   }
   
   #ifndef DISABLE_INDICATION
   
   /*
    * Internal helper function for _Provider_InvokeSubscribe that expects all
    * validation to be done beforehand.
    */
   MI_Result _Provider_InvokeEnable(
       _Inout_ Provider* provider,
       _In_ SubscribeReq* msg )
     {     {
         printf("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");      SubscriptionManager* subMgr = provider->subMgr;
         MI_Instance_Print(inst_in, stdout, 1);      AggregationContext* aggrContext;
         printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");  
       trace_EnablingIndicationsForClass(provider->classDecl->name, provider);
   
       aggrContext = SubMgr_CreateAggrContext( subMgr );
       if ( !aggrContext )
       {
           trace_AggregationContext_InitFailed();
           return MI_RESULT_SERVER_LIMITS_EXCEEDED;
       }
   
       /*
        * Set enabled to true, which will be set to false if
        * posting result during EnableIndications call
        *
        */
       SubMgr_SetEnabled( subMgr, MI_TRUE );
   
       (*provider->classDecl->providerFT->EnableIndications)(
           provider->self,
           &aggrContext->baseCtx.base,
           msg->nameSpace,
           msg->className);
   
       if ( MI_FALSE == SubMgr_IsEnabled(subMgr) )
       {
           /*
            * provider posted a final result during EnableIndications call,
            * Clean up already occurred during Post handling, return here
            *
            */
           trace_ProviderEnableIndication_Failed();
           return MI_RESULT_FAILED;
       }
   
       return MI_RESULT_OK;
   }
   
   /*
    * Internal helper function for _Provider_RemoveSubscription that expects all
    * validation to be done beforehand.
    */
   _Use_decl_annotations_
   MI_Result Provider_InvokeDisable(
       Provider* provider)
   {
       MI_Result result = MI_RESULT_OK;
       SubscriptionManager* subMgr;
       MI_Boolean locked;
   
       DEBUG_ASSERT( provider );
   
       subMgr = provider->subMgr;
   
       trace_Provider_InvokeDisable_Start( UintThreadID(), provider->classDecl->name, provider);
   
       locked = SubMgr_AcquireEnableLock( subMgr, AcquireFromDisable );
   
       if ( MI_TRUE == locked )
       {
           MI_Boolean wasEnabled = MI_FALSE;
           if ( MI_TRUE == SubMgr_IsEnabled(subMgr) )
           {
               wasEnabled = MI_TRUE;
               SubMgr_SetEnabled(subMgr, MI_FALSE);
           }
   
           if ( provider->classDecl->flags & MI_FLAG_INDICATION )
           {
               AggregationContext* aggrContext = SubMgr_RemoveAggrContext( subMgr );
   
               if ( MI_FALSE == SubMgr_IsTerminating( subMgr ) )
               {
                   DEBUG_ASSERT( (MI_TRUE == wasEnabled) ? (NULL != aggrContext) : (NULL == aggrContext) );
   
                   if ( aggrContext && ( MI_TRUE == wasEnabled ) )
                   {
                       provider->classDecl->providerFT->DisableIndications(
                           provider->self,
                           &aggrContext->baseCtx.base,
                           NULL,  // TODO: Set this based on the initial SubscribeReq, but copy the value so its lifetime matches the context
                           provider->classDecl->name );
                   }
               }
               // else don't need to invoke DisableIndications
   
               if ( aggrContext )
                   AggrContext_Delete( aggrContext );
           }
           else
           {
               // TODO: release lifecycle context
           }
       }
       else
       {
           /* active subscription(s) added right before acquire the lock */
           trace_Provider_InvokeDisable_AbandonSinceNewSubscriptionAdded( UintThreadID(), provider->classDecl->name, provider);
           return MI_RESULT_OK;
       }
   
       /*
        * Disabled the provider, reset flags,
        * new subscribe request will success.
        */
       SubMgr_SetTerminating( subMgr, MI_FALSE );
       SubMgr_SetAllCancelledSafe( subMgr, MI_FALSE );
       SubMgr_ReleaseEnableLock( subMgr );
   
       trace_Provider_InvokeDisable_Complete( UintThreadID(), provider->classDecl->name, provider);
       return result;
   }
   
   void _Provider_SubscribeFail(
       _In_ SubscriptionContext* subscrContext,
       _In_ SubscribeReq* msg,
       _In_ MI_Result result )
   {
       // TODO: Replace this whole func with Cancel and propagate the result to the subscription context
       PostResultMsg* finalmsg = PostResultMsg_NewAndSerialize(&msg->base.base, NULL, NULL, MI_RESULT_TYPE_MI, result);
       if (finalmsg)
       {
           Strand_SchedulePost(&subscrContext->baseCtx.strand,&finalmsg->base);
           PostResultMsg_Release(finalmsg);
           /*
            * subscribe failed and directly send final result to left side strand,
            * thus context.c:Context_PostMessageLeft won't be called,
            * so release the ref count added by SubscriptionContext.c:SubscrContext_Init
            */
           SubMgrSubscription_Release( subscrContext->subscription );
     }     }
       else
       {
           trace_OutOfMemory();
           Strand_ScheduleCancel(&subscrContext->baseCtx.strand);
       }
   }
   
   _Use_decl_annotations_
   void Provider_InvokeSubscribe(
       Provider* provider,
       SubscribeReq* msg,
       SubscriptionContext* subscrContext )
   {
       MI_Result result = MI_RESULT_OK;
       SubscriptionManager* subMgr;
       MI_Boolean locked;
       SubscriptionTargetType subType;
       SubMgrSubscription* subscription = NULL;
   
       DEBUG_ASSERT ( provider && subscrContext );
       DEBUG_ASSERT( provider->subMgr );
       STRAND_ASSERTONSTRAND(&subscrContext->baseCtx.strand);
   
       if( subscrContext->baseCtx.strand.canceled )
       {
           // abort creating subscription
           Strand_Leave( &subscrContext->baseCtx.strand );
           return;
       }
   
       subMgr = provider->subMgr;
       subType = (SubscriptionTargetType)msg->targetType;
   
       do
       {
           trace_ProviderInvokeSubscribe_Begin(UintThreadID(), provider, msg, msg->base.base.tag, subscrContext );
   
           /* To ensure enable/cancel thread safe */
           locked = SubMgr_AcquireEnableLock( subMgr, AcquireFromSubscribe );
           if ( MI_FALSE == locked )
           {
               result = MI_RESULT_FAILED;
               Strand_Leave( &subscrContext->baseCtx.strand );
               break;
           }
   
           /*
            * Sanity checks of the request prior to initializing the context and
            * completing the interaction open.
            *
            * These checks can return immediate failure without clean up
            */
           if (SUBSCRIP_TARGET_DEFAULT == subType )
           {
               /*
                * if class is not indication class, then indication manager has a bug
                */
               DEBUG_ASSERT (provider->classDecl->flags & MI_FLAG_INDICATION);
               /*
                * if classdecl is not valid, then omireg tool has a bug
                */
               DEBUG_ASSERT (
                   provider->classDecl->providerFT->EnableIndications &&
                   provider->classDecl->providerFT->Subscribe);
           }
           else if (SubscriptionTargetType_IsLifecycle( subType ))
           {
               // lifecycleCtx should have been initialized during provider Load().
               if ( ! subMgr->lifecycleCtx )
               {
                   trace_LifecycleSubscription_ContextNotInitialized(provider->classDecl->name);
                   result = MI_RESULT_FAILED;
                   break;
               }
   
               if ( ! LifeContext_IsTypeSupported(subMgr->lifecycleCtx, msg->targetType) )
               {
                   trace_LifecycleSubscription_UnsupportedTargetType(
                       provider->classDecl->name, msg->targetType, subMgr->lifecycleCtx->supportedTypesFromProv);
                   result = MI_RESULT_NOT_SUPPORTED;
                   Strand_Leave( &subscrContext->baseCtx.strand );
                   break;
               }
           }
           else
           {
               trace_InvokeSubscribeWithInvalidTargetType( subType );
               result = MI_RESULT_FAILED;
               Strand_Leave( &subscrContext->baseCtx.strand );
               break;
           }
   
           subscription = subscrContext->subscription;
           SubscriptionList_AddSubscription( &subMgr->subscrList, subscription );
   
           /*
            * Upon SubscriptionContext was initialized successfull,
            * it hold one refcount of msg, which will be released
            * inside _Context_Destory;
            *
            * SubscriptionContext was initialized successfully,
            * following logic should report error through
            * interaction interface then.
            */
   
           /*
            * Acquire post lock, so post indication and result from provider's thread
            * will be blocked until Enable/Subscribe call finished
            *
            */
           SubMgrSubscription_Addref( subscription );
           SubMgrSubscription_AcuquirePostLock( subscription );
   
           /* Alert indication setup */
           if (SUBSCRIP_TARGET_DEFAULT == msg->targetType )
           {
               SubMgr_SetEnableThread( subMgr );
   
               Strand_Leave( &subscrContext->baseCtx.strand );
               /*
                * EnableIndications must be called for each provider
                * prior to the first Subscribe call for alert indication
                */
               if ( MI_FALSE == SubMgr_IsEnabled( subMgr ) )
               {
                   result = _Provider_InvokeEnable( provider, msg );
                   if (MI_RESULT_OK != result)
                   {
                       trace_EnableIndication_Failed(provider->classDecl->name);
                       result = MI_RESULT_OK;
                       break;
                   }
               }
   
               DEBUG_ASSERT (SubMgr_IsEnabled( subMgr ));
   
               SubMgrSubscription_SetState(subscription, SubscriptionState_Subscribed);
   
               /*
                * Invoke Subscribe with dummpy context
                * provider cannot postinstance or indication to this context
                */
               {
                   Context ctx;
                   MI_Result r = MI_RESULT_OK;
                   Subunsub_Context_Init(&ctx, &r, &msg->base);
                   (*provider->classDecl->providerFT->Subscribe)(
                       provider->self,
                       &ctx.base,
                       msg->nameSpace,
                       msg->className,
                       &subscrContext->subscription->filter->base,
                       msg->bookmark,
                       msg->subscriptionID,
                       (void**)&subscrContext->subself);
                   Context_Close(&ctx);
               }
   
               if (SubscriptionState_Subscribed == subscrContext->subscription->state)
               {
                   trace_Provider_InvokeSubscribe(subscrContext->subscription);
   
                   /*
                    * Subscribe succeeded, send subscribe response,
                    * otherwise finalresult already sent within Subscribe call
                    */
                   SubscrContext_SendSubscribeResponseMsg( subscrContext );
   
   #if defined(_MSC_VER)
                   trace_SubscrForEvents_Succeeded_MSC(provider->classDecl->name, msg->subscriptionID);
   #else
                   trace_SubscrForEvents_Succeeded(provider->classDecl->name, msg->subscriptionID);
 #endif #endif
                   result = MI_RESULT_OK;
                   break;
               }
           }
           /*
            * Lifecycle indication setup
            */
           else if (SubscriptionTargetType_IsLifecycle( (SubscriptionTargetType)msg->targetType ))
           {
               if ( MI_FALSE == SubMgr_IsEnabled( subMgr ) )
                   SubMgr_SetEnabled( subMgr, MI_TRUE );
  
     /* Convert instance name to provider's format (borrow storage) */              SubMgrSubscription_SetState( subscrContext->subscription, SubscriptionState_Subscribed );
     r = Instance_InitConvert(  
         inst,  
         cd,  
         inst_in,  
         keys_only,  
         allow_keyless_inst,  
         MI_FALSE,  
         batch);  
  
     if (r != MI_RESULT_OK)              LifeContext_UpdateSupportedTypes( subMgr->lifecycleCtx );
   
               Strand_Leave( &subscrContext->baseCtx.strand );
               SubscrContext_SendSubscribeResponseMsg( subscrContext );
   
       #if defined(_MSC_VER)
               trace_SubscrForLifecycle_Succeeded_MSC(provider->classDecl->name, msg->subscriptionID);
       #else
               trace_SubscrForLifecycle_Succeeded(provider->classDecl->name, msg->subscriptionID);
       #endif
               result = MI_RESULT_OK;
               break;
           }
       }
       while( 0 );
   
       if ( subscription )
     {     {
         LOGW((T("instance conversion failed: %s, err %d"), cd->name, r));          /*
         return r;           * Release post lock, so indication and result
            * posted from provider will go through
            */
           SubMgrSubscription_ReleasePostLock( subscription );
           SubMgrSubscription_Release( subscription );
       }
   
       /*
        * Now release lock to allow Disable/other subscribe reqeuest to conitune
        */
       if ( MI_TRUE == locked )
           SubMgr_ReleaseEnableLock( subMgr );
   
       trace_ProviderInvokeSubscribe_End(UintThreadID(), provider, result);
   
       /*
        * Once the SubscrContext has been initialized, the interactions is "Open"
        * and must be shut down using the appropriate Strand calls.  Those calls
        * will handle clean up.  This must return MI_RESULT_OK for that to happen.
        */
       if ( result != MI_RESULT_OK )
       {
           _Provider_SubscribeFail( subscrContext, msg, result );
       }
   }
   
   /*
    * Invoke EnableIndication if not called yet;
    * and invoke Subscribe call to provider;
    *
    * To ensure enable/disable thread-safe, and since
    * OMI has single IO thread, this function has to be scheduled
    * on separate thread for OMI.
    * TODO: remove separate thread if have multi-IO threads implemented
    */
   MI_Result _Provider_InvokeSubscribeWrapper(
       _In_ Provider* provider,
       _Inout_ InteractionOpenParams* interactionParams )
   {
       SubscriptionContext* subscrContext;
       MI_Result result;
   
       result = SubMgr_CreateSubscription( provider->subMgr, provider, interactionParams, &subscrContext );
       if ( MI_RESULT_OK != result )
       {
           trace_FailedToAddSubscrMgr();
           return result;
       }
   
   //#if defined(_MSC_VER)
   //    Strand_ScheduleAux( &(subscrContext->baseCtx.strand), CONTEXT_STRANDAUX_INVOKESUBSCRIBE );
   //#else
       result = Schedule_SubscribeRequest( provider, (SubscribeReq*)interactionParams->msg, subscrContext );
       if( MI_RESULT_OK != result )
       {
           _Provider_SubscribeFail( subscrContext, (SubscribeReq*)interactionParams->msg, result );
           /*
            * schedule failed so CONTEXT_STRANDAUX_INVOKESUBSCRIBE won't be called,
            * so release the ref count added by _SubMgrSubscription_New
            */
           SubMgrSubscription_Release( subscrContext->subscription );
       }
   //#endif
   
       return MI_RESULT_OK;
   }
   
   _Use_decl_annotations_
   MI_Result Provider_RemoveSubscription(
       Provider* provider,
       MI_Uint64 subscriptionID)
   {
       SubMgrSubscription* subscription = NULL;
       SubscriptionManager* subMgr;
       MI_Result result = MI_RESULT_OK;
   
       DEBUG_ASSERT (provider && provider->subMgr);
       subMgr = provider->subMgr;
   
   #if defined(_MSC_VER)
       trace_RemovingSubscriptionForClass_MSC(subscriptionID, provider->classDecl->name);
   #else
       trace_RemovingSubscriptionForClass(subscriptionID, provider->classDecl->name);
   #endif
   
       subscription = SubMgr_GetSubscription( subMgr, subscriptionID );
       if (NULL == subscription)
       {
           /* Not present or not found means that there is nothing to do. */
           return MI_RESULT_OK;
       }
   
       SubMgrSubscription_SetState(subscription, SubscriptionState_Unsubscribed);
   
       result = SubMgr_DeleteSubscription( subMgr, subscription);
   
       /* check if the subscription list was empty or not */
       if ( MI_TRUE == SubMgr_IsSubListEmpty( subMgr ) )
       {
           /*
            * The specified subscription is the LAST one for its
            * SubscriptionManager. Indications should be disabled for this
            * provider. There is separate cleanup for Lifecycle and "normal"
            * indications.  SubscriptionManager will be cleaned up once the
            * provider processes the Disable call.
            */
           result = Provider_InvokeDisable ( provider );
     }     }
  
     *instOut = inst;      return result;
   }
   
   _Use_decl_annotations_
   MI_Result Provider_TerminateIndication(
       Provider* provider,
       MI_Result result,
       const ZChar* errorMessage,
       const MI_Instance* cimError )
   {
       SubscriptionManager* subMgr;
       MI_Boolean locked;
       DEBUG_ASSERT (provider && provider->subMgr);
   
       trace_Provider_TerminateIndication_Start( UintThreadID(), provider->classDecl->name, provider);
   
       Provider_Addref( provider );
   
       subMgr = provider->subMgr;
   
       /*
        * SubMgr_AcquireEnableLock cancel all subscriptions if have any,
        * internally it call Provider_InvokeDisable if no subscription;
        * otherwise just return;
        * Provider_InvokeDisable releases the aggregation context;
        */
       locked = SubMgr_AcquireEnableLock( subMgr, AcquireFromTerminate );
       DEBUG_ASSERT( MI_TRUE == locked );
       SubMgr_ReleaseEnableLock( subMgr );
   
       trace_Provider_TerminateIndication_Complete( UintThreadID(), provider->classDecl->name, provider);
   
       Provider_Release( provider );
   
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   #endif /* ifndef DISABLE_INDICATION */
   
 static MI_Result _HandleGetInstanceReq( static MI_Result _HandleGetInstanceReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     GetInstanceReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     MI_Instance* inst;     MI_Instance* inst;
     MI_Result r;     MI_Result r;
     const MI_Char* className;      const ZChar* className;
       GetInstanceReq* msg = (GetInstanceReq*)interactionParams->msg;
  
     /* Get classname from instance */     /* Get classname from instance */
     r = __MI_Instance_GetClassName(msg->instanceName, &className);     r = __MI_Instance_GetClassName(msg->instanceName, &className);
Line 441 
Line 1018 
         return r;         return r;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName(self, libraryName, className, prov);      r = _GetProviderByClassName(
           self,
           proventry,
           className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
  
     /* Allocate the instance for the provider */     /* Allocate the instance for the provider */
     r = _Instance_InitConvert_FromBatch(     r = _Instance_InitConvert_FromBatch(
         msg->base.batch,          msg->base.base.batch,
         (*prov)->classDecl,         (*prov)->classDecl,
         (*prov)->lib->module->schemaDecl,         (*prov)->lib->module->schemaDecl,
         msg->instanceName,         msg->instanceName,
         MI_TRUE,         MI_TRUE,
         MI_FALSE,         MI_FALSE,
         &inst );          &inst,
           msg->base.base.flags);
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
         return r;         return r;
  
 #if 0 #if 0
     /* Print instance */     /* Print instance */
     Instance_Print(inst, stdout, 0);      Instance_Print(inst, stdout, 0, MI_FALSE, MI_FALSE);
 #endif #endif
  
     /* If provider's GetInstance method null, use EnumerateInstances */     /* If provider's GetInstance method null, use EnumerateInstances */
Line 473 
Line 1056 
             return MI_RESULT_INVALID_CLASS;             return MI_RESULT_INVALID_CLASS;
  
         /* Create context */         /* Create context */
         ctx = (Context*)Batch_GetClear(msg->base.batch, sizeof(Context));;          ctx = (Context*)Batch_GetClear(msg->base.base.batch, sizeof(Context));;
         Context_Init(ctx, (*prov));          r = Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;          if( MI_RESULT_OK != r )
               return r;
  
         /* _PostInstance() filters by this if not null */         /* _PostInstance() filters by this if not null */
         ctx->instanceName = inst;         ctx->instanceName = inst;
  
         /* message will be freed in context release*/  
         Message_AddRef(&msg->base);  
   
         /* Invoke provider */         /* Invoke provider */
         (*(*prov)->classDecl->providerFT->EnumerateInstances)(         (*(*prov)->classDecl->providerFT->EnumerateInstances)(
             (*prov)->self,             (*prov)->self,
Line 498 
Line 1079 
         Context* ctx;         Context* ctx;
  
         /* Create context */         /* Create context */
         ctx = (Context*)Batch_GetClear(msg->base.batch, sizeof(Context));;          ctx = (Context*)Batch_GetClear(msg->base.base.batch, sizeof(Context));;
         Context_Init(ctx, (*prov));          r = Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;          if( MI_RESULT_OK != r )
               return r;
         /* message will be freed in context release*/  
         Message_AddRef(&msg->base);  
  
         /* Invoke provider */         /* Invoke provider */
         (*(*prov)->classDecl->providerFT->GetInstance)(         (*(*prov)->classDecl->providerFT->GetInstance)(
Line 518 
Line 1097 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   static void _PostClassToCallback(
       Context* self,
       InteractionOpenParams* params,
       const MI_Class* schema)
   {
       MI_Result result = MI_RESULT_OK;
       PostSchemaMsg* resp = PostSchemaMsg_New(self->request->base.operationId);
   
       if (!resp)
       {
           trace_PostSchemaMsg_Failed();
           result = MI_RESULT_FAILED;
           goto End;
       }
   
       if (self->request->base.flags & WSMANFlag)
       {
           result = WSBuf_ClassToBuf(
                       schema,
                       self->request->base.flags,
                       resp->base.batch,
                       &resp->packedSchemaWsmanPtr,
                       &resp->packedSchemaWsmanSize);
   
           trace_ProvMgr_PostingSchemaInWsmanToCallback();
   
           if(result != MI_RESULT_OK)
           {
               trace_SchemaConversion_ToCimXmlFailed(result);
               goto End;
           }
   
           resp->base.flags |= self->request->base.flags;
       }
       else
       {
           result = Instance_New(&resp->schemaInstance, schema->classDecl, resp->base.batch);
           if (result != MI_RESULT_OK)
           {
               trace_SchemaConversion_ToInstanceFailed(result);
               goto End;
           }
   
           result = InstanceToBatch(
               resp->schemaInstance,
               NULL,
               NULL,
               resp->base.batch,
               &resp->packedSchemaInstancePtr,
               &resp->packedSchemaInstanceSize);
           if (result != MI_RESULT_OK)
           {
               trace_SchemaInstancePackaging_Failed(result);
               goto End;
           }
   
           resp->base.flags |= BinaryProtocolFlag;
       }
   
       Context_CompleteOpen( self, params, MI_RESULT_OK );
       Context_PostSchema( self, &resp->base);
       {
           PostResultMsg* msg = PostResultMsg_New( self->request->base.operationId );
           if (msg)
           {
               Context_PostMessageLeft( self, &msg->base );
               PostResultMsg_Release( msg );
           }
       }
   
       Strand_ScheduleClose(&self->strand);
   End:
       if(resp)
       {
           PostSchemaMsg_Release(resp);
       }
   
       if( MI_RESULT_OK != result )
       {
           Context_CompleteOpen( self, params, result );
       }
   }
   
   
   static MI_Result _HandleGetClassReq(
       _In_ ProvMgr* self,
       _In_ const ProvRegEntry* proventry,
       _Inout_ InteractionOpenParams* interactionParams,
       _Out_ Provider** prov)
   {
       MI_Result r;
       MI_Class resultClass;
       Context* ctx = NULL;
       GetClassReq* msg = (GetClassReq*)interactionParams->msg;
   
       trace_ProvMgr_GetClassReq(tcs(msg->className), tcs(msg->nameSpace));
   
       memset(&resultClass, 0, sizeof(MI_Class));
   
       /* find provider */
       r = _GetProviderByClassName(
           self,
           proventry,
           msg->className,
           &msg->base.base,
           prov);
   
       if ( MI_RESULT_OK != r )
           return r;
   
       ctx = (Context*)Batch_GetClear(msg->base.base.batch,
               sizeof(Context));;
       r = Context_PartialInit(ctx, (*prov), interactionParams);
       if( MI_RESULT_OK != r )
           return r;
   
       // by default serializer will use the function tables to access resultClass as a wrapper to MI_ClassDecl
       // this place will be modified in future to fill in the appropriate extended function tables
       // providing access to schema in form of instance of cimclass
       Class_Construct(&resultClass, (*prov)->classDecl);
   
       _PostClassToCallback(ctx, interactionParams, &resultClass);
       return MI_RESULT_OK;
   }
   
 static MI_Result _HandleCreateInstanceReq( static MI_Result _HandleCreateInstanceReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     CreateInstanceReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     MI_Instance* inst;     MI_Instance* inst;
     MI_Result r;     MI_Result r;
     const MI_Char* className;      const ZChar* className;
       CreateInstanceReq* msg = (CreateInstanceReq*)interactionParams->msg;
  
     /* Get classname from instance */     /* Get classname from instance */
     r = __MI_Instance_GetClassName(msg->instance, &className);     r = __MI_Instance_GetClassName(msg->instance, &className);
Line 535 
Line 1240 
         return r;         return r;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName(self, libraryName, className, prov);      r = _GetProviderByClassName(
           self,
           proventry,
           className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
  
     /* Allocate the instance for the provider */     /* Allocate the instance for the provider */
     r = _Instance_InitConvert_FromBatch(     r = _Instance_InitConvert_FromBatch(
         msg->base.batch,          msg->base.base.batch,
         (*prov)->classDecl,         (*prov)->classDecl,
         (*prov)->lib->module->schemaDecl,         (*prov)->lib->module->schemaDecl,
         msg->instance,         msg->instance,
         MI_FALSE,         MI_FALSE,
         MI_TRUE,         MI_TRUE,
         &inst );          &inst,
           msg->base.base.flags);
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
         return r;         return r;
Line 558 
Line 1269 
         return MI_RESULT_INVALID_CLASS;         return MI_RESULT_INVALID_CLASS;
  
     {     {
         Context* ctx = (Context*)Batch_GetClear(msg->base.batch,          Context* ctx = (Context*)Batch_GetClear(msg->base.base.batch,
             sizeof(Context));;             sizeof(Context));;
         Context_Init(ctx, (*prov));          Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;          if( MI_RESULT_OK != r )
               return r;
   
         /* message will be freed in context release*/         /* message will be freed in context release*/
         Message_AddRef(&msg->base);  
         (*(*prov)->classDecl->providerFT->CreateInstance)((*prov)->self, &ctx->base,         (*(*prov)->classDecl->providerFT->CreateInstance)((*prov)->self, &ctx->base,
             msg->nameSpace, className, inst);             msg->nameSpace, className, inst);
     }     }
Line 572 
Line 1284 
 } }
  
 static MI_Result _HandleModifyInstanceReq( static MI_Result _HandleModifyInstanceReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     ModifyInstanceReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     MI_Instance* inst;     MI_Instance* inst;
     MI_Result r;     MI_Result r;
     const MI_Char* className;      const ZChar* className;
       ModifyInstanceReq* msg = (ModifyInstanceReq*)interactionParams->msg;
  
     /* Get classname from instance */     /* Get classname from instance */
     r = __MI_Instance_GetClassName(msg->instance, &className);     r = __MI_Instance_GetClassName(msg->instance, &className);
Line 588 
Line 1301 
         return r;         return r;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName(self, libraryName, className, prov);      r = _GetProviderByClassName(
           self,
           proventry,
           className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
  
     /* Allocate the instance for the provider */     /* Allocate the instance for the provider */
     r = _Instance_InitConvert_FromBatch(     r = _Instance_InitConvert_FromBatch(
         msg->base.batch,          msg->base.base.batch,
         (*prov)->classDecl,         (*prov)->classDecl,
         (*prov)->lib->module->schemaDecl,         (*prov)->lib->module->schemaDecl,
         msg->instance,         msg->instance,
         MI_FALSE,         MI_FALSE,
         MI_FALSE,         MI_FALSE,
         &inst );          &inst,
           msg->base.base.flags);
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
         return r;         return r;
Line 611 
Line 1330 
         return MI_RESULT_INVALID_CLASS;         return MI_RESULT_INVALID_CLASS;
  
     {     {
         Context* ctx = (Context*)Batch_GetClear(msg->base.batch,          Context* ctx = (Context*)Batch_GetClear(msg->base.base.batch,
             sizeof(Context));;             sizeof(Context));;
         Context_Init(ctx, (*prov));          r = Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;          if( MI_RESULT_OK != r )
               return r;
   
           /* Need to store instance in case we need to call GetInstance */
           ctx->keyInstance = inst;
   
         /* message will be freed in context release*/         /* message will be freed in context release*/
         Message_AddRef(&msg->base);  
         (*(*prov)->classDecl->providerFT->ModifyInstance)((*prov)->self, &ctx->base,         (*(*prov)->classDecl->providerFT->ModifyInstance)((*prov)->self, &ctx->base,
             msg->nameSpace, className, inst, NULL);             msg->nameSpace, className, inst, NULL);
     }     }
Line 625 
Line 1348 
 } }
  
 static MI_Result _HandleDeleteInstanceReq( static MI_Result _HandleDeleteInstanceReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     DeleteInstanceReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     MI_Instance* inst;     MI_Instance* inst;
     MI_Result r;     MI_Result r;
     const MI_Char* className;      const ZChar* className;
       DeleteInstanceReq* msg = (DeleteInstanceReq*)interactionParams->msg;
  
     /* Get classname from instance */     /* Get classname from instance */
     r = __MI_Instance_GetClassName(msg->instanceName, &className);     r = __MI_Instance_GetClassName(msg->instanceName, &className);
Line 641 
Line 1365 
         return r;         return r;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName(self, libraryName, className, prov);      r = _GetProviderByClassName(
           self,
           proventry,
           className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
  
     /* Allocate the instance for the provider */     /* Allocate the instance for the provider */
     r = _Instance_InitConvert_FromBatch(     r = _Instance_InitConvert_FromBatch(
         msg->base.batch,          msg->base.base.batch,
         (*prov)->classDecl,         (*prov)->classDecl,
         (*prov)->lib->module->schemaDecl,         (*prov)->lib->module->schemaDecl,
         msg->instanceName,         msg->instanceName,
         MI_TRUE,         MI_TRUE,
         MI_FALSE,         MI_FALSE,
         &inst);          &inst,
           msg->base.base.flags);
  
     if (MI_RESULT_OK != r)     if (MI_RESULT_OK != r)
         return r;         return r;
Line 664 
Line 1394 
         return MI_RESULT_INVALID_CLASS;         return MI_RESULT_INVALID_CLASS;
  
     {     {
         Context* ctx = (Context*)Batch_GetClear(msg->base.batch,          Context* ctx = (Context*)Batch_GetClear(msg->base.base.batch,
             sizeof(Context));;             sizeof(Context));;
         Context_Init(ctx, (*prov));          r = Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;          if( MI_RESULT_OK != r )
               return r;
   
         /* message will be freed in context release*/         /* message will be freed in context release*/
         Message_AddRef(&msg->base);  
         (*(*prov)->classDecl->providerFT->DeleteInstance)((*prov)->self, &ctx->base,         (*(*prov)->classDecl->providerFT->DeleteInstance)((*prov)->self, &ctx->base,
             msg->nameSpace, className, inst);             msg->nameSpace, className, inst);
     }     }
Line 677 
Line 1408 
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
   #ifndef DISABLE_INDICATION
   
   /*
    * Behaves conditionally depending on whether or not indications were
    * compiled into the product.
    */
 static MI_Result _HandleSubscribeReq( static MI_Result _HandleSubscribeReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     SubscribeReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     MI_Result r;     MI_Result r;
       SubscribeReq* msg = (SubscribeReq*)interactionParams->msg;
   
       *prov = NULL;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName( self, libraryName, msg->className, prov );      r = _GetProviderByClassName(
           self,
           proventry,
           msg->className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;  
   
     /* Invoke provider */  
     if (!(*prov)->classDecl->providerFT->EnableIndications || !(*prov)->classDecl->providerFT->Subscribe)  
         return MI_RESULT_INVALID_CLASS;  
   
     if ((*prov)->ctxIndications.chainType == CTX_TYPE_IND_NOTINITIALIZED)  
     {     {
         /* have to initialize provider first */          trace_ProvMgr_ClassNotFound( tcs(msg->className) );
         (*prov)->ctxIndications.chainType = CTX_TYPE_IND_READY;          return r;
   
         (*prov)->classDecl->providerFT->EnableIndications((*prov)->self,  
             &(*prov)->ctxIndications.base, msg->nameSpace, msg->className);  
     }     }
  
     if ((*prov)->ctxIndications.chainType == CTX_TYPE_IND_READY)      return _Provider_InvokeSubscribeWrapper( *prov, interactionParams );
     {  
         /* provider is ready for subscriptions */  
         Context* ctx = (Context*)Batch_GetClear(msg->base.batch, sizeof(Context));  
         Context_Init(ctx, (*prov));  
         ctx->request = &msg->base;  
         /* message will be freed in context release*/  
         Message_AddRef(&msg->base);  
         (*(*prov)->classDecl->providerFT->Subscribe)((*prov)->self, &ctx->base,  
             msg->nameSpace, msg->className, 0, __bookmark, msg->subscriptionID,  
             __subscriptionSelfPtr);  
     }     }
     else  
         return MI_RESULT_FAILED;    /* unexpected state */  
  
     return MI_RESULT_OK;  #endif /* ifndef DISABLE_INDICATION */
 }  
  
 static MI_Result _HandleInvokeReq( static MI_Result _HandleInvokeReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     InvokeReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     MI_Instance* inst = 0;     MI_Instance* inst = 0;
     MI_Instance* instParams = 0;     MI_Instance* instParams = 0;
     MI_Result r;     MI_Result r;
     MI_ConstString cn = 0;     MI_ConstString cn = 0;
     MI_MethodDecl* md = 0;     MI_MethodDecl* md = 0;
       InvokeReq* msg = (InvokeReq*)interactionParams->msg;
   
   #if 0
       MessagePrint(&msg->base, stdout);
   #endif
  
     /* parameter validation */     /* parameter validation */
     if (!msg || !msg->function)     if (!msg || !msg->function)
Line 747 
Line 1474 
         return MI_RESULT_INVALID_CLASS;         return MI_RESULT_INVALID_CLASS;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName( self, libraryName, cn, prov );      r = _GetProviderByClassName(
           self,
           proventry,
           cn,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
Line 766 
Line 1498 
     {     {
  
         r = _Instance_InitConvert_FromBatch(         r = _Instance_InitConvert_FromBatch(
             msg->base.batch,              msg->base.base.batch,
             (*prov)->classDecl,             (*prov)->classDecl,
             (*prov)->lib->module->schemaDecl,             (*prov)->lib->module->schemaDecl,
             msg->instance,             msg->instance,
             MI_TRUE,             MI_TRUE,
             MI_FALSE,             MI_FALSE,
             &inst );              &inst,
               msg->base.base.flags);
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
             return r;             return r;
Line 782 
Line 1515 
     {     {
         /* paramters (if any) */         /* paramters (if any) */
         r = _Instance_InitConvert_FromBatch(         r = _Instance_InitConvert_FromBatch(
             msg->base.batch,              msg->base.base.batch,
             (const MI_ClassDecl*)md,             (const MI_ClassDecl*)md,
             (*prov)->lib->module->schemaDecl,             (*prov)->lib->module->schemaDecl,
             msg->instanceParams,             msg->instanceParams,
             MI_FALSE,             MI_FALSE,
             MI_TRUE,             MI_TRUE,
             &instParams );              &instParams,
               msg->base.base.flags);
  
         if (MI_RESULT_OK != r)         if (MI_RESULT_OK != r)
             return r;             return r;
Line 796 
Line 1530 
  
 #if 0 #if 0
     /* Print instance */     /* Print instance */
     Instance_Print(inst, stdout, 0);      Instance_Print(inst, stdout, 0, 0, 0);
 #endif #endif
  
     /* Invoke provider */     /* Invoke provider */
Line 804 
Line 1538 
         return MI_RESULT_INVALID_CLASS;         return MI_RESULT_INVALID_CLASS;
  
     {     {
         Context* ctx = (Context*)Batch_GetClear(msg->base.batch, sizeof(Context));;          Context* ctx = (Context*)Batch_GetClear(msg->base.base.batch, sizeof(Context));
         Context_Init(ctx, (*prov));          r = Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;          if( MI_RESULT_OK != r )
         /* message will be freed in context release*/              return r;
         Message_AddRef(&msg->base);  
  
         /* call get first if fn is non-static */         /* call get first if fn is non-static */
         /*if (inst && (*prov)->classDecl->providerFT->GetInstance)         /*if (inst && (*prov)->classDecl->providerFT->GetInstance)
         {         {
             ctx->chainType = CTX_TYPE_INVOKE_WITH_INSTANCE;              ctx->ctxType = CTX_TYPE_INVOKE_WITH_INSTANCE;
             ctx->inst = inst;             ctx->inst = inst;
             ctx->instParams = instParams;             ctx->instParams = instParams;
             ctx->md = md;             ctx->md = md;
Line 831 
Line 1564 
 } }
  
 static MI_Result _HandleEnumerateInstancesReq( static MI_Result _HandleEnumerateInstancesReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     EnumerateInstancesReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     Context* ctx;     Context* ctx;
     MI_Result r;     MI_Result r;
       EnumerateInstancesReq* msg = (EnumerateInstancesReq*)interactionParams->msg;
       InstanceFilter* instanceFilter = NULL;
       MI_Filter* filter = NULL;
   
   #if 0
       MessagePrint(&msg->base, stdout);
   #endif
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName( self, libraryName, msg->className, prov );      r = _GetProviderByClassName(
           self,
           proventry,
           msg->className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
  
       DEBUG_ASSERT(msg->wql == NULL);
   
       /* Get WQL query, if any */
       if (msg->queryLanguage != NULL && msg->queryExpression != NULL)
       {
           /* Create filter then Get WQL query */
           instanceFilter = InstanceFilter_New( &(msg->base.base) );
   
           if (instanceFilter == NULL)
           {
               trace_InstanceFilter_AllocFailed();
               return MI_RESULT_INVALID_QUERY;
           }
   
           filter = &(instanceFilter->base);
   
           msg->wql = InstanceFilter_GetWQL(instanceFilter);
       }
   
     /* Validate WQL query (if any) against provider's class declaration */     /* Validate WQL query (if any) against provider's class declaration */
     if (msg->wql)     if (msg->wql)
     {     {
         if (WQL_Validate(msg->wql, (*prov)->classDecl) != 0)         if (WQL_Validate(msg->wql, (*prov)->classDecl) != 0)
         {         {
             LOGW((T("query validation failed: %s"), msg->wql->text));              trace_QueryValidationFailed(tcs(msg->wql->text));
             return MI_RESULT_INVALID_QUERY;             return MI_RESULT_INVALID_QUERY;
         }         }
     }     }
Line 862 
Line 1626 
     /* Create the context object */     /* Create the context object */
     {     {
         ctx = (Context*)Batch_GetClear(         ctx = (Context*)Batch_GetClear(
             msg->base.batch, sizeof(Context));;              msg->base.base.batch, sizeof(Context));;
  
         if (!ctx)         if (!ctx)
         {         {
             LOGF((T("allocation failed")));              trace_ProvMgr_AllocFailed();
             return MI_RESULT_FAILED;             return MI_RESULT_FAILED;
         }         }
  
         Context_Init(ctx, (*prov));          r = Context_Init(ctx, (*prov), interactionParams);
         ctx->request = &msg->base;  
           if( MI_RESULT_OK != r )
               return r;
     }     }
  
     LOGD((T("enumerate instances of %s"), msg->className));      trace_ProvMgr_EnumerateInstancesOfClass( tcs(msg->className) );
  
     /* message will be freed in context release */  
     Message_AddRef(&msg->base);  
     (*(*prov)->classDecl->providerFT->EnumerateInstances)(     (*(*prov)->classDecl->providerFT->EnumerateInstances)(
         (*prov)->self, &ctx->base,         (*prov)->self, &ctx->base,
         msg->nameSpace, msg->className, NULL, MI_FALSE, NULL);          msg->nameSpace, msg->className, NULL, MI_FALSE, filter);
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
 static MI_Result _HandleAssociatorsOfReq(  static MI_Result MI_CALL _HandleAssociatorsOfReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     AssociatorsOfReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     Context* ctx;     Context* ctx;
     MI_Result r;     MI_Result r;
     MI_Instance* inst = 0;     MI_Instance* inst = 0;
       AssociationsOfReq* msg = (AssociationsOfReq*)interactionParams->msg;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName( self, libraryName, msg->className, prov );      r = _GetProviderByClassName(
           self,
           proventry,
           msg->className,
           &msg->base.base,
           prov);
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
Line 911 
Line 1681 
     {     {
         Provider* provInst = 0;         Provider* provInst = 0;
  
         r = _GetProviderByClassName( self, libraryName, ((Instance*) msg->instance)->classDecl->name, &provInst );          r = _GetProviderByClassName(
               self,
               proventry,
               ((Instance*) msg->instance)->classDecl->name,
               &msg->base.base,
               &provInst );
  
         if ( MI_RESULT_OK != r )         if ( MI_RESULT_OK != r )
             return r;             return r;
  
         r = _Instance_InitConvert_FromBatch(         r = _Instance_InitConvert_FromBatch(
             msg->base.batch,              msg->base.base.batch,
             provInst->classDecl,             provInst->classDecl,
             (*prov)->lib->module->schemaDecl,             (*prov)->lib->module->schemaDecl,
             msg->instance,             msg->instance,
             MI_TRUE,             MI_TRUE,
             MI_FALSE,             MI_FALSE,
             &inst );              &inst,
               msg->base.base.flags);
  
         Provider_Release(provInst);         Provider_Release(provInst);
  
Line 932 
Line 1708 
     }     }
  
     ctx = (Context*)Batch_GetClear(     ctx = (Context*)Batch_GetClear(
         msg->base.batch, sizeof(Context));;          msg->base.base.batch, sizeof(Context));;
  
     if (!ctx)     if (!ctx)
     {     {
         LOGF((T("allocation failed")));          trace_ProvMgr_AllocFailed();
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
     Context_Init(ctx, (*prov));      r = Context_Init(ctx, (*prov), interactionParams);
     ctx->request = &msg->base;      if( MI_RESULT_OK != r )
           return r;
  
     /* message will be freed in context release */     /* message will be freed in context release */
     Message_AddRef(&msg->base);  
     (*(*prov)->classDecl->providerFT->AssociatorInstances)(     (*(*prov)->classDecl->providerFT->AssociatorInstances)(
         (*prov)->self,         (*prov)->self,
         &ctx->base,         &ctx->base,
Line 960 
Line 1736 
 } }
  
 static MI_Result _HandleReferencesOfReq( static MI_Result _HandleReferencesOfReq(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     ReferencesOfReq* msg,      _Inout_ InteractionOpenParams* interactionParams,
     Provider** prov)      _Out_ Provider** prov)
 { {
     Context* ctx;     Context* ctx;
     MI_Result r;     MI_Result r;
     MI_Instance* inst = 0;     MI_Instance* inst = 0;
       AssociationsOfReq* msg = (AssociationsOfReq*)interactionParams->msg;
  
     /* find provider */     /* find provider */
     r = _GetProviderByClassName( self, libraryName, msg->className, prov );      r = _GetProviderByClassName(
           self,
           proventry,
           msg->className,
           &msg->base.base,
           prov );
  
     if ( MI_RESULT_OK != r )     if ( MI_RESULT_OK != r )
         return r;         return r;
Line 987 
Line 1769 
  
         r = _GetProviderByClassName(         r = _GetProviderByClassName(
             self,             self,
             libraryName,              proventry,
             ((Instance*) msg->instance)->classDecl->name,             ((Instance*) msg->instance)->classDecl->name,
               &msg->base.base,
             &provInst );             &provInst );
  
         if ( MI_RESULT_OK != r )         if ( MI_RESULT_OK != r )
             return r;             return r;
  
         r = _Instance_InitConvert_FromBatch(         r = _Instance_InitConvert_FromBatch(
             msg->base.batch,              msg->base.base.batch,
             provInst->classDecl,             provInst->classDecl,
             (*prov)->lib->module->schemaDecl,             (*prov)->lib->module->schemaDecl,
             msg->instance,             msg->instance,
             MI_TRUE,             MI_TRUE,
             MI_FALSE,             MI_FALSE,
             &inst );              &inst,
               msg->base.base.flags);
  
         Provider_Release(provInst);         Provider_Release(provInst);
  
Line 1010 
Line 1794 
     }     }
  
     ctx = (Context*)Batch_GetClear(     ctx = (Context*)Batch_GetClear(
         msg->base.batch, sizeof(Context));;          msg->base.base.batch, sizeof(Context));;
  
     if (!ctx)     if (!ctx)
     {     {
         LOGF((T("allocation failed")));          trace_ProvMgr_AllocFailed();
         return MI_RESULT_FAILED;         return MI_RESULT_FAILED;
     }     }
  
     Context_Init(ctx, (*prov));      r = Context_Init(ctx, (*prov), interactionParams);
     ctx->request = &msg->base;      if( MI_RESULT_OK != r )
           return r;
  
     /* message will be freed in context release */     /* message will be freed in context release */
     Message_AddRef(&msg->base);  
     (*(*prov)->classDecl->providerFT->ReferenceInstances)(     (*(*prov)->classDecl->providerFT->ReferenceInstances)(
         (*prov)->self,         (*prov)->self,
         &ctx->base,         &ctx->base,
Line 1046 
Line 1830 
  
     for (p = lib->head; p; )     for (p = lib->head; p; )
     {     {
         MI_Uint64 provFireAtTime = p->idleSince + self->idleTimeoutUsec;          /* ATTN: idleSince is sometimes 0 */
   
           MI_Uint64 provFireAtTime;
           if (p->idleSince != 0)
               provFireAtTime = p->idleSince + self->idleTimeoutUsec;
           else
               provFireAtTime = ~((MI_Uint64)0);
  
         p_next = p->next;         p_next = p->next;
  
Line 1054 
Line 1844 
         if (!idleOnly ||         if (!idleOnly ||
             (!p->refusedUnload && 0 == p->refCounter && provFireAtTime <= currentTimeUsec))             (!p->refusedUnload && 0 == p->refCounter && provFireAtTime <= currentTimeUsec))
         {         {
             LOGD((T("Unloading provider %s"), p->classDecl->name));              trace_ProvMgr_UnloadingProvider( tcs(p->classDecl->name) );
   
   #ifndef DISABLE_INDICATION
               if (p->subMgr)
               {
                   if (p->subMgr->lifecycleCtx)
                   {
                       LifeContext_Delete(p->subMgr->lifecycleCtx);
                       p->subMgr->lifecycleCtx = NULL;
                   }
               }
   #endif /* ifndef DISABLE_INDICATION */
  
             /* Call provider unload() method */             /* Call provider unload() method */
             if (p->classDecl->providerFT->Unload)              if (p->classDecl->providerFT && p->classDecl->providerFT->Unload)
             {             {
                 Context ctx;                 Context ctx;
                 Context_Init(&ctx, 0);                  Context_Init(&ctx, 0, NULL);
                 (*p->classDecl->providerFT->Unload)(p->self, &ctx.base);                 (*p->classDecl->providerFT->Unload)(p->self, &ctx.base);
  
                 DEBUG_ASSERT(ctx.magic == (MI_Uint32)-1);                 DEBUG_ASSERT(ctx.magic == (MI_Uint32)-1);
             }             }
  
             Context_Destroy(&p->ctxIndications);  
   
             if (p->refCounter != 0)             if (p->refCounter != 0)
             {             {
                 /* Error condition - unloading active rpovider! */                 /* Error condition - unloading active rpovider! */
                 LOGE((T("Unloading active provider %s, with ref counter %d"), p->classDecl->name, (int)p->refCounter));                  trace_UnloadingActiveProvider(
                 LOGE_CHAR(("Unloading active provider for lib %s, with ref counter %d", lib->libraryName, (int)p->refCounter));                      tcs(p->classDecl->name), (int)p->refCounter);
                   trace_UnloadingActiveProviderWithLib(
                       scs(lib->libraryName), (int)p->refCounter);
  
                 // ATTN: _exit is a good option here, since provider's behavior maybe undefined                  /* ATTN: _exit is a good option here, since provider's behavior maybe undefined */
                   trace_UnloadingActiveProvider_ServerExit(scs(lib->libraryName));
                 _exit(1);                 _exit(1);
             }             }
  
Line 1083 
Line 1885 
                 (ListElem**)&lib->tail,                 (ListElem**)&lib->tail,
                 (ListElem*)p);                 (ListElem*)p);
  
             free(p);              Provider_Finalize( p );
               PAL_Free(p);
         }         }
         else if (idleOnly && 0 == p->refCounter && nextFireAtTime)         else if (idleOnly && 0 == p->refCounter && nextFireAtTime)
         {         {
Line 1098 
Line 1901 
     }     }
 } }
  
 static void _UnloadAllLibraries(  /*
    * Unload all libraries *NOT* thread safely
    */
   static void _UnloadAllLibrariesInternal(
     ProvMgr* self,     ProvMgr* self,
     MI_Boolean idleOnly,     MI_Boolean idleOnly,
     MI_Uint64 currentTimeUsec,     MI_Uint64 currentTimeUsec,
Line 1111 
Line 1917 
     {     {
         p_next = p->next;         p_next = p->next;
  
           Lock_Acquire( &p->provlock );
         _UnloadAllProviders(self,p,idleOnly,currentTimeUsec,nextFireAtTime);         _UnloadAllProviders(self,p,idleOnly,currentTimeUsec,nextFireAtTime);
           Lock_Release( &p->provlock );
  
         /* Unload libraries that have no loaded providers */         /* Unload libraries that have no loaded providers */
         if (!p->head)         if (!p->head)
Line 1120 
Line 1928 
             if (p->module->Unload)             if (p->module->Unload)
             {             {
                 Context ctx;                 Context ctx;
                 Context_Init(&ctx, 0);                  MI_Result r = MI_RESULT_OK;
   
                   Context_Init(&ctx, NULL, NULL);
                   ctx.result = &r;
   
                 (p->module->Unload)(p->self, (MI_Context*)&ctx);                 (p->module->Unload)(p->self, (MI_Context*)&ctx);
                 Context_Destroy(&ctx);  
                   if (ctx.magic != 0xFFFFFFFF)
                   {
                       trace_LibraryUnload_DidnotPostResult();
                   }
   
                   if (MI_RESULT_OK != r)
                   {
                       trace_FailedCallLibraryUnload(r, scs(p->libraryName));
                   }
             }             }
  
             Lib_Close(p->handle);              Shlib_Close(p->handle);
             LOGD_CHAR(("Unloading lib %s", p->libraryName));              trace_ProvMgr_UnloadingLibrary( scs(p->libraryName) );
  
             List_Remove(             List_Remove(
                 (ListElem**)&self->head,                 (ListElem**)&self->head,
                 (ListElem**)&self->tail,                 (ListElem**)&self->tail,
                 (ListElem*)p);                 (ListElem*)p);
  
             free(p);              PAL_Free(p);
         }         }
  
         p = p_next;         p = p_next;
Line 1141 
Line 1962 
 } }
  
 /* /*
     Timeout handler: unloads idle providers and libraris,   * Unload all libraries thread safely
    */
   static void _UnloadAllLibraries(
       ProvMgr* self,
       MI_Boolean idleOnly,
       MI_Uint64 currentTimeUsec,
       MI_Uint64* nextFireAtTime)
   {
       Lock_Acquire( &self->liblock );
       _UnloadAllLibrariesInternal( self, idleOnly, currentTimeUsec, nextFireAtTime );
   
       // If all libraries are gone, notify caller
       if (!self->head && self->idleCallback)
           (*self->idleCallback)(self,self->idleCallbackData);
   
       Lock_Release( &self->liblock );
   }
   
   /*
       Timeout handler: unloads idle providers and libraries,
     re-calculates new timeout (for next provider),     re-calculates new timeout (for next provider),
     notifies server/agent if all libraries are unloaded     notifies server/agent if all libraries are unloaded
 */ */
Line 1160 
Line 2000 
         MI_Uint64   nextFireAtTime = u64max;         MI_Uint64   nextFireAtTime = u64max;
  
         /* Unload all idle providers */         /* Unload all idle providers */
         //LOGI((T("Unloading idle providers")));          /* trace_UnloadingIdleProviders(); */
  
         _UnloadAllLibraries(self, MI_TRUE, currentTimeUsec, &nextFireAtTime);         _UnloadAllLibraries(self, MI_TRUE, currentTimeUsec, &nextFireAtTime);
  
Line 1175 
Line 2015 
             handler->fireTimeoutAt = TIME_NEVER;             handler->fireTimeoutAt = TIME_NEVER;
         }         }
  
         /* If all libraries are gone, notify caller */  
         if (!self->head && self->idleCallback)  
             (*self->idleCallback)(self,self->idleCallbackData);  
   
         return MI_TRUE;         return MI_TRUE;
     }     }
  
Line 1212 
Line 2048 
  
     Strlcpy(self->providerDir, providerDir, sizeof(self->providerDir)-1);     Strlcpy(self->providerDir, providerDir, sizeof(self->providerDir)-1);
  
     self->idleTimeoutUsec = MI_ULL(90) * MI_ULL(1000000);      self->idleTimeoutUsec = PROVMGR_IDLE_TIMEOUT_USEC;
  
     /* Add socket handler to catch timeout event */     /* Add socket handler to catch timeout event */
  
Line 1225 
Line 2061 
  
     Selector_AddHandler(selector, &self->timeoutHandler);     Selector_AddHandler(selector, &self->timeoutHandler);
  
       self->ioThreadId = Thread_ID(); /* IO thread always initializes for Linux */
       Lock_Init( &self->liblock );
   
   #ifndef DISABLE_INDICATION
       RequestHandler_Init(&g_requesthandler);
   #endif
   
     return MI_RESULT_OK;     return MI_RESULT_OK;
 } }
  
Line 1234 
Line 2077 
     if (!self)     if (!self)
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
   #ifndef DISABLE_INDICATION
       RequestHandler_Finalize(&g_requesthandler);
   #endif
   
     /* release opened libraries */     /* release opened libraries */
     _UnloadAllLibraries(self, MI_FALSE, 0, NULL);     _UnloadAllLibraries(self, MI_FALSE, 0, NULL);
  
       /* If local session is initialized then we need to clean-up */
       while (Atomic_Read(&self->localSessionInitialized) != 0)
       {
           if (Atomic_CompareAndSwap(&self->localSessionInitialized, 2, 1))
           {
               /* Initialized, so need to deinitialize */
               MI_Session_Close(&self->localSession, NULL, NULL);
               MI_Application_Close(&self->localApplication);
               self->localSessionInitialized = 0;
               /* Broadcast does a memory barrier so no need for assignment to be atomic */
               CondLock_Broadcast((ptrdiff_t) &self->localSession);
           }
           else if (self->localSessionInitialized == 1)
           {
               /* Initializing for some reason so wait for it to complete */
               ptrdiff_t init = self->localSessionInitialized;
               while (init == 1)
               {
                   CondLock_Wait((ptrdiff_t)&self->localSession, &self->localSessionInitialized, init, CONDLOCK_DEFAULT_SPINCOUNT);
                   init = self->localSessionInitialized;
               }
           }
       }
   
     memset(self, -1, sizeof(ProvMgr));     memset(self, -1, sizeof(ProvMgr));
  
     return MI_RESULT_OK;     return MI_RESULT_OK;
Line 1246 
Line 2117 
     Routes incoming message to appropriate     Routes incoming message to appropriate
     message handler based on message tag     message handler based on message tag
 */ */
 MI_Result ProvMgr_PostMessage(  MI_Result MI_CALL ProvMgr_NewRequest(
     ProvMgr* self,      _In_ ProvMgr* self,
     const char* libraryName,      _In_ const ProvRegEntry* proventry,
     Message* msg)      _Inout_ InteractionOpenParams* params )
 { {
     Provider* prov = 0;     Provider* prov = 0;
     MI_Result r = MI_RESULT_INVALID_PARAMETER;     MI_Result r = MI_RESULT_INVALID_PARAMETER;
  
     /* Check parameters */     /* Check parameters */
     if (!self || !msg)      if( !self || !params || !params->msg || !params->interaction )
         return MI_RESULT_INVALID_PARAMETER;         return MI_RESULT_INVALID_PARAMETER;
  
     /* Dispatch the message */     /* Dispatch the message */
     switch (msg->tag)      switch( params->msg->tag )
     {     {
         case GetInstanceReqTag:         case GetInstanceReqTag:
         {         {
             r = _HandleGetInstanceReq(self, libraryName,              r = _HandleGetInstanceReq(self, proventry, params, &prov);
                 (GetInstanceReq*)msg, &prov);              break;
           }
           case GetClassReqTag:
           {
               r = _HandleGetClassReq(self, proventry, params, &prov);
             break;             break;
         }         }
         case CreateInstanceReqTag:         case CreateInstanceReqTag:
         {         {
             r = _HandleCreateInstanceReq(self, libraryName,              r = _HandleCreateInstanceReq(self, proventry, params, &prov);
                 (CreateInstanceReq*)msg, &prov);  
             break;             break;
         }         }
         case ModifyInstanceReqTag:         case ModifyInstanceReqTag:
         {         {
             r = _HandleModifyInstanceReq(self, libraryName,              r = _HandleModifyInstanceReq(self, proventry, params, &prov);
                 (ModifyInstanceReq*)msg, &prov);  
             break;             break;
         }         }
         case DeleteInstanceReqTag:         case DeleteInstanceReqTag:
         {         {
             r = _HandleDeleteInstanceReq(self, libraryName,              r = _HandleDeleteInstanceReq(self, proventry, params, &prov);
                 (DeleteInstanceReq*)msg, &prov);  
             break;             break;
         }         }
         case InvokeReqTag:         case InvokeReqTag:
         {         {
             r = _HandleInvokeReq(self, libraryName,              r = _HandleInvokeReq(self, proventry, params, &prov);
                 (InvokeReq*)msg, &prov);  
             break;             break;
         }         }
         case EnumerateInstancesReqTag:         case EnumerateInstancesReqTag:
         {         {
             r = _HandleEnumerateInstancesReq(self, libraryName,              r = _HandleEnumerateInstancesReq(self, proventry, params, &prov);
                 (EnumerateInstancesReq*)msg, &prov);  
             break;             break;
         }         }
         case AssociatorsOfReqTag:         case AssociatorsOfReqTag:
         {         {
             r = _HandleAssociatorsOfReq(self, libraryName,              r = _HandleAssociatorsOfReq(self, proventry, params, &prov);
                 (AssociatorsOfReq*)msg, &prov);  
             break;             break;
         }         }
         case ReferencesOfReqTag:         case ReferencesOfReqTag:
         {         {
             r = _HandleReferencesOfReq(self, libraryName,              r = _HandleReferencesOfReq(self, proventry, params, &prov);
                 (ReferencesOfReq*)msg, &prov);  
             break;             break;
         }         }
   #ifndef DISABLE_INDICATION
         case SubscribeReqTag:         case SubscribeReqTag:
         {         {
             r = _HandleSubscribeReq(self, libraryName,              r = _HandleSubscribeReq(self, proventry, params, &prov);
                 (SubscribeReq*)msg, &prov);  
             break;             break;
         }         }
   #endif
         default:         default:
               trace_ProvMgr_NewRequest_UnsupportedMessage(
                   params->msg, MessageName(params->msg->tag));
             break;             break;
     }     }
  
     Provider_Release(prov);      Provider_Release(prov); /* Releases hold from Provider_AddRef in _OpenProvider() */
     return r;     return r;
 } }
  
 /* /*
     Increments provider's ref-counter   * Increments provider's ref-counter
 */ */
 void Provider_Addref(Provider* provider) void Provider_Addref(Provider* provider)
 { {
     if (provider)     if (provider)
         AtomicInc(&provider->refCounter);          Atomic_Inc(&provider->refCounter);
 } }
  
 /* /*
     Decrements provider's ref-counter and   * Finalize provider before free memory
     marks provider as idle if ref-counter is 0 and  
     'refuse-unload' was not called  
 */ */
 void Provider_Release(Provider* provider)  _Use_decl_annotations_
   void Provider_Finalize(Provider* provider)
 { {
     if (provider && AtomicDec(&provider->refCounter))      if (provider)
     {     {
         //LOGD((T("Releasing provider %s"), provider->classDecl->name));  #ifndef DISABLE_INDICATION
           DEBUG_ASSERT( provider->subMgr );
           SubMgr_Finalize( provider->subMgr );
   #endif
       }
   }
  
   /*
    * Decrements provider's ref-counter and
    * marks provider as idle if ref-counter is 0 and
    * 'refuse-unload' was not called
    */
   void Provider_Release(Provider* provider)
   {
       if (provider && Atomic_Dec(&provider->refCounter) == 0)
       {
         if (!provider->refusedUnload)         if (!provider->refusedUnload)
         {         {
             /* Provider becomes idle */             /* Provider becomes idle */
             if (MI_RESULT_OK != Time_Now(&provider->idleSince))              if (PAL_TRUE != PAL_Time(&provider->idleSince))
                 provider->idleSince = ~ (MI_Uint64)0;                 provider->idleSince = ~ (MI_Uint64)0;
  
             //LOGD((T("Setting idle-since to ") UINT64_FMT_T T(" for provider %s"), provider->idleSince, provider->classDecl->name));  
   
             /* Set timer if it's first idle provider */             /* Set timer if it's first idle provider */
             if (TIME_NEVER == provider->lib->provmgr->timeoutHandler.fireTimeoutAt)             if (TIME_NEVER == provider->lib->provmgr->timeoutHandler.fireTimeoutAt)
             {             {
                 if (MI_RESULT_OK == Time_Now(&provider->lib->provmgr->timeoutHandler.fireTimeoutAt))                  if (PAL_TRUE == PAL_Time(&provider->lib->provmgr->timeoutHandler.fireTimeoutAt))
                 {                 {
                     provider->lib->provmgr->timeoutHandler.fireTimeoutAt += provider->lib->provmgr->idleTimeoutUsec;                     provider->lib->provmgr->timeoutHandler.fireTimeoutAt += provider->lib->provmgr->idleTimeoutUsec;
  
                     //LOGD((T("Setting fire-at to ") UINT64_FMT_T, provider->lib->provmgr->timeoutHandler.fireTimeoutAt));  
   
                     /* wakeup main thread */                     /* wakeup main thread */
                     Selector_Wakeup(provider->lib->provmgr->selector);                      Selector_Wakeup(provider->lib->provmgr->selector, MI_TRUE);
                 }                 }
             }             }
         }         }
Line 1374 
Line 2253 
     provider->refusedUnload = flag;     provider->refusedUnload = flag;
 } }
  
 void Provider_NewInstanceCreated(  
     Provider* provider,  MI_Result ProvMgr_GetLocalSesson(
     Message* msg)      _Inout_ ProvMgr* self,
       _Out_ MI_Session *localSession)
   {
   #if defined(DISABLE_LOCALSESSION)
       MI_UNREFERENCED_PARAMETER(self);
       MI_UNREFERENCED_PARAMETER(localSession);
   
       return MI_RESULT_NOT_SUPPORTED;
   #else /* defined(DISABLE_LOCALSESSION) */
   
       while (Atomic_Read(&self->localSessionInitialized) != 2)
       {
           if (Atomic_CompareAndSwap(&self->localSessionInitialized, 0, 1) == 0)
           {
               /* Need to initialize */
               MI_Result miResult;
               miResult = MI_Application_Initialize(0, MI_T("OMI Local Session"), NULL, &self->localApplication);
               if (miResult == MI_RESULT_OK)
               {
                   miResult = MI_Application_NewSession(&self->localApplication, NULL, NULL, NULL, NULL, NULL, &self->localSession);
                   if (miResult == MI_RESULT_OK)
                   {
                       /* Succeeded, so mark as initialized */
                       *localSession = self->localSession;
                       self->localSessionInitialized = 2;
                   }
                   else
                   {
                       /* Failed, so reset state */
                       MI_Application_Close(&self->localApplication);
                       self->localSessionInitialized = 0;
                   }
               }
               else
               {
                   /* Failed so reset state */
                   self->localSessionInitialized = 0;
               }
               /* memory barrier as part of broadcast which is why state updates were not atomic */
               CondLock_Broadcast((ptrdiff_t) &self->localSession);
   
               return miResult;
           }
           else if (self->localSessionInitialized == 1)
 { {
     Selector_NewInstanceCreated(provider->lib->provmgr->selector, msg);              /* Wait for the initialization on another thread to complete */
               ptrdiff_t init = self->localSessionInitialized;
               while (init == 1)
               {
                   CondLock_Wait((ptrdiff_t)&self->localSession, &self->localSessionInitialized, init, CONDLOCK_DEFAULT_SPINCOUNT);
                   init = self->localSessionInitialized;
               }
               /* Need to try another trip around the loop to make sure it is initialized this time around */
           }
       }
   
       *localSession = self->localSession;
       return MI_RESULT_OK;
   #endif  /* defined(DISABLE_LOCALSESSION) */
 } }


Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

ViewCVS 0.9.2