Main Page | Namespace List | Alphabetical List | Class List | Directories | File List | Class Members | File Members

ClassLoader.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   SpikeStream Simulation                                                *
00003  *   Copyright (C) 2007 by David Gamez                                     *
00004  *   david@davidgamez.eu                                                   *
00005  *   Version 0.1                                                           *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 
00023 //SpikeStream includes
00024 #include "ClassLoader.h"
00025 #include "Debug.h"
00026 #include "Utilities.h"
00027 #include "SpikeStreamSimulation.h"
00028 
00029 //Other includes
00030 #include <dlfcn.h>
00031 #include <mysql++.h>
00032 #include <iostream>
00033 using namespace std;
00034 using namespace mysqlpp;
00035 
00036 
00037 /*! Exception thrown when a neuron class library or its parameter table cannot be found. */
00038 class NeuronTypeNotFoundException : public exception{
00039         virtual const char* what() const throw(){
00040                 return "Neuron type not found.";
00041         }
00042 } neuronTypeNotFoundException;
00043 
00044 
00045 /*! Exception thrown when a synapse class library or its parameter table cannot be found. */
00046 class SynapseTypeNotFoundException : public exception{
00047         virtual const char* what() const throw(){
00048                 return "Synapse type not found.";
00049         }
00050 } synapseTypeNotFoundException;
00051 
00052 
00053 /*! Exception thrown when a synapse class library or its parameter table cannot be found. */
00054 class SpikeStreamRootNotFoundException : public exception{
00055         virtual const char* what() const throw(){
00056                 return "Environment variable SPIKESTREAM_ROOT is not defined.";
00057         }
00058 } spikestreamRootNotFoundException;
00059 
00060 
00061 /*! Constructor.*/
00062 ClassLoader::ClassLoader(DBInterface *netDBInter){
00063         //Store reference to database interface
00064         networkDBInterface = netDBInter;
00065 
00066         //Load up the classes from libraries so they can be created easily on request
00067         loadNeuronClasses();
00068         loadSynapseClasses();
00069 }
00070 
00071 
00072 /*! Destructor.*/
00073 ClassLoader::~ ClassLoader(){
00074         #ifdef MEMORY_DEBUG
00075                 cout<<"DESTROYING CLASS LOADER"<<endl;
00076         #endif//MEMORY_DEBUG            
00077 }
00078 
00079 
00080 //-----------------------------------------------------------------------
00081 //------------------------ PUBLIC METHODS -------------------------------
00082 //-----------------------------------------------------------------------
00083 
00084 /*! Returns the name of the parameter table for a given connection group.*/
00085 string ClassLoader::getConnGrpParameterTableName(unsigned int connGrpID){
00086         if(synapseParameterTableMap.count(connGrpID)){
00087                 #ifdef CLASSLOADER_DEBUG
00088                         cout<<"ClassLoader: Found synapse parameter table "<<synapseParameterTableMap[connGrpID]<<endl;
00089                 #endif//CLASSLOADER_DEBUG
00090                 return synapseParameterTableMap[connGrpID];
00091         }
00092         SpikeStreamSimulation::systemError("ClassLoader: CANNOT FIND CONNECTION GRP ID IN PARAMETER TABLE MAP", connGrpID);
00093         throw synapseTypeNotFoundException;
00094 }
00095 
00096 
00097 /*! Returns the parameter table for a given neuron type. */
00098 string ClassLoader::getNeuronParameterTableName(unsigned short neuronType){
00099         if(neuronParameterTableMap.count(neuronType)){
00100                 #ifdef CLASSLOADER_DEBUG
00101                         cout<<"ClassLoader: Found parameter table "<<neuronParameterTableMap[neuronType]<<endl;
00102                 #endif//CLASSLOADER_DEBUG
00103                 return neuronParameterTableMap[neuronType];
00104         }
00105         SpikeStreamSimulation::systemError("ClassLoader: CANNOT FIND NEURON TYPE IN PARAMETER TABLE MAP", neuronType);
00106         throw neuronTypeNotFoundException;
00107 }
00108 
00109 
00110 /*! Creates a new neuron of the specified type. */
00111 Neuron* ClassLoader::getNewNeuron(unsigned short neuronType){
00112         if(neuronFunctionMap.count(neuronType)){
00113                 Neuron* tempNeuron = neuronFunctionMap[neuronType]();
00114                 #ifdef CLASSLOADER_DEBUG
00115                         cout<<"ClassLoader: Getting new neuron of type "<<(*tempNeuron->getDescription())<<endl;
00116                 #endif//CLASSLOADER_DEBUG
00117                 return tempNeuron;
00118         }
00119         else{
00120                 SpikeStreamSimulation::systemError("ClassLoader: CANNOT FIND OR RESOLVE CLASS FOR NEURON TYPE: ", neuronType);
00121                 throw neuronTypeNotFoundException;
00122         }
00123 }
00124 
00125 
00126 /*! Creates a new synapse of the specified type. */
00127 Synapse* ClassLoader::getNewSynapse(unsigned short synapseType){
00128         if(synapseFunctionMap.count(synapseType)){
00129                 Synapse* tempSynapse = synapseFunctionMap[synapseType]();
00130                 #ifdef CLASSLOADER_DEBUG
00131                         cout<<"ClassLoader: Getting new synapse of type "<<(*tempSynapse->getDescription())<<endl;
00132                 #endif//CLASSLOADER_DEBUG
00133                 return tempSynapse;
00134         }
00135         else{
00136                 SpikeStreamSimulation::systemError("ClassLoader: CANNOT FIND OR RESOLVE CLASS FOR SYNAPSE TYPE: ", synapseType);
00137                 throw synapseTypeNotFoundException;
00138         }
00139 }
00140 
00141 
00142 //-----------------------------------------------------------------------
00143 //------------------------ PRIVATE METHODS ------------------------------
00144 //-----------------------------------------------------------------------
00145 
00146 /*! Loads all the neuron classes from libraries and stores function pointers
00147         to the method that creates them so that they can be created easily
00148         on demand. */
00149 void ClassLoader::loadNeuronClasses(){
00150         try{
00151                 Query query= networkDBInterface->getQuery();
00152                 query.reset();
00153                 query<<"SELECT TypeID, ParameterTableName, ClassLibrary FROM NeuronTypes";
00154                 Result neurTypesResult = query.store();
00155                 //Work through result and store a function pointer and the parameter table name for each neuron type
00156                 for(Result::iterator iter = neurTypesResult.begin(); iter != neurTypesResult.end(); ++iter){
00157                         Row neurTypeRow(*iter);
00158                         unsigned int neuronType = Utilities::getUShort((std::string) neurTypeRow["TypeID"]);
00159         
00160                         //Check for duplicates
00161                         if(neuronFunctionMap.count(neuronType)){
00162                                 SpikeStreamSimulation::systemError("ClassLoader: NEURON TYPE HAS ALREADY BEEN LOADED!", neuronType);
00163                                 return;
00164                         }
00165         
00166                         //Get the path to the library
00167                         char* neurLibPath_char = getenv("SPIKESTREAM_ROOT");
00168                         string neuronLibraryPath;
00169                         if(neurLibPath_char != NULL){
00170                                 neuronLibraryPath = neurLibPath_char;
00171                         }
00172                         else{
00173                                 throw spikestreamRootNotFoundException;
00174                         }
00175                         neuronLibraryPath += "/lib/";
00176                         neuronLibraryPath += (std::string)neurTypeRow["ClassLibrary"];
00177                         #ifdef CLASSLOADER_DEBUG
00178                                 cout<<"ClassLoader: Neuron library path = "<<neuronLibraryPath<<endl;
00179                         #endif//CLASSLOADER_DEBUG
00180         
00181                         //Try to open the library and get the creating neuron function
00182                         void *hndl = dlopen(neuronLibraryPath.data() , RTLD_NOW);
00183                         if(hndl == NULL){
00184                                 SpikeStreamSimulation::systemError(dlerror());
00185                                 return;
00186                         }
00187                         CreateNeuronFunctionType createNeuronFunction = (CreateNeuronFunctionType) dlsym(hndl, "getClass");
00188                         if ( createNeuronFunction ) {
00189         
00190                                 //Output neuron description in debug mode.
00191                                 #ifdef CLASSLOADER_DEBUG
00192                                         Neuron* tempNeuron = createNeuronFunction();
00193                                         cout<<"ClassLoader: Loading neuron of type "<<(*tempNeuron->getDescription())<<endl;
00194                                 #endif//CLASSLOADER_DEBUG
00195         
00196                                 //Store function in map
00197                                 neuronFunctionMap[neuronType] = createNeuronFunction;
00198                         }
00199                         else{
00200                                 SpikeStreamSimulation::systemError("ClassLoader: CANNOT FIND OR RESOLVE CLASS WHEN LOADING ALL NEURON CLASSES");
00201                                 return;
00202                         }
00203         
00204                         //Store details about parameter table
00205                         neuronParameterTableMap[neuronType] = (std::string) neurTypeRow["ParameterTableName"];
00206                         #ifdef CLASSLOADER_DEBUG
00207                                 cout<<"ClassLoader: Neuron parameter table name is "<<neuronParameterTableMap[neuronType]<<endl;
00208                         #endif//CLASSLOADER_DEBUG
00209                 }
00210         }
00211         catch (const BadQuery& er) {// Handle any query errors
00212                 ostringstream errorStrStream;
00213                 errorStrStream<<"Bad query when loading neuron classes: \""<<er.what()<<"\"";
00214                 SpikeStreamSimulation::systemError(errorStrStream.str());
00215         }
00216         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00217                 ostringstream errorStrStream;
00218                 errorStrStream<<"Exception thrown loading neuron classes: \""<<er.what()<<"\"";
00219                 SpikeStreamSimulation::systemError(errorStrStream.str());
00220         }
00221         catch(std::exception& er){// Catch-all for any other exceptions
00222                 ostringstream errorStrStream;
00223                 errorStrStream<<"Exception thrown loading neuron classes: \""<<er.what()<<"\"";
00224                 SpikeStreamSimulation::systemError(errorStrStream.str());
00225         }
00226 }
00227 
00228 
00229 /*! Loads all the synapse classes from libraries and stores function pointers
00230         to the method that creates them so that they can be created easily
00231         on demand. */
00232 void ClassLoader::loadSynapseClasses(){
00233         try{
00234                 Query query= networkDBInterface->getQuery();
00235                 query.reset();
00236                 query<<"SELECT TypeID, ParameterTableName, ClassLibrary FROM SynapseTypes";
00237                 Result synTypesResult = query.store();
00238         
00239                 //Work through result and store a function pointer and the parameter table name for each neuron type
00240                 for(Result::iterator iter = synTypesResult.begin(); iter != synTypesResult.end(); ++iter){
00241                         Row synTypeRow(*iter);
00242                         unsigned int synapseType = Utilities::getUShort((std::string) synTypeRow["TypeID"]);
00243         
00244                         //Check for duplicates
00245                         if(synapseFunctionMap.count(synapseType)){
00246                                 SpikeStreamSimulation::systemError("ClassLoader: SYNAPSE TYPE HAS ALREADY BEEN LOADED!", synapseType);
00247                                 return;
00248                         }
00249         
00250                         //Get the path to the library
00251                         string synapseLibraryPath = getenv("SPIKESTREAM_ROOT");
00252                         synapseLibraryPath += "/lib/";
00253                         synapseLibraryPath += (std::string)synTypeRow["ClassLibrary"];
00254                         #ifdef CLASSLOADER_DEBUG
00255                                 cout<<"ClassLoader: Synapse library path = "<<synapseLibraryPath<<endl;
00256                         #endif//CLASSLOADER_DEBUG
00257         
00258                         //Try to open the library and get the creating neuron function
00259                         void *hndl = dlopen(synapseLibraryPath.data() , RTLD_NOW);
00260                         if(hndl == NULL){
00261                                 SpikeStreamSimulation::systemError(dlerror());
00262                                 return;
00263                         }
00264                         CreateSynapseFunctionType createSynapseFunction = (CreateSynapseFunctionType) dlsym(hndl, "getClass");
00265                         if ( createSynapseFunction ) {
00266         
00267                                 //Output synapse description in debug mode
00268                                 #ifdef CLASSLOADER_DEBUG
00269                                         Synapse* tempSynapse = createSynapseFunction();
00270                                         cout<<"ClassLoader: Loading synapse of type "<<(*tempSynapse->getDescription())<<endl;
00271                                 #endif//CLASSLOADER_DEBUG
00272         
00273                                 //Store function in map
00274                                 synapseFunctionMap[synapseType] = createSynapseFunction;
00275                         }
00276                         else{
00277                                 SpikeStreamSimulation::systemError("ClassLoader: CANNOT FIND OR RESOLVE CLASS WHEN LOADING ALL SYNAPSE CLASSES");
00278                                 return;
00279                         }
00280         
00281                         /*Store details about parameter table. Need the name of the parameter table for a 
00282                                 particular connection group, so query each parameter table for the connection
00283                                 groups and store the name of the parameter table for each one */
00284                         query.reset();
00285                         query<<"SELECT ConnGrpID FROM "<<(std::string) synTypeRow["ParameterTableName"];
00286                         Result connGrpIDRes = query.store();
00287                         for(Result::iterator cGrpIter = connGrpIDRes.begin(); cGrpIter != connGrpIDRes.end(); ++cGrpIter){
00288                                 Row connGrpIDRow(*cGrpIter);
00289                                 unsigned int tempConnGrpID = Utilities::getUInt((std::string)connGrpIDRow["ConnGrpID"]);
00290                                 synapseParameterTableMap[tempConnGrpID] = (std::string) synTypeRow["ParameterTableName"];
00291                                 #ifdef CLASSLOADER_DEBUG
00292                                         cout<<"ClassLoader: Synapse parameter table name for ConnGrpID "<<tempConnGrpID<<" = "<<synapseParameterTableMap[tempConnGrpID]<<endl;
00293                                 #endif//CLASSLOADER_DEBUG
00294                         }
00295                 }
00296         }
00297         catch (const BadQuery& er) {// Handle any query errors
00298                 ostringstream errorStrStream;
00299                 errorStrStream<<"Bad query when loading synapse classes: \""<<er.what()<<"\"";
00300                 SpikeStreamSimulation::systemError(errorStrStream.str());
00301         }
00302         catch (const Exception& er) {// Catch-all for any other MySQL++ exceptions
00303                 ostringstream errorStrStream;
00304                 errorStrStream<<"Exception thrown loading synapse classes: \""<<er.what()<<"\"";
00305                 SpikeStreamSimulation::systemError(errorStrStream.str());
00306         }
00307         catch(std::exception& er){// Catch-all for any other exceptions
00308                 ostringstream errorStrStream;
00309                 errorStrStream<<"Exception thrown loading synapse classes: \""<<er.what()<<"\"";
00310                 SpikeStreamSimulation::systemError(errorStrStream.str());
00311         }
00312 }
00313 
00314 

Generated on Mon Sep 3 22:24:34 2007 for SpikeStream Simulation by  doxygen 1.4.4