GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATResourceBroker.c

Go to the documentation of this file.
00001 /** @file GATResourceBroker.c
00002  *  Source file for the GATResourceBroker class.
00003  *
00004  *  An instance of this class is used to broker Resources. A resource can 
00005  *  either be a node or a component.
00006  *
00007  *  @date Thu Oct 23 2003
00008  *
00009  *  @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATResourceBroker.c,v 1.18 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/GATResourceBroker.c,v 1.18 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 "GATRegistry.h"
00031 #include "GATResourceBrokerCPI.h"
00032 
00033 /* 
00034  *  Define the type specific interface functions for the GATList_GATResource 
00035  *  list 
00036  */
00037 GATLIST_IMPLEMENT(extern, GATResource, GATList_GATResource, 
00038   GATType_GATResource);
00039 
00040 /* define the vtable types */
00041 GATOBJECT_DEFINE_VTABLE(GATResourceBroker);
00042 
00043 /* define the converters to/from GATObject */
00044 GATOBJECT_DEFINE_CONVERTERS(GATResourceBroker)
00045 
00046 /* Macros */
00047 
00048 /* Structures, unions and enums */
00049 struct GATResourceBroker_S {
00050   /* supported interfaces */
00051   GATResourceBroker_vtable *GATObject__vtable;
00052 
00053   /* instance data */
00054   GATResourceBrokerCPI_Instance data; /* instance data of the corresponding CPI object */
00055   GATResourceBrokerCPI cpi;         /* CPI object to use for all subsequent operations */
00056   GATResourceBrokerCPIList cpilist; /* CPI list of appropriate CPI objects */
00057 };
00058 
00059 /* Static function prototypes */
00060 static GATResult
00061 GATResourceBroker_GetCPIInstanceData(GATResourceBroker object, void **data);
00062 
00063 static GATResult 
00064 GATResourceBroker_SetJobEnvironment(GATResourceBroker broker,
00065   GATJobDescription description, GATJobID_const gatjobid);
00066 
00067 /* file scope variables */
00068 GATResourceBroker_vtable GATResourceBroker__vtable = {
00069   GATResourceBroker_GetType,
00070   GATResourceBroker_Destroy,
00071   GATResourceBroker_Equals,
00072   GATResourceBroker_Clone,
00073   GATResourceBroker_GetInterface,
00074   GATResourceBroker_GetCPIInstanceData
00075 };
00076 
00077 /* External functions */
00078 
00079 /** GATResourceBroker_Create
00080  *  @brief Create a new GATResourceBroker object
00081  *
00082  *  The function @c GATResourceBroker_Create creates a new 
00083  *  GATResourceBroker object
00084  *
00085  *  @param context The GAT context to use while the initialisation of the 
00086  *        new object.
00087  *  @param preferences The preferences to use while selecting the adaptor for 
00088  *        the corresponding CPI.
00089  *
00090  *  @return Returns a handle to the newly created GATResourceBroker object.
00091  *        Returns 0 (zero) if an error occurs.
00092  */
00093 GATResourceBroker 
00094 GATResourceBroker_Create(GATContext context, GATPreferences_const preferences,
00095   GATString vo_name)
00096 {
00097   GATResult err_code = GAT_MEMORYFAILURE;
00098   GATResourceBroker retval = (GATResourceBroker) malloc(
00099     sizeof(struct GATResourceBroker_S));
00100       
00101   if (NULL != retval)
00102   {
00103     memset(retval, 0, sizeof(struct GATResourceBroker_S));
00104     retval->GATObject__vtable = &GATResourceBroker__vtable;
00105 
00106     retval->data.context = context;
00107 
00108     /* the name of the virtual organisation to use is optional */
00109     if (NULL != vo_name)
00110     {
00111       err_code = GATString_Clone(vo_name, &retval->data.vo_name);
00112     }
00113     else
00114     {
00115       err_code = GAT_SUCCESS;
00116     }
00117 
00118     /* find a CPI object, which can handle this object */
00119     if (GAT_SUCCEEDED(err_code))
00120     {
00121       GATBool found_cpi = GATFalse;
00122       GATResourceBrokerCPIList current = NULL;
00123       GATRegistry_const registry = GATContext_internal_GetRegistry(context);
00124       
00125       /* use default preferences, if appropriate */
00126       if (NULL == preferences)
00127       {
00128         preferences = GATContext_GetPreferences(context);
00129       }
00130       retval->cpilist = GATRegistry_FindGATResourceBrokerCPI(registry, preferences);
00131       if (NULL == retval->cpilist)
00132       {
00133         GATResourceBroker_Destroy(&retval);
00134         err_code = GAT_NO_REGISTERED_CPI;
00135       }
00136       else 
00137       {
00138         /* create a new instance of the CPI provider */
00139         err_code = GAT_NO_MATCHING_CPI;
00140         for(current = retval->cpilist; NULL != current; current = current->next)
00141         {
00142           err_code = GATResourceBrokerCPI_CreateInstance(current->cpi, 
00143             &retval->data);
00144             
00145           if (GAT_SUCCESS == err_code)
00146           {
00147             retval->cpi = current->cpi;
00148             found_cpi = GATTrue;
00149             break;
00150           }
00151         }
00152 
00153         /* register this object with the engine */
00154         if (GAT_SUCCEEDED(retval))
00155         {
00156           err_code = GATRegistry_AddGATResourceBrokerToCPIList(context, 
00157             retval->cpi, retval);
00158         }
00159       }
00160     }
00161   }
00162   
00163   /* error handling */
00164   if (GAT_SUCCESS != err_code)
00165   {
00166     GATResourceBroker_Destroy(&retval);
00167   }
00168   return retval;
00169 }
00170 
00171 /** void GATResourceBroker_Destroy(GATResourceBroker *resource)
00172  *
00173  *  The function GATResourceBroker_Destroy is the destructor used to
00174  *  free all the memory allocated by an GATResourceBroker instance.
00175  *
00176  *  @param description The pointer to the GATResourceBroker to destroy
00177  */
00178 void
00179 GATResourceBroker_Destroy(GATResourceBroker *object)
00180 {
00181   if (NULL != object && NULL != *object)
00182   {
00183     GATString_Destroy(&(*object)->data.vo_name);
00184     if (NULL != (*object)->cpi)  /* during creation this may be zero */
00185     {
00186       GATRegistry_RemoveGATResourceBrokerFromCPIList((*object)->data.context, 
00187         (*object)->cpi, *object);
00188       GATResourceBrokerCPI_DestroyInstance((*object)->cpi, &(*object)->data);
00189     }
00190     GATResourceBrokerCPIList_Destroy((*object)->cpilist);
00191     free(*object);
00192     *object = NULL;
00193   }
00194 }
00195 
00196 /** GATResourceBroker_Equals
00197  *  @brief Compare two GATResourceBroker objects
00198  *
00199  *  The function @c GATResourceBroker_Equals compares two objects of the
00200  *  @c GATResourceBroker type.
00201  *
00202  *  @param lhs The first list to compare
00203  *  @param rhs The second list to compare
00204  *  @param isequal The pointer to the GATBool variable, which should receive 
00205  *        the result if the comparision
00206  *
00207  *  @return An error code.
00208  */
00209 GATResult
00210 GATResourceBroker_Equals(GATResourceBroker_const lhs,
00211   GATResourceBroker_const rhs, GATBool *isequal)
00212 {
00213   GATResult retval = GAT_INVALID_HANDLE;
00214 
00215   if (NULL != lhs && NULL != rhs)
00216   {
00217     retval = GAT_INVALID_PARAMETER;
00218     if (NULL != isequal)
00219     {
00220       if (NULL == lhs->data.vo_name && NULL == rhs->data.vo_name)
00221       {
00222         retval = GAT_SUCCESS;
00223         *isequal = GATTrue;
00224       }
00225       else if (NULL != lhs->data.vo_name && NULL != rhs->data.vo_name)
00226       {
00227         retval = GATString_Equals(lhs->data.vo_name, rhs->data.vo_name, isequal);
00228       }
00229       else
00230       {
00231         retval = GAT_SUCCESS;
00232         *isequal = GATFalse;
00233       }
00234       
00235       if (GAT_SUCCEEDED(retval) && GATTrue == *isequal)
00236       {
00237         retval = GATResourceBrokerCPI_EqualsInstance(lhs->cpi, &lhs->data, 
00238           &rhs->data, isequal);
00239       }
00240     }
00241   }
00242   return retval;
00243 }
00244 
00245 /** GATResourceBroker_Clone
00246  *  @brief Clone the given GATResourceBroker
00247  *
00248  *  The function @c GATResourceBroker_Clone generates a (deep) copy of 
00249  *  the given GATResourceBroker. 
00250  *
00251  *  @param description The object to clone
00252  *  @param new_object The pointer, through which the result is to be 
00253  *        returned.
00254  *
00255  *  @return An error type.
00256  */
00257 GATResult
00258 GATResourceBroker_Clone(GATResourceBroker_const handle, 
00259   GATResourceBroker *new_handle)
00260 {
00261   if (NULL != handle)
00262   {
00263     GAT_USES_STATUS(handle->data.context, "GATResourceBroker_Clone");
00264     if (NULL == new_handle)
00265     {
00266       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00267     }
00268     else
00269     {
00270       struct GATResourceBroker_S const *object = handle;
00271       GATResourceBroker new_object = 
00272         (GATResourceBroker) malloc(sizeof(struct GATResourceBroker_S));
00273       
00274       *new_handle = NULL;
00275       if (NULL == new_object)
00276       {
00277         GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00278       }
00279       else
00280       {
00281         memset(new_object, 0, sizeof(struct GATResourceBroker_S));
00282         new_object->GATObject__vtable = &GATResourceBroker__vtable;
00283 
00284         new_object->data.context = object->data.context;
00285         if (NULL != object->data.vo_name)
00286         {
00287           GAT_CREATE_STATUS(GATString_Clone(object->data.vo_name, 
00288             &new_object->data.vo_name));
00289         }
00290         
00291         new_object->cpilist = GATRegistry_CloneGATResourceBrokerCPIList(object->cpilist);
00292         if (GAT_FAILED(GAT_CURRENT_STATUS()) || NULL == new_object->cpilist)
00293         {
00294           GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00295         }
00296 
00297         if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00298         {
00299           /* re-find the cpi to use */
00300           GATResourceBrokerCPIList current = object->cpilist;
00301           GATResourceBrokerCPIList new_current = new_object->cpilist;
00302           
00303           for (/**/; NULL != current; 
00304                current = current->next, new_current = new_current->next)
00305           {
00306             if (current->cpi == object->cpi)
00307             {
00308               new_object->cpi = new_current->cpi;
00309               break;
00310             }
00311           }
00312           assert(NULL != new_object->cpi);
00313           
00314           /* clone the instance data */
00315           GAT_CREATE_STATUS(GATResourceBrokerCPI_CloneInstance(object->cpi, 
00316             &object->data, &new_object->data));
00317 
00318           /* register this object with the engine */
00319           GAT_CREATE_STATUS(GATRegistry_AddGATResourceBrokerToCPIList(
00320             new_object->data.context, new_object->cpi, new_object));
00321         }
00322       }
00323       
00324       /* destroy the newly allocated object, if some error occured */
00325       if (GAT_FAILED(GAT_CURRENT_STATUS()))
00326       {
00327         GATResourceBroker_Destroy(&new_object);
00328       }
00329       else
00330       {
00331         /* return the new object */
00332         *new_handle = new_object;
00333       }
00334     }
00335   }
00336   return GAT_INVALID_HANDLE;
00337 }
00338 
00339 /** GATType GATResourceBroker_GetType(GATResourceBroker_const resource)
00340  *  @brief Return the type of the GATResourceBroker
00341  *
00342  *  The function @c GATResourceBroker_GetType always returns 
00343  *  @c #GATType_GATResourceBroker. 
00344  *
00345  *  @param object The object to inspect
00346  *
00347  *  @return Returns always @c #GATType_GATResourceBroker. 
00348  */
00349 GATType
00350 GATResourceBroker_GetType(GATResourceBroker_const object)
00351 {
00352   GAT_UNUSED_PARAMETER(object);
00353   return GATType_GATResourceBroker;
00354 }
00355 
00356 /** int GATResourceBroker_GetInterface(GATResourceBroker_const file, GATInterface iftype, void const **ifp)
00357  *  @brief Get an interface supported by a GATObject
00358  *
00359  *  The function GATResourceBroker_GetInterface allows to get a pointer to an 
00360  *  additional interface supported by this GATResourceBroker.
00361  *
00362  *  @param object The object to be asked for the new interface.
00363  *  @param iftype The interface the object is to be asked for.
00364  *  @param ifp The pointer, through which the result is to be returned.
00365  *
00366  *  @return An error type.
00367  */
00368 GATResult 
00369 GATResourceBroker_GetInterface(GATResourceBroker_const object, 
00370   GATInterface iftype, void const **ifp)
00371 {
00372   GAT_UNUSED_PARAMETER(object);
00373   GAT_UNUSED_PARAMETER(iftype);
00374   if (NULL != object)
00375   {
00376     GAT_STATUS_APIENTRY(object->data.context, "GATResourceBroker_GetInterface");
00377     
00378     if (NULL != ifp)
00379     {
00380       *ifp = NULL;
00381       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00382     }
00383     else
00384     {
00385       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00386     }
00387     
00388     return GAT_RETURN_STATUS();
00389   }
00390   return GAT_INVALID_HANDLE;
00391 }
00392 
00393 
00394 /** GATResourceBroker_ReserveResource_Description
00395  *  @brief reserve a resource matching the description
00396  *
00397  *  The function @c GATResourceBroker_ReserveResource_Description tries to find 
00398  *  a resource, which matches the provided description and returns a 
00399  *  reservation for this resource.
00400  *
00401  *  @param broker The resource broker to use for this operation.
00402  *  @param description The resource description needed for selecting the 
00403  *        required resource.
00404  *  @param time The (optional) time, when the reservation has to start.
00405  *  @param duration The (optional) time period for which to reserve the
00406  *        resource.
00407  *  @param reservation The pointer to the GATReservation variable to use to 
00408  *        return the resulting reservation.
00409  *
00410  *  @return An error code.
00411  */
00412 GATResult
00413 GATResourceBroker_ReserveResource_Description(GATResourceBroker broker, 
00414   GATResourceDescription_const description, GATTime_const time_of_start, 
00415   GATTimePeriod_const duration, GATReservation *reservation)
00416 {
00417   if (NULL != broker)
00418   {
00419     GAT_STATUS_APIENTRY(broker->data.context, "GATResourceBroker_ReserveResource");
00420     GAT_CREATE_STATUS(GATResourceBrokerCPI_ReserveResource_Description(
00421       broker->cpi, &broker->data, description, time_of_start, duration, 
00422       reservation));
00423     return GAT_RETURN_STATUS();
00424   }
00425   return GAT_INVALID_HANDLE;
00426 }
00427 
00428 /** GATResourceBroker_ReserveResource
00429  *  @brief Reserve a given resource.
00430  *
00431  *  The function @c GATResourceBroker_ReserveResource tries to reserve
00432  *  the given resource and returns a reservation for this resource.
00433  *
00434  *  @param broker The resource broker to use for this operation.
00435  *  @param context The associated GAT context.
00436  *  @param resource The resource to reserve.
00437  *  @param time The (optional) time, when the reservation has to start.
00438  *  @param duration The (optional) time period for which to reserve the 
00439  *        resource.
00440  *  @param reservation The pointer to the GATReservation variable to use to 
00441  *        return the resulting reservation.
00442  *
00443  *  @return An error value.
00444  */
00445 GATResult
00446 GATResourceBroker_ReserveResource(GATResourceBroker broker, 
00447   GATResource_const resource, GATTime_const time_of_start, 
00448   GATTimePeriod_const duration, GATReservation *reservation)
00449 {
00450   if (NULL != broker)
00451   {
00452     GAT_STATUS_APIENTRY(broker->data.context, "GATResourceBroker_ReserveResource");
00453     GAT_CREATE_STATUS(GATResourceBrokerCPI_ReserveResource(broker->cpi, 
00454       &broker->data, resource, time_of_start, duration, reservation));
00455     return GAT_RETURN_STATUS();
00456   }
00457   return GAT_INVALID_HANDLE;
00458 }
00459 
00460 /** GATResourceBroker_FindResources
00461  *  @brief Find a list of matching resources.
00462  *
00463  *  The function GATResourceBroker_FindResources tries to find all resources
00464  *  matching the given description and returns the found resources as a list.
00465  *
00466  *  @param broker The resource broker to use for this operation.
00467  *  @param description The description to match while searching for resources.
00468  *  @param resources The pointer to a variable receiving the resulting list of
00469  *        matching resources.
00470  *
00471  *  @return An error value.
00472  */
00473 GATResult
00474 GATResourceBroker_FindResources(GATResourceBroker broker, 
00475   GATResourceDescription_const description, GATList_GATResource *resources)
00476 {
00477   if (NULL != broker)
00478   {
00479     GAT_STATUS_APIENTRY(broker->data.context, "GATResourceBroker_FindResources");
00480     GAT_CREATE_STATUS(GATResourceBrokerCPI_FindResources(broker->cpi, 
00481       &broker->data, description, resources));
00482     return GAT_RETURN_STATUS();
00483   }
00484   return GAT_INVALID_HANDLE;
00485 }
00486 
00487 /** GATResourceBroker_SubmitJob
00488  *  @brief Submit a new job.
00489  *
00490  *  The function GATResourceBroker_SubmitJob submits a new job to the resource
00491  *  described by the given job description.
00492  *
00493  *  @param broker The resource broker to use for this operation.
00494  *  @param description The job description containing the information about the
00495  *        job iteslf and the resource to use.
00496  *  @param job The pointer to a variable receiving the resulting GATJob object
00497  *        handle.
00498  *
00499  *  @return An error value.
00500  */
00501 GATResult GATResourceBroker_SubmitJob(GATResourceBroker broker,
00502   GATJobDescription_const description, GATJob *job)
00503 {
00504   if (NULL != broker)
00505   {
00506     GAT_STATUS_APIENTRY(broker->data.context, "GATResourceBroker_SubmitJob");
00507     GATJobDescription desc = NULL;
00508     
00509     /* create a new GAT jobid */
00510     GATString gatjobid = NULL;
00511     GATSelf_const self = GATContext_internal_GetSelf(broker->data.context);
00512     
00513     GAT_CREATE_STATUS(GATSelf_internal_CreateGATJobId(self, broker->data.context,
00514       &gatjobid));
00515 
00516     /* add the GAT_JOBID related environment variables for the new job */
00517     GAT_CREATE_STATUS(GATJobDescription_Clone(description, &desc));
00518     GAT_CREATE_STATUS(GATResourceBroker_SetJobEnvironment(broker, desc, 
00519         gatjobid));
00520 
00521     /* submit the job */
00522     GAT_CREATE_STATUS(GATResourceBrokerCPI_SubmitJob(broker->cpi, &broker->data, 
00523         desc, job));
00524     GATJobDescription_Destroy(&desc);
00525     
00526     /* associate a new GAT job id with this new job */
00527     GAT_CREATE_STATUS(GATJob_internal_SetGATJobId(*job, gatjobid));
00528     GATString_Destroy(&gatjobid);
00529     
00530     return GAT_RETURN_STATUS();
00531   }
00532   return GAT_INVALID_HANDLE;
00533 }
00534 
00535 
00536 /* Local functions */
00537 
00538 /*  GATResourceBroker_GetCPIInstanceData
00539  *  
00540  *  The function GATResourceBroker_GetCPIInstanceData returns the CPI instance data, 
00541  *  associated with the given GATResourceBroker object.
00542  *
00543  *  @param broker The object, for which to return the CPI instance data.
00544  *  @param data The pointer to the variable, which should receive the
00545  *        resulting CPI instance data.
00546  *
00547  *  @return An error code.
00548  */
00549 static GATResult
00550 GATResourceBroker_GetCPIInstanceData(GATResourceBroker broker, void **data)
00551 {
00552   if (NULL != broker)
00553   {
00554     GAT_USES_STATUS(broker->data.context, "GATResourceBroker_GetCPIInstanceData");
00555     
00556     if (NULL != data)
00557     {
00558       *data = (void *)&broker->data;
00559     }
00560     else
00561     {
00562       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00563     }
00564     
00565     return GAT_RETURN_STATUS();
00566   }
00567   return GAT_INVALID_HANDLE;
00568 }
00569 
00570 /*  GATResourceBroker_SetJobEnvironment
00571  *  
00572  *  The function GATResourceBroker_SetJobEnvironment sets the GAT_JOBID and
00573  *  GAT_PARENT_JOBID in the environment of the jobdescription for the job to 
00574  *  spawn.
00575  *
00576  *  @param broker The resource broker to use.
00577  *  @param description The job description to use for job submission.
00578  *  @param gatjobid The GAT job id to assign to the new job.
00579  *
00580  *  @return An error code.
00581  */
00582 static GATResult 
00583 GATResourceBroker_SetJobEnvironment(GATResourceBroker broker,
00584   GATJobDescription desc, GATJobID_const gatjobid)
00585 {
00586   if (NULL != broker)
00587   {
00588     GAT_USES_STATUS(broker->data.context, "GATResourceBroker_SetJobEnvironment");
00589     
00590     GATSelf_const self = GATContext_internal_GetSelf(broker->data.context);
00591     
00592     /* these are references only, do not destroy them ! */
00593     GATJobID_const parent_gatjobid = NULL;
00594     GATTable env = NULL;   
00595     
00596     GAT_CREATE_STATUS(GATJobDescription_internal_GetEnvironment(desc, &env));
00597     
00598     GAT_CREATE_STATUS(GATTable_Add_String(env, "GAT_JOBID", 
00599         GATString_GetBuffer(gatjobid)));
00600 
00601     GAT_CREATE_STATUS(GATSelf_internal_GetGATJobId(self, broker->data.context, 
00602       &parent_gatjobid));
00603     GAT_CREATE_STATUS(GATTable_Add_String(env, "PARENT_GAT_JOBID", 
00604         GATString_GetBuffer(parent_gatjobid)));
00605     
00606     return GAT_RETURN_STATUS();
00607   }
00608   return GAT_INVALID_HANDLE;
00609 }
00610