File: [OMI] / omi / base / instance.c
(download)
Revision: 1.1,
Wed May 30 21:47:49 2012 UTC (12 years, 1 month ago) by mike
Branch: MAIN
Initial revision
|
/*
**==============================================================================
**
** 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 <ctype.h>
#include "instance.h"
#include "helpers.h"
#include "naming.h"
#include "indent.h"
#include "types.h"
#include "schemadecl.h"
#include "alloc.h"
#include "field.h"
#include "io.h"
#if 0
# include "return.h"
#endif
/*
**==============================================================================
**
** Local definitions
**
**==============================================================================
*/
#define T MI_T
/* Magic number of InstanceHeader */
static MI_Uint32 _MAGIC = 0xB26AEA60;
/* Number of default pages for a self-owned batch object */
static MI_Uint32 _NUM_PAGES = 8;
/* The minimum number of reserved properties for a dynamic instance */
static MI_Uint32 _CAPACITY = 32;
/* Find capacity (lesser of _CAPACITY or x rounded to power of 2) */
static MI_Uint32 _FindCapacity(MI_Uint32 x)
{
if (x <= _CAPACITY)
return _CAPACITY;
else
{
MI_Uint32 r = x - 1;
r |= (r >> 1);
r |= (r >> 2);
r |= (r >> 4);
r |= (r >> 8);
r |= (r >> 16);
return r + 1;
}
}
/*
* Obtains the self pointer for this instance. For static instances, this
* it is the same as the instance parameter. For dynamic instances, the
* self pointer is given by instance->self.
*/
MI_INLINE Instance* _SelfOf(const MI_Instance* instance)
{
Instance* self = (Instance*)instance;
if (self)
{
if (self->self)
self = self->self;
return self;
}
DEBUG_ASSERT(0);
return NULL;
}
/* Return the index of the given property or (MI_Uin32)-1 if not found */
static MI_Uint32 _FindPropertyDecl(
const MI_ClassDecl* cd,
const MI_Char* name)
{
MI_PropertyDecl** start = cd->properties;
MI_PropertyDecl** end = start + cd->numProperties;
MI_PropertyDecl** p = start;
MI_Uint32 code;
code = Hash(name);
while (p != end)
{
if ((*p)->code == code && Zcasecmp((*p)->name, name) == 0)
return (MI_Uint32)(p - start);
p++;
}
return (MI_Uint32)-1;
}
static MI_PropertyDecl* _ClonePropertyDecl(
const MI_PropertyDecl* pd,
Batch* batch)
{
MI_PropertyDecl* p;
p = (MI_PropertyDecl*)BCalloc(batch, sizeof(MI_PropertyDecl), CALLSITE);
if (!p)
return NULL;
if (pd->name)
{
p->name = BStrdup(batch, pd->name, CALLSITE);
if (!p->name)
return NULL;
}
p->flags = pd->flags;
p->code = pd->code;
p->type = pd->type;
p->offset = pd->offset;
return p;
}
static MI_PropertyDecl** _ClonePropertyDecls(
MI_PropertyDecl** properties,
MI_Uint32 size,
Batch* batch)
{
MI_PropertyDecl** data;
MI_Uint32 i;
/* Allocate at least _CAPACITY properties */
MI_Uint32 cap = (size < _CAPACITY) ? _CAPACITY : size;
/* Allocate properties array */
data = (MI_PropertyDecl**)BAlloc(batch, sizeof(MI_PropertyDecl*) * cap,
CALLSITE);
if (!data)
return NULL;
/* Copy each property */
for (i = 0; i < size; i++)
{
MI_PropertyDecl* pd = _ClonePropertyDecl(properties[i], batch);
if (!pd)
return NULL;
data[i] = pd;
}
return data;
}
static MI_ClassDecl* _CloneClassDecl(
const MI_ClassDecl* cd,
Batch* batch)
{
MI_ClassDecl* p;
/* Instance.classDecl */
p = (MI_ClassDecl*)BCalloc(batch, sizeof(MI_ClassDecl), CALLSITE);
if (!p)
return NULL;
/* Instance.name */
if (cd->name)
{
p->name = BStrdup(batch, cd->name, CALLSITE);
if (!p->name)
return NULL;
}
/* Instance.size */
p->size = cd->size;
/* Instance.properties */
{
p->properties = _ClonePropertyDecls(cd->properties, cd->numProperties,
batch);
if (!p->properties)
return NULL;
p->numProperties = cd->numProperties;
}
return p;
}
MI_INLINE InstanceHeader* _HeaderOf(Instance* self)
{
return self ? ((InstanceHeader*)self - 1) : NULL;
}
MI_INLINE Instance* _InstanceOf(InstanceHeader* self)
{
return self ? (Instance*)(self + 1) : NULL;
}
static Instance* _AllocInstance(Batch* batch, size_t size)
{
InstanceHeader* h = (InstanceHeader*)BCalloc(
batch,
sizeof(InstanceHeader) + size,
CALLSITE);
if (!h)
return NULL;
h->magic = _MAGIC;
h->u.refs = 1;
return _InstanceOf(h);
}
static Instance* _ReallocInstance(
Batch* batch,
Instance* self,
size_t oldSize,
size_t newSize)
{
InstanceHeader* h = (InstanceHeader*)BRealloc(
batch,
_HeaderOf(self),
sizeof(InstanceHeader) + oldSize,
sizeof(InstanceHeader) + newSize,
CALLSITE);
if (!h)
return NULL;
h->magic = _MAGIC;
h->u.refs = 1;
return _InstanceOf(h);
}
static void _FreeInstance(
Batch* batch,
Instance* self)
{
InstanceHeader* h = _HeaderOf(self);
if (h)
{
DEBUG_ASSERT(h->magic == _MAGIC);
#if defined(CONFIG_ENABLE_DEBUG)
memset(h, 0xDD, sizeof(InstanceHeader) + sizeof(Instance));
#endif
BFree(batch, h, CALLSITE);
}
}
/*
* Each dynamic instance is 'wrapped' inside another instance (referred to
* by the self field). This requiredment is imposed by the
* MI_Instance_AddElement() function, which does not allow the address of
* the instance to change. Hence, indirection is required to allow the inner
* instance to be relocated in memory as new properties are added. The
* resulting layout is depicted below.
*
* (Wrapper)
* +-------------+
* | MI_Instance |
* +---------+---+
* | | | (Inner)
* +---------+---+ +-------------+
* | self | ------> | MI_Instance |
* +---------+---+ +---------+---+
* | | |
* +---------+---+
* | | |
* +---------+---+
*
* All methods of the instance type, must resolve the self pointer using
* _SelfOf(), which either returns the sole parameter itself (for static
* instances) or the self field (for dynamic instances).
*
*/
static Instance* _WrapInstance(
Instance* self,
Batch* batch)
{
Instance* wrapper;
if (!self)
return NULL;
/* Allocate space for outer wrapper instance */
wrapper = (Instance*)_AllocInstance(batch, sizeof(MI_Instance));
if (!wrapper)
return NULL;
/* Copy fields from inner instance to outer instance */
*wrapper = *self;
/* Set outer instance self to point to inner instance */
wrapper->self = self;
return wrapper;
}
MI_Uint32 _CountKeys(
const Instance* self)
{
MI_Uint32 n = 0;
const MI_ClassDecl* cd = self->classDecl;
MI_Uint32 i;
for (i = 0; i < cd->numProperties; i++)
{
if (cd->properties[i]->flags & MI_FLAG_KEY)
n++;
}
return n;
}
/*
**==============================================================================
**
** Public definitions
**
**==============================================================================
*/
MI_Result MI_CALL Instance_Construct(
MI_Instance* self_,
const MI_ClassDecl* classDecl,
Batch* batch_)
{
Instance* self = (Instance*)self_;
MI_ClassDecl* cd = (MI_ClassDecl*)classDecl;
Batch* batch = batch_;
/* Check for null arguments */
if (!self || !cd)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Create a new batch */
if (!batch)
{
batch = Batch_New(_NUM_PAGES);
if (!batch)
return MI_RESULT_FAILED;
}
/* Zero-fill the object */
memset(self, 0, cd->size);
/* MI_Instance.ft */
self->ft = &__mi_instanceFT;
/* MI_Instance.self */
self->self = self;
/* MI_Instance.classDecl */
self->classDecl = cd;
/* MI_Instance.batch */
self->batch = batch;
/* Flags */
self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
MI_RETURN(MI_RESULT_OK);
}
MI_Result Instance_New(
MI_Instance** selfOut,
const MI_ClassDecl* classDecl,
Batch* batch_)
{
Instance* self;
Batch* batch = batch_;
MI_Result r;
/* Check for null arguments */
if (!selfOut || !classDecl || !batch)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Null out selfOut */
*selfOut = NULL;
/* Create a new batch */
if (!batch)
{
batch = Batch_New(_NUM_PAGES);
if (!batch)
return MI_RESULT_FAILED;
}
/* Allocate structure */
self = _AllocInstance(batch, classDecl->size);
if (!self)
{
r = MI_RESULT_FAILED;
goto failed;
}
/* Initialize the object */
r = Instance_Construct((MI_Instance*)self, classDecl, batch);
if (r != MI_RESULT_OK)
goto failed;
/* Arrange to release batch if we created it */
self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
*selfOut = (MI_Instance*)self;
MI_RETURN(MI_RESULT_OK);
failed:
if (batch != batch_)
Batch_Delete(batch);
return r;
}
MI_Result MI_CALL Instance_InitConvert(
MI_Instance* self_,
const MI_ClassDecl* cd1,
const MI_Instance* inst_,
MI_Boolean keysOnly,
MI_Boolean allowKeylessInst,
MI_Boolean copy,
Batch* batch_)
{
Instance* self;
const Instance* inst = _SelfOf(inst_);
MI_Uint32 i;
MI_Result r;
const MI_ClassDecl* cd2;
const MI_SchemaDecl* sd1;
Batch* batch = batch_;
/* Resolve the schema declaration (based on type) */
if (cd1->flags & MI_FLAG_METHOD)
sd1 = ((MI_MethodDecl*)cd1)->schema;
else if (cd1->flags & MI_FLAG_CLASS)
sd1 = cd1->schema;
else
return MI_RESULT_FAILED;
/* Check parameters */
if (!self_ || !cd1 || !inst || !batch)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Create a new batch */
if (!batch)
{
batch = Batch_New(_NUM_PAGES);
if (!batch)
return MI_RESULT_FAILED;
}
cd2 = inst->classDecl;
/* Initialize the instance */
r = Instance_Construct(self_, cd1, batch);
if (r != MI_RESULT_OK)
goto failed;
/* Get the self pointer from the newly initialized instance */
self = _SelfOf(self_);
/* Arrange to release the batch */
self->releaseBatch = batch == batch_ ? MI_FALSE : MI_TRUE;
/* Copy the nameSpace */
if (inst->nameSpace)
{
self->nameSpace = BStrdup(batch, inst->nameSpace, CALLSITE);
if (!self->nameSpace)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* Copy the serverName */
if (inst->serverName)
{
self->serverName = BStrdup(batch, inst->serverName, CALLSITE);
if (!self->serverName)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* Validate that the two instances share the same key structure */
if (!allowKeylessInst)
{
for (i = 0; i < cd1->numProperties; i++)
{
const MI_PropertyDecl* pd1 = cd1->properties[i];
if (pd1->flags & MI_FLAG_KEY)
{
MI_Uint32 index;
index = _FindPropertyDecl(cd2, pd1->name);
if (index == (MI_Uint32)-1)
{
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
}
for (i = 0; i < cd2->numProperties; i++)
{
const MI_PropertyDecl* pd2 = cd2->properties[i];
if (pd2->flags & MI_FLAG_KEY)
{
MI_Uint32 index;
index = _FindPropertyDecl(cd1, pd2->name);
if (index == (MI_Uint32)-1)
{
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
}
}
/* ATTN: ignore unknown properties? */
/* Set non-null properties */
for (i = 0; i < cd2->numProperties; i++)
{
const MI_PropertyDecl* pd2 = cd2->properties[i];
Field* field = (Field*)((char*)inst + pd2->offset);
/* If requested, ignore non-keys */
if (keysOnly && !(pd2->flags & MI_FLAG_KEY))
continue;
/* Set the non-null key values */
if (Field_GetExists(field, pd2->type))
{
if (pd2->type == MI_STRING)
{
r = Instance_SetElementFromString(self_, pd2->name,
((MI_Value*)field)->string);
if (r != MI_RESULT_OK)
{
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
else if (pd2->type == MI_STRINGA)
{
r = Instance_SetElementFromStringA(self_, pd2->name,
(const MI_Char**)((MI_Value*)field)->stringa.data,
((MI_Value*)field)->stringa.size);
if (r != MI_RESULT_OK)
{
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
else if (pd2->type == MI_INSTANCE || pd2->type == MI_REFERENCE)
{
MI_Instance* tmpInst;
MI_ClassDecl* tmpCd;
MI_Value v;
/* Find the class declaration in the schema */
tmpCd = SchemaDecl_FindClassDecl(sd1,
_SelfOf(((MI_Value*)field)->instance)->classDecl->name);
if (!tmpCd)
{
r = MI_RESULT_FAILED;
goto failed;
}
/* Allocate static instance of this class */
if (Instance_New(&tmpInst, tmpCd, batch) != MI_RESULT_OK)
{
r = MI_RESULT_FAILED;
goto failed;
}
/* Convert instance */
r = Instance_InitConvert(tmpInst, tmpCd,
((MI_Value*)field)->instance, keysOnly, MI_FALSE, copy,
((Instance*)tmpInst)->batch);
if (r != MI_RESULT_OK)
{
__MI_Instance_Delete(tmpInst);
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
v.instance = tmpInst;
/* Set the instance value (use the ADOPT policy) */
r = __MI_Instance_SetElement(
self_,
pd2->name,
&v,
pd2->type,
MI_FLAG_ADOPT);
if (r == MI_RESULT_TYPE_MISMATCH)
{
/* Try to process instance as array with one element */
v.instancea.size = 1;
v.instancea.data = BAlloc(batch,
1 * sizeof(void*), CALLSITE);
if (!v.instancea.data)
{
__MI_Instance_Delete(tmpInst);
r = MI_RESULT_FAILED;
goto failed;
}
v.instancea.data[0] = tmpInst;
r = __MI_Instance_SetElement(self_, pd2->name, &v, pd2->type | MI_ARRAY_BIT,
MI_FLAG_ADOPT);
}
if (r != MI_RESULT_OK)
{
__MI_Instance_Delete(tmpInst);
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
else if (pd2->type == MI_INSTANCEA || pd2->type == MI_REFERENCEA)
{
MI_Value v;
MI_Uint32 j;
v.instancea.size = ((MI_Value*)field)->instancea.size;
v.instancea.data = BAlloc(batch,
v.instancea.size * sizeof(void*), CALLSITE);
if (!v.instancea.data)
{
r = MI_RESULT_FAILED;
goto failed;
}
for (j = 0; j < v.instancea.size; j++)
{
MI_Instance* tmpInst;
MI_ClassDecl* tmpCd;
/* Find the schema declaration */
tmpCd = SchemaDecl_FindClassDecl(sd1, _SelfOf(((
MI_Value*)field)->instancea.data[j])->classDecl->name);
if (!tmpCd)
{
r = MI_RESULT_FAILED;
goto failed;
}
/* Allocate the instance for the provider */
if (Instance_New(&tmpInst,tmpCd,batch) != MI_RESULT_OK)
{
r = MI_RESULT_FAILED;
goto failed;
}
r = Instance_InitConvert(tmpInst, tmpCd,
((MI_Value*)field)->instancea.data[j], keysOnly, MI_FALSE, copy,
((Instance*)tmpInst)->batch);
if (r != MI_RESULT_OK)
{
MI_Uint32 k;
for (k = 0; k < j; k++)
__MI_Instance_Delete(v.instancea.data[k]);
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
v.instancea.data[j] = tmpInst;
}
/* Set the value */
r = __MI_Instance_SetElement(self_, pd2->name, &v, pd2->type,
MI_FLAG_ADOPT);
if (r != MI_RESULT_OK)
{
for (j = 0; j < v.instancea.size; j++)
__MI_Instance_Delete(v.instancea.data[j]);
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
else
{
MI_Uint32 tmpFlags = copy ? 0 : MI_FLAG_BORROW;
/* Set the value */
r = __MI_Instance_SetElement(self_, pd2->name, (MI_Value*)field,
pd2->type, tmpFlags);
if (r != MI_RESULT_OK)
{
r = MI_RESULT_TYPE_MISMATCH;
goto failed;
}
}
}
}
failed:
if (batch != batch_)
Batch_Delete(batch);
return r;
}
MI_Result MI_CALL Instance_Clone(
const MI_Instance* self_,
MI_Instance** instOut,
Batch* batch_)
{
const Instance* self = _SelfOf(self_);
Batch* batch = batch_;
Instance* inst;
MI_Uint32 i;
MI_Result r;
/* Check for a null parameter */
if (!self || !instOut)
{
r = MI_RESULT_FAILED;
goto failed;
}
/* Create new batch? */
if (!batch)
{
batch = Batch_New(_NUM_PAGES);
if (!batch)
return MI_RESULT_FAILED;
}
/* Allocate the new instance */
{
MI_Uint32 cap = sizeof(MI_Instance) + _CAPACITY * sizeof(Field);
if (self->classDecl->size > cap)
cap = self->classDecl->size;
inst = _AllocInstance(batch, cap);
if (!inst)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* Instance.self */
inst->self = inst;
/* Instance.flags */
if (batch != batch_)
{
inst->releaseBatch = MI_TRUE;
}
/* Set Instance.batch */
inst->batch = batch;
/* Set MI_Instance.ft */
inst->ft = &__mi_instanceFT;
/* Instance.nameSpace */
if (self->nameSpace)
{
inst->nameSpace = BStrdup(batch, self->nameSpace, CALLSITE);
if (!inst->nameSpace)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* Instance.serverName */
if (self->serverName)
{
inst->serverName = BStrdup(batch, self->serverName, CALLSITE);
if (!inst->serverName)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* Set Instance.classDecl */
if ((void*)self != (void*)self_)
{
inst->classDecl = _CloneClassDecl(self->classDecl, batch);
if (!inst->classDecl)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
else
inst->classDecl = self->classDecl;
/* Clone each of the fields */
for (i = 0; i < self->classDecl->numProperties; i++)
{
const MI_PropertyDecl* pd = self->classDecl->properties[i];
r = Field_Copy(
(Field*)((char*)inst + pd->offset),
pd->type,
(Field*)((char*)self + pd->offset),
batch);
if (r != MI_RESULT_OK)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* Wrapper dynamic instances */
if ((void*)self != (void*)self_)
{
inst = _WrapInstance(inst, batch);
if (!inst)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
*instOut = (MI_Instance*)inst;
return MI_RESULT_OK;
failed:
if (batch != batch_)
Batch_Delete(batch);
return r;
}
MI_Result MI_CALL Instance_SetClassName(
MI_Instance* self_,
const MI_Char* className)
{
Instance* self = _SelfOf(self_);
MI_Char* oldClassName;
/* Check parameters */
if (!self || !className)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Save old className */
oldClassName = self->classDecl->name;
/* Set new className */
{
MI_Char* tmp = BStrdup(self->batch, className, CALLSITE);
if (!tmp)
MI_RETURN(MI_RESULT_FAILED);
self->classDecl->name = tmp;
}
/* Free old className */
if (oldClassName)
BFree(self->batch, oldClassName, CALLSITE);
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL Instance_NewDynamic(
MI_Instance** selfOut,
const MI_Char* className,
MI_Uint32 metaType,
Batch* batch_)
{
Instance* self = NULL;
Batch* batch = batch_;
MI_Result r;
/* Reject null arguments */
if (!selfOut || !className)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Null output self pointer */
*selfOut = NULL;
/* Create batch if necessary */
if (!batch)
{
batch = Batch_New(_NUM_PAGES);
if (!batch)
return MI_RESULT_FAILED;
}
/* Check that 'className' parameter is a legal CIM className */
if (!LegalName(className))
{
r = MI_RESULT_INVALID_PARAMETER;
goto failed;
}
/* Allocate instance and reserve room for properties */
{
self = _AllocInstance(batch,
sizeof(MI_Instance) + _CAPACITY * sizeof(Field));
if (!self)
{
r = MI_RESULT_FAILED;
goto failed;
}
self->self = self;
}
/* Set Instance.classDecl */
{
MI_ClassDecl* cd;
/* Allocate and set Instance.classDecl */
{
cd = (MI_ClassDecl*)BCalloc(batch, sizeof(MI_ClassDecl), CALLSITE);
if (!cd)
{
r = MI_RESULT_FAILED;
goto failed;
}
self->classDecl = cd;
}
/* MI_ClassDecl.flags: */
if (metaType & MI_FLAG_ASSOCIATION)
cd->flags |= MI_FLAG_ASSOCIATION;
else if (metaType & MI_FLAG_INDICATION)
cd->flags |= MI_FLAG_INDICATION;
else if (metaType & MI_FLAG_METHOD)
cd->flags |= MI_FLAG_METHOD;
else if (metaType & MI_FLAG_CLASS)
cd->flags |= MI_FLAG_CLASS;
else
cd->flags |= MI_FLAG_CLASS;
/* MI_ClassDecl.name: */
{
cd->name = BStrdup(batch, className, CALLSITE);
if (!cd->name)
{
r = MI_RESULT_FAILED;
goto failed;
}
}
/* MI_ClassDecl.code: */
cd->code = Hash(className);
/* MI_ClassDecl.properties: */
{
MI_PropertyDecl** data;
data = (MI_PropertyDecl**)BAlloc(batch,
_CAPACITY * sizeof(MI_PropertyDecl), CALLSITE);
if (!data)
{
r = MI_RESULT_FAILED;
goto failed;
}
cd->properties = data;
cd->numProperties = 0;
}
/* MI_ClassDecl.size: */
cd->size = sizeof(MI_Instance);
}
/* Set batch: */
self->batch = batch;
/* Set flags */
if (batch_)
self->releaseBatch = MI_FALSE;
else
self->releaseBatch = MI_TRUE;
/* Set MI_Instance.ft: */
self->ft = &__mi_instanceFT;
/* Set the self pointer */
self->self = self;
/* Set output instance (creating a wrapper for it) */
self = _WrapInstance(self, batch);
if (!self)
{
r = MI_RESULT_FAILED;
goto failed;
}
*selfOut = (MI_Instance*)self;
MI_RETURN(MI_RESULT_OK);
failed:
if (batch != batch_)
Batch_Delete(batch);
return r;
}
MI_Boolean Instance_MatchKeys(
const MI_Instance* self_,
const MI_Instance* inst_)
{
Instance* self;
Instance* inst;
/* Check parameters */
if (!self_ || !inst_)
{
return MI_FALSE;
}
self = _SelfOf(self_);
inst = _SelfOf(inst_);
/* Check parameters */
if (!self || !inst)
{
return MI_FALSE;
}
/* Verify they have the same number of keys (one or more) */
{
MI_Uint32 n = _CountKeys(self);
if (n == 0 || n != _CountKeys(inst))
{
return MI_FALSE;
}
}
/* Verify that key fields are identical */
{
const MI_ClassDecl* cd1 = self->classDecl;
const MI_ClassDecl* cd2 = inst->classDecl;
MI_Uint32 i;
for (i = 0; i < cd1->numProperties; i++)
{
const MI_PropertyDecl* pd1 = cd1->properties[i];
const MI_PropertyDecl* pd2;
Field* f1;
Field* f2;
MI_Uint32 index;
if (pd1->flags & MI_FLAG_KEY)
{
index = _FindPropertyDecl(cd2, pd1->name);
if (index == (MI_Uint32)-1)
{
return MI_FALSE;
}
pd2 = cd2->properties[index];
if (!(pd2->flags & MI_FLAG_KEY))
{
return MI_FALSE;
}
if (pd1->type != pd2->type)
return MI_FALSE;
f1 = (Field*)((char*)self + pd1->offset);
f2 = (Field*)((char*)inst + pd2->offset);
if (!Field_MatchKey(f1, f2, pd1->type))
{
return MI_FALSE;
}
}
}
}
return MI_TRUE;
}
/*
**==============================================================================
**
** MI_Instance function table and functions
**
**==============================================================================
*/
void __MI_Instance_Ref(MI_Instance* self)
{
InstanceHeader* h = _HeaderOf((Instance*)self);
if (h)
AtomicInc(&h->u.refs);
}
void __MI_Instance_Unref(MI_Instance* self)
{
InstanceHeader* h = _HeaderOf((Instance*)self);
if (h && AtomicDec(&h->u.refs))
__MI_Instance_Delete((MI_Instance*)self);
}
MI_Result MI_CALL __MI_Instance_Clone(
const MI_Instance* self,
MI_Instance** inst)
{
return Instance_Clone(self, inst, NULL);
}
MI_Result MI_CALL __MI_Instance_Destruct(
MI_Instance* self_)
{
Instance* self = _SelfOf(self_);
Batch* batch;
MI_Uint32 i;
/* Check for null parameter */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Save pointer to batch */
batch = self->batch;
if (!batch)
MI_RETURN(MI_RESULT_FAILED);
/* Release serverName */
if (self->serverName)
BFree(batch, self->serverName, CALLSITE);
/* Release nameSpace */
if (self->nameSpace)
BFree(batch, self->nameSpace, CALLSITE);
/* Release all memory used by properties */
for (i = 0; i < self->classDecl->numProperties; i++)
{
const MI_PropertyDecl* pd = self->classDecl->properties[i];
Field* field = (Field*)((char*)self + pd->offset);
Field_Destruct(field, pd->type, batch);
}
/* Free dynamic instance part (if any) */
if ((void*)self != (void*)self_)
{
for (i = 0; i < self->classDecl->numProperties; i++)
{
MI_PropertyDecl* pd = self->classDecl->properties[i];
BFree(batch, pd->name, CALLSITE);
BFree(batch, pd, CALLSITE);
}
BFree(batch, self->classDecl->name, CALLSITE);
BFree(batch, self->classDecl->properties, CALLSITE);
BFree(batch, self->classDecl, CALLSITE);
if ((void*)self != (void*)self_)
_FreeInstance(batch, self);
}
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_Delete(
MI_Instance* self_)
{
Instance* self = _SelfOf(self_);
MI_Result r;
Batch* batch;
MI_Boolean releaseBatch;
/* Check for null parameter */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Save pointer to batch */
batch = self->batch;
if (!batch)
MI_RETURN(MI_RESULT_FAILED);
/* Save */
releaseBatch = self->releaseBatch;
/* Destruct */
r = __MI_Instance_Destruct(self_);
if (r != MI_RESULT_OK)
MI_RETURN(r);
/* Release self pointer */
_FreeInstance(batch, (Instance*)self_);
/* Release the batch */
if (releaseBatch)
Batch_Delete(batch);
return r;
}
MI_Result MI_CALL __MI_Instance_IsA(
const MI_Instance* self_,
const MI_ClassDecl* classDecl,
MI_Boolean* resultOut)
{
Instance* self = _SelfOf(self_);
const MI_ClassDecl* p;
if (!self || !classDecl)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
for (p = self->classDecl; p; p = p->superClassDecl)
{
if (p == classDecl)
{
if (resultOut)
*resultOut = MI_TRUE;
MI_RETURN(MI_RESULT_OK);
}
}
if (resultOut)
*resultOut = MI_FALSE;
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_GetClassName(
const MI_Instance* self_,
const MI_Char** classNameOut)
{
Instance* self = _SelfOf(self_);
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
if (classNameOut)
*classNameOut = self->classDecl->name;
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_SetNameSpace(
MI_Instance* self_,
const MI_Char* nameSpace)
{
Instance* self = _SelfOf(self_);
MI_Char* oldNameSpace;
/* Check parameters */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Save old namespace */
oldNameSpace = self->nameSpace;
/* Set new namespace */
if (nameSpace)
{
MI_Char* tmp = BStrdup(self->batch, nameSpace, CALLSITE);
if (!tmp)
MI_RETURN(MI_RESULT_FAILED);
self->nameSpace = tmp;
}
else
self->nameSpace = NULL;
/* Free old namespace */
if (oldNameSpace)
BFree(self->batch, oldNameSpace, CALLSITE);
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_GetNameSpace(
const MI_Instance* self_,
const MI_Char** nameSpaceOut)
{
Instance* self = _SelfOf(self_);
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
if (nameSpaceOut)
*nameSpaceOut = self->nameSpace;
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_GetElementCount(
const MI_Instance* self_,
MI_Uint32* countOut)
{
Instance* self = _SelfOf(self_);
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
if (countOut)
*countOut = self->classDecl->numProperties;
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_AddElement(
MI_Instance* self_,
const MI_Char* name,
const MI_Value* value,
MI_Type type,
MI_Uint32 flags)
{
Instance* self = _SelfOf(self_);
MI_Uint32 index;
MI_ClassDecl* cd;
MI_Uint32 tflags = 0;
if (flags & MI_FLAG_BORROW)
tflags |= MI_FLAG_BORROW;
if (flags & MI_FLAG_NULL)
tflags |= MI_FLAG_NULL;
/* Check for null arguments */
if (!self || !name)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Reject attempts to extend a non-dynamic instances */
if ((void*)self == (void*)self_)
MI_RETURN(MI_RESULT_FAILED);
/* Check that 'name' parameter is a legal CIM name */
if (!LegalName(name))
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Find the property with this name */
index = _FindPropertyDecl(self->classDecl, name);
if (index != (MI_Uint32)-1)
MI_RETURN(MI_RESULT_ALREADY_EXISTS);
/* Get pointer to class declaration */
cd = (MI_ClassDecl*)self->classDecl;
/* Extend size of instance and properties array as needed */
if (cd->numProperties == _FindCapacity(cd->numProperties))
{
MI_Uint32 cap;
MI_PropertyDecl** data;
/* Double old capacity */
cap = 2 * cd->numProperties;
/* Reallocate properties array */
data = (MI_PropertyDecl**)BRealloc(
self->batch,
cd->properties,
cd->numProperties * sizeof(MI_PropertyDecl),
cap * sizeof(MI_PropertyDecl),
CALLSITE);
if (!data)
MI_RETURN(MI_RESULT_FAILED);
cd->properties = data;
/* Reallocate instance */
self = _ReallocInstance(
self->batch,
self,
sizeof(MI_Instance) + cd->numProperties * sizeof(Field),
sizeof(MI_Instance) + cap * sizeof(Field));
if (!self)
MI_RETURN(MI_RESULT_FAILED);
/* Set new self */
self->self = self;
}
/* Create and add new property */
{
MI_PropertyDecl* pd;
/* Allocate new peroperty declaration */
pd = (MI_PropertyDecl*)BCalloc(
self->batch, sizeof(MI_PropertyDecl), CALLSITE);
if (!pd)
MI_RETURN(MI_RESULT_FAILED);
/* MI_PropertyDecl.flags */
pd->flags = flags;
/* MI_PropertyDecl.code */
pd->code = Hash(name);
/* MI_PropertyDecl.name */
pd->name = BStrdup(self->batch, name, CALLSITE);
if (!pd->name)
MI_RETURN(MI_RESULT_FAILED);
/* MI_PropertyDecl.type */
pd->type = type;
/* MI_PropertyDecl.offset */
pd->offset = sizeof(MI_Instance) + cd->numProperties*sizeof(Field);
/* Add property to array */
cd->properties[cd->numProperties++] = pd;
/* Clear the new field */
memset((char*)self + pd->offset, 0, sizeof(Field));
/* Adjust size */
cd->size += sizeof(Field);
}
/* Reassign 'self' field (it may have changed) */
((Instance*)self_)->self = self;
/* Copy self of self wrapper */
memcpy(self_, self, sizeof(MI_Instance));
/* Set the last property */
MI_RETURN(__MI_Instance_SetElementAt(
self_, cd->numProperties - 1, value, type, tflags));
}
MI_Result MI_CALL __MI_Instance_SetElement(
MI_Instance* self_,
const MI_Char* name,
const MI_Value* value,
MI_Type type,
MI_Uint32 flags)
{
Instance* self = _SelfOf(self_);
MI_Uint32 index;
/* Check for null arguments */
if (!self || !name)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Find the property with this name */
index = _FindPropertyDecl(self->classDecl, name);
if (index == (MI_Uint32)-1)
MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
MI_RETURN(__MI_Instance_SetElementAt(self_, index, value, type, flags));
}
MI_Result MI_CALL __MI_Instance_SetElementAt(
MI_Instance* self_,
MI_Uint32 index,
const MI_Value* value,
MI_Type type,
MI_Uint32 flags)
{
Instance* self = _SelfOf(self_);
const MI_PropertyDecl* pd;
char* field;
/* Check for null arguments */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Check whether index is in range */
if (index > self->classDecl->numProperties)
MI_RETURN(MI_RESULT_FAILED);
/* Get pointer to properties declaration */
pd = self->classDecl->properties[index];
/* Check the type */
if (type != (MI_Type)pd->type)
MI_RETURN(MI_RESULT_TYPE_MISMATCH);
/* Get pointer to field */
field = (char*)self + pd->offset;
/* Set the value */
{
MI_Result r = Field_Set(
(Field*)((char*)self + pd->offset),
pd->type,
value,
flags,
self->batch);
if (r != MI_RESULT_OK)
return r;
}
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_GetElement(
const MI_Instance* self_,
const MI_Char* name,
MI_Value* valueOut,
MI_Type* typeOut,
MI_Uint32* flagsOut,
MI_Uint32* indexOut)
{
Instance* self = _SelfOf(self_);
MI_Uint32 index;
MI_Result r;
/* Check for null arguments */
if (!self || !name)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Find the property with this name */
index = _FindPropertyDecl(self->classDecl, name);
if (index == (MI_Uint32)-1)
MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
r = __MI_Instance_GetElementAt(
self_, index, NULL, valueOut, typeOut, flagsOut);
if (r != MI_RESULT_OK)
MI_RETURN(r);
if (indexOut)
*indexOut = index;
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_GetElementAt(
const MI_Instance* self_,
MI_Uint32 index,
const MI_Char** nameOut,
MI_Value* valueOut,
MI_Type* typeOut,
MI_Uint32* flagsOut)
{
Instance* self = _SelfOf(self_);
const MI_PropertyDecl* pd;
const Field* field;
/* Check for null arguments */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Check for bounds error */
if (index >= self->classDecl->numProperties)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
pd = self->classDecl->properties[index];
/* Get pointer to field */
field = (Field*)((char*)self + pd->offset);
/* set nameOut */
if (nameOut)
*nameOut = pd->name;
/* set valueOut */
if (valueOut)
memcpy(valueOut, field, Type_SizeOf((MI_Type)pd->type));
/* Set existsOut */
if (flagsOut)
{
*flagsOut = pd->flags;
if (!Field_GetExists(field, (MI_Type)pd->type))
*flagsOut |= MI_FLAG_NULL;
}
/* Set typeOut */
if (typeOut)
*typeOut = (MI_Type)pd->type;
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_ClearElement(
MI_Instance* self_,
const MI_Char* name)
{
Instance* self = _SelfOf(self_);
MI_Uint32 index;
/* Check for null arguments */
if (!self || !name)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Find the property with this name */
index = _FindPropertyDecl(self->classDecl, name);
if (index == (MI_Uint32)-1)
MI_RETURN(MI_RESULT_NO_SUCH_PROPERTY);
MI_RETURN(__MI_Instance_ClearElementAt(self_, index));
}
MI_Result MI_CALL __MI_Instance_ClearElementAt(
MI_Instance* self_,
MI_Uint32 index)
{
Instance* self = _SelfOf(self_);
const MI_PropertyDecl* pd;
char* field;
/* Check for null arguments */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Check whether index is in range */
if (index > self->classDecl->numProperties)
MI_RETURN(MI_RESULT_FAILED);
/* Get pointer to properties declaration */
pd = self->classDecl->properties[index];
/* Get pointer to field */
field = (char*)self + pd->offset;
/* Clear the value */
Field_Clear((Field*)((char*)self + pd->offset), pd->type,
self->batch);
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL Instance_Print(
const MI_Instance* self_,
FILE* os,
MI_Uint32 level,
MI_Boolean showNulls)
{
Instance* self = _SelfOf(self_);
const MI_ClassDecl* cd = self->classDecl;
MI_Uint32 i;
/* Check for null arguments */
if (!self)
MI_RETURN(MI_RESULT_INVALID_PARAMETER);
/* Print nameSpace and className */
if (self->nameSpace)
{
Indent(os, level);
Fzprintf(os, T("instance of %s:%s\n"), self->nameSpace, cd->name);
}
else
{
Indent(os, level);
Fzprintf(os, T("instance of %s\n"), cd->name);
}
Indent(os, level);
Fzprintf(os, T("{\n"));
level++;
/* Print the properties */
for (i = 0; i < cd->numProperties; i++)
{
const MI_PropertyDecl* pd = cd->properties[i];
const Field* field = (Field*)((char*)self + pd->offset);
if (showNulls || Field_GetExists(field, pd->type))
{
Indent(os, level);
if (pd->flags & MI_FLAG_KEY)
Fzprintf(os, T("[Key] "));
Fzprintf(os, T("%s="), pd->name);
Field_Print(field, os, pd->type, level);
if (pd->type == MI_INSTANCE || pd->type == MI_REFERENCE)
{
if (!field->instance.value)
fputc('\n', os);
}
else
fputc('\n', os);
}
}
level--;
Indent(os, level);
Fzprintf(os, T("}\n"));
MI_RETURN(MI_RESULT_OK);
}
MI_Result MI_CALL __MI_Instance_GetServerName(
const MI_Instance* self,
const MI_Char** name)
{
MI_RETURN(MI_RESULT_NOT_SUPPORTED);
}
MI_Result MI_CALL __MI_Instance_SetServerName(
_Inout_ MI_Instance* self,
_In_z_ const MI_Char* name)
{
MI_RETURN(MI_RESULT_NOT_SUPPORTED);
}
MI_Result MI_CALL __MI_Instance_GetClass(
_In_ const MI_Instance* self,
_Outptr_ MI_Class** instanceClass)
{
MI_RETURN(MI_RESULT_NOT_SUPPORTED);
}
MI_Result MI_CALL __MI_Instance_Print(
const MI_Instance* self,
FILE* os,
MI_Uint32 level)
{
return Instance_Print(self, os, level, MI_TRUE);
}
MI_InstanceFT __mi_instanceFT =
{
__MI_Instance_Clone,
__MI_Instance_Destruct,
__MI_Instance_Delete,
__MI_Instance_IsA,
__MI_Instance_GetClassName,
__MI_Instance_SetNameSpace,
__MI_Instance_GetNameSpace,
__MI_Instance_GetElementCount,
__MI_Instance_AddElement,
__MI_Instance_SetElement,
__MI_Instance_SetElementAt,
__MI_Instance_GetElement,
__MI_Instance_GetElementAt,
__MI_Instance_ClearElement,
__MI_Instance_ClearElementAt,
__MI_Instance_GetServerName,
__MI_Instance_SetServerName,
__MI_Instance_GetClass,
__MI_Instance_Print,
};