示例#1
0
	//--------------------------------------------------------------------
	void IThread::threadStart()
	{
		// Check if we have already a thread created
		if (mThread)
		{
			NR_Log(Log::LOG_KERNEL, Log::LL_WARNING, "IThread: the appropriate thread is already running!");
			return;
		}
		NR_Log(Log::LOG_KERNEL, "IThread: Create thread and start it");

		mThread.reset(new boost::thread(boost::bind(&IThread::run, this)));
		// initialise the attribute
		/*pthread_attr_init(&mThreadAttr);

		// create the joinable attribute for thsi thread
		pthread_attr_setdetachstate(&mThreadAttr, PTHREAD_CREATE_JOINABLE);

		// setup thread scheduling attribute
		pthread_attr_setschedpolicy(&mThreadAttr, SCHED_RR);
  		
		// now create a thread and let it run
		int res = pthread_create(&mThread, &mThreadAttr, IThread::run, (void *)this);
		if (res){
			NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: creation of a thread failed with error code %d", res);
			return;
		}*/
		mThreadState = THREAD_RUNNING;
   
		mThreadState = THREAD_RUNNING;
		mThread.reset(new boost::thread(boost::bind(IThread::run, this)));
		
	}
示例#2
0
	//------------------------------------------------------------------------
	Result EventManager::emit(const std::string& name, SharedPtr<Event> event)
	{
		// Profiling of the engine
		_nrEngineProfile("EventManager.emit");


		// if user want to send the message to all channels
		if (name.length() == 0){
			NR_Log(Log::LOG_ENGINE, Log::LL_CHATTY, "EventManager: Emit event '%s' to all channels", event->getEventType());
			ChannelDatabase::iterator it = mChannelDb.begin();
			for (; it != mChannelDb.end(); it++)
				it->second->push(event);

		}else{
			NR_Log(Log::LOG_ENGINE, Log::LL_CHATTY, "EventManager: Emit event '%s' to '%s'", event->getEventType(), name.c_str());
			// get the channel according to the name and emit the message
			SharedPtr<EventChannel> channel = getChannel(name);
			if (channel == NULL)
				return EVENT_CHANNEL_NOT_EXISTS;

			channel->push(event);
		}

		// ok
		return OK;
	}
示例#3
0
	//------------------------------------------------------------------------
	Result EventManager::registerFactory(const std::string& name, SharedPtr<EventFactory> factory)
	{
		// get a factory by name
		FactoryDatabase::iterator it = mFactoryDb.find(name);
		if (it != mFactoryDb.end()){
			NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "EventManager: The event factory %s is already registered", name.c_str());
			return EVENT_FACTORY_FOUND;
		}

		NR_Log(Log::LOG_ENGINE, Log::LL_NORMAL, "EventManager: Register event factory %s", name.c_str());
		mFactoryDb[name] = factory;
		return OK;
	}
示例#4
0
文件: Engine.cpp 项目: cgart/nrEngine
	//------------------------------------------------------------------------
	bool Engine::initializeEngine()
	{
		// give some info about the underlying engine
		NR_Log(Log::LOG_ENGINE | Log::LOG_CONSOLE | Log::LOG_KERNEL, (char*)"nrEngine v%s - %s", convertVersionToString(nrEngineVersion).c_str(), NR_VERSION_NAME);

		// initialize the clock
		SharedPtr<TimeSource> timeSource(new TimeSource());

		// initialize profiler singleton
		_profiler = (new Profiler(timeSource));
		if (_profiler == NULL)
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Profiler singleton could not be created. Probably memory is full");

		// now add the clock into kernel
		_clock->setTimeSource(timeSource);
		_clock->setTaskType(TASK_SYSTEM);
		_kernel->AddTask(SharedPtr<ITask>(_clock, null_deleter()), ORDER_SYS_FIRST);

		// initialize resource manager singleton
		_event = (new EventManager());
		if (_event == NULL)
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Event manager singleton could not be created. Probably memory is full");

		_event->createChannel(NR_DEFAULT_EVENT_CHANNEL);
		_event->setTaskType(TASK_SYSTEM);
		_kernel->AddTask(SharedPtr<ITask>(_event, null_deleter()), ORDER_SYS_SECOND);

		// initialise default scripting methods
		DefaultScriptingFunctions::addMethods();

		// initialize resource manager singleton
		_resmgr = (new ResourceManager());
		if (_resmgr == NULL)
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Resource manager singleton could not be created. Probably memory is full");

		// Add the file reading functionality
		ResourceLoader fileLoader (new FileStreamLoader());
		_resmgr->registerLoader((char*)"FileStreamLoader", fileLoader);

		// create an instance of plugin loader and add it to the resource manager
		ResourceLoader loader ( new PluginLoader() );
		_resmgr->registerLoader((char*)"PluginLoader", loader);

		// create simple scripting language instancies
		ResourceLoader scriptLoader( new ScriptLoader() );
		_resmgr->registerLoader((char*)"ScriptLoader", scriptLoader);

		return true;
	}
示例#5
0
	//------------------------------------------------------------------------
	Result EventManager::removeFactory(const std::string& name)
	{
		// check if the the factory list is not empty
		if (mFactoryDb.size() == 0) return OK;

		// get a factory by name
		FactoryDatabase::iterator it = mFactoryDb.find(name);
		if (it == mFactoryDb.end()){
			NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "EventManager: The event factory %s was not found", name.c_str());
			return EVENT_FACTORY_NOT_FOUND;
		}
		NR_Log(Log::LOG_ENGINE, Log::LL_NORMAL, "EventManager: Remove event factory %s", name.c_str());
		mFactoryDb.erase(it);
		return OK;
	}
示例#6
0
文件: nr3D.cpp 项目: cgart/nrEngine
		//----------------------------------------------------------------------
		nr3D::nr3D()
		{
			// initialize default variables
			mName = "nr3D-Package";
			mFullName = "3D-Engine package for nrEngine";
			NR_Log(Log::LOG_PLUGIN, "%s: %s",mName.c_str(), mFullName.c_str());

			// check whenever engine is valid
			if (!Engine::valid())
			{
				NR_Log(Log::LOG_PLUGIN, Log::LL_ERROR, "%s: Engine must be initialized before!", mName.c_str());
				NR_EXCEPT(ENGINE_ERROR, "Engine must be initialized before creating a nr3D", "nr3D::nr3D()");
			}

			// initialize glfw task
		}
示例#7
0
文件: Plugin.cpp 项目: cgart/nrEngine
	//----------------------------------------------------------------------------------
	Result Plugin::unloadResource()
	{
		// only unload, if we are loaded
		if (isResourceLoaded())
		{
			// call the release function of the plugin
			m_plgRelease();

			// set all symbols to NULL
			m_plgInitialize = NULL;
			m_plgEngineVersion = NULL;
			m_plgVersionString = NULL;
			m_plgError = NULL;
			m_plgRelease = NULL;

			// now unload the plugin handle from memory
			if (NR_PLUGIN_UNLOAD(mPluginHandle))
			{
				NR_Log(Log::LOG_ENGINE, Log::LL_ERROR,
					"Could not unload plugin %s. System Msg: %s",
					getResourceName().c_str(), getLastPluginError().c_str());
				return PLG_UNLOAD_ERROR;
			}
	
			// set the handle to 0
			mPluginHandle = NULL;
			markResourceUnloaded();
		}

		// OK
		return OK;
	}
示例#8
0
	//------------------------------------------------------------------------
	EventManager::EventManager(){
		setTaskName("EventSystem");

		NR_Log(Log::LOG_ENGINE, "EventManager: Initialize the event management system");

		// create default system wide channel
		createChannel(NR_DEFAULT_EVENT_CHANNEL);
	}
	//----------------------------------------------------------------------------------
	size_t FileStream::readDelim(void* buf, size_t count, const ::std::string& delim)
	{
		if (!mStream) return 0;
		if (delim.empty()){
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "FileStream::readDelim(): No delimiter provided");
			return 0;
		}

		if (delim.size() > 1){
			NR_Log(Log::LOG_ENGINE, Log::LL_WARNING,
				"FileStream::readDelim(): Only first character of delimiter \"%s\" is used", delim.c_str());
		}

		// Deal with both Unix & Windows LFs
		bool trimCR = false;
		if (delim.at(0) == '\n'){
			trimCR = true;
		}

		// maxCount + 1 since count excludes terminator in getline
		mStream->getline(static_cast<char*>(buf), count+1, delim.at(0));
		size_t ret = mStream->gcount();

		if (mStream->fail()){
			// Did we fail because of maxCount hit?
			if (ret == count){
				// clear failbit for next time
				mStream->clear();
			}else{
				NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "FileStream::readDelim(): Error during reading the stream");
			}
		}

		if (!ret){
			(static_cast<char*>(buf))[1] = '\0';
		}else{
			// trim off CR if we found CR/LF
			if (trimCR && (static_cast<char*>(buf))[ret] == '\r'){
				--ret;
				(static_cast<char*>(buf))[ret+1] = '\0';
			}
		}

		return ret;
	}
示例#10
0
	//--------------------------------------------------------------------
	void Profiler::logResults(Log::LogTarget lt){

		// if the profiler is enabled
		if (!mEnabled)
			return;
		
		// sort the history so we get profiles that need more time on the top
		mProfileHistory.sort();
				
		ProfileHistoryList::iterator iter;
	
		NR_Log(lt,  "--------------------------------------Profiler Results------------------------------");
		NR_Log(lt,  "| Name                        | Avg(\%) | Max(\%) | Min(\%) | Time sec     |  Calls   |");
		NR_Log(lt,  "------------------------------------------------------------------------------------");

		// log system results
		NR_Log(lt,  "| System Profiles                                                                  |");
		for (iter = mProfileHistory.begin(); iter != mProfileHistory.end(); iter++)
		{
			// only for system profiles
			if (iter->isSystemProfile){
				// create an indent that represents the hierarchical order of the profile
				std::string indent = "   ";
				//for (uint32 i = 0; i < (*iter).hierarchicalLvl; i++)
				//	indent = indent + " --";
				indent += (*iter).name;
				indent.resize(27, ' ');
	
				logLine(indent.c_str(), iter->minTime, iter->maxTime, iter->realTime, iter->totalTime, iter->totalCalls);
			}
		}
		
		// log application results
		NR_Log(lt,  "|----------------------------------------------------------------------------------|");
		NR_Log(lt,  "| Application Profiles                                                             |");
		for (iter = mProfileHistory.begin(); iter != mProfileHistory.end(); iter++)
		{
			// only for application profiles
			if (!iter->isSystemProfile){
				// create an indent that represents the hierarchical order of the profile
				std::string indent = "   ";
				//for (uint32 i = 0; i < (*iter).hierarchicalLvl; i++)
				//	indent = indent + " --";
				indent += (*iter).name;
				indent.resize(27, ' ');
	
				logLine(indent.c_str(), iter->minTime, iter->maxTime, iter->realTime, iter->totalTime, iter->totalCalls);
			}
		}
	
		NR_Log(lt,  "|                                                                                  |");
		NR_Log(lt,  "------------------------------------------------------------------------------------");

	}
示例#11
0
文件: Engine.cpp 项目: cgart/nrEngine
	//------------------------------------------------------------------------
	bool Engine::loadPlugin(const std::string& path, const std::string& file, const std::string& name)
	{
		// check if the engine is initialized
		if (_resmgr == NULL)
		{
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, (char*)"Engine was not initialized properly");
			return false;
		}

		// try to load the resource and check for the error code
		IResourcePtr plg = _resmgr->loadResource(name, (char*)"Plugins", path + file, (char*)"Plugin");

		return true;
	}
示例#12
0
	//----------------------------------------------------------------------------------
	Property& PropertyList::operator[](const std::string& name)
	{
		// search for the key
		for (iterator it = begin(); it != end(); it++) if (it->getName() == name) return *it;

		// we could not find it, so create it and return reference
		Property p(name);
		push_back(p);

		// some debug info
		NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Property: Initialize new property '%s'", name.c_str());

		return back();
	}
示例#13
0
	//------------------------------------------------------------------------
	Result EventManager::createChannel(const std::string& name)
	{
		// check first whenever such a channel is already in the database
		if (getChannel(name)) return EVENT_CHANNEL_EXISTS;

		// channel is not in the database, so create it and fill it's data
		SharedPtr<EventChannel> channel(new EventChannel(this, name));

		// push the channel into the database
		mChannelDb[name] = channel;
		NR_Log(Log::LOG_ENGINE, "EventManager: New channel \"%s\" created", name.c_str());

		// OK
		return OK;
	}
示例#14
0
	//------------------------------------------------------------------------
	Result EventChannel::add(EventActor* actor, bool notice)
	{
		// check if actor has got a name 
		if (actor == NULL) return OK;
		if (actor->getName().length() == 0)
		{
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "EventChannel (%s): Want to connect nameless actor", getName().c_str());
			return EVENT_NO_VALID_ACTOR;
		}
		
		// we first check whenever the actor is already connected
		if (isConnected(actor->getName())) return EVENT_ALREADY_CONNECTED;

		// connect the actor to the OnEvent - Signal slot
		mActorDb[actor->getName()] = actor;

		// notice an actor that he is got a connection now
		if (notice) actor->_noticeConnected(this);

		// Log debug stuff
		NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): New actor connected \"%s\"", getName().c_str(), actor->getName().c_str());

		return OK;
	}
示例#15
0
	//--------------------------------------------------------------------
	void IThread::run(void* _mythread)
	{
		// try to cast the given parameter to IThread pointer
		IThread* mythread = static_cast<IThread*>(_mythread);
		if (mythread == NULL)
		{
			NR_Log(Log::LOG_KERNEL, Log::LL_ERROR, "IThread: not valid parameter was specified for IThread::run(void*) method");
			return;
		}
		
		// now loop the thread until some messages occurs
		bool run = true;
		while (run){

			// kernel requested to suspend the thread
			if (mythread->mThreadState == THREAD_NEXT_SUSPEND)
			{
				// notice about suspending and go into sleep mode
				mythread->changeState(THREAD_SLEEPING);
				mythread->_noticeSuspend();

			// kernel requested to resume the execution
			}else if (mythread->mThreadState == THREAD_NEXT_RESUME)
			{
				// notice about resuming the work and start it again
				mythread->changeState(THREAD_RUNNING);
				mythread->_noticeResume();

			// kernel does not requested anything, so run the task
			}else if (mythread->mThreadState == THREAD_RUNNING)
			{
				mythread->_noticeUpdate();
			}

			// check for the stop message, then stop the thread
			// this is a reading mutex, so do not have to lock it
			run = mythread->mThreadState != THREAD_STOP;

			// we now yield the used timeslice for another threads
			yield(mythread);
		}
		
		// notice to stop the underlying task
		mythread->_noticeStop();

		// exit the thread
		//return NULL;
	}
	//------------------------------------------------------------------------
	void EventChannel::_disconnectAll()
	{
		// Profiling of the engine
		_nrEngineProfile("EventChannel._disconnectAll");

		// some logging
		NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): Disconnect all actors", getName().c_str());

		// iterate through all connections and close them
		ActorDatabase::iterator it = mActorDb.begin();
		for (; it != mActorDb.end(); it++){
			mActorDb.erase(it);
			it->second->_noticeDisconnected(this);
		}

	}
	//------------------------------------------------------------------------
	Result EventChannel::del(EventActor* actor, bool notice)
	{
		// we first check whenever the actor is already connected
		if (!isConnected(actor->getName())) return EVENT_NOT_CONNECTED;

		// disconnect the actor to the OnEvent - Signal slot
		mActorDb.erase(mActorDb.find(actor->getName()));

		// notice an actor that it is disconnected now
		if (notice) actor->_noticeDisconnected(this);

		// Log debug stuff
		NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): Actor \"%s\" disconnected ", getName().c_str(), actor->getName().c_str());

		return OK;
	}
	//------------------------------------------------------------------------
	Result EventChannel::add(EventActor* actor, bool notice)
	{
		// we first check whenever the actor is already connected
		if (isConnected(actor->getName())) return EVENT_ALREADY_CONNECTED;

		// connect the actor to the OnEvent - Signal slot
		mActorDb[actor->getName()] = actor;

		// notice an actor that he is got a connection now
		if (notice) actor->_noticeConnected(this);

		// Log debug stuff
		NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "EventChannel (%s): New actor connected \"%s\"", getName().c_str(), actor->getName().c_str());

		return OK;
	}
示例#19
0
	//------------------------------------------------------------------------
	Result EventManager::removeChannel(const std::string& name)
	{
		// check first whenever such a channel is already in the database
		SharedPtr<EventChannel> channel = getChannel(name);
		if (!channel) return EVENT_CHANNEL_NOT_EXISTS;

		// disconnect all the actor from the channel
		channel->_disconnectAll();
		mChannelDb.erase(mChannelDb.find(name));

		// log info
		NR_Log(Log::LOG_ENGINE, "EventManager: Remove channel \"%s\"", name.c_str());

		// OK
		return OK;
	}
示例#20
0
	//----------------------------------------------------------------------------------
	Property& PropertyManager::getPropertyByFullname(const std::string& fullname)
	{
		// iterate through all groups
		PropertyMap::iterator it = mPropertyMap.begin();
		for (; it != mPropertyMap.end(); it++)
		{
			// search for such an element
			PropertyList::iterator jt = it->second.begin();
			for (; jt != it->second.end(); jt++)
				if (jt->getFullname() == fullname)
				{
					return *jt;
				}
		}

		// we have not found any such element, so create one
		NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "PropertyManager: Property with fullname '%s' is not registered, so create it in default group", fullname.c_str());
		return getProperty(fullname, ".");
	}
	//----------------------------------------------------------------------------------
	Result FileStream::open (const ::std::string& fileName)
	{
		// create a pointer to the stream object and open the file
		mStream.reset (new ::std::ifstream(fileName.c_str()));

		// check if the file could be found
		if (!mStream->good())
		{
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "The file \"%s\" was not found", fileName.c_str());
			return FILE_NOT_FOUND;
		}
		mResFileName = fileName;

		// calculate the size
		mStream->seekg(0, ::std::ios_base::end);
		mSize = mStream->tellg();
		mStream->seekg(0, ::std::ios_base::beg);

		return OK;
	}
示例#22
0
	//------------------------------------------------------------------------
	SharedPtr<Timer> Clock::createTimer(){
	
		// create timer as observer
		SharedPtr<ITimeObserver> timer(
					new Timer(Clock::GetSingleton()),
					null_deleter());
		
		// add him to the list
		int32 id = addObserver(timer);
		
		if (id == 0){
			NR_Log(Log::LOG_ENGINE, Log::LL_WARNING, "Clock::createTimer(): Can not add timer to the observer list");
		}
		
		// set the id of the timer
		timer->_observerID = id;
		
		// return created timer
		return ::boost::dynamic_pointer_cast<Timer, ITimeObserver>(timer);
		
	}
示例#23
0
	//----------------------------------------------------------------------------------
	Property& PropertyManager::getProperty(const std::string& name, const std::string& group)
	{
        // get list which should contain the property
        PropertyList& list = mPropertyMap[group];

        // check if such a property exists in the database
        PropertyList::iterator it = list.begin();
        for (; it != list.end(); it++) 
            if (it->getName() == name) return *it;

        // we haven't found this property hence generate new one
        Property p;
        p.mName = name;
        p.mFullname = group + std::string(".") + name;

        // some debug info
        NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Property: Initialize new property '%s.%s'", group.c_str(), name.c_str());

        // add property into the list and return the reference
        list.push_back(p);
		return list.back();
	}
示例#24
0
	//-----------------------------------------------------------------------
	void Profiler::logLine(const char* name, float32 min, float32 max, float32 frameTime, float32 totalTime, uint32 totalCalls)
	{
		// create some strings containing the statistics
		char avg[32];
		sprintf(avg, "%2.2f", (totalTime / totalCalls) * 100.0f);

		char smin[32];
		sprintf(smin, "%2.2f", min * 100.0f);

		char smax[32];
		sprintf(smax, "%2.2f", max * 100.0f);

		char tim[32];
		sprintf(tim, "%4.6f", frameTime);

		char cls[32];
		sprintf(cls, "%d", totalCalls);

		char ttm[32];
		sprintf(ttm, "%4.6f", totalTime);
		
		NR_Log(Log::LOG_APP, "| %s |  %-6s|  %-6s|  %-6s| %-13s| %-9s|", name, avg, smax, smin, tim, cls);
	}
示例#25
0
文件: Plugin.cpp 项目: cgart/nrEngine
	//----------------------------------------------------------------------------------
	Result Plugin::reloadResource(PropertyList* params)
	{
		if (!isResourceLoaded())
		{
			// get filename
			const std::string& name = getResourceFilenameList().front();
			
			// now load the library
			mPluginHandle = (PluginHandle)NR_PLUGIN_LOAD(name.c_str());

			// check whenever the library could be loaded
			if (mPluginHandle == NULL)
			{
				NR_Log(Log::LOG_ENGINE, Log::LL_ERROR,
					"Plugin %s could not be loaded! System Msg: %s",
					getResourceName().c_str(), getLastPluginError().c_str());
				return PLG_COULD_NOT_LOAD;
			}

			// force the plugin resource object to initialize itself after loading
			return initialize(params);
		}
		return OK;
	}
示例#26
0
文件: Plugin.cpp 项目: cgart/nrEngine
	//----------------------------------------------------------------------------------
	Result Plugin::initialize(PropertyList* params)
	{
		NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Check if the loaded library is valid plugin");

		// get version information
		m_plgEngineVersion = (plgEngineVersion)getSymbol("plgEngineVersion");
		m_plgVersionString = (plgVersionString)getSymbol("plgVersionString");

		if (!m_plgEngineVersion || !m_plgVersionString)
		{
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin seems not to be written for the nrEngine");
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "plgVersionString/plgEngineVersion symbols were not found!!!");
			return PLG_SYMBOL_NOT_FOUND;
		}

		// Log this
		NR_Log(Log::LOG_ENGINE, "Plugin found: %s written for nrEngine v%s", m_plgVersionString(), convertVersionToString(m_plgEngineVersion()).c_str());

		// check if plugin is working with the current engine version
		if (m_plgEngineVersion() > nrEngineVersion){
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin has got greater version as the engine, so plugin not loaded");
			return PLG_WRONG_VERSION;
		}

		// log something
		NR_Log(Log::LOG_PLUGIN, "Initialize plugin %s", getResourceName().c_str());

#define GET_SYMBOL(var, type)\
		{\
			NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Get plugin symbol %s", #type);\
			var = (type)getSymbol(#type);\
			if (!var){\
				NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin symbol %s was not found", #type);\
				return PLG_SYMBOL_NOT_FOUND;\
			}\
		}

		// Get plugin symbols
		GET_SYMBOL(m_plgInitialize, plgInitialize);
		GET_SYMBOL(m_plgError, plgError);
		GET_SYMBOL(m_plgRelease, plgRelease);
#undef GET_SYMBOL

		// call the function and check for return code
		int result = m_plgInitialize(Engine::instance(), params);

		// check for error
		if (result != 0){
			NR_Log(Log::LOG_ENGINE, Log::LL_ERROR, "Plugin returns error %d (%s). See plugin log for more detail information", result, m_plgError(result));
			return PLG_EXTERNAL_ERROR;
		}

		// now get some extra symbols
		/*m_plgGetMethods = (plgGetMethods)getSymbol("plgGetMethods");
		m_plgCall = (plgCall)getSymbol("plgCall");

		if (m_plgGetMethods){

			// get the list of methods provided by this plugin
			m_plgGetMethods(mPlgMethods);

			NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "Plugin provides following symbols: ");

			// now go through each of this method and print some log info about it
			for (uint32 i=0; i < mPlgMethods.size(); i++){
				std::string params;				
				for (uint32 j=0; j < mPlgMethods[i].param.size(); j++){
					params += mPlgMethods[i].param[j].name;
					if (j < mPlgMethods[i].param.size() - 1) params += ", ";
				}
				NR_Log(Log::LOG_ENGINE, Log::LL_DEBUG, "  found  -  %s (%s)", mPlgMethods[i].name.c_str(), params.c_str());
			}		
		}*/
		
		// all right!
		return OK;
	}