plugins_manager.cpp 8.84 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 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

#ifdef WIN32
#else
    #include <stdio.h>
    #include <dlfcn.h>
#endif

//! \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
    return NULL;
#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;
42
		  std::cerr << "          cause: \"" << dlerror() << "\"" << std::endl;
43 44 45 46 47 48 49
        return NULL;
    }
#endif
}


// Create the object, parse the argument and load all the plugins
50 51
plugins_manager::plugins_manager(const arguments& args) 
{
52
/*
53 54 55 56 57 58 59 60 61
	QDir pluginsDir;
	if(args.is_defined("plugins"))
	{
		pluginsDir = QDir(args["plugins"].c_str()) ;
	}
	else if(QCoreApplication::instance() != NULL)
	{
		pluginsDir = QDir(QCoreApplication::instance()->applicationDirPath());
	}
62
	*/
63

64
	/*
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 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
	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
		}
	}
118
	*/
119 120 121 122 123
}

// Get instances of the function, the data and the
// fitter
//
124
function* plugins_manager::get_function()
125
{
126 127 128 129
#ifdef USING_STATIC
    return new rational_function() ;
#else
    if(_functions.empty())
130
	{
131
		return new rational_function() ;
132 133 134 135 136
	}
	else
	{
		return _functions.begin()->second ;
	}
137 138
#endif

139
}
140
data* plugins_manager::get_data()
141
{
Laurent Belcour's avatar
Laurent Belcour committed
142
	//if(_datas.empty())
143
	{
144 145 146
#ifdef DEBUG
        std::cout << "<<DEBUG>>  using vertical segment data loader" << std::endl ;
#endif
147
		return new vertical_segment() ;
Laurent Belcour's avatar
Laurent Belcour committed
148
	}/*
149 150
	else
	{
151
#ifdef DEBUG
152
		std::cout << "<<DEBUG>>  using \"" << _datas.begin()->first << "\" data loader" << std::endl ;
153
#endif
154
		return _datas.begin()->second ;
Laurent Belcour's avatar
Laurent Belcour committed
155
	}*/
156
}
157
fitter* plugins_manager::get_fitter()
158
{
159 160 161
#ifdef USING_STATIC
    return NULL;
#else
162 163 164 165 166 167
	if(_fitters.empty())
	{
		return NULL ;
	}
	else
	{
168
#ifdef DEBUG
169
		std::cout << "<<DEBUG>>  using \"" <<  _fitters.begin()->first << "\"" << std::endl ;
170
#endif
171 172
		return _fitters.begin()->second ;
	}
173
#endif
174 175 176 177 178 179
}

// Get instances of the function, the data and the
// fitter, select one based on the name. Return null
// if no one exist.
//
180
function* plugins_manager::get_function(const std::string& n)
181
{
182 183 184 185 186 187 188 189
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no function plugin specified, returning a rational function" << std::endl;
#endif
        return new rational_function();
    }

190
#ifdef USING_STATIC
191
	 /*
Laurent Belcour's avatar
Laurent Belcour committed
192 193 194 195 196 197 198 199 200 201 202
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
203 204
	 
	 FunctionPrototype myFunction = open_library<FunctionPrototype>(path.toStdString(), "provide_function");
205 206
	 */
	 FunctionPrototype myFunction = open_library<FunctionPrototype>(n, "provide_function");
207 208 209 210 211 212 213 214 215 216 217 218 219 220
    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

221
	if(_functions.count(n) == 0)
222
	{
223
		return new rational_function() ;
224 225 226
	}
	else
	{
Laurent Belcour's avatar
Laurent Belcour committed
227
		return _functions.find(n)->second ;
228
	}
229
#endif
230
}
231
data* plugins_manager::get_data(const std::string& n)
232
{
233 234
    if(n.empty())
    {
235
#ifdef DEBUG
236
        std::cout << "<<DEBUG>> no data plugin specified, returning a vertial_segment loader" << std::endl;
237
#endif
238 239 240 241
        return new vertical_segment();
    }

#ifdef USING_STATIC
242
	 /*
Laurent Belcour's avatar
Laurent Belcour committed
243 244 245 246 247 248 249 250 251 252 253
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
254 255
	 
	 DataPrototype myData = open_library<DataPrototype>(path.toStdString(), "provide_data");
256 257
	 */
	 DataPrototype myData = open_library<DataPrototype>(n, "provide_data");
258 259
    if(myData != NULL)
    {
260
#ifdef DEBUG
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
        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 ;
    }
280
#endif
281
}
282
fitter* plugins_manager::get_fitter(const std::string& n)
283
{
Laurent Belcour's avatar
Laurent Belcour committed
284 285 286 287 288 289 290 291
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no fitter plugin specified, returning null" << std::endl;
#endif
        return NULL;
    }

292
#ifdef USING_STATIC
293
/*
Laurent Belcour's avatar
Laurent Belcour committed
294 295 296 297 298 299 300 301 302 303 304
	 std::string file;
	 if(n[0] == '.')
	 {
		 file = n.substr(1, n.size()-1);
	 }
	 else
	 {
		 file = n;
	 }

    QString path = QDir::currentPath() + QString(file.c_str()) ;
305 306
    
	 FitterPrototype myFitter = open_library<FitterPrototype>(path.toStdString(), "provide_fitter");
307 308
*/
	 FitterPrototype myFitter = open_library<FitterPrototype>(n, "provide_fitter");
Laurent Belcour's avatar
Laurent Belcour committed
309 310 311 312 313 314 315 316 317
    if(myFitter != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
        return myFitter();
    }
    else
    {
318 319
        std::cerr << "<<ERROR>> no fitter provider found in file \"" << n << "\"" << std::endl;
        return NULL ;
Laurent Belcour's avatar
Laurent Belcour committed
320 321
    }
#else
322
	if(_fitters.count(n) == 0)
323 324 325 326 327
	{
		return NULL ;
	}
	else
	{
328
#ifdef DEBUG
329
		std::cout << "<<DEBUG>>  using \"" <<  n << "\"" << std::endl ;
330
#endif
Laurent Belcour's avatar
Laurent Belcour committed
331
		return _fitters.find(n)->second ;
332
	}
Laurent Belcour's avatar
Laurent Belcour committed
333
#endif
334
}
Laurent Belcour's avatar
Laurent Belcour committed
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
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;
	}
	*/
}
373 374 375 376
		
// \todo implement the Darwin (MACOS) version.
#ifdef WIN32
#include <windows.h>
377
size_t plugins_manager::get_system_memory()
378 379 380 381 382 383 384 385
{
	MEMORYSTATUSEX status;
	status.dwLength = sizeof(status);
	GlobalMemoryStatusEx(&status);
	return status.ullTotalPhys;
}
#else
#include <unistd.h>
386
size_t plugins_manager::get_system_memory()
387 388 389 390 391 392
{
	long pages = sysconf(_SC_PHYS_PAGES);
	long page_size = sysconf(_SC_PAGE_SIZE);
	return pages * page_size;
}
#endif