version 1.1, 2012/05/30 22:47:39
|
version 1.2, 2012/06/15 20:51:14
|
|
|
#include <base/strings.h> | #include <base/strings.h> |
#include <base/paths.h> | #include <base/paths.h> |
#include <base/io.h> | #include <base/io.h> |
|
#include <base/hashtable.h> |
#include <wql/wql.h> | #include <wql/wql.h> |
#include "disp.h" | #include "disp.h" |
| |
|
|
/* | /* |
**============================================================================== | **============================================================================== |
** | ** |
|
** ClassName hash implementation |
|
** |
|
**============================================================================== |
|
*/ |
|
|
|
typedef struct _ClassNameBucket /* derives from HashBucket */ |
|
{ |
|
struct _ClassNameBucket* next; |
|
char* key; |
|
} |
|
ClassNameBucket; |
|
|
|
static size_t ClassNameHash( |
|
const HashBucket* bucket_) |
|
{ |
|
/* Note: this algorithm has a poor distribution */ |
|
ClassNameBucket* bucket = (ClassNameBucket*)bucket_; |
|
size_t h = 0; |
|
char* key = bucket->key; |
|
|
|
while (*key) |
|
{ |
|
h += 5 * *key++; |
|
} |
|
|
|
return h; |
|
} |
|
|
|
static int ClassNameEqual( |
|
const HashBucket* bucket1_, |
|
const HashBucket* bucket2_) |
|
{ |
|
ClassNameBucket* bucket1 = (ClassNameBucket*)bucket1_; |
|
ClassNameBucket* bucket2 = (ClassNameBucket*)bucket2_; |
|
return Strcasecmp(bucket1->key, bucket2->key) == 0; |
|
} |
|
|
|
static void ClassNameRelease( |
|
HashBucket* bucket_) |
|
{ |
|
ClassNameBucket* bucket = (ClassNameBucket*)bucket_; |
|
|
|
free(bucket->key); |
|
free(bucket); |
|
} |
|
|
|
/* |
|
**============================================================================== |
|
** |
** Data structures | ** Data structures |
** | ** |
**============================================================================== | **============================================================================== |
|
|
DispResultMsg* dispStateMsg; | DispResultMsg* dispStateMsg; |
ProvRegAssocPosition pos; | ProvRegAssocPosition pos; |
MI_Boolean sentOk = MI_FALSE; | MI_Boolean sentOk = MI_FALSE; |
|
HashTable classNames; |
|
|
|
/* Create a hash table of class names */ |
|
|
|
r = HashTable_Init( |
|
&classNames, |
|
64, |
|
ClassNameHash, |
|
ClassNameEqual, |
|
ClassNameRelease); |
|
|
|
if (r != 0) |
|
return MI_RESULT_FAILED; |
| |
/* Validate input parameters */ | /* Validate input parameters */ |
if (!req->instance || !req->nameSpace) | if (!req->instance || !req->nameSpace) |
|
|
goto sendErrorBack; | goto sendErrorBack; |
} | } |
| |
|
/* ATTN: there is a bug in the provider registration tree causing |
|
* the association provider to be called twice. To avoid this for now, |
|
* we maintain a hash table of already dispatched classes. |
|
*/ |
|
|
/* While more classes */ | /* While more classes */ |
for (;;) | for (;;) |
{ | { |
|
|
goto sendErrorBack; | goto sendErrorBack; |
} | } |
| |
|
/* Check whether this class has been dispatched */ |
|
{ |
|
ClassNameBucket bucket; |
|
bucket.key = (char*)cn; |
|
|
|
if (!HashTable_Find(&classNames, (const HashBucket*)&bucket)) |
|
{ |
if (_DispatchAssocReq(self, cn, req, dispStateMsg)) | if (_DispatchAssocReq(self, cn, req, dispStateMsg)) |
sentOk = MI_TRUE; | sentOk = MI_TRUE; |
|
|
|
{ |
|
ClassNameBucket* bucket = (ClassNameBucket*)calloc( |
|
1, sizeof(ClassNameBucket)); |
|
|
|
if (!bucket) |
|
{ |
|
r = MI_RESULT_FAILED; |
|
goto sendErrorBack; |
|
} |
|
|
|
bucket->key = strdup(cn); |
|
|
|
if (HashTable_Insert(&classNames, (HashBucket*)bucket) != 0) |
|
{ |
|
r = MI_RESULT_FAILED; |
|
goto sendErrorBack; |
|
} |
|
} |
|
} |
|
} |
} | } |
| |
/* Finalize enumeration */ | /* Finalize enumeration */ |
|
|
goto sendErrorBack; | goto sendErrorBack; |
} | } |
| |
|
HashTable_Destroy(&classNames); |
DispResultMsg_Release(dispStateMsg); | DispResultMsg_Release(dispStateMsg); |
return MI_RESULT_OK; | return MI_RESULT_OK; |
| |
sendErrorBack: | sendErrorBack: |
DispResultMsg_Release(dispStateMsg); | DispResultMsg_Release(dispStateMsg); |
|
HashTable_Destroy(&classNames); |
return _SendErrorResponse(&req->base,r); | return _SendErrorResponse(&req->base,r); |
} | } |
| |