plugins_manager.cpp 9.56 KB
Newer Older
1
#include "plugins_manager.h"
2 3
#include "rational_function.h"
#include "vertical_segment.h"
4

5
/*
6
#include <QCoreApplication>
7
#include <QDir>
8
*/
9 10

#ifdef WIN32
11
    #include <windows.h>
12 13 14
#else
    #include <dlfcn.h>
#endif
15
#include <stdio.h>
16 17 18 19 20 21 22

//! \brief Open a dynamic library file (.so or .dll) and extract the associated
//! provide function. The template argument is used to cast the library to a
//! specific type.
template<typename T> T open_library(const std::string& filename, const char* function)
{
#ifdef WIN32
23
    HINSTANCE handle = LoadLibraryA(filename.c_str());
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
    if(handle != NULL)
    {
        T res = (T)GetProcAddress(handle, function);

        if(res == NULL)
        {
            std::cerr << "<<ERROR>> unable to load the symbol \"" << function << "\" from " << filename << std::endl;
            return NULL;
        }
#ifdef DEBUG_CORE
        std::cout << "<<DEBUG>> will provide a " << function << " for library \"" << filename << "\"" << std::endl;
#endif
        return res;
    }
    else
    {
        std::cerr << "<<ERROR>> unable to load the dynamic library file \"" << filename << "\"" << std::endl;
        std::cerr << "          cause: \"" << GetLastError() << "\"" << std::endl;
        return NULL;
    }
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#else
    void* handle = dlopen(filename.c_str(), RTLD_LAZY);
    if(handle != NULL)
    {
        void* res = dlsym(handle, function);

        if(dlerror() != NULL)
        {
            std::cerr << "<<ERROR>> unable to load the symbol \"" << function << "\" from " << filename << std::endl;
            return NULL;
        }
#ifdef DEBUG_CORE
        std::cout << "<<DEBUG>> will provide a " << function << " for library \"" << filename << "\"" << std::endl;
#endif
        return (T)res;
    }
    else
    {
        std::cerr << "<<ERROR>> unable to load the dynamic library file \"" << filename << "\"" << std::endl;
63
		  std::cerr << "          cause: \"" << dlerror() << "\"" << std::endl;
64 65 66 67 68 69 70
        return NULL;
    }
#endif
}


// Create the object, parse the argument and load all the plugins
71 72
plugins_manager::plugins_manager(const arguments& args) 
{
73
/*
74 75 76 77 78 79 80 81 82
	QDir pluginsDir;
	if(args.is_defined("plugins"))
	{
		pluginsDir = QDir(args["plugins"].c_str()) ;
	}
	else if(QCoreApplication::instance() != NULL)
	{
		pluginsDir = QDir(QCoreApplication::instance()->applicationDirPath());
	}
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
	foreach (QString fileName, pluginsDir.entryList(QDir::Files)) 
	{
		QPluginLoader loader ;
		loader.setLoadHints(QLibrary::ExportExternalSymbolsHint) ;
		loader.setFileName(pluginsDir.absoluteFilePath(fileName));
		
		// Convert filename for outputing		
		std::string filename(fileName.toStdString()) ;

		if(!loader.load())
		{
#ifdef DEBUG
			std::cout << "<<DEBUG>> " << loader.errorString().toStdString() << std::endl ;
#endif
			continue ;
		}

		QObject *plugin = loader.instance();
		if (plugin != NULL) 
		{
#ifdef DEBUG
			std::cout << "<<DEBUG>> loading plugin " << filename << std::endl ;
#endif
			if(dynamic_cast<function*>(plugin) != NULL)
			{
#ifdef DEBUG
				std::cout << "<<DEBUG>>  -> it is a function" << std::endl ;
#endif
				_functions.insert(std::pair<std::string, function*>(filename, dynamic_cast<function*>(plugin))) ;
			}
			
			if(dynamic_cast<data*>(plugin) != NULL)
			{
#ifdef DEBUG
				std::cout << "<<DEBUG>>  -> it is a data loader" << std::endl ;
#endif
				_datas.insert(std::pair<std::string, data*>(filename, dynamic_cast<data*>(plugin))) ;
			}
			if(dynamic_cast<fitter*>(plugin) != NULL)
			{
#ifdef DEBUG
				std::cout << "<<DEBUG>>  -> it is a fitter" << std::endl ;
#endif
				_fitters.insert(std::pair<std::string, fitter*>(filename, dynamic_cast<fitter*>(plugin))) ;
			}
		}
		else
		{
#ifdef DEBUG
			std::cout << "<<DEBUG>> " << loader.errorString().toStdString() << std::endl ;
#endif
		}
	}
139
	*/
140 141 142 143 144
}

// Get instances of the function, the data and the
// fitter
//
145
function* plugins_manager::get_function()
146
{
147 148 149 150
#ifdef USING_STATIC
    return new rational_function() ;
#else
    if(_functions.empty())
151
	{
152
		return new rational_function() ;
153 154 155 156 157
	}
	else
	{
		return _functions.begin()->second ;
	}
158 159
#endif

160
}
161
data* plugins_manager::get_data()
162
{
Laurent Belcour's avatar
Laurent Belcour committed
163
	//if(_datas.empty())
164
	{
165 166 167
#ifdef DEBUG
        std::cout << "<<DEBUG>>  using vertical segment data loader" << std::endl ;
#endif
168
		return new vertical_segment() ;
Laurent Belcour's avatar
Laurent Belcour committed
169
	}/*
170 171
	else
	{
172
#ifdef DEBUG
173
		std::cout << "<<DEBUG>>  using \"" << _datas.begin()->first << "\" data loader" << std::endl ;
174
#endif
175
		return _datas.begin()->second ;
Laurent Belcour's avatar
Laurent Belcour committed
176
	}*/
177
}
178
fitter* plugins_manager::get_fitter()
179
{
180 181 182
#ifdef USING_STATIC
    return NULL;
#else
183 184 185 186 187 188
	if(_fitters.empty())
	{
		return NULL ;
	}
	else
	{
189
#ifdef DEBUG
190
		std::cout << "<<DEBUG>>  using \"" <<  _fitters.begin()->first << "\"" << std::endl ;
191
#endif
192 193
		return _fitters.begin()->second ;
	}
194
#endif
195 196 197 198 199 200
}

// Get instances of the function, the data and the
// fitter, select one based on the name. Return null
// if no one exist.
//
201
function* plugins_manager::get_function(const std::string& n)
202
{
203 204 205 206 207 208 209 210
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no function plugin specified, returning a rational function" << std::endl;
#endif
        return new rational_function();
    }

211
#ifdef USING_STATIC
212
	 /*
Laurent Belcour's avatar
Laurent Belcour committed
213 214 215 216 217 218 219 220 221 222 223
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
224 225
	 
	 FunctionPrototype myFunction = open_library<FunctionPrototype>(path.toStdString(), "provide_function");
226 227
	 */
	 FunctionPrototype myFunction = open_library<FunctionPrototype>(n, "provide_function");
228 229 230 231 232 233 234 235 236 237 238 239 240 241
    if(myFunction != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myFunction();
    }
    else
    {
        std::cerr << "<<ERROR>> no function provider found in file \"" << n << "\"" << std::endl;
        return new rational_function() ;
    }
#else

242
	if(_functions.count(n) == 0)
243
	{
244
		return new rational_function() ;
245 246 247
	}
	else
	{
Laurent Belcour's avatar
Laurent Belcour committed
248
		return _functions.find(n)->second ;
249
	}
250
#endif
251
}
252
data* plugins_manager::get_data(const std::string& n)
253
{
254 255
    if(n.empty())
    {
256
#ifdef DEBUG
257
        std::cout << "<<DEBUG>> no data plugin specified, returning a vertial_segment loader" << std::endl;
258
#endif
259 260 261 262
        return new vertical_segment();
    }

#ifdef USING_STATIC
263
	 /*
Laurent Belcour's avatar
Laurent Belcour committed
264 265 266 267 268 269 270 271 272 273 274
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
275 276
	 
	 DataPrototype myData = open_library<DataPrototype>(path.toStdString(), "provide_data");
277 278
	 */
	 DataPrototype myData = open_library<DataPrototype>(n, "provide_data");
279 280
    if(myData != NULL)
    {
281
#ifdef DEBUG
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myData();
    }
    else
    {
        std::cerr << "<<ERROR>> no data provider found in file \"" << n << "\"" << std::endl;
        return new vertical_segment() ;
    }
#else

    if(_functions.count(n) == 0)
    {
        return new vertical_segment() ;
    }
    else
    {
        return _datas.find(n)->second ;
    }
301
#endif
302
}
303
fitter* plugins_manager::get_fitter(const std::string& n)
304
{
Laurent Belcour's avatar
Laurent Belcour committed
305 306 307 308 309 310 311 312
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no fitter plugin specified, returning null" << std::endl;
#endif
        return NULL;
    }

313
#ifdef USING_STATIC
314
/*
Laurent Belcour's avatar
Laurent Belcour committed
315 316 317 318 319 320 321 322 323 324 325
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
326 327
    
	 FitterPrototype myFitter = open_library<FitterPrototype>(path.toStdString(), "provide_fitter");
328 329
*/
	 FitterPrototype myFitter = open_library<FitterPrototype>(n, "provide_fitter");
Laurent Belcour's avatar
Laurent Belcour committed
330 331 332 333 334 335 336 337 338
    if(myFitter != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myFitter();
    }
    else
    {
339 340
        std::cerr << "<<ERROR>> no fitter provider found in file \"" << n << "\"" << std::endl;
        return NULL ;
Laurent Belcour's avatar
Laurent Belcour committed
341 342
    }
#else
343
	if(_fitters.count(n) == 0)
344 345 346 347 348
	{
		return NULL ;
	}
	else
	{
349
#ifdef DEBUG
350
		std::cout << "<<DEBUG>>  using \"" <<  n << "\"" << std::endl ;
351
#endif
Laurent Belcour's avatar
Laurent Belcour committed
352
		return _fitters.find(n)->second ;
353
	}
Laurent Belcour's avatar
Laurent Belcour committed
354
#endif
355
}
Laurent Belcour's avatar
Laurent Belcour committed
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
void plugins_manager::check_compatibility(data*& d, function*& f,
                                          const arguments& args)
{
	if(d->parametrization() == params::UNKNOWN_INPUT)
	{
		std::cout << "<<WARNING>> unknown parametrization for data" << std::endl;
	}

	if(f->parametrization() == params::UNKNOWN_INPUT)
	{
		std::cout << "<<DEBUG>> function will take the parametrization of the data" << std::endl;
		f->setParametrization(d->parametrization());
	}
	else if(d->parametrization() != f->parametrization())
	{
		std::cout << "<<INFO>> has to change the parametrization of the input data" << std::endl;
		data_params* dd = new data_params(d, f->parametrization());
		d = dd ;
	}
	else
	{
		std::cout << "<<DEBUG>> no change was made to the parametrization" << std::endl;
	}

	if(f->dimY() != d->dimY())
	{
		std::cout << "<<WARNING>> the data and the function have different Y dimensions" << std::endl;
	}

	/*
	// Check is the data has to be clusterized
	if(args.is_defined("cluster-dim"))
	{
	clustering* cluster = new clustering(d, args);
	d = cluster;
	}
	*/
}
394 395 396 397
		
// \todo implement the Darwin (MACOS) version.
#ifdef WIN32
#include <windows.h>
398
size_t plugins_manager::get_system_memory()
399 400 401 402 403 404 405 406
{
	MEMORYSTATUSEX status;
	status.dwLength = sizeof(status);
	GlobalMemoryStatusEx(&status);
	return status.ullTotalPhys;
}
#else
#include <unistd.h>
407
size_t plugins_manager::get_system_memory()
408 409 410 411 412 413
{
	long pages = sysconf(_SC_PHYS_PAGES);
	long page_size = sysconf(_SC_PAGE_SIZE);
	return pages * page_size;
}
#endif