GCOV Execution Analysis for plugin.c
The left column is the number of times the code was executed
during the unit test suites.
Exec | Code | Line # | |
---|---|---|---|
Source:plugin.c | 1 | ||
Graph:.libs/plugin.gcno | 2 | ||
Data:.libs/plugin.gcda | 3 | ||
Runs:378 | 4 | ||
Programs:378 | 5 | ||
/* -*- linux-c -*- | 6 | ||
* | 7 | ||
* Copyright (c) 2003 by Intel Corp. | 8 | ||
* (C) Copyright IBM Corp. 2003-2004 | 9 | ||
* | 10 | ||
* This program is distributed in the hope that it will be useful, | 11 | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This | 13 | ||
* file and program are licensed under a BSD style license. See | 14 | ||
* the Copying file included with the OpenHPI distribution for | 15 | ||
* full licensing terms. | 16 | ||
* | 17 | ||
* Authors: | 18 | ||
* Louis Zhuang < address removed > | 19 | ||
* Sean Dague <http://dague.net/sean> | 20 | ||
* David Judkovics < address removed > | 21 | ||
* Renier Morales < address removed > | 22 | ||
*/ | 23 | ||
24 | |||
#include <string.h> | 25 | ||
#include <ltdl.h> | 26 | ||
27 | |||
#include <glib.h> | 28 | ||
#include <oh_plugin.h> | 29 | ||
#include <oh_config.h> | 30 | ||
#include <oh_error.h> | 31 | ||
#include <oh_lock.h> | 32 | ||
#include <config.h> | 33 | ||
34 | |||
/* | 35 | ||
* List of plugins (oh_plugin). | 36 | ||
*/ | 37 | ||
static GSList *plugin_list = NULL; | 38 | ||
/* | 39 | ||
* Table of handlers (oh_handler). | 40 | ||
*/ | 41 | ||
static GHashTable *handler_table = NULL; | 42 | ||
/* | 43 | ||
* List of handler ids (unsigned int). | 44 | ||
*/ | 45 | ||
static GSList *handler_ids = NULL; | 46 | ||
47 | |||
48 | |||
extern GCond *oh_thread_wait; | 49 | ||
50 | |||
void oh_cond_signal(void) | 51 | ||
0 | { | 52 | |
0 | g_cond_signal(oh_thread_wait); | 53 | |
} | 54 | ||
55 | |||
/** | 56 | ||
* oh_init_ltdl | 57 | ||
* | 58 | ||
* Does all the initialization needed for the ltdl process to | 59 | ||
* work. It takes no arguments, and returns 0 on success, < 0 on error | 60 | ||
* | 61 | ||
* Returns: 0 on Success. | 62 | ||
**/ | 63 | ||
static int oh_init_ltdl(void) | 64 | ||
374 | { | 65 | |
374 | struct oh_global_param path_param = { .type = OPENHPI_PATH }; | 66 | |
374 | int err; | 67 | |
374 | static int init_done = 0; | 68 | |
69 | |||
374 | data_access_lock(); | 70 | |
374 | if (init_done) { | 71 | |
0 | data_access_unlock(); | 72 | |
0 | return 0; | 73 | |
} | 74 | ||
75 | |||
374 | err = lt_dlinit(); | 76 | |
374 | if (err != 0) { | 77 | |
0 | dbg("Can not init ltdl"); | 78 | |
0 | data_access_unlock(); | 79 | |
0 | return -1; | 80 | |
} | 81 | ||
82 | |||
374 | oh_get_global_param(&path_param); | 83 | |
84 | |||
374 | err = lt_dlsetsearchpath(path_param.u.path); | 85 | |
374 | if (err != 0) { | 86 | |
0 | dbg("Can not set lt_dl search path"); | 87 | |
0 | oh_exit_ltdl(); | 88 | |
0 | data_access_unlock(); | 89 | |
0 | return -1; | 90 | |
} | 91 | ||
92 | |||
374 | init_done = 1; | 93 | |
374 | data_access_unlock(); | 94 | |
95 | |||
374 | return 0; | 96 | |
} | 97 | ||
98 | |||
/** | 99 | ||
* oh_exit_ltdl | 100 | ||
* | 101 | ||
* Does everything needed to close the ltdl structures. | 102 | ||
* | 103 | ||
* Returns: 0 on Success. | 104 | ||
**/ | 105 | ||
int oh_exit_ltdl() | 106 | ||
0 | { | 107 | |
0 | int rv; | 108 | |
109 | |||
0 | rv = lt_dlexit(); | 110 | |
0 | if (rv < 0) { | 111 | |
0 | dbg("Could not exit ltdl!"); | 112 | |
0 | return -1; | 113 | |
} | 114 | ||
115 | |||
0 | return 0; | 116 | |
} | 117 | ||
118 | |||
/** | 119 | ||
* oh_lookup_plugin | 120 | ||
* @plugin_name | 121 | ||
* | 122 | ||
* Lookup and get a reference for @plugin_name. | 123 | ||
* | 124 | ||
* Returns: oh_plugin reference or NULL if plugin_name was not found. | 125 | ||
**/ | 126 | ||
struct oh_plugin *oh_lookup_plugin(char *plugin_name) | 127 | ||
748 | { | 128 | |
748 | GSList *node = NULL; | 129 | |
748 | struct oh_plugin *plugin = NULL; | 130 | |
131 | |||
748 | if (!plugin_name) { | 132 | |
0 | dbg("ERROR getting plugin. Invalid parameter."); | 133 | |
0 | return NULL; | 134 | |
} | 135 | ||
136 | |||
748 | data_access_lock(); | 137 | |
748 | for (node = plugin_list; node != NULL; node = node->next) { | 138 | |
374 | struct oh_plugin *p = node->data; | 139 | |
374 | if(strcmp(p->name, plugin_name) == 0) { | 140 | |
374 | plugin = p; | 141 | |
374 | break; | 142 | |
} | 143 | ||
} | 144 | ||
748 | data_access_unlock(); | 145 | |
146 | |||
748 | return plugin; | 147 | |
} | 148 | ||
149 | |||
/** | 150 | ||
* oh_lookup_next_plugin | 151 | ||
* @plugin_name: IN. If NULL is passed, the first plugin in the list is returned. | 152 | ||
* @next_plugin_name: OUT. Buffer to print the next plugin name to. | 153 | ||
* @size: IN. Size of the buffer at @next_plugin_name. | 154 | ||
* | 155 | ||
* Returns: 0 on Success. | 156 | ||
**/ | 157 | ||
int oh_lookup_next_plugin(char *plugin_name, | 158 | ||
char *next_plugin_name, | 159 | ||
unsigned int size) | 160 | ||
0 | { | 161 | |
0 | GSList *node = NULL; | 162 | |
163 | |||
0 | if (!next_plugin_name) { | 164 | |
0 | dbg("ERROR. Invalid parameter."); | 165 | |
0 | return -1; | 166 | |
} | 167 | ||
0 | memset(next_plugin_name, '\0', size); | 168 | |
169 | |||
0 | data_access_lock(); | 170 | |
0 | if (!plugin_name) { | 171 | |
0 | if (plugin_list) { | 172 | |
0 | struct oh_plugin *plugin = plugin_list->data; | 173 | |
0 | strncpy(next_plugin_name, plugin->name, size); | 174 | |
0 | data_access_unlock(); | 175 | |
0 | return 0; | 176 | |
} else { | 177 | ||
0 | trace("No plugins have been loaded yet."); | 178 | |
0 | data_access_unlock(); | 179 | |
0 | return -1; | 180 | |
} | 181 | ||
} else { | 182 | ||
0 | for (node = plugin_list; node != NULL; node = node->next) { | 183 | |
0 | struct oh_plugin *p = node->data; | 184 | |
0 | if (strcmp(p->name, plugin_name) == 0) { | 185 | |
0 | if (node->next) { | 186 | |
0 | p = node->next->data; | 187 | |
0 | strncpy(next_plugin_name, p->name, size); | 188 | |
0 | data_access_unlock(); | 189 | |
0 | return 0; | 190 | |
} else | 191 | ||
0 | break; | 192 | |
} | 193 | ||
} | 194 | ||
} | 195 | ||
0 | data_access_unlock(); | 196 | |
197 | |||
0 | return -1; | 198 | |
} | 199 | ||
200 | |||
/* list of static plugins. defined in plugin_static.c.in */ | 201 | ||
extern struct oh_static_plugin static_plugins[]; | 202 | ||
/** | 203 | ||
* oh_unload_plugin | 204 | ||
* @plugin_name | 205 | ||
* | 206 | ||
* Load plugin by name and make a instance. | 207 | ||
* | 208 | ||
* Returns: 0 on Success. | 209 | ||
**/ | 210 | ||
int oh_load_plugin(char *plugin_name) | 211 | ||
374 | { | 212 | |
374 | struct oh_plugin *plugin = NULL; | 213 | |
374 | int (*get_interface) (struct oh_abi_v2 ** pp, const uuid_t uuid); | 214 | |
374 | int err; | 215 | |
374 | struct oh_static_plugin *p = static_plugins; | 216 | |
217 | |||
374 | if (!plugin_name) { | 218 | |
0 | dbg("ERROR. NULL plugin name passed."); | 219 | |
0 | return -1; | 220 | |
} | 221 | ||
222 | |||
374 | data_access_lock(); | 223 | |
374 | if (oh_init_ltdl()) { | 224 | |
0 | data_access_unlock(); | 225 | |
0 | dbg("ERROR. Could not initialize ltdl for loading plugins."); | 226 | |
0 | return -1; | 227 | |
} | 228 | ||
229 | |||
374 | if (oh_lookup_plugin(plugin_name)) { | 230 | |
0 | dbg("Warning. Plugin %s already loaded. Not loading twice.", | 231 | |
plugin_name); | 232 | ||
0 | data_access_unlock(); | 233 | |
0 | return -1; | 234 | |
} | 235 | ||
236 | |||
374 | plugin = (struct oh_plugin *)g_malloc0(sizeof(struct oh_plugin)); | 237 | |
374 | if (!plugin) { | 238 | |
0 | dbg("Out of memory."); | 239 | |
0 | data_access_unlock(); | 240 | |
0 | return -1; | 241 | |
} | 242 | ||
374 | plugin->name = g_strdup(plugin_name); | 243 | |
374 | plugin->refcount = 1; | 244 | |
245 | |||
/* first take search plugin in the array of static plugin */ | 246 | ||
374 | while( p->name ) { | 247 | |
0 | if (!strcmp(plugin->name, p->name)) { | 248 | |
0 | plugin->dl_handle = 0; | 249 | |
0 | err = (*p->get_interface)((void **)&plugin->abi, UUID_OH_ABI_V2); | 250 | |
251 | |||
0 | if (err < 0 || !plugin->abi || !plugin->abi->open) { | 252 | |
0 | dbg("Can not get ABI V2"); | 253 | |
0 | goto err1; | 254 | |
} | 255 | ||
256 | |||
0 | trace( "found static plugin %s", p->name ); | 257 | |
258 | |||
0 | plugin_list = g_slist_append(plugin_list, plugin); | 259 | |
0 | data_access_unlock(); | 260 | |
261 | |||
0 | return 0; | 262 | |
} | 263 | ||
264 | |||
0 | p++; | 265 | |
} | 266 | ||
267 | |||
374 | plugin->dl_handle = lt_dlopenext(plugin->name); | 268 | |
374 | if (plugin->dl_handle == NULL) { | 269 | |
0 | dbg("Can not open %s plugin: %s", plugin->name, lt_dlerror()); | 270 | |
0 | goto err1; | 271 | |
} | 272 | ||
273 | |||
374 | get_interface = lt_dlsym(plugin->dl_handle, "get_interface"); | 274 | |
374 | if (!get_interface) { | 275 | |
0 | dbg("Can not get 'get_interface' symbol, is it a plugin?!"); | 276 | |
0 | goto err1; | 277 | |
} | 278 | ||
279 | |||
374 | err = get_interface(&plugin->abi, UUID_OH_ABI_V2); | 280 | |
374 | if (err < 0 || !plugin->abi || !plugin->abi->open) { | 281 | |
0 | dbg("Can not get ABI V1"); | 282 | |
0 | goto err1; | 283 | |
} | 284 | ||
374 | plugin_list = g_slist_append(plugin_list, plugin); | 285 | |
374 | data_access_unlock(); | 286 | |
287 | |||
374 | return 0; | 288 | |
289 | |||
err1: | 290 | ||
0 | if (plugin->dl_handle) { | 291 | |
0 | lt_dlclose(plugin->dl_handle); | 292 | |
0 | plugin->dl_handle = 0; | 293 | |
} | 294 | ||
0 | data_access_unlock(); | 295 | |
0 | g_free(plugin); | 296 | |
297 | |||
0 | return -1; | 298 | |
} | 299 | ||
300 | |||
/** | 301 | ||
* oh_unload_plugin | 302 | ||
* @plugin_name | 303 | ||
* | 304 | ||
* Returns: 0 on Success. | 305 | ||
**/ | 306 | ||
int oh_unload_plugin(char *plugin_name) | 307 | ||
0 | { | 308 | |
0 | struct oh_plugin *plugin = NULL; | 309 | |
310 | |||
0 | if (!plugin_name) { | 311 | |
0 | dbg("ERROR unloading plugin. NULL parameter passed."); | 312 | |
0 | return -1; | 313 | |
} | 314 | ||
315 | |||
0 | data_access_lock(); | 316 | |
317 | |||
0 | plugin = oh_lookup_plugin(plugin_name); | 318 | |
0 | if (!plugin) { | 319 | |
0 | dbg("ERROR unloading plugin. Plugin not found."); | 320 | |
0 | data_access_unlock(); | 321 | |
0 | return -2; | 322 | |
} | 323 | ||
324 | |||
0 | if (plugin->refcount > 1) { | 325 | |
0 | dbg("ERROR unloading plugin. Handlers are still referencing it."); | 326 | |
0 | data_access_unlock(); | 327 | |
0 | return -3; | 328 | |
} | 329 | ||
330 | |||
0 | if (plugin->dl_handle) { | 331 | |
0 | lt_dlclose(plugin->dl_handle); | 332 | |
0 | plugin->dl_handle = 0; | 333 | |
} | 334 | ||
335 | |||
0 | plugin_list = g_slist_remove(plugin_list, plugin); | 336 | |
0 | data_access_unlock(); | 337 | |
338 | |||
0 | if (plugin->name) | 339 | |
0 | g_free(plugin->name); | 340 | |
341 | |||
0 | g_free(plugin); | 342 | |
343 | |||
0 | return 0; | 344 | |
} | 345 | ||
346 | |||
static int oh_init_handler_table(void) | 347 | ||
374 | { | 348 | |
374 | if (!handler_table) | 349 | |
374 | handler_table = g_hash_table_new(g_int_hash, g_int_equal); | 350 | |
351 | |||
374 | return (handler_table) ? 0 : -1; | 352 | |
} | 353 | ||
354 | |||
/** | 355 | ||
* oh_lookup_handler | 356 | ||
* @hid | 357 | ||
* | 358 | ||
* Returns: NULL on Failure. | 359 | ||
**/ | 360 | ||
struct oh_handler *oh_lookup_handler(unsigned int hid) | 361 | ||
1090 | { | 362 | |
1090 | struct oh_handler *handler = NULL; | 363 | |
364 | |||
1090 | data_access_lock(); | 365 | |
1090 | if (!handler_table) { | 366 | |
0 | data_access_unlock(); | 367 | |
0 | return NULL; | 368 | |
} | 369 | ||
370 | |||
1090 | handler = g_hash_table_lookup(handler_table, &hid); | 371 | |
1090 | data_access_unlock(); | 372 | |
373 | |||
1090 | return handler; | 374 | |
} | 375 | ||
376 | |||
/** | 377 | ||
* oh_lookup_next_handler | 378 | ||
* @hid: If 0, will return the first handler id in the list. | 379 | ||
* @next_hid | 380 | ||
* | 381 | ||
* Returns: 0 on Success. | 382 | ||
**/ | 383 | ||
int oh_lookup_next_handler(unsigned int hid, unsigned int *next_hid) | 384 | ||
1872 | { | 385 | |
1872 | GSList *node = NULL; | 386 | |
387 | |||
1872 | if (!next_hid) { | 388 | |
0 | dbg("ERROR. Invalid parameter."); | 389 | |
0 | return -1; | 390 | |
} | 391 | ||
1872 | *next_hid = 0; | 392 | |
393 | |||
1872 | data_access_lock(); | 394 | |
1872 | if (!hid) { | 395 | |
1123 | if (handler_ids) { | 396 | |
1123 | unsigned int *id = handler_ids->data; | 397 | |
1123 | *next_hid = *id; | 398 | |
1123 | data_access_unlock(); | 399 | |
1123 | return 0; | 400 | |
} else { | 401 | ||
0 | data_access_unlock(); | 402 | |
0 | return -1; | 403 | |
} | 404 | ||
} else { | 405 | ||
749 | for (node = handler_ids; node; node = node->next) { | 406 | |
749 | unsigned int *id = node->data; | 407 | |
749 | if (*id == hid) { | 408 | |
749 | if (node->next) { | 409 | |
0 | id = node->next->data; | 410 | |
0 | *next_hid = *id; | 411 | |
0 | data_access_unlock(); | 412 | |
0 | return 0; | 413 | |
} else | 414 | ||
0 | break; | 415 | |
} | 416 | ||
} | 417 | ||
} | 418 | ||
749 | data_access_unlock(); | 419 | |
420 | |||
749 | return -1; | 421 | |
} | 422 | ||
423 | |||
static struct oh_handler *new_handler(GHashTable *handler_config) | 424 | ||
374 | { | 425 | |
374 | struct oh_plugin *plugin = NULL; | 426 | |
374 | struct oh_handler *handler = NULL; | 427 | |
374 | static unsigned int handler_id = 1; | 428 | |
429 | |||
374 | if (!handler_config) { | 430 | |
0 | dbg("ERROR creating new handler. Invalid parameter."); | 431 | |
0 | return NULL; | 432 | |
} | 433 | ||
434 | |||
374 | handler = (struct oh_handler *)g_malloc0(sizeof(struct oh_handler)); | 435 | |
374 | if (!handler) { | 436 | |
0 | dbg("Out of Memory!"); | 437 | |
0 | return NULL; | 438 | |
} | 439 | ||
440 | |||
374 | plugin = oh_lookup_plugin((char *)g_hash_table_lookup(handler_config, "plugin")); | 441 | |
374 | if(!plugin || plugin->refcount < 1) { | 442 | |
0 | dbg("Attempt to create handler for unknown plugin %s", | 443 | |
(char *)g_hash_table_lookup(handler_config, "plugin")); | 444 | ||
0 | goto err; | 445 | |
} | 446 | ||
447 | |||
374 | handler->plugin_name = g_strdup(plugin->name); | 448 | |
374 | handler->abi = plugin->abi; | 449 | |
374 | handler->config = handler_config; | 450 | |
451 | |||
374 | handler->hnd = handler->abi->open(handler->config); | 452 | |
374 | if (!handler->hnd) { | 453 | |
0 | dbg("A plugin instance could not be opened."); | 454 | |
0 | goto err; | 455 | |
} | 456 | ||
457 | |||
374 | handler->id = handler_id++; | 458 | |
374 | plugin->refcount++; | 459 | |
460 | |||
374 | return handler; | 461 | |
err: | 462 | ||
0 | g_free(handler); | 463 | |
0 | return NULL; | 464 | |
} | 465 | ||
466 | |||
/** | 467 | ||
* oh_load_handler | 468 | ||
* @handler_config | 469 | ||
* | 470 | ||
* Returns: 0 on Failure, otherwise the handler id | 471 | ||
**/ | 472 | ||
unsigned int oh_load_handler (GHashTable *handler_config) | 473 | ||
374 | { | 474 | |
374 | struct oh_handler *handler; | 475 | |
476 | |||
374 | if (!handler_config) { | 477 | |
0 | dbg("ERROR loading handler. Invalid handler configuration passed."); | 478 | |
0 | return 0; | 479 | |
} | 480 | ||
481 | |||
374 | data_access_lock(); | 482 | |
374 | if (oh_init_handler_table()) { | 483 | |
0 | data_access_unlock(); | 484 | |
0 | dbg("ERROR. Could not initialize handler table."); | 485 | |
0 | return 0; | 486 | |
} | 487 | ||
488 | |||
374 | handler = new_handler(handler_config); | 489 | |
490 | |||
374 | if (handler == NULL) { | 491 | |
0 | data_access_unlock(); | 492 | |
0 | return 0; | 493 | |
} | 494 | ||
495 | |||
374 | g_hash_table_insert(handler_table, | 496 | |
&(handler->id), | 497 | ||
handler); | 498 | ||
374 | handler_ids = g_slist_append(handler_ids, &(handler->id)); | 499 | |
500 | |||
374 | data_access_unlock(); | 501 | |
502 | |||
374 | return handler->id; | 503 | |
} | 504 | ||
505 | |||
/** | 506 | ||
* oh_unload_handler | 507 | ||
* @hid | 508 | ||
* | 509 | ||
* Returns: 0 on Success. | 510 | ||
**/ | 511 | ||
int oh_unload_handler(unsigned int hid) | 512 | ||
0 | { | 513 | |
0 | struct oh_handler *handler = NULL; | 514 | |
0 | struct oh_plugin *plugin = NULL; | 515 | |
516 | |||
0 | if (!hid) { | 517 | |
0 | dbg("ERROR unloading handler. Invalid handler id passed."); | 518 | |
0 | return -1; | 519 | |
} | 520 | ||
521 | |||
0 | data_access_lock(); | 522 | |
0 | handler = oh_lookup_handler(hid); | 523 | |
0 | if (!handler) { | 524 | |
0 | dbg("ERROR unloading handler. Handler not found."); | 525 | |
0 | data_access_unlock(); | 526 | |
0 | return -1; | 527 | |
} | 528 | ||
529 | |||
0 | if (handler->abi && handler->abi->close) | 530 | |
0 | handler->abi->close(handler->hnd); | 531 | |
532 | |||
0 | g_hash_table_remove(handler_table, &(handler->id)); | 533 | |
0 | handler_ids = g_slist_remove(handler_ids, &(handler->id)); | 534 | |
0 | plugin = oh_lookup_plugin(handler->plugin_name); | 535 | |
0 | if (!plugin) { | 536 | |
0 | dbg("WHAT?! Handler loaded, but plugin does not exist!"); | 537 | |
} else { | 538 | ||
0 | plugin->refcount--; | 539 | |
} | 540 | ||
0 | data_access_unlock(); | 541 | |
542 | |||
0 | g_free(handler->plugin_name); | 543 | |
0 | g_free(handler); | 544 | |
545 | |||
0 | return 0; | 546 | |
} | 547 |