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

File: [OMI] / omi / provmgr / context.c (download)
Revision: 1.2, Fri Jun 15 19:51:14 2012 UTC (11 years, 11 months ago) by mike
Branch: MAIN
CVS Tags: OMI_1_0_1
Changes since 1.1: +1 -1 lines
OMI 1.0.1

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include "context.h"
#include <protocol/wsbuf.h>
#include <wql/wql.h>

static const MI_Uint32 _MAGIC = 0x35eb3d3b;

static MI_Result _ProcessResult(
    MI_Context* self_,
    MI_Result result,
    const MI_Char* message,
    const MI_Instance* error)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC)
        return MI_RESULT_INVALID_PARAMETER;

    LOGD_CHAR(("post result from provider, %d", (int)result));

    /* If no instances matched during GetInstance over EnumerateInstance */
    if (self->instanceName && !self->matchedInstanceName)
    {
        if (result == MI_RESULT_OK)
            result = MI_RESULT_NOT_FOUND;
    }

    message = message;
    error = error;

    if (self->request && !self->cancelled)
    {
        PostResultMsg* resp = PostResultMsg_New( self->request ? self->request->msgID : 0 );

        if (!resp)
            return MI_RESULT_FAILED;

        resp->result = result;
        Message_SetRequest(&resp->base,self->request);
        (*self->request->callback)(&resp->base, self->request->callbackData);
        PostResultMsg_Release(resp);
    }

    if (self->result)
        *self->result = result;

    /* destory context */
    Context_Destroy(self);

    return MI_RESULT_OK;
}

static MI_Boolean _FilterProperty(const MI_Char* name, void *data)
{
    WQL* wql = (WQL*)data;

    if (WQL_ContainsProperty(wql, name))
        return MI_FALSE;
    else
        return MI_TRUE;
}

static MI_Result _PostInstanceToCallback(
    Context* self,
    const MI_Instance* instance)
{
    PostInstanceMsg* resp = PostInstanceMsg_New(self->request->msgID);

    if (!resp)
        return MI_RESULT_FAILED;

    if (self->request->flags & WSMANFlag)
    {
        const MI_ClassDecl* castToClassDecl = 0;

        /* Enumerate response with 'base-properties-only' option 
            may require instance conversion */
        if (EnumerateInstancesReqTag == self->request->tag)
        {
            EnumerateInstancesReq* req = (EnumerateInstancesReq*)self->request;

            if (req->requestClassName)
            {
                castToClassDecl = instance->classDecl;

                while (castToClassDecl && 
                    Zcasecmp(req->requestClassName, castToClassDecl->name) != 0)
                {
                    castToClassDecl = castToClassDecl->superClassDecl;
                }
            }
        }

        {
            EnumerateInstancesReq* req = NULL;

            if (EnumerateInstancesReqTag == self->request->tag)
                req = (EnumerateInstancesReq*)self->request;

            if (req && req->wql)
            {
                WSBuf_InstanceToBuf(
                    instance,
                    _FilterProperty,
                    req->wql,
                    castToClassDecl,
                    resp->base.batch, 
                    self->request->flags,
                    &resp->packedInstancePtr, 
                    &resp->packedInstanceSize);
            }
            else
            {
                WSBuf_InstanceToBuf(
                    instance,
                    NULL, /* filterProperty */
                    NULL, /* filterPropertyData */
                    castToClassDecl,
                    resp->base.batch, 
                    self->request->flags,
                    &resp->packedInstancePtr, 
                    &resp->packedInstanceSize);
            }
        }

        resp->base.flags |= self->request->flags;
    }
    else
    {
        EnumerateInstancesReq* req = NULL;

        if (EnumerateInstancesReqTag == self->request->tag)
            req = (EnumerateInstancesReq*)self->request;

        if (req && req->wql)
        {
            InstanceToBatch(instance, _FilterProperty, req->wql, 
                resp->base.batch, &resp->packedInstancePtr, 
                &resp->packedInstanceSize);
        }
        else
        {
            InstanceToBatch(instance, NULL, NULL, resp->base.batch, 
                &resp->packedInstancePtr, &resp->packedInstanceSize);
        }

        resp->base.flags |= BinaryProtocolFlag;
    }

    /* count message in for back-pressure feature (only Instances) */
    if (self->provider)
        Provider_NewInstanceCreated(self->provider, &resp->base);


    Message_SetRequest(&resp->base,self->request);
    (*self->request->callback)(&resp->base, self->request->callbackData);
    PostInstanceMsg_Release(resp);

    return MI_RESULT_OK;
}

/* successfully received instance from 'gi' - call invoke with this instance now */
static void _CallInvoke(
    Context* self,
    const MI_Instance* instance)
{
    Context* ctx = (Context*)Batch_GetClear(self->request->batch, sizeof(Context));;

    Context_Init(ctx, self->provider);

    ctx->request = self->request;
    /* message will be freed in context release*/
    Message_AddRef(ctx->request);

    /* disregard all other messages for this context */
    self->cancelled = MI_TRUE;
    /* ATTN! clone instance, since invoke can overlive instance (if it's async)!!! */
    (*self->md->function)(self->prov_self, &ctx->base, 
        __nameSpace, __className, __methodName, instance, self->instParams);
}


static MI_Result MI_CALL _PostResult(
    MI_Context* self_,
    MI_Result result)
{
    return _ProcessResult(self_, result, 0, 0);
}

static MI_Result MI_CALL _PostResultWithMessage(
    MI_Context* self_,
    MI_Result result,
    const MI_Char* message)
{
    return _ProcessResult(self_, result, message, 0);
}


static MI_Result MI_CALL _PostResultWithError(
    _In_ MI_Context* self_,
    MI_Result result,
    _In_ const MI_Instance* error)
{
    return _ProcessResult(self_, result, 0, error);
}

static MI_Result MI_CALL _PostInstance(
    MI_Context* self_,
    const MI_Instance* instance)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !instance)
        return MI_RESULT_INVALID_PARAMETER;

    if (self->request && !self->cancelled)
    {
        if (self->instanceName == NULL)
        {
            if (CTX_TYPE_INVOKE_WITH_INSTANCE == self->chainType)
            {
                _CallInvoke(self, instance);
                return MI_RESULT_OK;
            }
            else if (EnumerateInstancesReqTag == self->request->tag)
            {
                EnumerateInstancesReq* req = 
                    (EnumerateInstancesReq*)self->request;

                if (req->wql)
                {
                    int r;

                    r = WQL_Eval(req->wql, WQL_LookupInstanceProperty, 
                        (void*)instance);

                    if (r == 0)
                    {
                        /* Instance matched the query */
                        return _PostInstanceToCallback(self, instance);
                    }
                    else
                    {
                        /* Mismatch or failure */
                        return MI_RESULT_OK;
                    }
                }
            }

            return _PostInstanceToCallback(self, instance);
        }
        else if (Instance_MatchKeys(instance, self->instanceName))
        {
            /* Handle GetInstance through EnumerateInstances */
            if (!self->matchedInstanceName)
            {
                self->matchedInstanceName = MI_TRUE;
                return _PostInstanceToCallback(self, instance);
            }
        }
    }

    return MI_RESULT_OK;
}

static MI_Result MI_CALL _ConstructInstance(
    MI_Context* self_,
    const MI_ClassDecl* classDecl,
    MI_Instance* instance)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !instance || !classDecl)
        return MI_RESULT_INVALID_PARAMETER;

    return Instance_Construct(instance, classDecl, self->request->batch);
}

static MI_Result MI_CALL _ConstructParameters(
    MI_Context* self_,
    const MI_MethodDecl* methodDecl,
    MI_Instance* instance)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !instance || !methodDecl)
        return MI_RESULT_INVALID_PARAMETER;

    return Parameters_Init(instance, methodDecl, self->request->batch);
}

static MI_Result MI_CALL _NewInstance(
    MI_Context* self_,
    const MI_ClassDecl* classDecl,
    MI_Instance** instance)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !classDecl || !instance)
        return MI_RESULT_INVALID_PARAMETER;

    return Instance_New(instance, classDecl, self->request->batch);
}

static MI_Result MI_CALL _NewDynamicInstance(
    MI_Context* self_,
    const MI_Char* className,
    MI_Uint32 flags,
    MI_Instance** instance)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !className || !instance)
        return MI_RESULT_INVALID_PARAMETER;

    return Instance_NewDynamic(instance, className, flags, 
        self->request->batch);
}

static MI_Result MI_CALL _NewParameters(
    MI_Context* self_,
    const MI_MethodDecl* methodDecl,
    MI_Instance** instance)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !methodDecl || !instance)
        return MI_RESULT_INVALID_PARAMETER;

    return Parameters_New(instance, methodDecl, self->request->batch);
}

static MI_Result MI_CALL _Canceled(
    const MI_Context* self_,
    MI_Boolean* flag)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !flag)
        return MI_RESULT_INVALID_PARAMETER;

    *flag = self->cancelled;
    return MI_RESULT_OK;
}

static MI_Result MI_CALL _PostIndication(
    MI_Context* context,
    const MI_Instance* indication,
    MI_Uint32 subscriptionIDCount,
    const MI_Char* bookmark)
{
    /* ATTN: just use _PostInstance() for now */
    MI_UNUSED(subscriptionIDCount);
    MI_UNUSED(bookmark);
    return _PostInstance(context, indication);
}

static MI_Result MI_CALL _GetLocale(
    const MI_Context* context,
    MI_LocaleType localeType,
    MI_Char locale[MI_MAX_LOCALE_SIZE])
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result MI_CALL _RegisterCancel(
    MI_Context* context,
    MI_CancelCallback callback,
    void* callbackData)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result MI_CALL _RequestUnload(
    MI_Context* self_)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !self->provider)
        return MI_RESULT_INVALID_PARAMETER;

    Provider_SetRefuseUnloadFlag(self->provider, MI_FALSE);
    return MI_RESULT_OK;
}

static MI_Result MI_CALL _RefuseUnload(
    MI_Context* self_)
{
    Context* self = (Context*)self_;

    if (!self || self->magic != _MAGIC || !self->provider)
        return MI_RESULT_INVALID_PARAMETER;

    Provider_SetRefuseUnloadFlag(self->provider, MI_TRUE);
    return MI_RESULT_OK;
}

static MI_Result _GetLocalSession(
    _In_ const MI_Context* context,
    _Out_ MI_Session* session)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _SetStringOption(
    _In_ MI_Context* context,
    _In_z_ const MI_Char* name,
    _In_z_ const MI_Char* value)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _GetStringOption(
    _In_  MI_Context* context,
    _In_z_ const MI_Char* name,
    _Outptr_result_z_  const MI_Char** value)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _GetNumberOption(
    _In_  MI_Context* context,
    _In_z_ const MI_Char *name,
    _Out_opt_  MI_Uint32* value)
{
    return MI_RESULT_NOT_SUPPORTED;
}      

static MI_Result _GetCustomOption(
    _In_  MI_Context* context,
    _In_z_ const MI_Char* name,
    _Out_opt_  MI_Type* valueType,
    _Out_opt_  MI_Value* value)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _GetCustomOptionCount(
    _In_  MI_Context* context,
    _Out_opt_ MI_Uint32* count)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _GetCustomOptionAt(
    _In_  MI_Context* context,
    _In_ MI_Uint32 index,
    _Outptr_opt_result_maybenull_z_  const MI_Char** name,
    _Out_opt_  MI_Type* valueType,
    _Out_opt_  MI_Value* value)
{
    return MI_RESULT_NOT_SUPPORTED;
}    

static MI_Result _WriteMessage(
    _In_ MI_Context* context,
    MI_Uint32 channel,
    _In_z_ const MI_Char* message)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _WriteProgress(
    _In_ MI_Context* context,
    _In_z_ const MI_Char* activity,
    _In_z_ const MI_Char* currentOperation,
    _In_z_ const MI_Char* statusDescription,
    MI_Uint32 percentComplete,
    MI_Uint32 secondsRemaining)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _WriteStreamParameter(
    _In_ MI_Context* context,
    _In_z_ const MI_Char* name,
    _In_ const MI_Value* value,
    _In_ MI_Type type,
    _In_ MI_Uint32 flags)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _WriteCimError(
    _In_ MI_Context* context,
    _In_ const MI_Instance *error,
    _Out_ MI_Boolean *flag)
{
    return MI_RESULT_NOT_SUPPORTED;
}     

static MI_Result _PromptUser(
    _In_ MI_Context* context,
    _In_z_ const MI_Char* message, 
    MI_PromptType promptType,
    _Out_ MI_Boolean* result)
{
    return MI_RESULT_NOT_SUPPORTED;
}    

static MI_Result _ShouldProcess(
    _In_ MI_Context* context,
    _In_z_ const MI_Char* target,
    _In_z_ const MI_Char* action,
    _Out_ MI_Boolean* result)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _ShouldContinue(
    _In_ MI_Context* context,
    _In_z_ const MI_Char* message,
    _Out_ MI_Boolean* result)
{
    return MI_RESULT_NOT_SUPPORTED;
} 

static MI_Result _PostError(
    _In_ MI_Context* context,
    MI_Uint32 resultCode,
    _In_z_ const MI_Char* resultType,
    _In_z_ const MI_Char* errorMessage)
{
    return MI_RESULT_NOT_SUPPORTED;
}

static MI_Result _PostCimError(
    _In_ MI_Context* context,
    _In_ const MI_Instance *error)
{
    return MI_RESULT_NOT_SUPPORTED;
}  

static MI_Result _WriteError(
    _In_ MI_Context* context,
    MI_Uint32 resultCode,
    _In_z_ const MI_Char* resultType,
    _In_z_ const MI_Char* errorMessage,
    _Out_ MI_Boolean *flag)
{
    return MI_RESULT_NOT_SUPPORTED;
}

MI_ContextFT __mi_contextFT =
{
    _PostResult,
    _PostResultWithMessage,
    _PostResultWithError,
    _PostInstance,
    _PostIndication,
    _ConstructInstance,
    _ConstructParameters,
    _NewInstance,
    _NewDynamicInstance,
    _NewParameters,
    _Canceled,
    _GetLocale,
    _RegisterCancel,
    _RequestUnload,
    _RefuseUnload,
    _GetLocalSession,
    _SetStringOption,
    _GetStringOption,
    _GetNumberOption,
    _GetCustomOption,
    _GetCustomOptionCount,
    _GetCustomOptionAt,
    _WriteMessage,
    _WriteProgress,
    _WriteStreamParameter,
    _WriteCimError,
    _PromptUser,
    _ShouldProcess,
    _ShouldContinue,
    _PostError,
    _PostCimError,
    _WriteError,
};

void Context_Init(
    Context* self,
    Provider*   provider)
{
    memset(self, 0, sizeof(Context));
    self->base.ft = &__mi_contextFT;
    self->magic = _MAGIC;
    self->provider = provider;
    Provider_Addref(self->provider);
}

void Context_Destroy(
    Context* self)
{
    Message* req = self ? self->request : 0;

    if (self)
        Provider_Release(self->provider);

    memset(self, -1, sizeof(Context));

    /* Context typ[ically allocated from message's batch
        so it may be freed right inside 'Release' call */
    if (req)
        Message_Release(req);
}

ViewCVS 0.9.2