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

pacanows's avatar
pacanows committed
5
#ifdef _WIN32
6
    #include <windows.h>
7 8 9
#else
    #include <dlfcn.h>
#endif
10
#include <stdio.h>
11 12 13 14 15 16

//! \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)
{
pacanows's avatar
pacanows committed
17
#ifdef _WIN32
18
    HINSTANCE handle = LoadLibraryA(filename.c_str());
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
    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;
    }
39
#else
40 41 42
    void* handle = dlopen(filename.c_str(), RTLD_GLOBAL | RTLD_LAZY);
    
	 if(handle != NULL)
43 44 45
	 {
		 void (*res)();
		 *(void **)(&res) = dlsym(handle, function);
46 47 48 49 50 51 52 53 54 55 56 57 58 59

        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;
60
		  std::cerr << "          cause: \"" << dlerror() << "\"" << std::endl;
61 62 63 64 65
        return NULL;
    }
#endif
}

66 67 68 69 70 71 72 73
//! \brief load a function from the ALTA input file.
function* plugins_manager::get_function(const std::string& filename)
{
	std::ifstream file;
	file.open(filename.c_str()) ;
	if(!file.is_open())
	{
		std::cerr << "<<ERROR>> unable to open file \"" << filename << "\"" << std::endl ;
74
		return NULL;
75 76
	}

77 78 79
	// Set the precision of the input
	file.precision(10);

80 81
	// Parameters of the function object
	int nX, nY;
82 83
	params::input param_in   = params::UNKNOWN_INPUT; 
	params::output param_out = params::UNKNOWN_OUTPUT;
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
	arguments args;

	// Test for the first line of the file. Should be a ALTA FUNC HEADER
	std::string line ;
	std::getline(file, line) ;
	if(line != "#ALTA FUNC HEADER")
	{
		std::cerr << "<<ERROR>> this is not a function file" << std::endl;
	}

	// Parse the header for the function command line and the dimension
	// of the function
	while(line != "#ALTA HEADER END")
	{
		std::getline(file, line) ;
		std::stringstream linestream(line) ;

		linestream.ignore(1) ;

		std::string comment ;
		linestream >> comment ;

		if(comment == std::string("DIM"))
		{
			linestream >> nX >> nY ;
109 110 111 112 113 114 115 116 117 118 119 120 121
		}
		else if(comment == std::string("PARAM_IN"))
		{
			std::string name;
			linestream >> name;
			std::cout << "<<DEBUG>> parsed input parametrization: " << name << std::endl;
			param_in = params::parse_input(name);
		}
		else if(comment == std::string("PARAM_OUT"))
		{
			std::string name;
			linestream >> name;
			param_out = params::parse_output(name);
122 123
		}
		else if(comment == std::string("CMD"))
124
      {
125 126 127 128 129 130 131 132
			args = arguments::create_arguments(line.substr(4, std::string::npos));
		}
	}

	// Create the function from the command line
	function* f = get_function(args);
	f->setDimX(nX);
	f->setDimY(nY);
Laurent Belcour's avatar
Laurent Belcour committed
133 134 135 136
    if(f->input_parametrization() == params::UNKNOWN_INPUT)
    {
        f->setParametrization(param_in);
    }
137
	f->setParametrization(param_out);
138 139

	// Load the function part from the file object
140
    f->load(file);
141 142 143 144

	return f;
}

145 146 147
//! Get an instance of the function selected based on the name <em>n</em>.
//! Return NULL if no one exist.
function* plugins_manager::get_function(const arguments& args)
148
{
149
    if(!args.is_defined("func"))
150 151 152 153 154 155 156
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no function plugin specified, returning a rational function" << std::endl;
#endif
        return new rational_function();
    }

157 158
    // The function to be returned.
    function* func = NULL;
Laurent Belcour's avatar
Laurent Belcour committed
159

160
    if(args.is_vec("func"))
161
    {
162 163 164 165 166 167 168 169
        std::vector<std::string> args_vec = args.get_vec("func");

        // Treating the case []
        if(args_vec.size() == 0)
        {
            return NULL;
        }

170
        //! create a <em>compound</em> class to store multiple
171
        //! functions in it.
172 173
		  compound_function* compound = new compound_function();
	
174 175 176 177 178 179
          //! For each args_vec element, create a function object and add
          //! it to the compound one.
          for(unsigned int i=0; i<args_vec.size(); ++i)
          {
              std::string n("--func ");
              n.append(args_vec[i]);
180 181 182
#ifdef DEBUG
              std::cout << "<<DEBUG>> load function with args: " << n << std::endl;
#endif
183 184 185 186 187 188 189 190
              arguments temp_args = arguments::create_arguments(n);
              function* f = get_function(temp_args);
              if(dynamic_cast<nonlinear_function*>(f) == NULL)
              {
                  std::cerr << "<<ERROR>> only non-linear function care compatible with a compound" << std::endl;
              }
              else
              {
191
                  compound->push_back(dynamic_cast<nonlinear_function*>(f), temp_args);
192 193
              }
          }
194

195 196
		  //! return the compound class
		  func = compound;
197 198 199
    }
    else
    {
200
        const std::string filename = args["func"];
201 202 203 204 205
        FunctionPrototype myFunction = open_library<FunctionPrototype>(filename, "provide_function");
        if(myFunction != NULL)
        {
#ifdef DEBUG
            std::cout << "<<DEBUG>> using function provider in file \"" << filename << "\"" << std::endl;
206
#endif
207
            func =  myFunction();
208 209 210 211 212 213
        }
        else
        {
            std::cerr << "<<ERROR>> no function provider found in file \"" << filename << "\"" << std::endl;
            return new rational_function() ;
        }
214 215
    }

216 217 218
    // Treat the case of the Fresnel
    if(args.is_defined("fresnel"))
    {
219 220 221 222 223 224 225 226
		 // Cast into a non linear function, only those are permitted to use
		 // a Fresnel term.
		 nonlinear_function* nl_func = dynamic_cast<nonlinear_function*>(func);
		 if(nl_func == NULL)
		 {
			 std::cerr << "<<ERROR>> only non-linear function are permitted to use Fresnel" << std::endl;
			 return func;
		 }
227

228
		 std::cout << "<<DEBUG>> multiplying by a Fresnel term" << std::endl;
229

230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
		 std::string n("--func ");
		 if(args.is_vec("fresnel"))
		 {
			 std::string temp = args["fresnel"];
			 n.append(temp.substr(1, temp.size()-2));
		 }
		 else
		 {
			 std::string fname = args["fresnel"];
			 if(fname.empty()) // Nothing to do except print error, no plugin defined
			 {
				 std::cerr << "<<ERROR>> Fresnel plugin not defined" << std::endl;
				 std::cerr << "<<ERROR>> using --fresnel alone is not permitted" << std::endl;
				 return func;
			 }
			 else // Case where the fresnel parameters is only the plugin filename
			 {
				 n.append(fname);
			 }
		 }

251
		 nonlinear_function* func_fres = dynamic_cast<nonlinear_function*>(get_function(arguments::create_arguments(n)));
252 253 254 255 256 257 258 259 260
		 if(func_fres != NULL)
		 {
			return new product_function(nl_func, func_fres);
		 }
		 else
		 {
			 std::cerr << "<<ERROR>> the right part of the product is not a nonlinear function. Will use only the left part." << std::endl;
			 return func;
		 }
261

262
	 }
263
/*
264 265 266 267 268 269 270
	 // Correction of the data by 1/cosine(theta_L)
	 if(args.is_defined("data-correct-cosine"))
	 {
		 nonlinear_function* cosine = new cosine_function();
		 func = new product_function(cosine, dynamic_cast<nonlinear_function*>(func));
	 }
	 // End of correction
271
*/			
272
    return func;
273
}
274
ptr<data> plugins_manager::get_data(const std::string& n)
275
{
276 277
    if(n.empty())
    {
278
#ifdef DEBUG
279
        std::cout << "<<DEBUG>> no data plugin specified, returning a vertial_segment loader" << std::endl;
280
#endif
281 282 283
        return new vertical_segment();
    }

284
	 DataPrototype myData = open_library<DataPrototype>(n, "provide_data");
285 286
    if(myData != NULL)
    {
287
#ifdef DEBUG
288 289 290 291 292 293 294 295 296
        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() ;
    }
297
}
298
ptr<fitter> plugins_manager::get_fitter(const std::string& n)
299
{
Laurent Belcour's avatar
Laurent Belcour committed
300 301 302 303 304
    if(n.empty())
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> no fitter plugin specified, returning null" << std::endl;
#endif
305
        return ptr<NULL>;
Laurent Belcour's avatar
Laurent Belcour committed
306 307
    }

308
    FitterPrototype myFitter = open_library<FitterPrototype>(n, "provide_fitter");
Laurent Belcour's avatar
Laurent Belcour committed
309 310 311 312 313
    if(myFitter != NULL)
    {
#ifdef DEBUG
        std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
314
        return ptr<myFitter()>;
Laurent Belcour's avatar
Laurent Belcour committed
315 316 317
    }
    else
    {
318
        std::cerr << "<<ERROR>> no fitter provider found in file \"" << n << "\"" << std::endl;
319
        return ptr<NULL> ;
Laurent Belcour's avatar
Laurent Belcour committed
320
    }
321
}
322

323
void plugins_manager::check_compatibility(ptr<data>& d, function*& f,
324
                                          const arguments& args)
Laurent Belcour's avatar
Laurent Belcour committed
325
{
326 327
	if(d->input_parametrization() == params::UNKNOWN_INPUT &&
		f->input_parametrization() == params::UNKNOWN_INPUT)
Laurent Belcour's avatar
Laurent Belcour committed
328
	{
329
		std::cout << "<<WARNING>> both function and data objects have no parametrization" << std::endl;
Laurent Belcour's avatar
Laurent Belcour committed
330 331 332
	}
	else
	{
333 334 335 336 337 338 339 340 341 342
		if(d->input_parametrization() == params::UNKNOWN_INPUT)
		{
			std::cout << "<<WARNING>> unknown parametrization for data" << std::endl;
		}

		if(f->input_parametrization() == params::UNKNOWN_INPUT)
		{
			std::cout << "<<DEBUG>> function will take the parametrization of the data" << std::endl;
			f->setParametrization(d->input_parametrization());
		}
343
		else if(d->input_parametrization() != f->input_parametrization() && args.is_defined("change-param"))
344
		{
345
			std::cout << "<<INFO>> has to change the parametrization of the input data " << params::get_name(d->input_parametrization()) << std::endl;
346
            std::cout << "<<INFO>> to " << params::get_name(f->input_parametrization()) << std::endl;
347 348 349 350 351 352 353
			data_params* dd = new data_params(d, f->input_parametrization());
			d = dd ;
		}
		else
		{
			std::cout << "<<DEBUG>> no change was made to the parametrization" << std::endl;
		}
Laurent Belcour's avatar
Laurent Belcour committed
354 355 356 357
	}

	if(f->dimY() != d->dimY())
	{
Laurent Belcour's avatar
Laurent Belcour committed
358
        f->setDimY(d->dimY());
Laurent Belcour's avatar
Laurent Belcour committed
359 360 361 362 363 364 365 366 367 368 369
	}

	/*
	// Check is the data has to be clusterized
	if(args.is_defined("cluster-dim"))
	{
	clustering* cluster = new clustering(d, args);
	d = cluster;
	}
	*/
}
370 371 372 373
		
// \todo implement the Darwin (MACOS) version.
#ifdef WIN32
#include <windows.h>
374
size_t plugins_manager::get_system_memory()
375 376 377 378 379 380
{
	MEMORYSTATUSEX status;
	status.dwLength = sizeof(status);
	GlobalMemoryStatusEx(&status);
	return status.ullTotalPhys;
}
381 382 383 384 385
#elif __APPLE__
size_t plugins_manager::get_system_memory()
{
	return 0;
}
386 387
#else
#include <unistd.h>
388
size_t plugins_manager::get_system_memory()
389 390 391 392 393 394
{
	long pages = sysconf(_SC_PHYS_PAGES);
	long page_size = sysconf(_SC_PAGE_SIZE);
	return pages * page_size;
}
#endif