GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATRequest.c

Go to the documentation of this file.
00001 /** @file GATRequest.c
00002  *  Source file for the GATRequest class.
00003  *
00004  *  A GATRequest represents an information or command request coming from
00005  *  another process.
00006  *
00007  *  @date Fri Jan 30 2004
00008  *
00009  *  @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATRequest.c,v 1.9 2004/04/20 12:33:22 hartmutkaiser Exp $
00010  *
00011  *  Copyright (C) Hartmut Kaiser
00012  *  This file is part of the GAT Engine.
00013  *  Contributed by Hartmut Kaiser <hartmutkaiser [at] t-online [dot] 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/GATRequest.c,v 1.9 2004/04/20 12:33:22 hartmutkaiser Exp $";
00021  
00022 /* System Header objects */
00023 #include <stdlib.h>
00024 #include <string.h>
00025 #include <assert.h>
00026 
00027 /* GAT Header objects */
00028 #include "GAT.h"
00029 #include "GATInternal.h"
00030 #include "GATUtil.h"
00031 #include "GATRegistry.h"
00032 #include "GATInternal.h"
00033 #include "GATRequestCPI.h"
00034 
00035 /* define the vtable types */
00036 GATOBJECT_DEFINE_VTABLE(GATRequest);
00037 
00038 /* define the converters to/from GATObject */
00039 GATOBJECT_DEFINE_CONVERTERS(GATRequest)
00040 
00041 /* Macros */
00042 
00043 /* Structures, unions and enums */
00044 struct GATRequest_S {
00045   /* supported interfaces */
00046   GATRequest_vtable *GATObject__vtable;
00047 
00048   /* instance data */
00049   GATRequestCPI_Instance data; /* instance data of the corresponding CPI object */
00050   GATRequestCPI cpi;         /* CPI object to use for all subsequent operations */
00051   GATRequestCPIList cpilist; /* CPI list of appropriate CPI objects */
00052 };
00053 
00054 /* Static function prototypes */
00055 
00056 static GATResult
00057 GATRequest_GetCPIInstanceData(GATRequest object, void **data);
00058 
00059 
00060 /* file scope variables */
00061 GATRequest_vtable GATRequest__vtable = {
00062   GATRequest_GetType,
00063   GATRequest_Destroy,
00064   GATRequest_Equals,
00065   GATRequest_Clone,
00066   GATRequest_GetInterface,
00067   GATRequest_GetCPIInstanceData
00068 };
00069 
00070 /* External functions */
00071 
00072 /** GATRequest_Create
00073  *  @brief Create a new GATRequest object
00074  *
00075  *  The function @c GATRequest_internal_Create creates a new 
00076  *  GATRequest object
00077  *
00078  *  @param context The GAT context to use while the initialisation of the 
00079  *        new object.
00080  *  @param preferences The preferences to use while selecting the adaptor for 
00081  *        the corresponding CPI.
00082  *
00083  *  @return Returns a handle to the newly created GATRequest object.
00084  *        Returns 0 (zero) if an error occurs.
00085  */
00086 GATRequest 
00087 GATRequest_Create(GATContext context, GATPreferences_const preferences, 
00088   GATRequestListener listener, void *client_contextdata, GATRequestType type, 
00089   GATTable_const parameters, char const *request_name, 
00090   void *initialisation_data)
00091 {
00092   GAT_STATUS_APIENTRY(context, "GATRequest_Create");
00093   
00094   GATRequest new_request = (GATRequest) malloc(sizeof(struct GATRequest_S));
00095   if (NULL != new_request)
00096   {
00097     memset(new_request, 0, sizeof(struct GATRequest_S));
00098     new_request->GATObject__vtable = &GATRequest__vtable;
00099 
00100     new_request->data.context = context;
00101     new_request->data.type = type;
00102     new_request->data.listener = listener;
00103     new_request->data.client_contextdata = client_contextdata;
00104     new_request->data.source = new_request;
00105     new_request->data.request_name = GATUtil_strdup(request_name);
00106     
00107     if (NULL == new_request->data.request_name)
00108     {
00109       GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00110     }
00111     if (NULL != parameters)
00112     {
00113       GAT_CREATE_STATUS(GATTable_Clone(parameters, &new_request->data.parameters));
00114     }
00115     
00116     /* find a CPI object, which can handle this object */
00117     if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00118     {
00119       GATRegistry_const registry = GATContext_internal_GetRegistry(context);
00120       
00121       if (NULL == preferences)
00122       {
00123         preferences = GATContext_GetPreferences(context);
00124       }
00125       new_request->cpilist = GATRegistry_FindGATRequestCPI(registry, preferences);
00126       
00127       if (NULL == new_request->cpilist)
00128       {
00129         GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00130       }
00131       else 
00132       {
00133         /* create a new instance of the CPI provider */
00134         GATBool found_cpi = GATFalse;
00135         GATRequestCPIList current = NULL;
00136         for(current = new_request->cpilist; NULL != current; current = current->next)
00137         {
00138           GAT_CREATE_STATUS(GATRequestCPI_CreateInstance(current->cpi, 
00139             &new_request->data, initialisation_data));
00140           if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00141           {
00142             new_request->cpi = current->cpi;
00143             found_cpi = GATTrue;
00144             break;
00145           }
00146         }
00147 
00148         /* no available CPI object can handle this */
00149         if (GATFalse == found_cpi)
00150         {
00151           GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00152         }
00153         else
00154         {
00155           /* register this object with the engine */
00156           GAT_CREATE_STATUS(GATRegistry_AddGATRequestToCPIList(context, 
00157             new_request->cpi, new_request));
00158         }
00159       }
00160     }
00161     else
00162     {
00163       GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00164     }
00165   }
00166   
00167   /* error handling */
00168   if (GAT_FAILED(GAT_CURRENT_STATUS()))
00169   {
00170     /* FIXME: GATStatus(err_code) */
00171     GATRequest_Destroy(&new_request);
00172   }
00173   
00174   GAT_STORE_STATUS();
00175   return new_request;
00176 }
00177 
00178 /** void GATRequest_Destroy(GATRequest *resource)
00179  *
00180  *  The function GATRequest_Destroy is the destructor used to
00181  *  free all the memory allocated by an GATRequest instance.
00182  *
00183  *  @param description The pointer to the GATRequest to destroy
00184  */
00185 void
00186 GATRequest_Destroy(GATRequest *object)
00187 {
00188   if (NULL != object && NULL != *object)
00189   {
00190     GATTable_Destroy(&(*object)->data.parameters);
00191     GATRequestNotifier_Destroy((GATRequestNotifier *)&(*object)->data.notifier);
00192     free((*object)->data.request_name);
00193     if (NULL != (*object)->cpi)  /* during creation this may be zero */
00194     {
00195       GATRegistry_RemoveGATRequestFromCPIList((*object)->data.context, 
00196         (*object)->cpi, *object);
00197       GATRequestCPI_DestroyInstance((*object)->cpi, &(*object)->data);
00198     }
00199     GATRequestCPIList_Destroy((*object)->cpilist);
00200     free(*object);
00201     *object = NULL;
00202   }
00203 }
00204 
00205 /** GATRequest_Equals
00206  *  @brief Compare two GATRequest objects
00207  *
00208  *  The function @c GATRequest_Equals compares two objects of the
00209  *  @c GATRequest type.
00210  *
00211  *  @param lhs The first list to compare
00212  *  @param rhs The second list to compare
00213  *  @param isequal The pointer to the GATBool variable, which should receive 
00214  *        the result if the comparision
00215  *
00216  *  @return An error code.
00217  */
00218 GATResult 
00219 GATRequest_Equals(GATRequest_const lhs,
00220   GATRequest_const rhs, GATBool *isequal)
00221 {
00222   if (NULL != lhs && NULL != rhs)
00223   {
00224     GAT_STATUS_APIENTRY(lhs->data.context, "GATRequest_Equals");
00225     
00226     if (NULL != isequal)
00227     {
00228       *isequal = (!strcmp(lhs->data.request_name, rhs->data.request_name) &&
00229           (lhs->data.type == rhs->data.type)) ? 
00230         GATTrue : GATFalse;
00231       
00232       if (GATTrue == *isequal)
00233       {
00234         GAT_CREATE_STATUS(GATRequestCPI_EqualsInstance(lhs->cpi, &lhs->data, 
00235           &rhs->data, isequal));
00236       }
00237     }
00238     else
00239     {
00240       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00241     }
00242 
00243     return GAT_RETURN_STATUS();
00244   }
00245   return GAT_INVALID_HANDLE;
00246 }
00247 
00248 /** GATRequest_Clone
00249  *  @brief Clone the given GATRequest
00250  *
00251  *  The function @c GATRequest_Clone generates a (deep) copy of 
00252  *  the given GATRequest. 
00253  *
00254  *  @param description The object to clone
00255  *  @param new_object The pointer, through which the result is to be 
00256  *        returned.
00257  *
00258  *  @return An error type.
00259  */
00260 GATResult 
00261 GATRequest_Clone(GATRequest_const handle, GATRequest *new_handle)
00262 {
00263   if (NULL != handle)
00264   {
00265     GAT_STATUS_APIENTRY(handle->data.context, "GATRequest_Clone");
00266     
00267     if (NULL == new_handle)
00268     {
00269       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00270     }
00271     else
00272     {
00273       struct GATRequest_S const *object = handle;
00274       GATRequest new_object = (GATRequest) malloc(sizeof(struct GATRequest_S));
00275       
00276       *new_handle = NULL;
00277       if (NULL == new_object)
00278       {
00279         GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00280       }
00281       else
00282       {
00283         memset(new_object, 0, sizeof(struct GATRequest_S));
00284         new_object->GATObject__vtable = &GATRequest__vtable;
00285 
00286         new_object->data.context = object->data.context;
00287         new_object->data.type = object->data.type;
00288         new_object->data.listener = object->data.listener;
00289         new_object->data.client_contextdata = object->data.client_contextdata;
00290         new_object->data.source = new_object;
00291         new_object->data.request_name = GATUtil_strdup(object->data.request_name);
00292         GAT_CREATE_STATUS_IF(NULL == new_object->data.request_name, GAT_MEMORYFAILURE);
00293         
00294         new_object->cpilist = GATRegistry_CloneGATRequestCPIList(object->cpilist);
00295         if (NULL == new_object->cpilist)
00296         {
00297           GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00298         }
00299         else
00300         {
00301           /* re-find the cpi to use */
00302           GATRequestCPIList current = object->cpilist;
00303           GATRequestCPIList new_current = new_object->cpilist;
00304           
00305           for (/**/; NULL != current; 
00306                current = current->next, new_current = new_current->next)
00307           {
00308             if (current->cpi == object->cpi)
00309             {
00310               new_object->cpi = new_current->cpi;
00311               break;
00312             }
00313           }
00314           assert(NULL != new_object->cpi);
00315           
00316           /* clone the instance data */
00317           GAT_CREATE_STATUS(GATRequestCPI_CloneInstance(object->cpi, &object->data, 
00318             &new_object->data));
00319 
00320           GAT_CREATE_STATUS(GATRegistry_AddGATRequestToCPIList(new_object->data.context, 
00321             new_object->cpi, new_object));
00322          }
00323        }
00324 
00325       /* destroy the newly allocated object, if some error occured */
00326       if (GAT_FAILED(GAT_CURRENT_STATUS()))
00327       {
00328         GATRequest_Destroy(&new_object);
00329       }
00330       else
00331       {
00332         /* return the new object */
00333         *new_handle = new_object;
00334       }
00335     }
00336     
00337     return GAT_RETURN_STATUS();
00338   }
00339   return GAT_INVALID_HANDLE;
00340 }
00341 
00342 /** GATType GATRequest_GetType(GATRequest_const resource)
00343  *  @brief Return the type of the GATRequest
00344  *
00345  *  The function @c GATRequest_GetType always returns 
00346  *  @c #GATType_GATRequest. 
00347  *
00348  *  @param object The object to inspect
00349  *
00350  *  @return Returns always @c #GATType_GATRequest. 
00351  */
00352 GATType
00353 GATRequest_GetType(GATRequest_const object)
00354 {
00355   GAT_UNUSED_PARAMETER(object);
00356   return GATType_GATRequest;
00357 }
00358 
00359 /** GATResult GATRequest_GetInterface(GATRequest_const file, GATInterface iftype, void const **ifp)
00360  *  @brief Get an interface supported by a GATObject
00361  *
00362  *  The function GATRequest_GetInterface allows to get a pointer to an 
00363  *  additional interface supported by this GATRequest.
00364  *
00365  *  @param object The object to be asked for the new interface.
00366  *  @param iftype The interface the object is to be asked for.
00367  *  @param ifp The pointer, through which the result is to be returned.
00368  *
00369  *  @return An error type.
00370  */
00371 GATResult 
00372 GATRequest_GetInterface(GATRequest_const object, GATInterface iftype, 
00373   void const **ifp)
00374 {
00375   if (NULL != object)
00376   {
00377     GAT_STATUS_APIENTRY(object->data.context, "GATRequest_GetInterface");
00378     
00379     if (NULL != ifp)
00380     {
00381       *ifp = NULL;
00382       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00383     }
00384     else
00385     {
00386       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00387     }
00388 
00389     return GAT_RETURN_STATUS();
00390   }
00391   return GAT_INVALID_HANDLE;
00392 }
00393 
00394 /** GATRequest_GetRequestNotifier
00395  *  
00396  *  The functions GATRequest_GetRequestNotifier gets the GATRequestNotifier 
00397  *  associated with this GATRequest.
00398  *
00399  *  @param request The GATRequest object to query for its request name.
00400  *  @param The pointer to a variable, which should receive the returned
00401  *        request notifier associated with this GATRequest object.
00402  *
00403  *  @return An error code.
00404  */
00405 GATResult 
00406 GATRequest_GetRequestNotifier(GATRequest_const request,
00407   GATRequestNotifier_const *notifier_to_return)
00408 {
00409   if (NULL != request)
00410   {
00411     GAT_USES_STATUS(request->data.context, "GATRequest_GetRequestNotifier");
00412     
00413     GATRequestNotifier_const notifier = request->data.notifier;
00414     if (NULL == notifier)
00415     {
00416       GAT_CREATE_STATUS(GATRequestCPI_InitRequestNotifier(request->cpi, 
00417         &request->data, &notifier));
00418     }
00419     
00420     if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00421     {
00422       if (NULL != notifier_to_return)
00423       {
00424         if (NULL == request->data.notifier)
00425         {
00426           ((GATRequest)request)->data.notifier = notifier;
00427         }
00428         *notifier_to_return = notifier;
00429       }
00430       else
00431       {
00432         if (NULL == request->data.notifier)
00433         {
00434           GATRequestNotifier_Destroy((GATRequestNotifier *)&notifier);
00435         }
00436         GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00437       }
00438     }
00439     
00440     return GAT_RETURN_STATUS();
00441   }
00442   return GAT_INVALID_HANDLE;
00443 }
00444   
00445 /** GATRequest_GetRequestName
00446  *  
00447  *  The functions GATRequest_GetRequestName gets the GATRequest name associated 
00448  *  with this GATRequest.
00449  *
00450  *  @param request The GATRequest object to query for its request name.
00451  *
00452  *  @return The request name or 0 (zero) if an error occurs.
00453  */
00454 char const *
00455 GATRequest_GetRequestName(GATRequest_const request)
00456 {
00457   char const *retval = NULL;
00458   if (NULL != request)
00459   {
00460     retval = request->data.request_name;
00461   }
00462   return retval;
00463 }  
00464 
00465 /** GATRequest_IssueCommand
00466  *  
00467  *  The function GATRequest_IssueCommand is to be called by an adaptor to issue
00468  *  the command or query for the information, which corresponds to this 
00469  *  GATRequest.
00470  *
00471  *  @param request The request object, for which the command should be issued 
00472  *        or the information is to be queried.
00473  *
00474  *  @return An error code.
00475  */
00476 GATResult
00477 GATRequest_IssueCommand(GATRequest_const request)
00478 {
00479   if (NULL != request)
00480   {
00481     GAT_USES_STATUS(request->data.context, "GATRequest_IssueCommand");
00482     GAT_CREATE_STATUS(request->data.listener(request->data.client_contextdata, 
00483       request));
00484     return GAT_RETURN_STATUS();
00485   }
00486   return GAT_INVALID_HANDLE;
00487 }
00488 
00489 /* Local functions */
00490 
00491 /*  GATRequest_GetCPIInstanceData
00492  *  
00493  *  The function GATRequest_GetCPIInstanceData returns the CPI instance data, 
00494  *  associated with the given GATRequest object.
00495  *
00496  *  @param object The object, for which to return the CPI instance data.
00497  *  @param data The pointer to the variable, which should receive the
00498  *        resulting CPI instance data.
00499  *
00500  *  @return An error code.
00501  */
00502 static GATResult
00503 GATRequest_GetCPIInstanceData(GATRequest object, void **data)
00504 {
00505   if (NULL != object)
00506   {
00507     GAT_USES_STATUS(object->data.context, "GATRequest_GetCPIInstanceData");
00508     if (NULL != data)
00509     {
00510       *data = (void *)&object->data;
00511     }
00512     else
00513     {
00514       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00515     }
00516     
00517     return GAT_RETURN_STATUS();
00518   }
00519   return GAT_INVALID_HANDLE;
00520 }
00521 
00522