GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATAdvertService.c

Go to the documentation of this file.
00001 /** @file GATAdvertService.c
00002  *  Source file for the GATAdvertService class.
00003  *
00004  *  @date Fri Feb 13 2004
00005  *
00006  *  @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATAdvertService.c,v 1.12 2004/04/29 14:18:49 hartmutkaiser Exp $
00007  *
00008  *  Copyright (C) Hartmut Kaiser
00009  *  This file is part of the GAT Engine.
00010  *  Contributed by Hartmut Kaiser <hartmutkaiser [at] t-online [dot] de>.
00011  *
00012  *  Use, modification and distribution is subject to the Gridlab Software
00013  *  License. (See accompanying file GLlicense.txt or copy at
00014  *  http://www.gridlab.org/GLlicense.txt)
00015  */
00016 
00017 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATAdvertService.c,v 1.12 2004/04/29 14:18:49 hartmutkaiser Exp $";
00018  
00019 /* System Header objects */
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <assert.h>
00023 #include <time.h>
00024 #include <errno.h>
00025 #include <sys/utsname.h>
00026 
00027 /* GAT Header objects */
00028 #include "GAT.h"
00029 #include "GATUtil.h"
00030 #include "GATInternal.h"
00031 #include "GATRegistry.h"
00032 #include "GATAdvertServiceCPI.h"
00033 #include "GATMetricEvent.h"
00034 #include "GATMonitorable.h"
00035 
00036 /* define the vtable types */
00037 GATOBJECT_DEFINE_VTABLE(GATAdvertService);
00038 GATMONITORABLE_DEFINE_VTABLE(GATAdvertService);
00039 
00040 /* define the converters to/from GATObject */
00041 GATOBJECT_DEFINE_CONVERTERS(GATAdvertService)
00042 
00043 /* Macros */
00044 
00045 /* Structures, unions and enums */
00046 struct GATAdvertService_S {
00047   /* supported interfaces */
00048   GATAdvertService_vtable *GATObject__vtable;
00049   GATAdvertService_IMonitorable_vtable *GATMonitorable__vtable;
00050 
00051   /* instance data */
00052   GATAdvertServiceCPI_Instance data; /* instance data of the corresponding CPI object */
00053   GATAdvertServiceCPI cpi;         /* CPI object to use for all subsequent operations */
00054   GATAdvertServiceCPIList cpilist; /* CPI list of appropriate CPI objects */
00055 };
00056 
00057 /* Static function prototypes */
00058 
00059 static GATResult
00060 GATAdvertService_GetCPIInstanceData(GATAdvertService object, void **data);
00061 
00062 static GATResult
00063 GATAdvertService_EnsureMetaDataItem(GATContext context, char const *item, 
00064   GATTable metadata, char const *defaultvalue);
00065 
00066 static char *
00067 GATAdvertService_ExtractName(GATString_const path);
00068 
00069 static GATResult
00070 GATAdvertService_ResolvePath(
00071   GATString_const cwd, GATString_const path, char **absolute_path);
00072 
00073 /* file scope variables */
00074 GATAdvertService_vtable GATAdvertService__vtable = {
00075   GATAdvertService_GetType,
00076   GATAdvertService_Destroy,
00077   GATAdvertService_Equals,
00078   GATAdvertService_Clone,
00079   GATAdvertService_GetInterface,
00080   GATAdvertService_GetCPIInstanceData
00081 };
00082 
00083 static GATAdvertService_IMonitorable_vtable 
00084   GATAdvertService_IMonitorable__vtable = 
00085 {
00086   GATAdvertService_AddMetricListener,
00087   GATAdvertService_RegisterPolling,
00088   GATAdvertService_RemoveRegisteredMetric,
00089   GATAdvertService_GetMetrics
00090 };
00091 
00092 /* External functions */
00093 
00094 /** GATAdvertService_Create
00095  *  @brief Create a new GATAdvertService object
00096  *
00097  *  The function @c GATAdvertService_Create creates a new 
00098  *  GATAdvertService object
00099  *
00100  *  @param context The GAT context to use while the initialisation of the 
00101  *        new object.
00102  *  @param preferences The preferences to use while selecting the adaptor for 
00103  *        the corresponding CPI.
00104  *
00105  *  @return Returns a handle to the newly created GATAdvertService object.
00106  *        Returns 0 (zero) if an error occurs.
00107  */
00108 GATAdvertService 
00109 GATAdvertService_Create(GATContext context, GATPreferences_const preferences)
00110 {
00111   GAT_STATUS_APIENTRY(context, "GATAdvertService_Create");
00112   
00113   GATAdvertService new_advertservice = (GATAdvertService) malloc(
00114     sizeof(struct GATAdvertService_S));
00115   if (NULL != new_advertservice)
00116   {
00117     memset(new_advertservice, 0, sizeof(struct GATAdvertService_S));
00118     new_advertservice->GATObject__vtable = &GATAdvertService__vtable;
00119     new_advertservice->GATMonitorable__vtable = 
00120       &GATAdvertService_IMonitorable__vtable;
00121 
00122     new_advertservice->data.context = context;
00123     new_advertservice->data.source = 
00124       GATAdvertService_ToGATObject_const(new_advertservice);
00125     new_advertservice->data.pwd = GATString_Create("/", 2, "ASCII");
00126     
00127     GAT_CREATE_STATUS_IF(NULL == new_advertservice->data.pwd, GAT_MEMORYFAILURE);
00128     
00129     /* find a CPI object, which can handle this object */
00130     {
00131       GATRegistry_const registry = GATContext_internal_GetRegistry(context);
00132       
00133       /* use default preferences, if appropriate */
00134       if (NULL == preferences)
00135       {
00136         preferences = GATContext_GetPreferences(context);
00137       }
00138       new_advertservice->cpilist = GATRegistry_FindGATAdvertServiceCPI(registry, preferences);
00139       
00140       if (NULL == new_advertservice->cpilist)
00141       {
00142         GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00143       }
00144       else if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00145       {
00146         /* create a new instance of the CPI provider */
00147         GATBool found_cpi = GATFalse;
00148         GATAdvertServiceCPIList current = NULL;
00149         for(current = new_advertservice->cpilist; NULL != current; current = current->next)
00150         {
00151           GAT_CREATE_STATUS(GATAdvertServiceCPI_CreateInstance(current->cpi, 
00152             &new_advertservice->data));
00153           if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00154           {
00155             new_advertservice->cpi = current->cpi;
00156             found_cpi = GATTrue;
00157             break;
00158           }
00159         }
00160 
00161         /* no available CPI object can handle this */
00162         if (GATFalse == found_cpi)
00163         {
00164           GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00165         }
00166         else
00167         {
00168           /* now, initialise the monitoring framework with the help of the
00169              CPI provider found */
00170           GATList_GATMetric metrics = NULL;
00171           GATResult retval = GATAdvertServiceCPI_GetMetrics(new_advertservice->cpi, 
00172             &new_advertservice->data, &metrics);
00173             
00174           if (GAT_SUCCEEDED(retval))
00175           {
00176             new_advertservice->data.monitorable = GATMonitorable_Impl_Create(metrics);
00177             if (NULL == new_advertservice->data.monitorable)
00178             {
00179               GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00180             }
00181             GATList_GATMetric_Destroy(&metrics);
00182           }
00183           else if (GAT_NOTIMPL == retval)
00184           {
00185             retval = GAT_SUCCESS;   /* no monitoring supported here */
00186           }
00187           else
00188           {
00189             GAT_CREATE_STATUS(retval);
00190           }
00191 
00192           /* register this object with the engine */
00193           GAT_CREATE_STATUS(GATRegistry_AddGATAdvertServiceToCPIList(context, 
00194             new_advertservice->cpi, new_advertservice));
00195         }
00196       }
00197     }
00198   }
00199   else
00200   {
00201     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00202   }
00203 
00204   /* error handling */
00205   if (GAT_FAILED(GAT_CURRENT_STATUS()))
00206   {
00207     GATAdvertService_Destroy(&new_advertservice);
00208   }
00209   GAT_STORE_STATUS();
00210   return new_advertservice;
00211 }
00212 
00213 /** void GATAdvertService_Destroy(GATAdvertService *resource)
00214  *
00215  *  The function GATAdvertService_Destroy is the destructor used to
00216  *  free all the memory allocated by an GATAdvertService instance.
00217  *
00218  *  @param description The pointer to the GATAdvertService to destroy
00219  */
00220 void
00221 GATAdvertService_Destroy(GATAdvertService *object)
00222 {
00223   if (NULL != object && NULL != *object)
00224   {
00225     GATString_Destroy(&(*object)->data.pwd);
00226     GATMonitorable_Impl_Destroy(&(*object)->data.monitorable);
00227     if (NULL != (*object)->cpi)  /* during creation this may be zero */
00228     {
00229       GATRegistry_RemoveGATAdvertServiceFromCPIList((*object)->data.context, 
00230         (*object)->cpi, *object);
00231       GATAdvertServiceCPI_DestroyInstance((*object)->cpi, &(*object)->data);
00232     }
00233     GATAdvertServiceCPIList_Destroy((*object)->cpilist);
00234     free(*object);
00235     *object = NULL;
00236   }
00237 }
00238 
00239 /** GATAdvertService_Equals
00240  *  @brief Compare two GATAdvertService objects
00241  *
00242  *  The function @c GATAdvertService_Equals compares two objects of the
00243  *  @c GATAdvertService type.
00244  *
00245  *  @param lhs The first list to compare
00246  *  @param rhs The second list to compare
00247  *  @param isequal The pointer to the GATBool variable, which should receive 
00248  *        the result if the comparision
00249  *
00250  *  @return An error code.
00251  */
00252 GATResult 
00253 GATAdvertService_Equals(GATAdvertService_const lhs,
00254   GATAdvertService_const rhs, GATBool *isequal)
00255 {
00256   if (NULL != lhs && NULL != rhs)
00257   {
00258     GAT_STATUS_APIENTRY(lhs->data.context, "GATAdvertService_Equals");
00259     if (NULL != isequal)
00260     {
00261       GAT_CREATE_STATUS(GATString_Equals(lhs->data.pwd, rhs->data.pwd, isequal));
00262       if (GATTrue == *isequal)
00263       {
00264         GAT_CREATE_STATUS(GATAdvertServiceCPI_EqualsInstance(lhs->cpi, 
00265           &lhs->data, &rhs->data, isequal));
00266       }
00267     }
00268     else
00269     {
00270       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00271     }
00272     return GAT_RETURN_STATUS();
00273   }
00274   return GAT_INVALID_HANDLE;
00275 }
00276 
00277 /** GATAdvertService_Clone
00278  *  @brief Clone the given GATAdvertService
00279  *
00280  *  The function @c GATAdvertService_Clone generates a (deep) copy of 
00281  *  the given GATAdvertService. 
00282  *
00283  *  @param description The object to clone
00284  *  @param new_object The pointer, through which the result is to be 
00285  *        returned.
00286  *
00287  *  @return An error type.
00288  */
00289 GATResult 
00290 GATAdvertService_Clone(GATAdvertService_const handle, 
00291   GATAdvertService *new_handle)
00292 {
00293   if (NULL != handle)
00294   {
00295     GAT_STATUS_APIENTRY(handle->data.context, "GATAdvertService_Clone");
00296     
00297     if (NULL == new_handle)
00298     {
00299       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00300     }
00301     else
00302     {
00303       struct GATAdvertService_S const *object = handle;
00304       GATAdvertService new_object = 
00305         (GATAdvertService)malloc(sizeof(struct GATAdvertService_S));
00306       
00307       *new_handle = NULL;
00308       if (NULL == new_object)
00309       {
00310         GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00311       }
00312       else
00313       {
00314         memset(new_object, 0, sizeof(struct GATAdvertService_S));
00315         new_object->GATObject__vtable = &GATAdvertService__vtable;
00316         new_object->GATMonitorable__vtable = &GATAdvertService_IMonitorable__vtable;
00317 
00318         new_object->data.context = object->data.context;
00319         new_object->data.source = GATAdvertService_ToGATObject_const(new_object);
00320         
00321         new_object->cpilist = GATRegistry_CloneGATAdvertServiceCPIList(
00322           object->cpilist);
00323         if (NULL == new_object->cpilist)
00324         {
00325           GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00326         }
00327         GAT_CREATE_STATUS(GATString_Clone(object->data.pwd, 
00328           &new_object->data.pwd));
00329           
00330         if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00331         {
00332           /* re-find the cpi to use */
00333           GATAdvertServiceCPIList current = object->cpilist;
00334           GATAdvertServiceCPIList new_current = new_object->cpilist;
00335           
00336           for (/**/; NULL != current; 
00337                current = current->next, new_current = new_current->next)
00338           {
00339             if (current->cpi == object->cpi)
00340             {
00341               new_object->cpi = new_current->cpi;
00342               break;
00343             }
00344           }
00345           assert(NULL != new_object->cpi);
00346           
00347           /* clone the instance data */
00348           GAT_CREATE_STATUS(GATAdvertServiceCPI_CloneInstance(object->cpi, 
00349             &object->data, &new_object->data));
00350 
00351           /* clone the monitoring data */
00352           if (NULL != object->data.monitorable)
00353           {
00354             GAT_CREATE_STATUS(GATMonitorable_Impl_Clone(object->data.monitorable, 
00355               &new_object->data.monitorable));
00356           }
00357  
00358           GAT_CREATE_STATUS(GATRegistry_AddGATAdvertServiceToCPIList(
00359             new_object->data.context, new_object->cpi, new_object));
00360         }
00361 
00362         /* detroy the newly allocated object, if some error occured */
00363         if (GAT_FAILED(GAT_CURRENT_STATUS()))
00364         {
00365           GATAdvertService_Destroy(&new_object);
00366         }
00367         else
00368         {
00369           /* return the new object */
00370           *new_handle = new_object;
00371         }
00372       }
00373     }
00374     return GAT_RETURN_STATUS();
00375   }
00376   return GAT_INVALID_HANDLE;
00377 }
00378 
00379 /** GATType GATAdvertService_GetType(GATAdvertService_const resource)
00380  *  @brief Return the type of the GATAdvertService
00381  *
00382  *  The function @c GATAdvertService_GetType always returns 
00383  *  @c #GATType_GATAdvertService. 
00384  *
00385  *  @param object The object to inspect
00386  *
00387  *  @return Returns always @c #GATType_GATAdvertService. 
00388  */
00389 GATType
00390 GATAdvertService_GetType(GATAdvertService_const object)
00391 {
00392   GAT_UNUSED_PARAMETER(object);
00393   return GATType_GATAdvertService;
00394 }
00395 
00396 /** GATResult GATAdvertService_GetInterface(GATAdvertService_const file, GATInterface iftype, void const **ifp)
00397  *  @brief Get an interface supported by a GATObject
00398  *
00399  *  The function GATAdvertService_GetInterface allows to get a pointer to an 
00400  *  additional interface supported by this GATAdvertService.
00401  *
00402  *  @param object The object to be asked for the new interface.
00403  *  @param iftype The interface the object is to be asked for.
00404  *  @param ifp The pointer, through which the result is to be returned.
00405  *
00406  *  @return An error type.
00407  */
00408 GATResult 
00409 GATAdvertService_GetInterface(GATAdvertService_const object, GATInterface iftype, 
00410   void const **ifp)
00411 {
00412   if (NULL != object)
00413   {
00414     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_GetInterface");
00415     
00416     if (NULL != ifp)
00417     {
00418       if (GATInterface_IMonitorable == iftype && NULL != object->data.monitorable)
00419       {
00420         *ifp = (void const *) &object->GATMonitorable__vtable;
00421       }
00422       else
00423       {
00424         ifp = NULL;
00425         GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00426       }
00427     }
00428     else
00429     {
00430       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00431     }
00432     
00433     return GAT_RETURN_STATUS();
00434   }
00435   return GAT_INVALID_HANDLE;
00436 }
00437 
00438 
00439 /* GATMonitorable API */
00440 
00441 /** GATAdvertService_AddMetricListener
00442  *
00443  *  The function GATAdvertService_AddMetricListener adds the passed instance of a 
00444  *  GATMetricListener to the list of GATMetricListeners which are notified of 
00445  *  fired GATMetricEvents of the type described by the provided GATMetric 
00446  *  instance.
00447  *
00448  *  @param object The GATAdvertService instance to add the GATMetricListener to.
00449  *  @param listener The GATMetricListener to call, when the corresponding 
00450  *        GATMetricEvent is fired.
00451  *  @param listener_data The client supplied data, which will be passed through
00452  *        to the GATMetricListener.
00453  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00454  *        to the GATMetricListener.
00455  *  @param cookie The returned value should be used to remove the 
00456  *        GATMetricListener from this GATMonitorable.
00457  *
00458  *  @return An error code.
00459  */ 
00460 GATResult 
00461 GATAdvertService_AddMetricListener(GATAdvertService object, 
00462   GATMetricListener listener, void *listener_data, GATMetric metric,
00463   GATuint32 *cookie)
00464 {
00465   if (NULL != object)
00466   {
00467     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_AddMetricListener");
00468     
00469     if (NULL != object->data.monitorable)
00470     {
00471       GAT_CREATE_STATUS(GATMonitorable_Impl_AddMetricListener(
00472         object->data.monitorable, listener, listener_data, metric, cookie));
00473     } 
00474     else
00475     { 
00476       /* this may happen, if the adaptor has not registered any GATMetrics */
00477       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00478     }
00479     
00480     return GAT_RETURN_STATUS();
00481   }
00482   return GAT_INVALID_HANDLE;
00483 }
00484 
00485 /** GATAdvertService_RegisterPolling
00486  *
00487  *  The function GATAdvertService_RegisterPolling registers a continuous 
00488  *  metric with the given GATAdvertService instance.
00489  *
00490  *  @param object The GATAdvertService instance to register the metric with.
00491  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00492  *        to the GATMetricListener. This metric instance must be of type
00493  *        GATMeasurementType_Continuous, otherwise an error is returned.
00494  *  @param event The pointer to a variable, which should receive the resulting
00495  *        GATMetricEvent. The GATMetricEvent instance should be freed by the 
00496  *        caller when it isn't used anymore.
00497  *  @param cookie The returned value should be used to remove the 
00498  *        GATMetricListener from this GATAdvertService.
00499  *
00500  *  @return An error code.
00501  */ 
00502 GATResult 
00503 GATAdvertService_RegisterPolling(GATAdvertService object, GATMetric metric, 
00504   GATMetricEvent *event, GATuint32 *cookie)
00505 {
00506   GATResult retval = GAT_INVALID_HANDLE;
00507   if (NULL != object)
00508   {
00509     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_RegisterPolling");
00510     
00511     if (NULL != object->data.monitorable)
00512     {
00513       GAT_CREATE_STATUS(GATMonitorable_Impl_RegisterPolling(
00514         object->data.monitorable, metric, 0, cookie));
00515 
00516       /* ask the CPI provider to return the corresponding metric event */
00517       GAT_CREATE_STATUS(GATAdvertServiceCPI_GetMetricEvent(object->cpi, 
00518         &object->data, metric, event));
00519 
00520       if (GAT_FAILED(GAT_CURRENT_STATUS()) && NULL != cookie && 0 != *cookie)
00521       {
00522         GATMonitorable_Impl_RemoveRegisteredMetric(object->data.monitorable,
00523           metric, *cookie);
00524         *cookie = 0;
00525       }
00526     } 
00527     else
00528     { 
00529       /* this may happen, if the adaptor has not registered any GATMetrics */
00530       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00531     }
00532     
00533     return GAT_RETURN_STATUS();
00534   }
00535   return GAT_INVALID_HANDLE;
00536 }
00537 
00538 /** GATAdvertService_RemoveRegisteredMetric
00539  *
00540  *  The function GATAdvertService_RemoveRegisteredMetric removes a GATMetricListener, 
00541  *  which was previously registered with GATAdvertService_AddMetricListener.
00542  *
00543  *  @param object The GATAdvertService instance to remove the GATMetricListener from.
00544  *  @param listener The GTAMetricListener to call, when the corresponding 
00545  *        GATMetricEvent is fired.
00546  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00547  *        to the GATMetricListener.
00548  *  @param cookie This value identifies the GATMetricListener to remove, it 
00549  *        was returned from the corresponding GATMonitorable_AddMetricListener 
00550  *        or GATMonitorable_MetricRegisterPolling functions.
00551  *  
00552  *  @return An error code.
00553  */
00554 GATResult 
00555 GATAdvertService_RemoveRegisteredMetric(GATAdvertService object, 
00556   GATMetric metric, GATuint32 cookie)
00557 {
00558   if (NULL != object)
00559   {
00560     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_RemoveRegisteredMetric");
00561 
00562     if (NULL != object->data.monitorable)
00563     {
00564       GAT_CREATE_STATUS(GATMonitorable_Impl_RemoveRegisteredMetric(
00565         object->data.monitorable, metric, cookie));
00566     } 
00567     else
00568     { 
00569       /* this may happen, if the adaptor has not registered any GATMetrics */
00570       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00571     }
00572 
00573     return GAT_RETURN_STATUS();
00574   }
00575   return GAT_INVALID_HANDLE;
00576 }
00577 
00578 /** GATAdvertService_GetMetrics
00579  *
00580  *  The function GATAdvertService_GetMetrics returns a list of metrics supported 
00581  *  by this GATAdvertService.
00582  *
00583  *  @param object The GATAdvertService instance, for which the supported metrics 
00584  *        should be returned.
00585  *  @param metrics The pointer to the variable, which receives the resulting 
00586  *        list of metrics.
00587  *
00588  *  @return An error code.
00589  */
00590 GATResult 
00591 GATAdvertService_GetMetrics(GATAdvertService_const object, 
00592   GATList_GATMetric *metrics)
00593 {
00594   if (NULL != object)
00595   {
00596     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_GetMetrics");
00597     
00598     if (NULL != object->data.monitorable)
00599     {
00600       GAT_CREATE_STATUS(GATMonitorable_Impl_GetMetrics(
00601         object->data.monitorable, metrics));
00602     } 
00603     else
00604     { 
00605       /* this may happen, if the adaptor has not registered any GATMetrics */
00606       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00607     }
00608 
00609     return GAT_RETURN_STATUS();
00610   }
00611   return GAT_INVALID_HANDLE;
00612 }
00613 
00614 
00615 /* API specific functions */
00616 
00617 /** GATAdvertService_Add
00618  *  
00619  *  The function GATAdvertService_Add adds an Advertizable instance and related 
00620  *  meta data to the GATAdvertService, at path (absolute or relative to PWD). 
00621  *  If an GATAdvertService entry exists at the specified path, that entry gets 
00622  *  overwritten.
00623  *
00624  *  @param object The GATAdvertService instance, to which the advertisable 
00625  *        should be added.
00626  *  @param advertisable The advertisable object, which should be stored in the 
00627  *        given advertservice.
00628  *  @param metadata The meta data to rassociate with the newly created entry.
00629  *  @param path The path inside the advert service, where the newly created 
00630  *        entry is to be stored.
00631  *
00632  *  @return An error code.
00633  */
00634 GATResult  
00635 GATAdvertService_Add(GATAdvertService object, GATObject_const advertisable, 
00636   GATTable metadata, GATString_const path)
00637 {
00638   if (NULL != object)
00639   {
00640     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_Add");
00641     
00642     if (NULL != path)
00643     {
00644       /* verify, that a GAT_NAME and GAT_PATH metadata attributes are given, 
00645         supply default values, if appropriate */
00646       char *name = GATAdvertService_ExtractName(path);
00647       char *resolved_path = NULL;
00648       struct utsname sysinfo;
00649       time_t curr_time = 0;
00650       char buffer[64];
00651       char *newline = NULL;
00652       
00653       GAT_CREATE_STATUS_IF(NULL == name, GAT_MEMORYFAILURE);
00654       GAT_CREATE_STATUS(GATAdvertService_ResolvePath(object->data.pwd, path, 
00655         &resolved_path));
00656       
00657       GAT_CREATE_STATUS(GATAdvertService_EnsureMetaDataItem(object->data.context,
00658         "GAT_NAME", metadata, name));
00659       GAT_CREATE_STATUS(GATAdvertService_EnsureMetaDataItem(object->data.context,
00660         "GAT_PATH", metadata, resolved_path));
00661       GAT_CREATE_STATUS(GATAdvertService_EnsureMetaDataItem(object->data.context,
00662         "GAT_TYPE", metadata, GATType_GetName(GATObject_GetType(advertisable))));
00663         
00664       GAT_CREATE_STATUS_IF(uname (&sysinfo) < 0, POSIX_TO_GAT(errno));
00665       GAT_CREATE_STATUS(GATAdvertService_EnsureMetaDataItem(object->data.context,
00666         "GAT_HOSTNAME", metadata, sysinfo.nodename));
00667       
00668       curr_time = time(NULL);
00669       strcpy(buffer, asctime(gmtime(&curr_time)));
00670       newline = strchr(buffer, '\n');
00671       
00672       if (NULL != newline)
00673       {
00674         *newline = '\0';
00675       }
00676       strcat(buffer, " GMT");
00677       GAT_CREATE_STATUS(GATAdvertService_EnsureMetaDataItem(object->data.context,
00678         "GAT_CREATIONTIME", metadata, buffer));
00679       
00680       free(name);
00681       free(resolved_path);
00682           
00683       /* add the advertisable to the advert service */
00684       GAT_CREATE_STATUS(GATAdvertServiceCPI_Add(object->cpi, &object->data, 
00685         advertisable, metadata, path));
00686     }
00687     else
00688     {
00689       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00690     }      
00691     return GAT_RETURN_STATUS();
00692   }
00693   return GAT_INVALID_HANDLE;
00694 }
00695 
00696 /** GATAdvertService_Delete
00697  *  
00698  *  The function GATAdvertService_Delete deletes the specified entry from the 
00699  *  GATAdvertService.
00700  *
00701  *  @param object The GATAdvertService instance, from which the given path 
00702  *        should be deleted.
00703  *  @param path The path of the entry to delete from the given advert service.
00704  *
00705  *  @return An error code.
00706  */
00707 GATResult
00708 GATAdvertService_Delete(GATAdvertService object, GATString_const path)
00709 {
00710   if (NULL != object)
00711   {
00712     GAT_STATUS_APIENTRY(object->data.context, "");
00713     
00714     GAT_CREATE_STATUS(GATAdvertServiceCPI_Delete(object->cpi, &object->data, 
00715       path));
00716     return GAT_RETURN_STATUS();
00717   }
00718   return GAT_INVALID_HANDLE;
00719 }
00720 
00721 /** GATAdvertService_GetMetaData
00722  *  
00723  *  The function GATAdvertService_GetMetaData gets the meta data for the 
00724  *  specified AD entry.
00725  *
00726  *  @param object The GATAdvertService instance, from which the metadata of the
00727  *        given path should be returned.
00728  *  @param path The path of the entry, for which the meta data should be 
00729  *        retrieved.
00730  *  @param The pointer to a variable, which receives the requested meta data 
00731  *        (the returned GATTable object should be free'd by the user of this
00732  *        function).
00733  *
00734  *  @return An error code.
00735  */
00736 GATResult
00737 GATAdvertService_GetMetaData(GATAdvertService_const object, 
00738   GATString_const path, GATTable *metadata)
00739 {
00740   if (NULL != object)
00741   {
00742     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_GetMetaData");
00743     GAT_CREATE_STATUS(GATAdvertServiceCPI_GetMetaData(object->cpi, 
00744       &object->data, path, metadata));
00745     return GAT_RETURN_STATUS();
00746   }
00747   return GAT_INVALID_HANDLE;
00748 }
00749 
00750 /** GATAdvertService_GetAdvertisable
00751  *  
00752  *  The function GATAdvertService_GetAdvertisable gets the Advertisable instance 
00753  *  for the specified GATAdvertService entry.
00754  *
00755  *  @param object The GATAdvertService instance, from which the advertisable of 
00756  *        the given path should be returned.
00757  *  @param path The path of the entry, for which the stroed advertisable should 
00758  *        be retrieved.
00759  *  @param advertisable The pointer to a variable, which should receive the 
00760  *        requested advertisable object (the returned GATObject should be 
00761  *        free'd by the user of this function).
00762  *
00763  *  @return An error code.
00764  */
00765 GATResult
00766 GATAdvertService_GetAdvertisable(GATAdvertService_const object, 
00767   GATString_const path, GATObject *advertisable)
00768 {
00769   if (NULL != object)
00770   {
00771     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_GetAdvertisable");
00772     GAT_CREATE_STATUS(GATAdvertServiceCPI_GetAdvertisable(object->cpi, 
00773       &object->data, path, advertisable));
00774     return GAT_RETURN_STATUS();
00775   }
00776   return GAT_INVALID_HANDLE;
00777 }
00778 
00779 /** GATAdvertService_Find
00780  *  
00781  *  The function GATAdvertService_Find queries the GATAdvertService for entries 
00782  *  matching the specified set of meta data.
00783  *
00784  *  @param object The GATAdvertService instance, inside which the query should 
00785  *        be executed.
00786  *  @param metadata The meta data search criteria to use for the query.
00787  *  @param paths The pointer to a variable, which should receive the list of
00788  *        paths pointing to matching entries inside the given advert service
00789  *        (the returned list of strings should be free'd by the user of this 
00790  *        function).
00791  *
00792  *  @return An error code.
00793  */
00794 GATResult
00795 GATAdvertService_Find(GATAdvertService_const object, GATTable_const metadata,
00796   GATList_String *paths)
00797 {
00798   if (NULL != object)
00799   {
00800     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_Find");
00801     GAT_CREATE_STATUS(GATAdvertServiceCPI_Find(object->cpi, &object->data, 
00802       metadata, paths));
00803     return GAT_RETURN_STATUS();
00804   }
00805   return GAT_INVALID_HANDLE;
00806 }
00807 
00808 /** GATAdvertService_SetPWD
00809  *  
00810  *  The function GATAdvertService_SetPWD specifies the element of the 
00811  *  GATAdvertService namespace to be used as reference for relative paths.
00812  *
00813  *  @param object The GATAdvertService instance, for which the reference should 
00814  *        be set.
00815  *  @param path The path referencing the namespace element to be used as the
00816  *        reference for relative paths.
00817  *
00818  *  @return An error code.
00819  */
00820 GATResult 
00821 GATAdvertService_SetPWD(GATAdvertService object, GATString_const path)
00822 {
00823   if (NULL != object)
00824   {
00825     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_SetPWD");
00826 
00827     char const *pathstr = GATString_GetBuffer(path);
00828 
00829     if (NULL != pathstr && '/' == pathstr[0])
00830     {
00831       GATString_Destroy(&object->data.pwd);
00832       GAT_CREATE_STATUS(GATString_Clone(path, &object->data.pwd));
00833     }
00834     else
00835     {
00836       /* the path should start with a '/' */
00837       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00838     }
00839         
00840     return GAT_RETURN_STATUS();
00841   }
00842   return GAT_INVALID_HANDLE;
00843 }
00844 
00845 /** GATAdvertService_GetPWD
00846  *  
00847  *  The function GATAdvertService_GetPWD gets the path of the element of the 
00848  *  GATAdvertService namespace, which is used as reference for relative paths.
00849  *
00850  *  @param object The GATAdvertService instance, for which the reference should 
00851  *        be retrieved.
00852  *  @param path The pointer of the variable, which should receive the path 
00853  *        referencing the namespace element, which is used as the reference for 
00854  *        relative paths.
00855  *
00856  *  @return An error code.
00857  */
00858 GATResult 
00859 GATAdvertService_GetPWD(GATAdvertService object, GATString *path)
00860 {
00861   if (NULL != object)
00862   {
00863     GAT_STATUS_APIENTRY(object->data.context, "GATAdvertService_SetPWD");
00864     GAT_CREATE_STATUS(GATString_Clone(object->data.pwd, path));
00865     return GAT_RETURN_STATUS();
00866   }
00867   return GAT_INVALID_HANDLE;
00868 }
00869 
00870 /* Local functions */
00871 
00872 /*  GATAdvertService_GetCPIInstanceData
00873  *  
00874  *  The function GATAdvertService_GetCPIInstanceData returns the CPI instance data, 
00875  *  associated with the given GATAdvertService object.
00876  *
00877  *  @param object The object, for which to return the CPI instance data.
00878  *  @param data The pointer to the variable, which should receive the
00879  *        resulting CPI instance data.
00880  *
00881  *  @return An error code.
00882  */
00883 static GATResult
00884 GATAdvertService_GetCPIInstanceData(GATAdvertService object, void **data)
00885 {
00886   if (NULL != object)
00887   {
00888     GAT_USES_STATUS(object->data.context, "GATAdvertService_GetCPIInstanceData");
00889 
00890     if (NULL != data)
00891     {
00892       *data = (void *)&object->data;
00893     }
00894     else
00895     {
00896       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00897     }
00898     
00899     return GAT_RETURN_STATUS();
00900   }
00901   return GAT_INVALID_HANDLE;
00902 }
00903 
00904 /** GATAdvertService_EnsureMetaDataItem
00905  *  
00906  *  Ensure, that a given item was inserted  into the GATTable, supply a default
00907  *  value, if appropriate.
00908  */
00909 static GATResult
00910 GATAdvertService_EnsureMetaDataItem(GATContext context, char const *item, 
00911   GATTable metadata, char const *defaultvalue)
00912 {
00913   GAT_USES_STATUS(context, "GATAdvertService_EnsureMetaDataItem");
00914   
00915   if (GAT_FAILED(GATTable_Get_String(metadata, item, 0, 0)))
00916   {
00917     GAT_CREATE_STATUS(GATTable_Add_String(metadata, item, defaultvalue));
00918   }
00919   return GAT_RETURN_STATUS();
00920 }
00921 
00922 /** GATAdvertService_ExtractName
00923  *  
00924  *  Extract the name component from the given path.
00925  */
00926 static char *
00927 GATAdvertService_ExtractName(GATString_const path)
00928 {
00929   char const *pathstr = GATString_GetBuffer(path);
00930   char *last_delim = strrchr(pathstr, '/');
00931   char *result = NULL;
00932   
00933   if (NULL == last_delim)
00934   {
00935     result = GATUtil_strdup(pathstr);
00936   }
00937   else
00938   {
00939     result = GATUtil_strdup(last_delim+1);
00940   }
00941   return result;
00942 }
00943 
00944 /** GATAdvertService_ResolvePath
00945  *  
00946  */
00947 static GATResult
00948 GATAdvertService_ResolvePath(
00949   GATString_const cwd, GATString_const path, char **absolute_path)
00950 {
00951   GATResult retval = GAT_INVALID_PARAMETER;
00952   char *new_path = NULL;
00953   char const *pwd = GATString_GetBuffer(cwd);
00954   char const *pathstr = GATString_GetBuffer(path);
00955   
00956   if (NULL != pwd && NULL != pathstr)
00957   {
00958     int len = strlen(pwd);
00959     if (0 == len)
00960     {
00961       retval = GAT_INVALID_PARAMETER;
00962     }
00963     else if ('/' != pathstr[0])
00964     {
00965       /* the given path is relative */
00966       retval = GATUtil_appendstring(&new_path, pwd);
00967       if (GAT_SUCCEEDED(retval) && '/' != new_path[len-1])
00968       {
00969         /* make sure the pwd ends with an '/' */
00970         retval = GATUtil_appendstring(&new_path, "/");
00971       }
00972 
00973       if (GAT_SUCCEEDED(retval))
00974       {      
00975         /* append the relative part of the path */
00976         retval = GATUtil_appendstring(&new_path, pathstr);
00977       }
00978     }
00979     else
00980     {
00981       /* the given path is absolute */
00982       new_path = GATUtil_strdup(pathstr);
00983       if (NULL == new_path)
00984       {
00985         retval = GAT_MEMORYFAILURE;
00986       }
00987       else
00988       {
00989         retval = GAT_SUCCESS;
00990       }
00991     }
00992   
00993     /* return the complete path */
00994     if (GAT_SUCCEEDED(retval))
00995     {
00996       if (NULL != absolute_path)
00997       {
00998         *absolute_path = new_path;
00999       }
01000       else
01001       {
01002         retval = GAT_INVALID_PARAMETER;
01003       }
01004     }    
01005     if (GAT_FAILED(retval))
01006     {
01007       free(new_path);
01008     }
01009   }
01010   return retval;
01011 }