1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
|
/*
*
* Generic interface (implementation) manager
*
* Copyright 2001 Alan Robertson <alanr@unix.sh>
* Licensed under the GNU Lesser General Public License
*
* This manager will manage any number of types of interfaces.
*
* This means that when any implementations of our client interfaces register
* or unregister, it is us that makes their interfaces show up in the outside
* world.
*
* And, of course, we have to do this in a very generic way, since we have
* no idea about the client programs or interface types, or anything else.
*
* We do that by getting a parameter passed to us which tell us the names
* of the interface types we want to manage, and the address of a GHashTable
* for each type that we put the implementation in when they register
* themselves.
*
* So, each type of interface that we manage gets its own private
* GHashTable of the implementations of that type that are currently
* registered.
*
* For example, if we manage communication modules, their exported
* interfaces will be registered in a hash table. If we manage
* authentication modules, they'll have their (separate) hash table that
* their exported interfaces are registered in.
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#define PIL_PLUGINTYPE InterfaceMgr
#define PIL_PLUGINTYPE_S "InterfaceMgr"
#define PIL_PLUGIN generic
#define PIL_PLUGIN_S "generic"
#define PIL_PLUGINLICENSE LICENSE_LGPL
#define PIL_PLUGINLICENSEURL URL_LGPL
/* We are an interface manager... */
#define ENABLE_PLUGIN_MANAGER_PRIVATE
#define ENABLE_PIL_DEFS_PRIVATE
#include <lha_internal.h>
#include <pils/generic.h>
#include <stdio.h>
PIL_PLUGIN_BOILERPLATE("1.0", GenDebugFlag, CloseGeneralPluginManager)
/*
* Key is interface type, value is a PILGenericIfMgmtRqst.
* The key is g_strdup()ed, but the struct is not copied.
*/
static gboolean FreeAKey(gpointer key, gpointer value, gpointer data);
/*
* Places to store information gotten during registration.
*/
static const PILPluginImports* GenPIImports; /* Imported plugin fcns */
static PILPlugin* GenPlugin; /* Our plugin info */
static PILInterfaceImports* GenIfImports; /* Interface imported fcns */
/* Our exported generic interface management functions */
static PIL_rc RegisterGenIF(PILInterface* ifenv, void** imports);
static PIL_rc UnregisterGenIF(PILInterface*iifinfo);
static PIL_rc CloseGenInterfaceManager(PILInterface*, void* info);
/*
* Our Interface Manager interfaces - exported to the universe!
*
* (or at least to the interface management universe ;-).
*
* These are the interfaces which are used to manage our
* client implementations
*/
static PILInterfaceOps GenIfOps =
{ RegisterGenIF
, UnregisterGenIF
};
PIL_rc PIL_PLUGIN_INIT(PILPlugin*us, PILPluginImports* imports, void*);
/*
* Our user_ptr is presumed to point to NULL-terminated array of
* PILGenericIfMgmtRqst structs.
*
* These requests have pointers to GHashTables for us
* to put plugins into when they show up, and drop from when
* they disappear.
*
* Issues include:
* - freeing all memory,
* - making sure things are all cleaned up correctly
* - Thread-safety?
*
* IMHO the global system should handle thread-safety.
*/
static PIL_rc AddAnInterfaceType(PILPlugin*us, GHashTable* MasterTable, PILGenericIfMgmtRqst* req);
PIL_rc
PIL_PLUGIN_INIT(PILPlugin*us, PILPluginImports* imports, void *user_ptr)
{
PIL_rc ret;
PILGenericIfMgmtRqst* user_req;
PILGenericIfMgmtRqst* curreq;
GHashTable* MasterTable = NULL;
/*
* Force the compiler to check our parameters...
*/
PILPluginInitFun fun = &PIL_PLUGIN_INIT; (void)fun;
GenPIImports = imports;
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "IF manager %s: initializing.", PIL_PLUGIN_S);
}
if (user_ptr == NULL) {
PILCallLog(GenPIImports->log, PIL_CRIT
, "%s Interface Manager requires non-NULL "
" PILGenericIfMgmtRqst user pointer at initialization."
, PIL_PLUGIN_S);
return PIL_INVAL;
}
GenPlugin = us;
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "IF manager %s: registering as a plugin."
, PIL_PLUGIN_S);
}
user_req = user_ptr;
MasterTable = g_hash_table_new(g_str_hash, g_str_equal);
us->ud_plugin = MasterTable; /* Override passed value */
/* Register ourselves as a plugin */
if ((ret = imports->register_plugin(us, &OurPIExports)) != PIL_OK) {
PILCallLog(imports->log, PIL_CRIT
, "IF manager %s unable to register as plugin (%s)"
, PIL_PLUGIN_S, PIL_strerror(ret));
return ret;
}
/*
* Register to manage implementations
* for all the interface types we've been asked to manage.
*/
for(curreq = user_req; curreq->iftype != NULL; ++curreq) {
PIL_rc newret;
newret = AddAnInterfaceType(us, MasterTable, curreq);
if (newret != PIL_OK) {
ret = newret;
}
}
/*
* Our plugin and all our registered plugin types
* have ud_plugin pointing at MasterTable.
*/
return ret;
}
static PIL_rc
AddAnInterfaceType(PILPlugin*us, GHashTable* MasterTable, PILGenericIfMgmtRqst* req)
{
PIL_rc rc;
PILInterface* GenIf; /* Our Generic Interface info*/
g_assert(MasterTable != NULL);
g_hash_table_insert(MasterTable, g_strdup(req->iftype), req);
if (req->ifmap == NULL) {
PILCallLog(GenPIImports->log, PIL_CRIT
, "IF manager %s: iftype %s has NULL"
" ifmap pointer address."
, PIL_PLUGIN_S, req->iftype);
return PIL_INVAL;
}
if ((*req->ifmap) != NULL) {
PILCallLog(GenPIImports->log, PIL_CRIT
, "IF manager %s: iftype %s GHashTable pointer"
" was not initialized to NULL"
, PIL_PLUGIN_S, req->iftype);
return PIL_INVAL;
}
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "IF manager %s: registering ourselves"
" to manage interface type %s"
, PIL_PLUGIN_S, req->iftype);
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: ifmap: 0x%lx callback: 0x%lx"
" imports: 0x%lx"
, PIL_PLUGIN_S
, (unsigned long)req->ifmap
, (unsigned long)req->callback
, (unsigned long)req->importfuns);
}
/* Create the hash table to communicate with this client */
*(req->ifmap) = g_hash_table_new(g_str_hash, g_str_equal);
rc = GenPIImports->register_interface(us
, PIL_PLUGINTYPE_S
, req->iftype /* the iftype we're managing here */
, &GenIfOps
, CloseGenInterfaceManager
, &GenIf
, (void*)&GenIfImports
, MasterTable); /* Point ud_interface to MasterTable */
/* We don't ever want to be unloaded... */
GenIfImports->ModRefCount(GenIf, +100);
if (rc != PIL_OK) {
PILCallLog(GenPIImports->log, PIL_CRIT
, "Generic interface manager %s: unable to register"
" to manage interface type %s: %s"
, PIL_PLUGIN_S, req->iftype
, PIL_strerror(rc));
}
return rc;
}
static void
CloseGeneralPluginManager(PILPlugin* us)
{
GHashTable* MasterTable = us->ud_plugin;
int count;
g_assert(MasterTable != NULL);
/*
* All our clients have already been shut down automatically
* This is the final shutdown for us...
*/
/* There *shouldn't* be any keys in there ;-) */
if ((count=g_hash_table_size(MasterTable)) > 0) {
/* But just in case there are... */
g_hash_table_foreach_remove(MasterTable, FreeAKey, NULL);
}
g_hash_table_destroy(MasterTable);
us->ud_plugin = NULL;
return;
}
/*
* We get called for every time an implementation registers itself as
* implementing one of the kinds of interfaces we manage.
*
* It's our job to make the implementation that's
* registering with us available to the system.
*
* We do that by adding it to a GHashTable for its interface type
* Our users in the rest of the system takes it from there...
*
* The key to the GHashTable is the implementation name, and the data is
* a pointer to the information the implementation exports.
*
* It's a piece of cake ;-)
*/
static PIL_rc
RegisterGenIF(PILInterface* intf, void** imports)
{
PILGenericIfMgmtRqst* ifinfo;
GHashTable* MasterTable = intf->ifmanager->ud_interface;
g_assert(MasterTable != NULL);
/* Reference count should now be one */
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: interface %s/%s registering."
, PIL_PLUGIN_S, intf->interfacetype->typename
, intf->interfacename);
}
g_assert(intf->refcnt == 1);
/*
* We need to add it to the table that goes with this particular
* type of interface.
*/
if ((ifinfo = g_hash_table_lookup(MasterTable
, intf->interfacetype->typename)) != NULL) {
GHashTable* ifmap = *(ifinfo->ifmap);
g_hash_table_insert(ifmap, intf->interfacename,intf->exports);
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: Inserted interface [%s] in hash"
" table @ 0x%08lx"
, PIL_PLUGIN_S, intf->interfacename
, (unsigned long)ifmap);
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: Exports are here: 0x%08x"
, PIL_PLUGIN_S
, GPOINTER_TO_UINT(intf->exports));
}
if (ifinfo->callback != NULL) {
PILInterfaceType* t = intf->interfacetype;
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: callback 0x%lx"
, PIL_PLUGIN_S
, (unsigned long)ifinfo->callback);
}
ifinfo->callback(PIL_REGISTER
, t->universe->piuniv, intf->interfacename
, t->typename, ifinfo->userptr);
}
*imports = ifinfo->importfuns;
return PIL_OK;
}else{
PILCallLog(GenPIImports->log, PIL_WARN
, "RegisterGenIF: interface type %s not found"
, intf->interfacename);
}
return PIL_INVAL;
}
/* Unregister an implementation -
* We get called from the interface management system when someone
* has requested that an implementation of a client interface be
* unregistered.
*/
static PIL_rc
UnregisterGenIF(PILInterface*intf)
{
GHashTable* MasterTable = intf->ifmanager->ud_interface;
PILGenericIfMgmtRqst* ifinfo;
g_assert(MasterTable != NULL);
g_assert(intf->refcnt >= 0);
/*
* Go through the "master table" and find client table,
* notify client we're about to remove this entry, then
* then remove this entry from it.
*/
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: unregistering interface %s/%s."
, PIL_PLUGIN_S, intf->interfacetype->typename
, intf->interfacename);
}
if ((ifinfo = g_hash_table_lookup(MasterTable
, intf->interfacetype->typename)) != NULL) {
GHashTable* ifmap = *(ifinfo->ifmap);
if (ifinfo->callback != NULL) {
PILInterfaceType* t = intf->interfacetype;
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_DEBUG
, "%s IF manager: callback 0x%lx"
, PIL_PLUGIN_S
, (unsigned long)ifinfo->callback);
}
ifinfo->callback(PIL_UNREGISTER
, t->universe->piuniv, intf->interfacename
, t->typename, ifinfo->userptr);
}
/* Remove the client entry from master table */
g_hash_table_remove(ifmap, intf->interfacename);
}else{
PILCallLog(GenPIImports->log, PIL_WARN
, "UnregisterGenIF: interface type %s not found"
, intf->interfacename);
return PIL_INVAL;
}
return PIL_OK;
}
/*
* Close down the generic interface manager.
*/
static PIL_rc
CloseGenInterfaceManager(PILInterface*intf, void* info)
{
void* key;
void* data;
GHashTable* MasterTable = intf->ud_interface;
if (GenDebugFlag) {
PILCallLog(GenPIImports->log, PIL_INFO
, "In CloseGenInterFaceManager on %s/%s (MasterTable: 0x%08lx)"
, intf->interfacetype->typename, intf->interfacename
, (unsigned long)MasterTable);
}
g_assert(MasterTable != NULL);
if (g_hash_table_lookup_extended(MasterTable
, intf->interfacename, &key, &data)) {
PILGenericIfMgmtRqst* ifinfo = data;
g_hash_table_destroy(*(ifinfo->ifmap));
*(ifinfo->ifmap) = NULL;
g_hash_table_remove(MasterTable, key);
g_free(key);
}else{
g_assert_not_reached();
}
return PIL_OK;
}
static gboolean
FreeAKey(gpointer key, gpointer value, gpointer data)
{
g_free(key);
return TRUE;
}
|