Ejemplo n.º 1
0
CP_C_API void cp_release_symbol(cp_context_t *context, const void *ptr) {
    hnode_t *node;
    symbol_info_t *symbol_info;
    symbol_provider_info_t *provider_info;

    CHECK_NOT_NULL(context);
    CHECK_NOT_NULL(ptr);

    cpi_lock_context(context);
    cpi_check_invocation(context, CPI_CF_LOGGER | CPI_CF_LISTENER, __func__);
    do {

        // Look up the symbol
        if ((node = hash_lookup(context->resolved_symbols, ptr)) == NULL) {
            cpi_errorf(context, N_("Could not release unknown symbol at address %p."), ptr);
            break;
        }
        symbol_info = hnode_get(node);
        provider_info = symbol_info->provider_info;

        // Decrease usage count
        assert(symbol_info->usage_count > 0);
        symbol_info->usage_count--;
        assert(provider_info->usage_count > 0);
        provider_info->usage_count--;

        // Check if the symbol is not being used anymore
        if (symbol_info->usage_count == 0) {
            hash_delete_free(context->resolved_symbols, node);
            free(symbol_info);
            if (cpi_is_logged(context, CP_LOG_DEBUG)) {
                char owner[64];
                /* TRANSLATORS: First %s is the context owner */
                cpi_debugf(context, _("%s released the symbol at address %p defined by plug-in %s."), cpi_context_owner(context, owner, sizeof(owner)), ptr, provider_info->plugin->plugin->identifier);
            }
        }

        // Check if the symbol providing plug-in is not being used anymore
        if (provider_info->usage_count == 0) {
            node = hash_lookup(context->symbol_providers, provider_info->plugin);
            assert(node != NULL);
            hash_delete_free(context->symbol_providers, node);
            if (!provider_info->imported) {
                cpi_ptrset_remove(context->plugin->imported, provider_info->plugin);
                cpi_ptrset_remove(provider_info->plugin->importing, context->plugin);
                cpi_debugf(context, _("A dynamic dependency from plug-in %s to plug-in %s was removed."), context->plugin->plugin->identifier, provider_info->plugin->plugin->identifier);
            }
            free(provider_info);
        }

    } while (0);
    cpi_unlock_context(context);
}
Ejemplo n.º 2
0
CP_C_API void cp_unregister_ploader(cp_context_t *ctx, cp_plugin_loader_t *loader) {
	hnode_t *hnode;
	
	CHECK_NOT_NULL(ctx);
	CHECK_NOT_NULL(loader);

	cpi_lock_context(ctx);
	cpi_check_invocation(ctx, CPI_CF_ANY, __func__);
	hnode = hash_lookup(ctx->env->loaders_to_plugins, loader);
	if (hnode != NULL) {
		hash_t *loader_plugins = hnode_get(hnode);

		// Uninstall all plug-ins loaded by the loader
		while (!hash_isempty(loader_plugins)) {
			hscan_t hscan;
			hnode_t *hnode2;
			cp_status_t status;
	
			hash_scan_begin(&hscan, loader_plugins);
			hnode2 = hash_scan_next(&hscan);
			assert(hnode2 != NULL);
			status = cp_uninstall_plugin(ctx, hnode_getkey(hnode2));
			assert(status == CP_OK);
		}
		hash_delete_free(ctx->env->loaders_to_plugins, hnode);
		assert(hash_isempty(loader_plugins));
		hash_destroy(loader_plugins);
		cpi_debugf(ctx, N_("The plug-in loader %p was unregistered."), (void *) loader);
	}
	cpi_unlock_context(ctx);
}
Ejemplo n.º 3
0
CP_C_API cp_status_t cp_register_pcollection(cp_context_t *context, const char *dir) {
	cp_status_t status = CP_OK;
	
	CHECK_NOT_NULL(context);
	CHECK_NOT_NULL(dir);
	
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_ANY, __func__);
	do {
	
		// Initialize plug-in loader
		if ((status = init_local_ploader(context)) != CP_OK) {
			break;
		}
		
		// Register directory
		status = cp_lpl_register_dir(context->env->local_loader, dir);
	
	} while (0);

	// Report error or success
	if (status != CP_OK) {
		cpi_errorf(context, N_("The plug-in collection in path %s could not be registered due to insufficient memory."), dir);
	} else {
		cpi_debugf(context, N_("The plug-in collection in path %s was registered."), dir);
	}
	cpi_unlock_context(context);

	return status;
}
Ejemplo n.º 4
0
CP_C_API cp_status_t cp_register_logger(cp_context_t *context, cp_logger_func_t logger, void *user_data, cp_log_severity_t min_severity) {
	logger_t l;
	logger_t *lh = NULL;
	lnode_t *node = NULL;
	cp_status_t status = CP_OK;

	CHECK_NOT_NULL(context);
	CHECK_NOT_NULL(logger);
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
	do {
	
		// Check if logger already exists and allocate new holder if necessary
		l.logger = logger;
		if ((node = list_find(context->env->loggers, &l, comp_logger)) == NULL) {
			lh = malloc(sizeof(logger_t));
			node = lnode_create(lh);
			if (lh == NULL || node == NULL) {
				status = CP_ERR_RESOURCE;
				break;
			}
			lh->logger = logger;
			lh->plugin = context->plugin;
			list_append(context->env->loggers, node);
		} else {
			lh = lnode_get(node);
		}
		
		// Initialize or update the logger holder
		lh->user_data = user_data;
		lh->min_severity = min_severity;
		
		// Update global limits
		update_logging_limits(context);
		
	} while (0);

	// Report error
	if (status == CP_ERR_RESOURCE) {
		cpi_error(context, N_("Logger could not be registered due to insufficient memory."));		
	} else if (cpi_is_logged(context, CP_LOG_DEBUG)) {
		char owner[64];
		/* TRANSLATORS: %s is the context owner */
		cpi_debugf(context, N_("%s registered a logger."), cpi_context_owner(context, owner, sizeof(owner)));
	}
	cpi_unlock_context(context);

	// Release resources on error
	if (status != CP_OK) {
		if (node != NULL) {
			lnode_destroy(node);
		}
		if (lh != NULL) {
			free(lh);
		}
	}

	return status;
}
Ejemplo n.º 5
0
CP_C_API void cp_unregister_pcollection(cp_context_t *context, const char *dir) {
	CHECK_NOT_NULL(context);
	CHECK_NOT_NULL(dir);
	
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_ANY, __func__);
	if (context->env->local_loader != NULL) {
		cp_lpl_unregister_dir(context->env->local_loader, dir);
	}
	cpi_debugf(context, N_("The plug-in collection in path %s was unregistered."), dir);
	cpi_unlock_context(context);
}
Ejemplo n.º 6
0
CP_C_API cp_status_t cp_register_ploader(cp_context_t *ctx, cp_plugin_loader_t *loader) {
	cp_status_t status = CP_OK;
	hash_t *loader_plugins = NULL;
	
	CHECK_NOT_NULL(ctx);
	CHECK_NOT_NULL(loader);
	
	cpi_lock_context(ctx);
	cpi_check_invocation(ctx, CPI_CF_ANY, __func__);
	do {
		if ((loader_plugins = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL)) == NULL) {
			status = CP_ERR_RESOURCE;
			break;
		}
		if (!hash_alloc_insert(ctx->env->loaders_to_plugins, loader, loader_plugins)) {
			status = CP_ERR_RESOURCE;
			break;
		}
	} while (0);
	
	// Report error or success
	if (status != CP_OK) {
		cpi_errorf(ctx, N_("The plug-in loader %p could not be registered due to insufficient memory."), (void *) loader);
	} else {
		cpi_debugf(ctx, N_("The plug-in loader %p was registered."), (void *) loader);
	}
	cpi_unlock_context(ctx);
	
	// Release resources
	if (status != CP_OK) {
		if (loader_plugins != NULL) {
			assert(hash_isempty(loader_plugins));
			hash_destroy(loader_plugins);
		}
	}
	
	return status;
}
Ejemplo n.º 7
0
CP_C_API void cp_unregister_logger(cp_context_t *context, cp_logger_func_t logger) {
	logger_t l;
	lnode_t *node;
	
	CHECK_NOT_NULL(context);
	CHECK_NOT_NULL(logger);
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
	
	l.logger = logger;
	if ((node = list_find(context->env->loggers, &l, comp_logger)) != NULL) {
		logger_t *lh = lnode_get(node);
		list_delete(context->env->loggers, node);
		lnode_destroy(node);
		free(lh);
		update_logging_limits(context);
	}
	if (cpi_is_logged(context, CP_LOG_DEBUG)) {
		char owner[64];
		/* TRANSLATORS: %s is the context owner */
		cpi_debugf(context, N_("%s unregistered a logger."), cpi_context_owner(context, owner, sizeof(owner)));
	}
	cpi_unlock_context(context);
}
Ejemplo n.º 8
0
CP_C_API void * cp_resolve_symbol(cp_context_t *context, const char *id, const char *name, cp_status_t *error) {
    cp_status_t status = CP_OK;
    int error_reported = 1;
    hnode_t *node;
    void *symbol = NULL;
    symbol_info_t *symbol_info = NULL;
    symbol_provider_info_t *provider_info = NULL;
    cp_plugin_t *pp = NULL;

    CHECK_NOT_NULL(context);
    CHECK_NOT_NULL(id);
    CHECK_NOT_NULL(name);

    // Resolve the symbol
    cpi_lock_context(context);
    cpi_check_invocation(context, CPI_CF_LOGGER | CPI_CF_LISTENER | CPI_CF_STOP, __func__);
    do {

        // Allocate space for symbol hashes, if necessary
        if (context->resolved_symbols == NULL) {
            context->resolved_symbols = hash_create(HASHCOUNT_T_MAX, cpi_comp_ptr, cpi_hashfunc_ptr);
        }
        if (context->symbol_providers == NULL) {
            context->symbol_providers = hash_create(HASHCOUNT_T_MAX, cpi_comp_ptr, cpi_hashfunc_ptr);
        }
        if (context->resolved_symbols == NULL
                || context->symbol_providers == NULL) {
            status = CP_ERR_RESOURCE;
            break;
        }

        // Look up the symbol defining plug-in
        node = hash_lookup(context->env->plugins, id);
        if (node == NULL) {
            cpi_warnf(context, N_("Symbol %s in unknown plug-in %s could not be resolved."), name, id);
            status = CP_ERR_UNKNOWN;
            break;
        }
        pp = hnode_get(node);

        // Make sure the plug-in has been started
        if ((status = cpi_start_plugin(context, pp)) != CP_OK) {
            printf("Symbol %s in plug-in %s could not be resolved because the plug-in could not be started.\n", name, id);
            cpi_errorf(context, N_("Symbol %s in plug-in %s could not be resolved because the plug-in could not be started."), name, id);
            error_reported = 1;
            break;
        }

        // Check for a context specific symbol
        if (pp->defined_symbols != NULL && (node = hash_lookup(pp->defined_symbols, name)) != NULL) {
            symbol = hnode_get(node);
        }

        // Fall back to global symbols, if necessary
        if (symbol == NULL && pp->runtime_lib != NULL) {
            symbol = DLSYM(pp->runtime_lib, name);
        }
        if (symbol == NULL) {
            const char *error = DLERROR();
            if (error == NULL) {
                error = _("Unspecified error.");
            }
            cpi_warnf(context, N_("Symbol %s in plug-in %s could not be resolved: %s"), name, id, error);
            status = CP_ERR_UNKNOWN;
            break;
        }

        // Lookup or initialize symbol provider information
        if ((node = hash_lookup(context->symbol_providers, pp)) != NULL) {
            provider_info = hnode_get(node);
        } else {
            if ((provider_info = malloc(sizeof(symbol_provider_info_t))) == NULL) {
                status = CP_ERR_RESOURCE;
                break;
            }
            memset(provider_info, 0, sizeof(symbol_provider_info_t));
            provider_info->plugin = pp;
            provider_info->imported = (context->plugin == NULL || cpi_ptrset_contains(context->plugin->imported, pp));
            if (!hash_alloc_insert(context->symbol_providers, pp, provider_info)) {
                status = CP_ERR_RESOURCE;
                break;
            }
        }

        // Lookup or initialize symbol information
        if ((node = hash_lookup(context->resolved_symbols, symbol)) != NULL) {
            symbol_info = hnode_get(node);
        } else {
            if ((symbol_info = malloc(sizeof(symbol_info_t))) == NULL) {
                status = CP_ERR_RESOURCE;
                break;
            }
            memset(symbol_info, 0, sizeof(symbol_info_t));
            symbol_info->provider_info = provider_info;
            if (!hash_alloc_insert(context->resolved_symbols, symbol, symbol_info)) {
                status = CP_ERR_RESOURCE;
                break;
            }
        }

        // Add dependencies (for plug-in)
        if (provider_info != NULL
                && !provider_info->imported
                && provider_info->usage_count == 0) {
            if (!cpi_ptrset_add(context->plugin->imported, pp)) {
                status = CP_ERR_RESOURCE;
                break;
            }
            if (!cpi_ptrset_add(pp->importing, context->plugin)) {
                cpi_ptrset_remove(context->plugin->imported, pp);
                status = CP_ERR_RESOURCE;
                break;
            }
            cpi_debugf(context, "A dynamic dependency was created from plug-in %s to plug-in %s.", context->plugin->plugin->identifier, pp->plugin->identifier);
        }

        // Increase usage counts
        symbol_info->usage_count++;
        provider_info->usage_count++;

        if (cpi_is_logged(context, CP_LOG_DEBUG)) {
            char owner[64];
            /* TRANSLATORS: First %s is the context owner */
            cpi_debugf(context, "%s resolved symbol %s defined by plug-in %s.", cpi_context_owner(context, owner, sizeof(owner)), name, id);
        }
    } while (0);

    // Clean up
    if (symbol_info != NULL && symbol_info->usage_count == 0) {
        if ((node = hash_lookup(context->resolved_symbols, symbol)) != NULL) {
            hash_delete_free(context->resolved_symbols, node);
        }
        free(symbol_info);
    }
    if (provider_info != NULL && provider_info->usage_count == 0) {
        if ((node = hash_lookup(context->symbol_providers, pp)) != NULL) {
            hash_delete_free(context->symbol_providers, node);
        }
        free(provider_info);
    }

    // Report insufficient memory error
    if (status == CP_ERR_RESOURCE && !error_reported) {
        cpi_errorf(context, N_("Symbol %s in plug-in %s could not be resolved due to insufficient memory."), name, id);
    }
    cpi_unlock_context(context);

    // Return error code
    if (error != NULL) {
        *error = status;
    }

    // Return symbol
    return symbol;
}