GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

GATLoader.c

Go to the documentation of this file.
00001 /** @file GATLoader.c
00002  * Main file for the GATLoader class.
00003  * 
00004  * A GATLoader is responsible for loading and maintaining a list of
00005  * adaptors.
00006  * 
00007  * @date Thu Sep 18 2003
00008  * 
00009  * @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATLoader.c,v 1.23 2004/04/22 10:25:05 hartmutkaiser Exp $
00010  *
00011  *  Copyright (C) Tom Goodale
00012  *  This file is part of the GAT Engine.
00013  *  Contributed by Tom Goodale <goodale@aei.mpg.de>.
00014  *
00015  *  Use, modification and distribution is subject to the Gridlab Software
00016  *  License. (See accompanying file GLlicense.txt or copy at
00017  *  http://www.gridlab.org/GLlicense.txt)
00018  */
00019 
00020 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATLoader.c,v 1.23 2004/04/22 10:25:05 hartmutkaiser Exp $";
00021 
00022 /* System Header Files */
00023 
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <ctype.h>
00028 
00029 /* GAT Header Files */
00030 
00031 #include "GATUtil.h"
00032 #include "GATLoader.h"
00033 
00034 #include "GATErrors.h"
00035 #include "GATTestUtils.h"
00036 
00037 #include "ltdl/ltdl.h"
00038 #include "uuid.h"
00039 
00040 /* Macros */
00041 #define REGISTRATION_SUFFIX     "_register"
00042 
00043 /* Structures, unions and enums */
00044 struct AdaptorInstance
00045 {
00046   struct AdaptorInstance *next;
00047   char *path;
00048   char *name;
00049   char *nickname;
00050   lt_dlhandle handle;
00051 };
00052 
00053 struct GATLoader_S
00054 {
00055   struct AdaptorInstance *list;
00056 };
00057 
00058 /* Static function prototypes */
00059 
00060 static struct AdaptorInstance *
00061 AdaptorInstance_Create(const char *path, const char *name, const char *nickname);
00062 
00063 static char *
00064 CanonicaliseName(const char *original);
00065 
00066 static void 
00067 AdaptorInstance_Destroy(struct AdaptorInstance *this);
00068 
00069 static GATResult 
00070 LoadAdaptor(GATContext error_context, struct AdaptorInstance *instance, 
00071   GATRegistry registry, GATTable_const system_config, 
00072   GATTable_const instance_config);
00073 
00074 /* File scope variables */
00075 
00076 /* External functions */
00077 
00078 /** GATLoader_Create
00079  *  The  GATLoader constructor.
00080  *  This is the constructor for GATLoader objects.
00081  *
00082  * @return A new GATLoader
00083  */
00084 GATLoader GATLoader_Create(void)
00085 {
00086   GATLoader this;
00087 
00088   this = (GATLoader)malloc(sizeof(*this));
00089 
00090   if(this)
00091   {
00092     lt_dlinit();
00093 
00094     this->list = NULL;
00095   }
00096 
00097   return this;
00098 }
00099 
00100 /** GATLoader_Destroy
00101  *  The GATLoader destructor.
00102  *  This is the destructor for GATLoader objects.
00103  *
00104  * @param this An old GATLoader
00105  */
00106 void GATLoader_Destroy(GATLoader *this)
00107 {
00108   if(NULL != this && NULL != *this)
00109   {
00110     struct AdaptorInstance *adaptor = (*this)->list;
00111 
00112     lt_dlexit();
00113     
00114     /* free all AdaptorInstance's */
00115     while (NULL != adaptor)
00116     {
00117       struct AdaptorInstance *next = adaptor;
00118       adaptor = adaptor->next;
00119       AdaptorInstance_Destroy(next);
00120     }
00121     
00122     free(*this);
00123     *this = NULL;
00124   }
00125 }
00126 
00127 /** GATLoader_LoadAdaptor
00128  *  Loads a given adaptor.
00129  *  Given a path, load the adaptor pointed to there, 
00130  *  invoking its registration function and passing that
00131  *  both a system and an instance configuration tables.
00132  *  Each adaptor may be given a nickname, which is 
00133  *  otherwise extracted from the file part of the
00134  *  path.  All nicknames must be unique.
00135  *
00136  *  @param this The loader object.
00137  *  @param registry The registry the adaptor should register its CPIs with.
00138  *  @param system_config The system configuration table.
00139  *  @param instance_config The configuration table for this instance.
00140  *  @param path The path to the adaptor file.
00141  *  @param name The name of the adaptor.
00142  *  @param nickname The name the loader should know this adaptor instance as.
00143  *
00144  * @return An error code.
00145  */
00146 GATResult 
00147 GATLoader_LoadAdaptor(GATLoader this, GATContext error_context, 
00148   GATRegistry registry, GATTable_const system_config, 
00149   GATTable_const instance_config, const char *path, const char *name, 
00150   const char *nickname)
00151 {
00152   GAT_USES_STATUS(error_context, "GATLoader_LoadAdaptor");
00153   
00154   struct AdaptorInstance *last = NULL;
00155   struct AdaptorInstance *instance = 
00156     AdaptorInstance_Create(path, name, nickname);
00157 
00158   if (NULL != instance)
00159   {
00160     /* Check for duplication */
00161     struct AdaptorInstance *current = NULL;
00162     for(current = this->list; NULL != current; 
00163         last = current, current = current->next)
00164     {
00165       if (!strcmp(current->nickname, instance->nickname))
00166       {
00167         GAT_CREATE_STATUS(GAT_DUPLICATE_ADAPTOR);
00168       }
00169     }
00170   }
00171   else
00172   {
00173     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00174   }
00175 
00176   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00177   {
00178     /* Ok, try to load it */
00179     instance->handle = lt_dlopenext(instance->path);
00180 
00181     if (NULL != instance->handle)
00182     {
00183       GAT_CREATE_STATUS(LoadAdaptor(error_context, instance, registry, 
00184         system_config, instance_config));
00185     }
00186     else
00187     {
00188       GAT_CREATE_STATUS_MSG(GAT_FAILED_TO_LOAD_ADAPTOR, instance->path);
00189     }
00190   }
00191 
00192   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00193   {
00194     /* Everything worked, so add it to the list */
00195     if (NULL != last)
00196     {
00197       last->next = instance;
00198     }
00199     else
00200     {
00201       this->list = instance;
00202     }
00203   }
00204   else
00205   {
00206     AdaptorInstance_Destroy(instance);
00207   }
00208 
00209   return GAT_RETURN_STATUS();
00210 }
00211 
00212 /* Local functions */
00213 
00214 /** AdaptorInstance_Create
00215  *  Creates an adaptor structure.
00216  *  The loader stores details of adaptors internally;
00217  *  this function initialises a structure to hold this info.
00218  *
00219  * @param path The adaptor path.
00220  * @param name The adaptor's name.
00221  * @param nickname The adaptor's nickname.
00222  *
00223  * @return A new AdaptorInstance.
00224  */
00225 static struct AdaptorInstance *
00226 AdaptorInstance_Create(const char *path, const char *name, const char *nickname)
00227 {
00228   
00229   struct AdaptorInstance *this;
00230 
00231   /* Create a new element for the adaptor list */
00232   this = (struct AdaptorInstance *)malloc(sizeof(*this));
00233 
00234   if(this)
00235   {
00236     this->next = NULL;
00237     
00238     this->path = GATUtil_strdup(path);
00239 
00240     if(!name)
00241     {
00242       this->name = CanonicaliseName(path);
00243     }
00244     else
00245     {
00246       this->name = GATUtil_strdup(name);
00247     }
00248       
00249     if(!nickname)
00250     {
00251       this->nickname = GATUtil_strdup(this->name);
00252     }
00253     else
00254     {
00255       this->nickname = GATUtil_strdup(nickname);
00256     }
00257 
00258     if(! this->path || ! this->name || ! this->nickname)
00259     {
00260       free(this->path);
00261       free(this->name);
00262       free(this->nickname);
00263       free(this);
00264       this = NULL;
00265     }
00266 
00267   }
00268 
00269   return this;
00270 }
00271 
00272 /** AdaptorInstance_Destroy
00273  *  Destroys an adaptor structure.
00274  *  The loader stores details of adaptors internally;
00275  *  this function destroys a structure holding this info.
00276  *
00277  * @param this An AdaptorInstance to be destroyed.
00278  */
00279 static void 
00280 AdaptorInstance_Destroy(struct AdaptorInstance *object)
00281 {
00282   if(NULL != object)
00283   {
00284     free(object->path);
00285     free(object->name);
00286     free(object->nickname);
00287 
00288 /* the following was freed already by the ltdl library
00289     if(this->handle)
00290     {
00291       lt_dlclose(this->handle);
00292     }
00293 */
00294     free(object);
00295   }
00296 }
00297 
00298 /** CanonicaliseName
00299  *  Extract the canonical name of an adaptor from its full path name.
00300  *  We need the name of the adaptor in order to invoke its 
00301  *  registration function.  CanonicaliseName takes the path
00302  *  to an adaptor and extracts the base filename from it.
00303  *  Additionally, if it is a libtool library, it removes the "lib"
00304  *  prefix which libtool insists on having.
00305  *
00306  * @param input The path to an adaptor file.
00307  *
00308  * @return A canonoical name for the adaptor.
00309  */
00310 static char *
00311 CanonicaliseName(const char *original)
00312 {
00313   char *retval;
00314   const char *start;
00315   const char *end;
00316   char *pos;
00317 
00318   /* Find filename part of name */
00319   start = strrchr(original, '/');
00320 
00321   if(!start)
00322   {
00323     start = original;
00324   }
00325   else
00326   {
00327     start++;
00328   }
00329 
00330   /* Scan forward and end at any character not in [a-zA-Z0-9_-] */
00331 
00332   for(end = start; 
00333       *end && (isalnum(*end) || *end == '_' || *end == '-'); 
00334       end++)
00335   {
00336     /* Do nothing */
00337   }
00338 
00339   if(!strcmp(end,".la"))
00340   {
00341     /* It's a libtool library, which insists on having lib as
00342      * first three chars.
00343      */
00344     if(start[0] == 'l' && start[1] == 'i' && start[2] == 'b')
00345     {
00346       start += 3;
00347     }
00348   }
00349 
00350   /* Allocate memory */
00351   retval = (char *)malloc(end-start + 1);
00352 
00353   if(retval)
00354   {
00355     /* Copy data */
00356     for(pos = retval; start < end ; start++, pos++)
00357     {
00358       *pos = *start;
00359     }
00360 
00361     *pos = 0;
00362   }
00363 
00364   return retval;
00365 }
00366 
00367 /** LoadAdaptor
00368  *  Loads a given adaptor.
00369  *  Given an AdaptorInstance, invokes its registration function and passes that
00370  *  both a system and an instance configuration tables.
00371  *
00372  * @param instance The AdaptorInstance holding data about the adaptor.
00373  * @param registry The registry the adaptor should register its CPIs with.
00374  * @param system_config The system configuration table.
00375  * @param instance_config The configuration table for this instance.
00376  *
00377  * @return An error code.
00378  */
00379 static GATResult 
00380 LoadAdaptor (GATContext error_context, struct AdaptorInstance *instance, 
00381   GATRegistry registry, GATTable_const system_config, 
00382   GATTable_const instance_config)
00383 {
00384   GAT_USES_STATUS(error_context, "LoadAdaptor");
00385 
00386   typedef GATResult (*registrationproc_t)(GATContext, GATRegistry, 
00387     GATTable_const, GATTable_const, void *);
00388 
00389   registrationproc_t func = NULL;
00390   
00391   char *funcname = (char *)malloc(strlen(instance->name) + 
00392     sizeof(REGISTRATION_SUFFIX) + 1);
00393   if (NULL != funcname)
00394   {
00395     /* try to find old entry point */
00396     sprintf (funcname, "%s%s", instance->name, REGISTRATION_SUFFIX);
00397     func = (registrationproc_t)lt_dlsym (instance->handle, funcname);
00398     if (NULL != func)
00399     {
00400       GAT_CREATE_STATUS(func(error_context, registry, system_config, 
00401         instance_config, instance->nickname));
00402     }
00403     else
00404     {
00405       GAT_CREATE_STATUS(GAT_NO_ADAPTOR_REGISTRATION_FUNC);
00406 //        GAT_DEBUG ("could not load adaptor\n");
00407     }
00408     free (funcname);
00409   }
00410   else
00411   {
00412     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00413 //    GAT_DEBUG ("Mem-Failure\n");
00414   }
00415 
00416   /* TODO: sometimes, no error seems to get issued on adaptor load
00417    * failure - needs fix.  -- Andre. */
00418   {
00419     char buffer[256];
00420     snprintf (buffer, sizeof(buffer), "Loading adaptor %s", instance->nickname);
00421 
00422     GAT_TEST_START (buffer);
00423     GAT_TEST_TRACE (GAT_SUCCEEDED(GAT_CURRENT_STATUS()), error_context);
00424     GAT_TEST_STOP  ();
00425   }
00426 
00427   return GAT_RETURN_STATUS();
00428 }
00429