2002-06-04 21:36:48 +02:00
|
|
|
/*
|
|
|
|
* plugin_manager.cpp
|
|
|
|
* firebird_test
|
|
|
|
*
|
|
|
|
* Created by john on Wed Jan 09 2002.
|
|
|
|
* Copyright (c) 2001 __MyCompanyName__. All rights reserved.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "../jrd/plugin_manager.h"
|
|
|
|
#include "../jrd/os/path_utils.h"
|
2003-01-16 18:47:10 +01:00
|
|
|
#include "../jrd/gds_proto.h"
|
2002-06-04 21:36:48 +02:00
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
PluginManager::Plugin PluginManager::findPlugin(const Firebird::PathName &name)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
2004-02-02 12:02:12 +01:00
|
|
|
for (Module *itr = moduleList; itr; itr = itr->next)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
if (itr->name() == name)
|
|
|
|
return itr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Module *result = 0;
|
|
|
|
|
|
|
|
result = loadPluginModule(name);
|
|
|
|
if (!result)
|
|
|
|
{
|
|
|
|
result = loadBuiltinModule(name);
|
|
|
|
if (!result)
|
|
|
|
{
|
|
|
|
// Throw a module not found error here?
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Link the new module into the module list
|
2002-07-21 08:14:32 +02:00
|
|
|
result->aquire();
|
2002-06-04 21:36:48 +02:00
|
|
|
if (moduleList)
|
|
|
|
{
|
|
|
|
moduleList->prev = &(result->next);
|
|
|
|
}
|
|
|
|
result->next = moduleList;
|
|
|
|
result->prev = &moduleList;
|
|
|
|
moduleList = result;
|
|
|
|
return Plugin(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PluginManager::loadAllPlugins()
|
|
|
|
{
|
|
|
|
char fb_lib_path[MAXPATHLEN];
|
|
|
|
gds__prefix(fb_lib_path, "");
|
2004-02-08 18:08:34 +01:00
|
|
|
Firebird::PathName fbLibPath(fb_lib_path);
|
|
|
|
Firebird::PathName checkDir;
|
2002-06-04 21:36:48 +02:00
|
|
|
|
2004-02-28 20:44:04 +01:00
|
|
|
for (spIterator pathItr = searchPaths.begin(); pathItr != searchPaths.end(); ++pathItr)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
if (pathItr->second) // This path is fb relative
|
|
|
|
{
|
|
|
|
PathUtils::concatPath(checkDir, fbLibPath, pathItr->first);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
checkDir = pathItr->first;
|
|
|
|
}
|
|
|
|
|
2004-02-28 20:44:04 +01:00
|
|
|
PathUtils::dir_iterator *dirItr = PathUtils::newDirItr(*pool, checkDir);
|
2004-02-02 12:02:12 +01:00
|
|
|
while (*dirItr)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
// See if we have already loaded this module
|
|
|
|
bool alreadyLoaded = false;
|
2004-02-02 12:02:12 +01:00
|
|
|
for (Module *itr = moduleList; itr; itr = itr->next)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
if (itr->name() == **dirItr)
|
|
|
|
{
|
|
|
|
alreadyLoaded = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if the module has been explicitly excluded from loading
|
2004-02-28 20:44:04 +01:00
|
|
|
if (!alreadyLoaded && ignoreModules.getCount() > 0)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
2004-02-08 18:08:34 +01:00
|
|
|
Firebird::PathName pathComponent, modName;
|
2002-06-04 21:36:48 +02:00
|
|
|
PathUtils::splitLastComponent(pathComponent, modName, **dirItr);
|
2004-02-28 20:44:04 +01:00
|
|
|
for (Firebird::ObjectsArray<Firebird::PathName>::iterator itr2 = ignoreModules.begin();
|
2002-06-04 21:36:48 +02:00
|
|
|
itr2 != ignoreModules.end(); ++itr2)
|
|
|
|
{
|
|
|
|
if (modName == *itr2)
|
|
|
|
{
|
|
|
|
alreadyLoaded = true; // a harmless fib
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we haven't already loaded, and the module is loadable
|
|
|
|
// as defined by the host os, then by all means load it!
|
|
|
|
if (!alreadyLoaded && ModuleLoader::isLoadableModule(**dirItr))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
Module *mod = FB_NEW(*pool) PluginModule(pool, **dirItr,
|
2002-06-04 21:36:48 +02:00
|
|
|
ModuleLoader::loadModule(**dirItr));
|
|
|
|
if (moduleList)
|
|
|
|
{
|
|
|
|
moduleList->prev = &(mod->next);
|
|
|
|
}
|
|
|
|
mod->next = moduleList;
|
|
|
|
mod->prev = &moduleList;
|
|
|
|
moduleList = mod;
|
|
|
|
}
|
|
|
|
++(*dirItr);
|
|
|
|
}
|
2004-02-28 20:44:04 +01:00
|
|
|
delete dirItr;
|
2002-06-04 21:36:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
PluginManager::Module *PluginManager::loadPluginModule(const Firebird::PathName& name)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
char fb_lib_path[MAXPATHLEN];
|
|
|
|
gds__prefix(fb_lib_path, "");
|
2004-02-08 18:08:34 +01:00
|
|
|
Firebird::PathName fbLibPath(fb_lib_path);
|
|
|
|
Firebird::PathName checkPath;
|
2002-06-04 21:36:48 +02:00
|
|
|
|
|
|
|
// Check to see if the module name was specified as a relative path
|
|
|
|
// from one of our search paths. This only makes sense if the name
|
|
|
|
// of the module is relative.
|
|
|
|
if (PathUtils::isRelative(name))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
if (itr->second) // This path is fb relative
|
|
|
|
{
|
|
|
|
PathUtils::concatPath(checkPath, fbLibPath, itr->first);
|
|
|
|
PathUtils::concatPath(checkPath, checkPath, name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
PathUtils::concatPath(checkPath, itr->first, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ModuleLoader::isLoadableModule(checkPath))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
return FB_NEW(*pool) PluginModule(pool, name,
|
2002-06-04 21:36:48 +02:00
|
|
|
ModuleLoader::loadModule(checkPath));
|
|
|
|
}
|
|
|
|
ModuleLoader::doctorModuleExtention(checkPath);
|
|
|
|
if (ModuleLoader::isLoadableModule(checkPath))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
return FB_NEW(*pool) PluginModule(pool, checkPath,
|
2002-06-04 21:36:48 +02:00
|
|
|
ModuleLoader::loadModule(checkPath));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get this far we know the module isn't given as a relative path.
|
|
|
|
// Check to see if it is a valid absolute path that happens to fall in one
|
|
|
|
// of our search paths. This only makes sense if the name of the module
|
|
|
|
// is absolute.
|
|
|
|
|
|
|
|
if (!PathUtils::isRelative(name))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
2004-02-08 18:08:34 +01:00
|
|
|
Firebird::PathName::size_type pos = 0;
|
|
|
|
Firebird::PathName::size_type checkPos;
|
2002-06-04 21:36:48 +02:00
|
|
|
|
|
|
|
if (itr->second) // use fb path prefix
|
|
|
|
{
|
|
|
|
checkPos = name.find(fbLibPath, pos);
|
2004-02-08 18:08:34 +01:00
|
|
|
if (checkPos == Firebird::PathName::npos || checkPos != pos)
|
2002-06-04 21:36:48 +02:00
|
|
|
continue; // The fb path prefix isn't a prefix for this module. Opps.
|
|
|
|
pos += fbLibPath.length();
|
|
|
|
}
|
|
|
|
checkPos = name.find(itr->first, pos);
|
2004-02-08 18:08:34 +01:00
|
|
|
if (checkPos == Firebird::PathName::npos || checkPos != pos)
|
2002-06-04 21:36:48 +02:00
|
|
|
continue; // The search path isn't a prefix for this module. Opps.
|
|
|
|
// OK, the module has the correct prefix path, lets try to load it.
|
|
|
|
if (ModuleLoader::isLoadableModule(name))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
return FB_NEW(*pool) PluginModule(pool, name,
|
2002-06-04 21:36:48 +02:00
|
|
|
ModuleLoader::loadModule(name));
|
|
|
|
}
|
|
|
|
checkPath = name;
|
|
|
|
ModuleLoader::doctorModuleExtention(checkPath);
|
|
|
|
if (ModuleLoader::isLoadableModule(checkPath))
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
return FB_NEW(*pool) PluginModule(pool, checkPath,
|
2002-06-04 21:36:48 +02:00
|
|
|
ModuleLoader::loadModule(checkPath));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we made it this far there is nothing left we can try.
|
|
|
|
// The module _must_ not be an on-disk module :-)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
PluginManager::Module *PluginManager::loadBuiltinModule(const Firebird::PathName& name)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
void PluginManager::addSearchPath(const Firebird::PathName& path, bool isFBRelative)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
if (itr->first == path && itr->second == isFBRelative)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-02-28 20:44:04 +01:00
|
|
|
searchPaths.push(Path(getDefaultMemoryPool(), path, isFBRelative));
|
2002-06-04 21:36:48 +02:00
|
|
|
}
|
|
|
|
|
2004-02-08 18:08:34 +01:00
|
|
|
void PluginManager::removeSearchPath(const Firebird::PathName& path, bool isFBRelative)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
2002-06-04 21:36:48 +02:00
|
|
|
{
|
|
|
|
if (itr->first == path && itr->second == isFBRelative)
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
searchPaths.remove(itr);
|
2002-06-04 21:36:48 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const PluginManager::Plugin& PluginManager::Plugin::operator=(const Plugin& other)
|
|
|
|
{
|
|
|
|
if (this != &other)
|
|
|
|
{
|
|
|
|
if (module != 0)
|
|
|
|
module->release();
|
|
|
|
module = other.module;
|
|
|
|
if (module != 0)
|
|
|
|
module->aquire();
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2002-09-24 01:19:47 +02:00
|
|
|
PluginManager::~PluginManager()
|
|
|
|
{
|
2004-02-02 12:02:12 +01:00
|
|
|
while (moduleList)
|
2002-09-24 01:19:47 +02:00
|
|
|
{
|
|
|
|
#if defined(DEV_BUILD)
|
|
|
|
if (moduleList->refCnt != 1)
|
|
|
|
{
|
|
|
|
ib_printf("Freeing loadable module with reference count != 1: %s (%d)\n",
|
|
|
|
moduleList->module_name.c_str(), moduleList->refCnt);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
delete moduleList;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-04 21:36:48 +02:00
|
|
|
PluginManager::Module::~Module()
|
|
|
|
{
|
2002-09-25 07:56:56 +02:00
|
|
|
if (next)
|
|
|
|
next->prev = prev;
|
|
|
|
*prev = next;
|
|
|
|
|
2002-06-04 21:36:48 +02:00
|
|
|
unload_module();
|
|
|
|
}
|
|
|
|
|
|
|
|
void *PluginManager::BuiltinModule::lookupSymbol(Firebird::string& symbol)
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
int n;
|
|
|
|
if (! symbols.find(symbol, n))
|
2002-06-04 21:36:48 +02:00
|
|
|
return 0;
|
2004-02-28 20:44:04 +01:00
|
|
|
return symbols[n].second;
|
2002-06-04 21:36:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void *PluginManager::PluginModule::lookupSymbol(Firebird::string& symbol)
|
|
|
|
{
|
|
|
|
if (module != 0)
|
|
|
|
return module->findSymbol(symbol);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PluginManager::PluginModule::unload_module()
|
|
|
|
{
|
|
|
|
if (module != 0)
|
|
|
|
delete module;
|
|
|
|
module = 0;
|
2002-07-21 08:14:32 +02:00
|
|
|
}
|
2002-09-24 02:27:23 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Code that handles loading the generic firebird/plugin directory
|
|
|
|
|
2003-02-05 16:18:26 +01:00
|
|
|
const char *PluginManager::ENGINE_PLUGIN_DIR = "plugins";
|
|
|
|
|
2003-02-10 12:51:37 +01:00
|
|
|
#ifdef DARWIN
|
2003-02-05 16:18:26 +01:00
|
|
|
const char *PluginManager::ENGINE_PLUGIN_REGISTRATION_ENTRYPOINT = "_register_plugin";
|
2003-02-10 12:51:37 +01:00
|
|
|
#else
|
|
|
|
const char *PluginManager::ENGINE_PLUGIN_REGISTRATION_ENTRYPOINT = "register_plugin";
|
2002-09-24 02:27:23 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
void PluginManager::load_engine_plugins()
|
|
|
|
{
|
2003-02-05 16:18:26 +01:00
|
|
|
PluginManager& enginePluginManager = getEnginePluginManager();
|
|
|
|
|
2002-09-24 02:27:23 +02:00
|
|
|
enginePluginManager.addSearchPath(ENGINE_PLUGIN_DIR);
|
|
|
|
enginePluginManager.loadAllPlugins();
|
|
|
|
|
|
|
|
Firebird::string entryPoint(ENGINE_PLUGIN_REGISTRATION_ENTRYPOINT);
|
2004-02-02 12:02:12 +01:00
|
|
|
for (PluginManager::iterator itr = enginePluginManager.begin();
|
2002-09-24 02:27:23 +02:00
|
|
|
itr != enginePluginManager.end(); ++itr)
|
|
|
|
{
|
|
|
|
engineRegistrationFuncType regFunc = (engineRegistrationFuncType)
|
|
|
|
(*itr).lookupSymbol(entryPoint);
|
|
|
|
if (!regFunc)
|
|
|
|
continue;
|
|
|
|
PluginManager::Plugin p = *itr;
|
|
|
|
(*regFunc)(&p);
|
|
|
|
}
|
|
|
|
}
|
2003-02-05 16:18:26 +01:00
|
|
|
|
2004-02-28 20:44:04 +01:00
|
|
|
static PluginManager *manager = 0;
|
|
|
|
#ifdef DEBUG_OBJECT_ALLOC
|
|
|
|
static MemoryPool *objectPool = 0;
|
|
|
|
void PluginManager::releaseEnginePluginManager()
|
|
|
|
{
|
|
|
|
if (manager) {
|
|
|
|
delete manager;
|
|
|
|
manager = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (objectPool) {
|
|
|
|
char name[MAXPATHLEN];
|
|
|
|
gds__prefix(name, "ObjPool.log");
|
|
|
|
FILE* file = fopen(name, "w+b");
|
|
|
|
if (file) {
|
|
|
|
fprintf(file,"Object pool allocated blocks\n");
|
|
|
|
objectPool->print_contents(file);
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2003-02-05 16:18:26 +01:00
|
|
|
PluginManager& PluginManager::getEnginePluginManager()
|
|
|
|
{
|
2004-02-28 20:44:04 +01:00
|
|
|
#ifdef DEBUG_OBJECT_ALLOC
|
|
|
|
if (! objectPool) {
|
|
|
|
objectPool = MemoryPool::createPool();
|
|
|
|
}
|
|
|
|
if (! manager) {
|
|
|
|
manager = FB_NEW(*objectPool) PluginManager(objectPool);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (! manager) {
|
|
|
|
manager = FB_NEW(*getDefaultMemoryPool())
|
|
|
|
PluginManager(getDefaultMemoryPool());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return *manager;
|
2003-02-05 16:18:26 +01:00
|
|
|
}
|