mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-25 00:43:03 +01:00
315 lines
7.8 KiB
C++
315 lines
7.8 KiB
C++
/*
|
|
* 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"
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
PluginManager::Plugin PluginManager::findPlugin(const Firebird::PathName &name)
|
|
{
|
|
for (Module *itr = moduleList; itr; itr = itr->next)
|
|
{
|
|
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
|
|
result->aquire();
|
|
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, "");
|
|
Firebird::PathName fbLibPath(fb_lib_path);
|
|
Firebird::PathName checkDir;
|
|
|
|
for (spIterator pathItr = searchPaths.begin(); pathItr != searchPaths.end(); ++pathItr)
|
|
{
|
|
if (pathItr->second) // This path is fb relative
|
|
{
|
|
PathUtils::concatPath(checkDir, fbLibPath, pathItr->first);
|
|
}
|
|
else
|
|
{
|
|
checkDir = pathItr->first;
|
|
}
|
|
|
|
PathUtils::dir_iterator *dirItr =
|
|
PathUtils::newDirItr(getPool(), checkDir);
|
|
while (*dirItr)
|
|
{
|
|
// See if we have already loaded this module
|
|
bool alreadyLoaded = false;
|
|
for (Module *itr = moduleList; itr; itr = itr->next)
|
|
{
|
|
if (itr->name() == **dirItr)
|
|
{
|
|
alreadyLoaded = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Check to see if the module has been explicitly excluded from loading
|
|
if (!alreadyLoaded && ignoreModules.getCount() > 0)
|
|
{
|
|
Firebird::PathName pathComponent, modName;
|
|
PathUtils::splitLastComponent(pathComponent, modName, **dirItr);
|
|
for (Firebird::ObjectsArray<Firebird::PathName>::iterator itr2 = ignoreModules.begin();
|
|
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))
|
|
{
|
|
Module *mod = FB_NEW(getPool()) PluginModule(getPool(), **dirItr,
|
|
ModuleLoader::loadModule(**dirItr));
|
|
if (moduleList)
|
|
{
|
|
moduleList->prev = &(mod->next);
|
|
}
|
|
mod->next = moduleList;
|
|
mod->prev = &moduleList;
|
|
moduleList = mod;
|
|
}
|
|
++(*dirItr);
|
|
}
|
|
delete dirItr;
|
|
}
|
|
}
|
|
|
|
PluginManager::Module *PluginManager::loadPluginModule(const Firebird::PathName& name)
|
|
{
|
|
char fb_lib_path[MAXPATHLEN];
|
|
gds__prefix(fb_lib_path, "");
|
|
Firebird::PathName fbLibPath(fb_lib_path);
|
|
Firebird::PathName checkPath;
|
|
|
|
// 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))
|
|
{
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
|
{
|
|
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))
|
|
{
|
|
return FB_NEW(getPool()) PluginModule(getPool(), name,
|
|
ModuleLoader::loadModule(checkPath));
|
|
}
|
|
ModuleLoader::doctorModuleExtention(checkPath);
|
|
if (ModuleLoader::isLoadableModule(checkPath))
|
|
{
|
|
return FB_NEW(getPool()) PluginModule(getPool(), checkPath,
|
|
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))
|
|
{
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
|
{
|
|
Firebird::PathName::size_type pos = 0;
|
|
Firebird::PathName::size_type checkPos;
|
|
|
|
if (itr->second) // use fb path prefix
|
|
{
|
|
checkPos = name.find(fbLibPath, pos);
|
|
if (checkPos == Firebird::PathName::npos || checkPos != pos)
|
|
continue; // The fb path prefix isn't a prefix for this module. Opps.
|
|
pos += fbLibPath.length();
|
|
}
|
|
checkPos = name.find(itr->first, pos);
|
|
if (checkPos == Firebird::PathName::npos || checkPos != pos)
|
|
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))
|
|
{
|
|
return FB_NEW(getPool()) PluginModule(getPool(), name,
|
|
ModuleLoader::loadModule(name));
|
|
}
|
|
checkPath = name;
|
|
ModuleLoader::doctorModuleExtention(checkPath);
|
|
if (ModuleLoader::isLoadableModule(checkPath))
|
|
{
|
|
return FB_NEW(getPool()) PluginModule(getPool(), checkPath,
|
|
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;
|
|
}
|
|
|
|
PluginManager::Module *PluginManager::loadBuiltinModule(const Firebird::PathName& name)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void PluginManager::addSearchPath(const Firebird::PathName& path, bool isFBRelative)
|
|
{
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
|
{
|
|
if (itr->first == path && itr->second == isFBRelative)
|
|
return;
|
|
}
|
|
|
|
searchPaths.push(Path(path, isFBRelative));
|
|
}
|
|
|
|
void PluginManager::removeSearchPath(const Firebird::PathName& path, bool isFBRelative)
|
|
{
|
|
for (spIterator itr = searchPaths.begin(); itr != searchPaths.end(); ++itr)
|
|
{
|
|
if (itr->first == path && itr->second == isFBRelative)
|
|
{
|
|
searchPaths.remove(itr);
|
|
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;
|
|
}
|
|
|
|
PluginManager::~PluginManager()
|
|
{
|
|
while (moduleList)
|
|
{
|
|
#if defined(DEV_BUILD)
|
|
if (moduleList->refCnt != 1)
|
|
{
|
|
printf("Freeing loadable module with reference count != 1: %s (%d)\n",
|
|
moduleList->module_name.c_str(), moduleList->refCnt);
|
|
}
|
|
#endif
|
|
delete moduleList;
|
|
}
|
|
}
|
|
|
|
PluginManager::Module::~Module()
|
|
{
|
|
if (next)
|
|
next->prev = prev;
|
|
*prev = next;
|
|
|
|
unload_module();
|
|
}
|
|
|
|
void *PluginManager::BuiltinModule::lookupSymbol(const Firebird::string& symbol)
|
|
{
|
|
size_t n;
|
|
if (! symbols.find(symbol, n))
|
|
return 0;
|
|
return symbols[n].second;
|
|
}
|
|
|
|
void *PluginManager::PluginModule::lookupSymbol(const Firebird::string& symbol)
|
|
{
|
|
if (module != 0)
|
|
return module->findSymbol(symbol);
|
|
return 0;
|
|
}
|
|
|
|
void PluginManager::PluginModule::unload_module()
|
|
{
|
|
if (module != 0)
|
|
delete module;
|
|
module = 0;
|
|
}
|
|
|
|
|
|
|
|
// Code that handles loading the generic firebird/plugin directory
|
|
|
|
const char *PluginManager::ENGINE_PLUGIN_DIR = "plugins";
|
|
|
|
#ifdef DARWIN
|
|
const char *PluginManager::ENGINE_PLUGIN_REGISTRATION_ENTRYPOINT = "_register_plugin";
|
|
#else
|
|
const char *PluginManager::ENGINE_PLUGIN_REGISTRATION_ENTRYPOINT = "register_plugin";
|
|
#endif
|
|
|
|
void PluginManager::load_engine_plugins()
|
|
{
|
|
enginePluginManager().addSearchPath(ENGINE_PLUGIN_DIR);
|
|
enginePluginManager().loadAllPlugins();
|
|
|
|
Firebird::string entryPoint(ENGINE_PLUGIN_REGISTRATION_ENTRYPOINT);
|
|
for (PluginManager::iterator itr = enginePluginManager().begin();
|
|
itr != enginePluginManager().end(); ++itr)
|
|
{
|
|
engineRegistrationFuncType regFunc = (engineRegistrationFuncType)
|
|
(*itr).lookupSymbol(entryPoint);
|
|
if (!regFunc)
|
|
continue;
|
|
PluginManager::Plugin p = *itr;
|
|
(*regFunc)(&p);
|
|
}
|
|
}
|
|
|
|
Firebird::InitInstance<PluginManager> PluginManager::enginePluginManager;
|