GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATEndpoint.c

Go to the documentation of this file.
00001 /** @file GATEndpoint.c
00002  * Main .c for the GATEndpoint class.
00003  * 
00004  * An GATEndpoint represents an end of a byte stream.
00005  * 
00006  * @date $Date: 2004/05/10 15:17:32 $
00007  * 
00008  * @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATEndpoint.c,v 1.22 2004/05/10 15:17:32 hartmutkaiser Exp $
00009  *
00010  *  Copyright (C) Kelly Davis
00011  *  This is part of the GAT Engine.
00012  *  Contributed by Kelly Davis <kdavis@aei.mpg.de>
00013  *
00014  *  Use, modification and distribution is subject to the Gridlab Software
00015  *  License. (See accompanying file GLlicense.txt or copy at
00016  *  http://www.gridlab.org/GLlicense.txt)
00017  */
00018  
00019 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATEndpoint.c,v 1.22 2004/05/10 15:17:32 hartmutkaiser Exp $";
00020  
00021 /* System Header Files */
00022 
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <string.h>
00026 #include <assert.h>
00027 #include <errno.h>
00028 
00029 /* POSIX.1 Files */
00030 #include <sys/utsname.h>
00031 
00032 /* GAT Header Files */
00033 #include "GAT.h"
00034 #include "GATRegistry.h"
00035 #include "GATInternal.h"
00036 #include "GATXdsWrapper.h"
00037 #include "GATEndpointCPI.h"
00038 #include "GATMetricEvent.h"
00039 
00040 /* define the vtable types */
00041 GATOBJECT_DEFINE_VTABLE(GATEndpoint);
00042 GATSERIALISABLE_DEFINE_VTABLE(GATEndpoint);
00043 GATMONITORABLE_DEFINE_VTABLE(GATEndpoint);
00044 
00045 /* Declare the converters to/from GATObject */
00046 GATOBJECT_DEFINE_CONVERTERS(GATEndpoint);
00047 
00048 /* Macros */
00049 
00050 /* Structures, unions and enums */
00051 struct GATEndpoint_S
00052 {
00053   /* supported interfaces */
00054   GATEndpoint_vtable *GATObject__vtable;
00055   GATEndpoint_ISerialisable_vtable *GATSerialisable__vtable;
00056   GATEndpoint_IMonitorable_vtable *GATMonitorable__vtable;
00057   
00058   /* instance data */
00059   GATEndpointCPI_Instance data; /* instance data of the corresponding CPI object */
00060   GATEndpointCPI cpi;           /* CPI object to use for all subsequent operations */
00061   GATEndpointCPIList cpilist;   /* CPI list of appropriate CPI objects */
00062 };
00063 
00064 /* Static function prototypes */
00065 static GATResult
00066 GATEndpoint_GetCPIInstanceData(GATEndpoint endpoint, void **data);
00067 
00068 static int
00069 GATEndpoint_DeSerialise_Create(GATContext context, GATObject stream, 
00070   char const *name, GATEndpoint *new_endpoint);
00071 
00072 static GATResult
00073 GATEndpoint_GetNodename(struct utsname systemInfo, char **nodename );
00074 
00075 static GATResult 
00076 GATEndpoint_CloneString(char **destination, const char *source);
00077 
00078 /* Endpoint scope variables */
00079 static GATEndpoint_vtable GATEndpoint__vtable = {
00080   GATEndpoint_GetType,
00081   GATEndpoint_Destroy,
00082   GATEndpoint_Equals,
00083   GATEndpoint_Clone,
00084   GATEndpoint_GetInterface,
00085   GATEndpoint_GetCPIInstanceData
00086 };
00087 
00088 static GATEndpoint_ISerialisable_vtable GATEndpoint_ISerialisable__vtable = {
00089   GATEndpoint_Serialise,
00090   GATEndpoint_DeSerialise,
00091   GATEndpoint_GetIsDirty
00092 };
00093 
00094 static GATEndpoint_IMonitorable_vtable  GATEndpoint_IMonitorable__vtable = {
00095   GATEndpoint_AddMetricListener,
00096   GATEndpoint_RegisterPolling,
00097   GATEndpoint_RemoveRegisteredMetric,
00098   GATEndpoint_GetMetrics
00099 };
00100 
00101 /* External functions */
00102 
00103 /** GATEndpoint_Register_GATSerialisable
00104  *  The GATEndpoint_Register_GATSerialisable function registers the serialization
00105  *  vtable with the GAT engine to allow generic object creation.
00106  *  This function is called by the GAT engine, there is no need to use it 
00107  *  directly.
00108  */
00109 GATResult GATEndpoint_Register_GATSerialisable(void)
00110 {
00111   return GATObject_Register_GATSerialisable(GATType_GATEndpoint, 
00112     &GATEndpoint_ISerialisable__vtable);
00113 }
00114 
00115 /**
00116  *  Constructs a unconnected instance of this class.
00117  *
00118  * @param context Used to broker resources.
00119  * @param preferences User preferences for this instance.
00120  */
00121 GATEndpoint 
00122 GATEndpoint_Create(GATContext context, GATPreferences_const preferences)
00123 {
00124   GAT_STATUS_APIENTRY(context, "GATEndpoint_Create");
00125 
00126   GATEndpoint new_endpoint = (GATEndpoint) malloc(sizeof(struct GATEndpoint_S));
00127   if(NULL != new_endpoint)
00128   {
00129     memset(new_endpoint, 0, sizeof(struct GATEndpoint_S));
00130     new_endpoint->GATObject__vtable = &GATEndpoint__vtable;
00131     new_endpoint->GATSerialisable__vtable = &GATEndpoint_ISerialisable__vtable;
00132     new_endpoint->GATMonitorable__vtable = &GATEndpoint_IMonitorable__vtable;
00133     
00134     new_endpoint->data.context = context;
00135     new_endpoint->data.isdirty = GATFalse;
00136     new_endpoint->data.source = GATEndpoint_ToGATObject_const(new_endpoint);
00137     
00138     /* find a CPI object, which can handle the endpoint */
00139     {
00140       struct utsname systemInfo;
00141       
00142       if (0 != uname(&systemInfo))
00143       {
00144         GAT_CREATE_STATUS(GAT_FAIL);
00145       }
00146       else 
00147       {
00148         GATRegistry_const registry = GATContext_internal_GetRegistry(context);
00149 
00150         GAT_CREATE_STATUS(GATEndpoint_GetNodename(systemInfo, 
00151           &new_endpoint->data.nodename));
00152             
00153         /* use default preferences, if appropriate */
00154         if (NULL == preferences)
00155         {
00156           preferences = GATContext_GetPreferences(context);
00157         }
00158         new_endpoint->cpilist = GATRegistry_FindGATEndpointCPI(registry, preferences);
00159         
00160         if (NULL == new_endpoint->cpilist)
00161         {
00162           GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00163         }
00164         else if(GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00165         {
00166           /* create a new instance of the CPI provider */
00167           GATBool found_cpi = GATFalse;
00168           GATEndpointCPIList current = NULL;
00169           for(current = new_endpoint->cpilist; NULL != current; current = current->next)
00170           {
00171             GAT_CREATE_STATUS(GATEndpointCPI_CreateInstance(current->cpi, 
00172               &new_endpoint->data));
00173             if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00174             {
00175                 new_endpoint->cpi = current->cpi;
00176                 found_cpi = GATTrue;
00177                 break;
00178             }
00179           }
00180   
00181           /* no available CPI object can handle this */
00182           if (GATFalse == found_cpi)
00183           {
00184             GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00185           }
00186           else
00187           {
00188             /* now, initialise the monitoring framework with the help of the 
00189                CPI provider found */
00190             GATList_GATMetric metrics = NULL;
00191             GATResult retval = GATEndpointCPI_GetMetrics(new_endpoint->cpi, 
00192               &new_endpoint->data, &metrics);            
00193 
00194             if (GAT_SUCCEEDED(retval))
00195             {
00196                 new_endpoint->data.monitorable = GATMonitorable_Impl_Create(metrics);
00197                 if (NULL == new_endpoint->data.monitorable)
00198                 {
00199                   GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00200                 }
00201                 GATList_GATMetric_Destroy(&metrics);
00202             }
00203             else if (GAT_NOTIMPL == retval)
00204             {
00205               retval = GAT_SUCCESS;   /* no monitoring supported here */
00206             }
00207             else
00208             {
00209               GAT_CREATE_STATUS(retval);
00210             }
00211 
00212             /* register this object with the engine */
00213             GAT_CREATE_STATUS(GATRegistry_AddGATEndpointToCPIList(context, 
00214                 new_endpoint->cpi, new_endpoint));
00215           }
00216         }
00217       }
00218     }
00219   }
00220   else
00221   {
00222     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00223   }
00224   
00225   /* error handling */
00226   if (GAT_FAILED(GAT_CURRENT_STATUS()))
00227   {
00228     GATEndpoint_Destroy(&new_endpoint);
00229   }
00230   
00231   GAT_STORE_STATUS();
00232   return new_endpoint;
00233 }
00234 
00235 /** GATEndpoint_Destroy
00236  *  The GATEndpoint destructor.
00237  *  This is the destructor for GATEndpoint objects.
00238  *
00239  * @param endpoint An old GATEndpoint
00240  */
00241 void GATEndpoint_Destroy(GATEndpoint *endpoint)
00242 {
00243   if(NULL != endpoint && NULL != *endpoint)
00244   {
00245     GATMonitorable_Impl_Destroy(&(*endpoint)->data.monitorable);
00246     if (NULL != (*endpoint)->cpi)
00247     {
00248       GATRegistry_RemoveGATEndpointFromCPIList((*endpoint)->data.context, 
00249         (*endpoint)->cpi, *endpoint);
00250       GATEndpointCPI_DestroyInstance((*endpoint)->cpi, &(*endpoint)->data);
00251     }
00252     GATEndpointCPIList_Destroy((*endpoint)->cpilist);
00253     free((*endpoint)->data.nodename);
00254     free(*endpoint);
00255     *endpoint = NULL;
00256   }
00257 }
00258 
00259 /** int GATEndpoint_GetType(GATEndpoint_const endpoint)
00260  *  @brief Return the type of the GATEndpoint
00261  *
00262  *  The function @c GATEndpoint_GetType always returns GATType_GATEndpoint. 
00263  *
00264  *  @param object The object to inspect
00265  *
00266  *  @return returns always @c #GATType_GATEndpoint.
00267  */
00268 GATType GATEndpoint_GetType(GATEndpoint_const endpoint)
00269 {
00270   GAT_UNUSED_PARAMETER(endpoint);
00271   return GATType_GATEndpoint;
00272 }
00273 
00274 /** int GATEndpoint_Clone(GATEndpoint_const endpoint, GATEndpoint *new_endpoint)
00275  *  @brief Clone the given GATEndpoint
00276  *
00277  *  The function @c GATEndpoint_Clone generates a (deep) copy of the given
00278  *  GATEndpoint. 
00279  *
00280  *  @param endpoint The object to clone
00281  *  @param new_endpoint The pointer, through which the result is to be 
00282  *        returned.
00283  *
00284  *  @return An error type.
00285  */
00286 GATResult GATEndpoint_Clone(GATEndpoint_const endpoint, GATEndpoint *new_object)
00287 {
00288   if (NULL != endpoint)
00289   {
00290     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_Clone");
00291     
00292     if (NULL != new_object)
00293     {
00294       struct GATEndpoint_S const *passedEndpoint = endpoint;
00295       GATEndpoint new_endpoint = (GATEndpoint) malloc(sizeof(struct GATEndpoint_S));
00296       
00297       *new_object = NULL;
00298       if (NULL == new_endpoint)
00299       {
00300         GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00301       }
00302       else
00303       {
00304         memset(new_endpoint, 0, sizeof(struct GATEndpoint_S));
00305         new_endpoint->GATObject__vtable = &GATEndpoint__vtable;
00306         new_endpoint->GATSerialisable__vtable = &GATEndpoint_ISerialisable__vtable;
00307         new_endpoint->GATMonitorable__vtable = &GATEndpoint_IMonitorable__vtable;
00308         
00309         new_endpoint->data.context = passedEndpoint->data.context;
00310         new_endpoint->data.isdirty = GATFalse;
00311         new_endpoint->data.source = GATEndpoint_ToGATObject_const(new_endpoint);
00312         new_endpoint->cpilist = GATRegistry_CloneGATEndpointCPIList(
00313           passedEndpoint->cpilist);
00314         
00315         GAT_CREATE_STATUS(GATEndpoint_CloneString(&(new_endpoint->data.nodename), 
00316           passedEndpoint->data.nodename ));
00317                 
00318         if (NULL == new_endpoint->cpilist)
00319         {
00320           GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00321         }
00322         else
00323         {
00324           /* re-find the cpi to use */
00325           GATEndpointCPIList current = passedEndpoint->cpilist;
00326           GATEndpointCPIList new_current = new_endpoint->cpilist;
00327           
00328           for (/**/; NULL != current; 
00329                current = current->next, new_current = new_current->next)
00330           {
00331             if (current->cpi == passedEndpoint->cpi)
00332             {
00333               new_endpoint->cpi = new_current->cpi;
00334               break;
00335             }
00336           }
00337           assert(NULL != new_endpoint->cpi);
00338           
00339           /* clone the instance data */
00340           GAT_CREATE_STATUS(GATEndpointCPI_CloneInstance(passedEndpoint->cpi, 
00341             &passedEndpoint->data, &new_endpoint->data));
00342 
00343           /* clone the monitoring data */
00344           if (NULL != passedEndpoint->data.monitorable)
00345           {
00346             GAT_CREATE_STATUS(GATMonitorable_Impl_Clone(
00347               passedEndpoint->data.monitorable, &new_endpoint->data.monitorable));
00348           }
00349           
00350           /* register this object with the engine */
00351           GAT_CREATE_STATUS(GATRegistry_AddGATEndpointToCPIList(
00352             new_endpoint->data.context, new_endpoint->cpi, new_endpoint));
00353         }
00354       }
00355       
00356       /* destroy the newly allocated object, if some error occured */
00357       if (GAT_FAILED(GAT_CURRENT_STATUS()))
00358       {
00359         GATEndpoint_Destroy(&new_endpoint);
00360       }
00361       else
00362       {
00363         /* return the new object */
00364         *new_object = new_endpoint;
00365       }
00366     }
00367     else
00368     {
00369       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00370     }
00371 
00372     return GAT_RETURN_STATUS();
00373   }
00374   
00375   return GAT_INVALID_HANDLE;
00376 }
00377 
00378 /** int GATEndpoint_Equals(GATEndpoint_const lhs, GATEndpoint_const rhs, GATBool *isequal)
00379  *  @brief Compares two GATEndpoint objects
00380  *
00381  *  The function @c GATEndpoint_Equals compares two endpoint objects of type 
00382  *  @c #GATEndpoint.
00383  *
00384  *  @param lhs The first endpoint object to compare
00385  *  @param rhs The second endpoint object to compare
00386  *  @param isequal The pointer to the GATBool variable, which should receive 
00387  *        the result if the comparision
00388  *
00389  *  @return An error code.
00390  */
00391 GATResult 
00392 GATEndpoint_Equals(GATEndpoint_const lhs, GATEndpoint_const rhs, GATBool *isequal)
00393 {
00394   if (NULL != lhs && NULL != rhs)
00395   {
00396     GAT_STATUS_APIENTRY(lhs->data.context, "GATEndpoint_Equals");
00397     if (NULL != isequal)
00398     {
00399       *isequal = GATFalse;
00400       if (0 == strcmp(lhs->data.nodename, rhs->data.nodename))
00401       {
00402         GAT_CREATE_STATUS(GATEndpointCPI_EqualsInstance(lhs->cpi, &lhs->data, 
00403           &rhs->data, isequal));
00404       }
00405     }
00406     return GAT_RETURN_STATUS();
00407   }
00408   return GAT_INVALID_HANDLE;
00409 }
00410 
00411 /** int GATEndpoint_GetInterface(GATEndpoint_const endpoint, GATInterface iftype, void const **ifp)
00412  *  @brief Get an interface supported by a GATObject
00413  *
00414  *  The function GATEndpoint_GetInterface allows to get a pointer to an 
00415  *  additional interface supported by this GATEndpoint.
00416  *
00417  *  @param object The object to be asked for the new interface.
00418  *  @param iftype The interface the object is to be asked for.
00419  *  @param ifp The pointer, through which the result is to be returned.
00420  *
00421  *  @return An error type.
00422  */
00423 GATResult 
00424 GATEndpoint_GetInterface(GATEndpoint_const endpoint, GATInterface iftype, 
00425   void const **ifp)
00426 {
00427   if (NULL != endpoint)
00428   {
00429     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_GetInterface");
00430     
00431     if (NULL != ifp)
00432     {
00433       *ifp = NULL;
00434       if (GATInterface_ISerialisable == iftype || 
00435           GATInterface_IAdvertisable == iftype)
00436       {
00437         *ifp = (void const *) &endpoint->GATSerialisable__vtable;
00438       }
00439       else if (GATInterface_IMonitorable == iftype && NULL != endpoint->data.monitorable)
00440       {
00441         *ifp = (void const *) &endpoint->GATMonitorable__vtable;
00442       }
00443       else
00444       {
00445         *ifp = NULL;
00446         GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00447       }
00448     }
00449     else
00450     {
00451       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00452     }
00453     return GAT_RETURN_STATUS();
00454   }
00455   return GAT_INVALID_HANDLE;
00456 }
00457 
00458 /**
00459  *  When a GATEndpoint is obtained from an Advert Directory, it can be
00460  *  used to create a GATPipe connected to the advertising application,
00461  *  by calling connect on the GATEndpoint instance.  This method takes
00462  *  no parameters.  The GATEndpoint can be destroyed at any time
00463  *  without affecting the obtained GATPipe.
00464  *
00465  * @param endpoint The GATEndpoint on which to act
00466  * @param peep A GATPipe connected to the endpoint
00467  */
00468 GATResult GATEndpoint_Connect(GATEndpoint_const endpoint, GATPipe *peep)
00469 {
00470   if (NULL != endpoint)
00471   {
00472     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_Connect");
00473     GAT_CREATE_STATUS(GATEndpointCPI_Connect(endpoint->cpi, &endpoint->data, 
00474       peep));
00475     return GAT_RETURN_STATUS();
00476   }
00477   return GAT_INVALID_HANDLE;
00478 }
00479 
00480 /**
00481  * The creator of an GATEndpoint can use the GATEndpoint to create
00482  * GATPipes, which represent incoming connections.  This is done by
00483  * calling Listen on the GATEndpoint instance.  The GATEndpoint can
00484  * be destroyed at any time without affecting the obtained GATPipe.
00485  *
00486  * @param endpoint The GATEndpoint on which to act
00487  * @param peep A GATPipe connected to the endpoint
00488  */
00489 GATResult GATEndpoint_Listen(GATEndpoint_const endpoint, GATPipe *peep)
00490 {
00491   if (NULL != endpoint)
00492   {
00493     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_Listen");
00494     GAT_CREATE_STATUS(GATEndpointCPI_Listen(endpoint->cpi, &endpoint->data, 
00495       peep));
00496     return GAT_RETURN_STATUS();
00497   }
00498   return GAT_INVALID_HANDLE;
00499 }
00500 
00501 /**
00502  * The creator of an GATEndpoint can use the GATEndpoint to create
00503  * GATPipes, which represent incoming connections.  This is done by
00504  * calling Listen on the GATEndpoint instance.  This call is
00505  * asynchroneous, and returns immediately.  The GATPipe creation is
00506  * performed on the passed GATPipeListener \object. The
00507  * GATEndpoint can be destroyed at any time without affecting the
00508  * obtained GATPipe.
00509  *
00510  * @param endpoint The GATEndpoint on which to act
00511  * @param peepListener GATPipeListener object which handles incoming connections
00512  * @param listenerData Callback data
00513  */
00514 GATResult 
00515 GATEndpoint_AddGATPipeListener(GATEndpoint_const endpoint, 
00516   GATPipeListener peepListener, void *listenerData)
00517 {
00518   if (NULL != endpoint)
00519   {
00520     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_AddGATPipeListener");
00521     GAT_CREATE_STATUS(GATEndpointCPI_AddGATPipeListener(endpoint->cpi, 
00522       &endpoint->data, peepListener, listenerData));
00523     return GAT_RETURN_STATUS();
00524   }
00525   return GAT_INVALID_HANDLE;
00526 }
00527 
00528 /* GATMonitorable */
00529 
00530 /** GATEndpoint_AddMetricListener
00531  *
00532  *  The function GATEndpoint_AddMetricListener adds the passed instance of a 
00533  *  GATMetricListener to the list of GATMetricListeners which are notified of 
00534  *  fired GATMetricEvents of the type described by the provided GATMetric 
00535  *  instance.
00536  *
00537  *  @param endpoint The GATEndpoint instance to add the GATMetricListener to.
00538  *  @param listener The GTAMetricListener to call, when the corresponding 
00539  *        GATMetricEvent is fired.
00540  *  @param listener_data The client supplied data, which will be passed through
00541  *        to the GATMetricListener.
00542  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00543  *        to the GATMetricListener.
00544  *  @param cookie The returned value should be used to remove the 
00545  *        GATMetricListener from this GATMonitorable.
00546  *
00547  *  @return An error code.
00548  */ 
00549 GATResult 
00550 GATEndpoint_AddMetricListener(GATEndpoint endpoint, GATMetricListener listener,
00551   void *listener_data, GATMetric metric, GATuint32 *cookie)
00552 {
00553   if (NULL != endpoint)
00554   {
00555     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_AddMetricListener");
00556     
00557     if (NULL != endpoint->data.monitorable)
00558     {
00559       GAT_CREATE_STATUS(GATMonitorable_Impl_AddMetricListener(endpoint->data.monitorable, 
00560         listener, listener_data, metric, cookie));
00561     } 
00562     else
00563     { 
00564       /* this may happen, if the adaptor has not registered any GATMetrics */
00565       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00566     }
00567     
00568     return GAT_RETURN_STATUS();
00569   }
00570   return GAT_INVALID_HANDLE;
00571 }
00572 
00573 /** GATEndpoint_RegisterPolling
00574  *
00575  *  The function GATEndpoint_RegisterPolling registers a continuous 
00576  *  metric with the given GATEndpoint instance.
00577  *
00578  *  @param endpoint The GATEndpoint instance to register the metric with.
00579  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00580  *        to the GATMetricListener. This metric instance must be of type
00581  *        GATMeasurementType_Continuous, otherwise an error is returned.
00582  *  @param event The pointer to a variable, which should receive the resulting
00583  *        GATMetricEvent. The GATMetricEvent instance should be freed by the 
00584  *        caller when it isn't used anymore.
00585  *  @param cookie The returned value should be used to remove the 
00586  *        GATMetricListener from this GATEndpoint.
00587  *
00588  *  @return An error code.
00589  */ 
00590 GATResult 
00591 GATEndpoint_RegisterPolling(GATEndpoint endpoint, GATMetric metric, GATMetricEvent *event, 
00592   GATuint32 *cookie)
00593 {
00594   if (NULL != endpoint)
00595   {
00596     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_RegisterPolling");
00597     
00598     if (NULL != endpoint->data.monitorable)
00599     {
00600       GAT_CREATE_STATUS(GATMonitorable_Impl_RegisterPolling(
00601         endpoint->data.monitorable, metric, 0, cookie));
00602 
00603       /* ask the CPI provider to return the corresponding metric event */
00604       GAT_CREATE_STATUS(GATEndpointCPI_GetMetricEvent(endpoint->cpi, 
00605         &endpoint->data, metric, event));
00606 
00607       if (GAT_FAILED(GAT_CURRENT_STATUS()) && NULL != cookie && 0 != *cookie)
00608       {
00609         GATMonitorable_Impl_RemoveRegisteredMetric(endpoint->data.monitorable,
00610           metric, *cookie);
00611         *cookie = 0;
00612       }
00613     } 
00614     else
00615     { 
00616       /* this may happen, if the adaptor has not registered any GATMetrics */
00617       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00618     }
00619     
00620     return GAT_RETURN_STATUS();
00621   }
00622   return GAT_INVALID_HANDLE;
00623 }
00624 
00625 /** GATEndpoint_RemoveRegisteredMetric
00626  *
00627  *  The function GATEndpoint_RemoveRegisteredMetric removes a GATMetricListener, 
00628  *  which was previously registered with GATEndpoint_AddMetricListener.
00629  *
00630  *  @param endpoint The GATEndpoint instance to remove the GATMetricListener from.
00631  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00632  *        to the GATMetricListener.
00633  *  @param cookie This value identifies the GATMetricListener to remove, it 
00634  *        was returned from the corresponding GATMonitorable_AddMetricListener 
00635  *        or GATMonitorable_MetricRegisterPolling functions.
00636  *  
00637  *  @return An error code.
00638  */
00639 GATResult GATEndpoint_RemoveRegisteredMetric(GATEndpoint endpoint, GATMetric metric, 
00640   GATuint32 cookie)
00641 {
00642   if (NULL != endpoint)
00643   {
00644     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_RemoveRegisteredMetric");
00645     
00646     if (NULL != endpoint->data.monitorable)
00647     {
00648       GAT_CREATE_STATUS(GATMonitorable_Impl_RemoveRegisteredMetric(
00649         endpoint->data.monitorable, metric, cookie));
00650     } 
00651     else
00652     { 
00653       /* this may happen, if the adaptor has not registered any GATMetrics */
00654       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00655     }
00656     
00657     return GAT_RETURN_STATUS();
00658   }
00659   return GAT_INVALID_HANDLE;
00660 }
00661 
00662 /** GATEndpoint_GetMetrics
00663  *
00664  *  The function GATEndpoint_GetMetrics returns a list of metrics supported by this
00665  *  GATEndpoint.
00666  *
00667  *  @param endpoint The GATEndpoint instance, for which the supported metrics should be 
00668  *        returned.
00669  *  @param metrics The pointer to the variable, which receives the resulting 
00670  *        list of metrics.
00671  *
00672  *  @return An error code.
00673  */
00674 GATResult 
00675 GATEndpoint_GetMetrics(GATEndpoint_const endpoint, GATList_GATMetric *metrics)
00676 {
00677   if (NULL != endpoint)
00678   {
00679     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_GetMetrics");
00680     
00681     if (NULL != endpoint->data.monitorable)
00682     {
00683       GAT_CREATE_STATUS(GATMonitorable_Impl_GetMetrics(
00684         endpoint->data.monitorable, metrics));
00685     } 
00686     else
00687     { 
00688       /* this may happen, if the adaptor has not registered any GATMetrics */
00689       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00690     }
00691     
00692     return GAT_RETURN_STATUS();
00693   }
00694   return GAT_INVALID_HANDLE;
00695 }
00696 
00697 
00698 /* GATAdvertiseable API */
00699 
00700 /** GATEndpointCPI_SerialiseCallback
00701  *
00702  *  The function GATEndpointCPI_SerialiseCallback is used as a callback function 
00703  *  for the serialisation of a GATEndpoint object. It should be provided to 
00704  *  serialise the associated CPI provider data for the given object.
00705  *
00706  *  @param object The object to serialise. This is the same as the object 
00707  *        passed as the first parameter to the function GATXds_SerialiseObject.
00708  *  @param stream The stream interface to use for the serialisation.
00709  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
00710  *        internal dirty flag of this object is to be reset (no used here)
00711  *
00712  *  @return An error code.
00713  *
00714  *  @remark This function is called from the GAT engine, there is no need to 
00715  *        call it directly.
00716  */
00717 static GATResult 
00718 GATEndpointCPI_SerialiseCallback(GATObject object, GATObject stream, 
00719   GATBool clear_dirty)
00720 {
00721   GATEndpoint endpoint = GATObject_ToGATEndpoint(object);
00722   if (NULL != endpoint)
00723   {
00724     GAT_USES_STATUS(endpoint->data.context, "GATEndpointCPI_SerialiseCallback");
00725     
00726     GAT_CREATE_STATUS(GATEndpointCPI_Serialise(endpoint->cpi, &endpoint->data, 
00727       stream, clear_dirty));
00728 
00729     if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()) && GATTrue == clear_dirty)
00730     {
00731       endpoint->data.isdirty = GATFalse;
00732     }
00733 
00734     return GAT_RETURN_STATUS();
00735   }
00736   return GAT_INVALID_HANDLE;
00737 }
00738 
00739 /** int GATEndpoint_Serialise(GATEndpoint endpoint, GATObject stream, GATBool clear_dirty)
00740  *  @brief Serialise a GATEndpoint object
00741  *
00742  *  The function GATEndpoint_Serialise serialises the given GATFIle object into the
00743  *  given stream. 
00744  *
00745  *  @param endpoint The GATEndpoint object to serialise.
00746  *  @param stream The stream interface to use for the serialisation.
00747  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
00748  *        internal dirty flag of this object is to be reset (no used here)
00749  *
00750  *  @return An error code.
00751  */
00752 GATResult 
00753 GATEndpoint_Serialise(GATEndpoint endpoint, GATObject stream, 
00754   GATBool clear_dirty)
00755 {
00756   if (NULL != endpoint)
00757   {
00758     GAT_USES_STATUS(endpoint->data.context, "GATEndpoint_Serialise");
00759     
00760     GAT_CREATE_STATUS(GATXds_SerialiseObject(GATEndpoint_ToGATObject(endpoint), 
00761       stream, clear_dirty, GATEndpointCPI_SerialiseCallback, 
00762       "uint32 string", GATENDPOINT_VERSION1, endpoint->data.nodename));
00763     
00764     return GAT_RETURN_STATUS();
00765   }
00766   return GAT_INVALID_HANDLE;
00767 }
00768 
00769 /** GATEndpointCPI_VersionCallback
00770  *
00771  *  The function GATEndpointCPI_VersionCallback is used as a callback function
00772  *  during the de-serialisation of a GATEndpoint. It should be provided to test,
00773  *  whether the de-serialised version matches the expected version.
00774  *
00775  *  @param version The version number, which was de-serialised from the stream.
00776  *
00777  *  @return This function should return GATTrue, if the version matches the 
00778  *        expected value (version is valid), GATFalse otherwise.
00779  *
00780  *  @remark This function is called from the GAT engine, there is no need to 
00781  *        call it directly.
00782  */
00783 static GATBool
00784 GATEndpointCPI_VersionCallback(GATuint32 version)
00785 {
00786   GATBool retval = GATFalse;
00787   if ((version & ~GATENDPOINT_MINOR_MASK) <= GATENDPOINT_LASTVERSION)
00788   {
00789     retval = GATTrue;
00790   }
00791   return retval;
00792 }
00793 
00794 /** GATEndpointCPI_DeSerialiseCallback
00795  *
00796  *  The function GATEndpointCPI_DeSerialiseCallback is used as a callback function
00797  *  during the de-serialisation of a GATEndpoint. It should be provided for the
00798  *  instantiation of the new GATEndpoint object based on the already de-serialised 
00799  *  data items and the de-serialisation of the associated CPI provider data for 
00800  *  the given object.
00801  *
00802  *  @param context The GAT context to be used for object construction.
00803  *  @param stream The stream interface to use for the serialisation.
00804  *  @param object The pointer to the variable, which should receive the newly 
00805  *        constructed object.
00806  *  @param version The version of the saved data read from the input stream.
00807  *  @param args This parameter is the pointer to the va_list containing 
00808  *        pointers to the already de-serialised data items accordingly to the
00809  *        format string, provided during the call to the 
00810  *        GATEndpoint_DeSerialise function.
00811  *
00812  *  @return An error code.
00813  *
00814  *  @remark This function is called from the GAT engine, there is no need to 
00815  *        call it directly.
00816  */
00817 static GATResult
00818 GATEndpointCPI_DeSerialiseCallback(GATContext context, GATObject stream, 
00819   GATObject *object, GATuint32 version, va_list args)
00820 {
00821   GAT_USES_STATUS(context, "GATEndpointCPI_DeSerialiseCallback");
00822   
00823   /* the version was eaten already */
00824   char const **nodename = va_arg(args, char const **);
00825   GATEndpoint endpoint = NULL;
00826 
00827   struct utsname sysinfo;
00828   
00829   GAT_CREATE_STATUS_IF(uname(&sysinfo) != 0, POSIX_TO_GAT(errno));  
00830   GAT_CREATE_STATUS(GATEndpoint_DeSerialise_Create(context, stream, 
00831     *nodename, &endpoint));
00832   
00833   /* Silly stuff */
00834   GAT_UNUSED_PARAMETER(version);
00835   
00836   /* construct the new object */
00837   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00838   {
00839     if (NULL != object)
00840     {
00841       *object = GATEndpoint_ToGATObject(endpoint);
00842     }
00843     else
00844     {
00845       GATEndpoint_Destroy(&endpoint);
00846       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00847     }
00848   }
00849   
00850   return GAT_RETURN_STATUS();
00851 }
00852 
00853 /** GATEndpoint GATEndpoint_DeSerialise(GATContext context, GATObject stream, GATResult clear_dirty)
00854  *  @brief De-serialise a GATEndpoint object
00855  *
00856  *  The function GATEndpoint_DeSerialise de-serialises a streamed GATEndpoint object  
00857  *  from the given stream  It constructs a new instance of the de-serialised 
00858  *  object.
00859  *
00860  *  @param context The GAT context to be used for object construction.
00861  *  @param stream The stream interface to use for the serialisation.
00862  *  @param result The pointer to a variable, which receives the status code of
00863  *        the operation.
00864  *
00865  *  @return The newly constructed GATEndpoint object.
00866  */
00867 GATEndpoint 
00868 GATEndpoint_DeSerialise(GATContext context, GATObject stream, GATResult *result)
00869 {
00870   GAT_USES_STATUS(context, "GATEndpoint_DeSerialise");
00871   
00872   GATObject object = NULL;     /* the new object will be created here */
00873   GATEndpoint endpoint = NULL;
00874   
00875   /* we must provide all instance data items to be de-serialised for this
00876      GATEndpoint object accordingly to the provided format string */
00877   GATuint32 version = 0;
00878   char *nodename = NULL;
00879   
00880   /* read the data */
00881   GAT_CREATE_STATUS(GATXds_DeSerialiseObject(context, stream, 
00882     GATEndpointCPI_DeSerialiseCallback, GATEndpointCPI_VersionCallback, 
00883     &object, "uint32 string", &version, &nodename));
00884 
00885   free(nodename);
00886   
00887   endpoint = GATObject_ToGATEndpoint(object);
00888   if (NULL == endpoint)
00889   {
00890     GAT_CREATE_STATUS(GAT_BAD_OBJECT_CONVERSION);
00891   }
00892   
00893   if (GAT_FAILED(GAT_CURRENT_STATUS()))
00894   {
00895     GATObject_Destroy(&object);
00896     endpoint = NULL;
00897   }
00898   
00899   if (NULL != result)
00900   { 
00901     *result = GAT_CURRENT_STATUS();
00902   }
00903   
00904   GAT_STORE_STATUS();
00905   return endpoint;
00906 }
00907 
00908 /** GATEndpoint_GetIsDirty
00909  *  
00910  *  The function GATEndpoint_GetIsDirty retrieves the status of the dirty flag of 
00911  *  this GATEndpoint object.
00912  *
00913  *  @param endpoint The GATEndpoint object to inspect for its dirty status.
00914  *  @param isdirty The pointer to a variable, which receives the dirty status.
00915  *
00916  *  @return An error code.
00917  */
00918 GATResult GATEndpoint_GetIsDirty(GATEndpoint_const endpoint, GATBool *isdirty)
00919 {
00920   if (NULL != endpoint)
00921   {
00922     GAT_STATUS_APIENTRY(endpoint->data.context, "GATEndpoint_GetIsDirty");
00923     
00924     if (NULL != isdirty)
00925     {
00926       *isdirty = endpoint->data.isdirty;
00927     }
00928     else
00929     {
00930       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00931     }
00932     
00933     return GAT_RETURN_STATUS();
00934   }  
00935   return GAT_INVALID_HANDLE;
00936 }
00937 
00938 /* Local functions */
00939 
00940 /** GATEndpoint_DeSerialise_Create
00941  *
00942  *  The function GATEndpoint_DeSerialise_Create creates a new GATEndpoint object and
00943  *  tries to find a CPI provider to associate with this endpoint object. The CPI
00944  *  provider is selected by testing, which adapter is able to handle the 
00945  *  streamed instance data of the original CPI provider.
00946  *
00947  *  @param context The GAT context to use for creation of the GATEndpoint object.
00948  *  @param stream The object from which the adaptor should read the streamed
00949  *        instance data.
00950  *  @param new_object The pointer to the variable, which should receive the 
00951  *        newly constructed GATEndpoint object.
00952  *
00953  *  @return An error code.
00954  */
00955 static GATResult
00956 GATEndpoint_DeSerialise_Create(GATContext context, GATObject stream, 
00957   char const *name, GATEndpoint *new_object)
00958 {
00959   GAT_USES_STATUS(context, "GATEndpoint_DeSerialise_Create");
00960   
00961   GATEndpoint new_endpoint = (GATEndpoint) malloc(sizeof(struct GATEndpoint_S));
00962 
00963   if(NULL != new_endpoint)
00964   {
00965     memset(new_endpoint, 0, sizeof(struct GATEndpoint_S));
00966     new_endpoint->GATObject__vtable = &GATEndpoint__vtable;
00967     new_endpoint->GATSerialisable__vtable = &GATEndpoint_ISerialisable__vtable;
00968     new_endpoint->GATMonitorable__vtable = &GATEndpoint_IMonitorable__vtable;
00969     
00970     new_endpoint->data.context = context;
00971     new_endpoint->data.isdirty = GATFalse;
00972     new_endpoint->data.source = GATEndpoint_ToGATObject_const(new_endpoint);
00973     
00974     /* find a CPI object, which can handle the data at the given stream 
00975        location */
00976     {
00977       GATRegistry_const registry = GATContext_internal_GetRegistry(context);
00978       GATPreferences_const preferences = NULL;
00979             
00980       /* use default preferences, if appropriate */
00981       if (NULL == preferences)
00982       {
00983         preferences = GATContext_GetPreferences(context);
00984       }
00985 
00986       GAT_CREATE_STATUS(GATEndpoint_CloneString(&new_endpoint->data.nodename, 
00987         name));
00988       new_endpoint->cpilist = GATRegistry_FindGATEndpointCPI(registry, preferences);
00989       if (NULL == new_endpoint->cpilist)
00990       {
00991         GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00992       }
00993       else if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00994       {
00995         /* find out the current stream position */
00996         GATuint32 offset = 0;
00997         GATBool found_cpi = GATFalse;
00998         GATEndpointCPIList current = NULL;
00999         
01000         GAT_CREATE_STATUS(GATStreamable_Seek(stream, GATOrigin_Current, 0, 
01001           &offset));
01002         if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01003         {
01004           /* create new instance data of the CPI provider */
01005           for(current = new_endpoint->cpilist; NULL != current; 
01006               current = current->next)
01007           {
01008             /* try, whether this cpi can handle the input */
01009             GAT_CREATE_STATUS(GATEndpointCPI_DeSerialise(current->cpi, stream, 
01010               &new_endpoint->data));
01011             if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01012             {
01013               new_endpoint->cpi = current->cpi;
01014               found_cpi = GATTrue;
01015               break;
01016             }
01017             
01018             /* reset stream pointer to the beginning of the CPI instance data */
01019             GAT_CREATE_STATUS(GATStreamable_Seek(stream, GATOrigin_Set, offset, 0));
01020           }
01021         }
01022         
01023         /* no available CPI object can handle this */
01024         if (GATFalse == found_cpi)
01025         {
01026           GAT_CREATE_STATUS(GAT_NO_MATCHING_CPI);
01027         }
01028         else
01029         {
01030           /* try to re-init the monitoring support, since the adaptor found may
01031              support another set of GATMetric's, than the original one. */
01032           GATList_GATMetric metrics = NULL;
01033 
01034           GATResult retval = GATEndpointCPI_GetMetrics(new_endpoint->cpi, 
01035             &new_endpoint->data, &metrics);            
01036           if (GAT_SUCCEEDED(retval))
01037           {
01038             new_endpoint->data.monitorable = GATMonitorable_Impl_Create(metrics);
01039             if (NULL == new_endpoint->data.monitorable)
01040             {
01041               GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
01042             }
01043             GATList_GATMetric_Destroy(&metrics);
01044           }
01045           else if (GAT_NOTIMPL != retval)
01046           {
01047             GAT_CREATE_STATUS(retval);
01048           }
01049           {
01050             retval = GAT_SUCCESS;   /* no monitoring supported here */
01051           }
01052           
01053           if (GAT_SUCCEEDED(retval))
01054           {
01055             GAT_CREATE_STATUS(GATRegistry_AddGATEndpointToCPIList(
01056               new_endpoint->data.context, new_endpoint->cpi, new_endpoint));
01057           }
01058         }
01059       }
01060     }
01061   }
01062   else
01063   {
01064     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
01065   }
01066 
01067   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01068   {
01069     if (NULL != new_object)
01070     {
01071       *new_object = new_endpoint;
01072     }
01073     else
01074     {
01075       GATEndpoint_Destroy(&new_endpoint);
01076       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
01077     }
01078   }
01079   else
01080   {
01081     GATEndpoint_Destroy(&new_endpoint);
01082   }
01083   
01084   return GAT_RETURN_STATUS();
01085 }
01086 
01087 /** GATEndpoint_GetNodename
01088  *
01089  * This function takes a <code>struct utsname</code> struct and returns a copy
01090  * of the <code>nodename</code> element in the passed structure.
01091  *
01092  * @param systemInfo The <code>struct utsname</code> to quell info from
01093  * @param nodename A copy of the nodename contained in the passed structure
01094  * @return A GAT error code
01095  */
01096 static GATResult 
01097 GATEndpoint_GetNodename(struct utsname systemInfo, char **nodename)
01098 {
01099   GATResult retval = GAT_INVALID_PARAMETER;
01100   if (NULL != nodename)
01101   {
01102     retval = GATEndpoint_CloneString(nodename, systemInfo.nodename);
01103   }
01104   return retval;
01105 }
01106 
01107 /** GATEndpoint_CloneString
01108  * Creates a clone of a string
01109  *
01110  * @param destination The destination string
01111  * @param source The source string
01112  * @return The error code
01113  */
01114 static GATResult 
01115 GATEndpoint_CloneString(char **destination, const char *source)
01116 {
01117   GATResult retval = GAT_INVALID_PARAMETER;;
01118 
01119   if (NULL != destination && NULL != source)
01120   {
01121     int sourceLength = strlen(source) + 1;
01122     char *tempDestination = (char *) malloc(sourceLength);
01123     
01124     if (NULL != tempDestination)
01125     {
01126       strcpy( tempDestination, source );
01127       *destination = tempDestination;
01128       retval = GAT_SUCCESS;
01129     }
01130     else
01131     {
01132       retval = GAT_MEMORYFAILURE;
01133     }
01134   }
01135   return retval;
01136 }
01137 
01138 /*  GATEndpoint_GetCPIInstanceData
01139  *  
01140  *  The function GATEndpoint_GetCPIInstanceData returns the CPI instance data, 
01141  *  associated with the given GATFile object.
01142  *
01143  *  @param endpoint The object, for which to return the CPI instance data.
01144  *  @param data The pointer to the variable, which should receive the
01145  *        resulting CPI instance data.
01146  *
01147  *  @return An error code.
01148  */
01149 static GATResult
01150 GATEndpoint_GetCPIInstanceData(GATEndpoint endpoint, void **data)
01151 {
01152   if (NULL != endpoint)
01153   {
01154     GAT_USES_STATUS(endpoint->data.context, "GATEndpoint_GetCPIInstanceData");
01155 
01156     if (NULL != data)
01157     {
01158       *data = (void *)&endpoint->data;
01159     }
01160     else
01161     {
01162       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
01163     }
01164     
01165     return GAT_RETURN_STATUS();
01166   }
01167   return GAT_INVALID_HANDLE;
01168 }
01169