GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATMonitorable.c

Go to the documentation of this file.
00001 /** @file GATMonitorable.c
00002  *  Source file for the GATMonitorable_Impl class.
00003  *
00004  *  This implementation of the GATMonitorable interface, which is meant as a 
00005  *  generic helper class, which may be used by other GATObjects to implement 
00006  *  its GATMonitorable interface.
00007  *
00008  *  The GATMonitorable_Impl class is essentially a table of lists, where the 
00009  *  GATMetric is used as the key type for the table and the list contains the
00010  *  GATMetricListener's for the GATMetric used as the key.
00011  *
00012  *  @date Mon Nov 3 2003
00013  *
00014  *  @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATMonitorable.c,v 1.16 2004/04/02 12:31:58 hartmutkaiser Exp $
00015  *
00016  *  Use, modification and distribution is subject to the Gridlab Software
00017  *  License. (See accompanying file GLlicense.txt or copy at
00018  *  http://www.gridlab.org/GLlicense.txt)
00019  */
00020  
00021 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATMonitorable.c,v 1.16 2004/04/02 12:31:58 hartmutkaiser Exp $";
00022  
00023 /* System Header Files */
00024 #include <stdlib.h>
00025 #include <string.h>
00026 
00027 /* GAT Header Files */
00028 #include "GAT.h"
00029 
00030 #include "GATTableAnyKey.h"
00031 #include "GATInternal.h"
00032 #include "GATMonitorable.h"
00033 
00034 /*
00035  *  The structure stored for a GATMetric inside the corresponding list
00036  */
00037 typedef struct GATMetricListenerData {
00038   GATMetricListener listener;              /* the GATMetrciListener to call */
00039   void *data;               /* the supplied data for this GATMetricListener */
00040   GATuint32 cookie;  /* cookie identifying the registered GATMetricListener */
00041 } GATMetricListenerData;
00042 
00043 /* 
00044  *  Define the type specific interface functions for the GATList_GATMetric and
00045  *  GATMetricListener lists 
00046  */
00047 GATLIST_IMPLEMENT(extern, GATMetric, GATList_GATMetric, GATType_GATMetric);
00048 GATLIST_DEFINE_QUALIFIED(static, GATMetricListenerData, 
00049   GATList_GATMetricListenerData, GATType_PlainOldData);
00050 
00051 /* Declare the converters to/from GATObject */
00052 GATOBJECT_DEFINE_CONVERTERS_QUALIFIED(static, GATList_GATMetricListenerData,
00053   GATType_GATList);
00054 
00055 /*
00056  *  Define the vtable for this object
00057  */
00058 GATOBJECT_DEFINE_VTABLE(GATMonitorable_Impl);
00059 GATMONITORABLE_DEFINE_VTABLE(GATMonitorable_Impl);
00060 
00061 /* Macros */
00062 
00063 /* Structures, unions and enums */
00064 
00065 /*
00066  *  The GATMonitorable_Impl_S structure holds the internal representation of a 
00067  *  GATMonitorable_Impl instance.
00068  */
00069 struct GATMonitorable_Impl_S {
00070   /* the vtable of this structure */
00071   GATMonitorable_Impl_vtable *GATObject__vtable;
00072   GATMonitorable_Impl_IMonitorable_vtable *GATMonitorable_Impl__vtable;
00073   
00074   /* Instance data */
00075   GATTable metrics;   /* table of lists containing the GATMetricListener */
00076 };
00077 
00078 /* Static function prototypes */
00079 static GATType 
00080 GATMonitorable_Impl_GetType(GATMonitorable_Impl_const monitorable);
00081 
00082 static GATResult 
00083 GATMonitorable_Impl_GetInterface(GATMonitorable_Impl_const monitorable, 
00084   GATInterface iftype, void const **ifp);
00085 
00086 /* callback functions for the GATMetric table */
00087 static GATuint32 
00088   GATMonitorable_Impl_GetKeySize(GATTable_const monitorable, 
00089     void const *key);
00090   
00091 static GATBool 
00092   GATMonitorable_Impl_EqualKeys(GATTable_const monitorable, void const *key1, 
00093     void const *key2);
00094   
00095 static GATResult
00096   GATMonitorable_Impl_CloneKey(GATTable_const monitorable, void const *src,
00097     void **dest);
00098 
00099 static unsigned long 
00100   GATMonitorable_Impl_HashKey(GATTable_const monitorable, void const *key);
00101   
00102 static void
00103   GATMonitorable_Impl_DestroyKey(GATTable_const monitorable, void **key);
00104 
00105 static GATMetric_const GATMonitorable_Impl_GetMetric();
00106 static GATMetricListener GATMonitorable_Impl_GetMetricListener();
00107 
00108 /* File scope variables */
00109 static GATMonitorable_Impl_vtable GATMonitorable_Impl__vtable = {
00110   GATMonitorable_Impl_GetType,
00111   GATMonitorable_Impl_Destroy,
00112   GATMonitorable_Impl_Equals,
00113   GATMonitorable_Impl_Clone,
00114   GATMonitorable_Impl_GetInterface,
00115   NULL
00116 };
00117 
00118 static GATMonitorable_Impl_IMonitorable_vtable 
00119   GATMonitorable_Impl_IMonitorable__vtable = 
00120 {
00121   GATMonitorable_Impl_AddMetricListener,
00122   GATMonitorable_Impl_RegisterPolling,
00123   GATMonitorable_Impl_RemoveRegisteredMetric,
00124   GATMonitorable_Impl_GetMetrics
00125 };
00126 
00127 /* holds the next available cookie used for identifying the registered events */
00128 static GATuint32 cookie_jar = 0;
00129 
00130 /* External functions */
00131 
00132 /** GATMonitorable_Impl_Create
00133  *
00134  *  Create a new instance of the GATMonitorable_Impl class.
00135  *
00136  *  @return The newly constructed instance.
00137  */
00138 GATMonitorable_Impl GATMonitorable_Impl_Create(GATList_GATMetric metrics)
00139 {
00140   GATMonitorable_Impl new_monitorable = 
00141     (GATMonitorable_Impl) malloc(sizeof(struct GATMonitorable_Impl_S));
00142   
00143   if (NULL != new_monitorable)
00144   {
00145     new_monitorable->GATObject__vtable = &GATMonitorable_Impl__vtable;
00146     new_monitorable->GATMonitorable_Impl__vtable = 
00147       &GATMonitorable_Impl_IMonitorable__vtable;
00148       
00149     new_monitorable->metrics = GATTable_CreateAnyKey(
00150       GATMonitorable_Impl_GetKeySize, GATMonitorable_Impl_EqualKeys,
00151       GATMonitorable_Impl_CloneKey, GATMonitorable_Impl_HashKey, 
00152       GATMonitorable_Impl_DestroyKey);
00153     
00154     if (NULL == new_monitorable->metrics)
00155     {
00156       GATMonitorable_Impl_Destroy(&new_monitorable);
00157     }
00158     else 
00159     {
00160       /* register all GATMetrics, which should be supported here */
00161       GATList_GATMetric_Iterator it = GATList_GATMetric_Begin(metrics);
00162       GATList_GATMetric_Iterator end = GATList_GATMetric_End(metrics);
00163       GATList_GATMetricListenerData list = 
00164         GATList_GATMetricListenerData_Create();
00165       
00166       if (NULL != list)
00167       {
00168         for (/**/; it != end; it = GATList_GATMetric_Next(it))
00169         {
00170           GATMetric *metric = GATList_GATMetric_Get(it);
00171           if (NULL == metric)
00172           {
00173             break;
00174           }
00175           
00176           /* this clones the empty list into the table */
00177           GATTable_Add_GATObject(new_monitorable->metrics, *metric, 
00178             GATList_GATMetricListenerData_ToGATObject_const(list));
00179         }
00180       }
00181       GATList_GATMetricListenerData_Destroy(&list);
00182             
00183       if (it != end)
00184       {
00185         /* some error occured */
00186         GATMonitorable_Impl_Destroy(&new_monitorable);
00187       }
00188     }
00189   }
00190   return new_monitorable;
00191 }
00192 
00193 /** GATMonitorable_Impl_Destroy
00194  *  The GATMonitorable_Impl destructor.
00195  *  This is the destructor for GATMonitorable_Impl objects.
00196  *
00197  * @param monitorable An old GATMonitorable_Impl
00198  */
00199 void GATMonitorable_Impl_Destroy(GATMonitorable_Impl *monitorable)
00200 {
00201   if (NULL != monitorable && NULL != *monitorable)
00202   {
00203     GATTable_Destroy(&(*monitorable)->metrics);
00204     free(*(monitorable));
00205     *monitorable = NULL;
00206   }
00207 }
00208 
00209 /* GATMonitorable API functions */
00210 
00211 /** GATMonitorable_Impl_AddMetricListener
00212  *
00213  *  The function GATMonitorable_Impl_AddMetricListener adds the passed instance 
00214  *  of a GATMetricListener to the list of GATMetricListeners which are notified 
00215  *  of fired GATMetricEvents of the type described by the provided GATMetric 
00216  *  instance.
00217  *
00218  *  @param monitorable The GATMonitorable instance to add the GATMetricListener
00219  *        to.
00220  *  @param listener The GATMetricListener to call, when the corresponding 
00221  *        GATMetricEvent is fired.
00222  *  @param listener_data The client supplied data, which will be passed through
00223  *        to the GATMetricListener.
00224  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00225  *        to the GATMetricListener. This metric instance must be of type
00226  *        GATMeasurementType_EventLike, otherwise an error is returned.
00227  *  @param cookie The returned value should be used to remove the 
00228  *        GATMetricListener from this GATMonitorable.
00229  *
00230  *  @return An error code.
00231  */ 
00232 GATResult 
00233 GATMonitorable_Impl_AddMetricListener(GATMonitorable_Impl monitorable, 
00234   GATMetricListener listener, void *listener_data, GATMetric metric,
00235   GATuint32 *cookie)
00236 {
00237   GATResult retval = GAT_INVALID_HANDLE;
00238   if (NULL != monitorable)
00239   {
00240     if (NULL == metric || 
00241         GATMeasurementType_EventLike != GATMetric_GetMeasurementType(metric))
00242     {
00243       retval = GAT_INVALID_PARAMETER;
00244     }
00245     else
00246     {
00247       GATObject object = NULL;
00248       
00249       retval = GATTable_internal_Get_GATObjectRef(monitorable->metrics, metric, 
00250         &object);
00251       if (GAT_SUCCESS == retval)
00252       {
00253         /* insert the listener data into the appropriate list */
00254         GATMetricListenerData data;
00255         GATList_GATMetricListenerData list = 
00256           GATObject_ToGATList_GATMetricListenerData(object);
00257         GATList_GATMetricListenerData_Iterator it = 
00258           GATList_GATMetricListenerData_Begin(list);
00259         
00260         /* verify, that this listener isn't already registered with this 
00261            GATMetric */
00262         GATList_GATMetricListenerData_Iterator end = 
00263           GATList_GATMetricListenerData_End(list);
00264         for (/**/; it != end; it = GATList_GATMetricListenerData_Next(it))
00265         {
00266           GATMetricListenerData *value = GATList_GATMetricListenerData_Get(it);
00267           if (NULL == value)
00268           {
00269             retval = GAT_FAIL;
00270             break;
00271           }
00272           
00273           if (value->listener == listener)
00274           {
00275             retval = GAT_KEY_ALREADY_EXISTS;
00276             break;
00277           }
00278         }
00279         
00280         if (GAT_SUCCESS == retval)
00281         {
00282           if (NULL != cookie)
00283           {
00284             GATuint32 mycookie = ++cookie_jar;
00285             
00286             data.listener = listener;
00287             data.data = listener_data;
00288             data.cookie = mycookie;
00289             
00290             /* 
00291              * NOTE: this code directly accesses the list stored inside the 
00292              *       table 
00293              */
00294             it = GATList_GATMetricListenerData_Insert(list, end, data);
00295             if (NULL == it)
00296             {
00297               retval = GAT_MEMORYFAILURE;
00298             } 
00299             else
00300             {
00301               *cookie = mycookie;
00302             }
00303           }
00304           else
00305           {
00306             retval = GAT_INVALID_PARAMETER;
00307           }
00308         }
00309       }
00310     }
00311   }
00312   return retval;
00313 }
00314 
00315 /** GATMonitorable_Impl_RegisterPolling
00316  *
00317  *  The function GATMonitorable_Impl_RegisterPolling registers a continuous 
00318  *  metric with the given GATMonitorable instance.
00319  *
00320  *  @param monitorable The GATMonitorable instance to register the metric
00321  *        with.
00322  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00323  *        to the GATMetricListener. This metric instance must be of type
00324  *        GATMeasurementType_Continuous, otherwise an error is returned.
00325  *  @param event The pointer to a variable, which should receive the resulting
00326  *        GATMetricEvent (this parameter is ignored for this function).
00327  *  @param cookie The returned value should be used to remove the 
00328  *        GATMetricListener from this GATMonitorable.
00329  *
00330  *  @return An error code.
00331  */ 
00332 GATResult 
00333 GATMonitorable_Impl_RegisterPolling(GATMonitorable_Impl monitorable, 
00334   GATMetric metric, GATMetricEvent *event, GATuint32 *cookie)
00335 {
00336   GATResult retval = GAT_INVALID_HANDLE;
00337   if (NULL != monitorable)
00338   {
00339     if (NULL == metric || 
00340         GATMeasurementType_Continuous != GATMetric_GetMeasurementType(metric))
00341     {
00342       retval = GAT_INVALID_PARAMETER;
00343     }
00344     else
00345     {
00346       GATObject object = NULL;
00347       
00348       retval = GATTable_internal_Get_GATObjectRef(monitorable->metrics, metric, 
00349         &object);
00350       if (GAT_SUCCESS == retval)
00351       {
00352         /* insert the listener data into the appropriate list */
00353         GATMetricListenerData data;
00354         GATList_GATMetricListenerData list = 
00355           GATObject_ToGATList_GATMetricListenerData(object);
00356         GATList_GATMetricListenerData_Iterator it = 
00357           GATList_GATMetricListenerData_Begin(list);
00358         
00359         /* verify, that this listener isn't already registered with this 
00360           GATMetric */
00361         GATList_GATMetricListenerData_Iterator end = 
00362           GATList_GATMetricListenerData_End(list);
00363         for (/**/; it != end; it = GATList_GATMetricListenerData_Next(it))
00364         {
00365           GATMetricListenerData *value = GATList_GATMetricListenerData_Get(it);
00366           if (NULL == value)
00367           {
00368             retval = GAT_FAIL;
00369             break;
00370           }
00371           
00372           if (NULL == value->listener && NULL == value->data)
00373           {
00374             retval = GAT_KEY_ALREADY_EXISTS;
00375             break;
00376           }
00377         }
00378         
00379         if (GAT_SUCCESS == retval)
00380         {
00381           if (NULL != cookie)
00382           {
00383             GATuint32 mycookie = ++cookie_jar;
00384             GATList_GATMetricListenerData_Iterator new_it = NULL;
00385             
00386             data.listener = NULL;  /* this is a continuous metric */
00387             data.data = NULL;
00388             data.cookie = mycookie;
00389             
00390             /* 
00391              * NOTE: this code directly accesses the list stored inside the 
00392              *       table 
00393              */
00394             
00395             new_it = GATList_GATMetricListenerData_Insert(list, end, data);
00396             if (NULL == new_it)
00397             {
00398               retval = GAT_MEMORYFAILURE;
00399             } 
00400             else
00401             {
00402               *cookie = mycookie;
00403             }
00404           }
00405           else
00406           {
00407             retval = GAT_INVALID_PARAMETER;
00408           }
00409         }
00410       }
00411     }
00412   }
00413   return retval;
00414 }
00415 
00416 /** GATMonitorable_Impl_RemoveRegisteredMetric
00417  *
00418  *  The function GATMonitorable_Impl_RemoveRegisteredMetric removes a 
00419  *  GATMetricListener, which was previously registered with 
00420  *  GATMonitorable_AddMetricListener.
00421  *
00422  *  @param monitorable The GATMonitorable instance to remove the metric from.
00423  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00424  *        to the GATMetricListener.
00425  *  @param cookie This value identifies the GATMetricListener to remove, it 
00426  *        was returned from the corresponding GATMonitorable_AddMetricListener 
00427  *        or GATMonitorable_MetricRegisterPolling functions.
00428  *  
00429  *  @return An error code.
00430  */
00431 GATResult 
00432 GATMonitorable_Impl_RemoveRegisteredMetric(GATMonitorable_Impl monitorable, 
00433   GATMetric metric, GATuint32 cookie)
00434 {
00435   GATResult retval = GAT_FAIL;
00436   if (NULL != monitorable)
00437   {
00438     GATObject_const object = NULL;
00439     
00440     retval = GATTable_Get_GATObject(monitorable->metrics, metric, &object);
00441     if (GAT_SUCCESS == retval)
00442     {
00443       /* find the listener data inside the appropriate list */
00444       GATList_GATMetricListenerData_const list = 
00445         GATObject_ToGATList_GATMetricListenerData_const(object);
00446       GATList_GATMetricListenerData_Iterator it = 
00447         GATList_GATMetricListenerData_Begin(list);
00448       GATList_GATMetricListenerData_Iterator end = 
00449         GATList_GATMetricListenerData_End(list);
00450 
00451       retval = GAT_KEY_NOT_FOUND;
00452       for (/**/; it != end; it = GATList_GATMetricListenerData_Next(it))
00453       {
00454         GATMetricListenerData *value = GATList_GATMetricListenerData_Get(it);
00455         if (NULL == value)
00456         {
00457           retval = GAT_FAIL;
00458           break;
00459         }
00460         
00461         if (value->cookie == cookie)
00462         {
00463           retval = GAT_SUCCESS;
00464           break;
00465         }
00466       }
00467       
00468       /* NOTE: this code directly accesses the list stored inside the table */
00469       if (GAT_SUCCESS == retval)
00470       {
00471         GATList_GATMetricListenerData_Erase(
00472           (GATList_GATMetricListenerData) list, it);
00473       }
00474     }
00475   }      
00476   return retval;
00477 }
00478 
00479 /** GATMonitorable_Impl_GetMetrics
00480  *
00481  *  The function GATMonitorable_Impl_GetMetrics returns a list of metrics 
00482  *  supported by this GATMonitorable.
00483  *
00484  *  @param monitorable The GATMonitorable instance, for which the supported 
00485  *        metrics should be returned.
00486  *  @param metrics The pointer to the variable, which receives the resulting 
00487  *        list of metrics.
00488  *
00489  *  @return An error code.
00490  */
00491 GATResult
00492 GATMonitorable_Impl_GetMetrics(GATMonitorable_Impl_const monitorable, 
00493   GATList_GATMetric *metrics)
00494 {
00495   GATResult retval = GAT_INVALID_HANDLE;
00496   if (NULL != monitorable)
00497   {
00498     GATList_GATMetric list = GATList_GATMetric_Create();
00499     if (NULL == list)
00500     {
00501       retval = GAT_MEMORYFAILURE;
00502     }
00503     else
00504     {
00505       GATMetric **keys = (GATMetric **) GATTable_GetKeys(monitorable->metrics);
00506       if (NULL == keys)
00507       {
00508         retval = GAT_MEMORYFAILURE;
00509       }
00510       else
00511       {
00512         /* copy the metrics into the output list */
00513         GATuint32 i = 0;
00514         GATMetric *key = keys[0];
00515         
00516         retval = GAT_SUCCESS;   /* 'no keys' is valid */
00517         for (/**/; NULL != key; key = keys[++i])
00518         {
00519           GATList_GATMetric_Iterator it = 
00520             GATList_GATMetric_Insert(list, GATList_GATMetric_End(list), *key);
00521           if (NULL == it)
00522           {
00523             retval = GAT_MEMORYFAILURE;
00524             break;
00525           }
00526         }
00527         
00528         /* free the key list */
00529         for (i = 0, key = keys[0]; NULL != key; key = keys[++i])
00530         {
00531           free(*key);
00532         }
00533         free(keys);
00534       }
00535     
00536       if (GAT_SUCCESS == retval)
00537       {
00538         if (NULL != metrics)
00539         {
00540           *metrics = list;
00541         }
00542         else
00543         {
00544           retval = GAT_INVALID_PARAMETER;
00545         }
00546       }
00547       else
00548       {
00549         GATList_GATMetric_Destroy(&list);
00550       }
00551     }
00552   }
00553   return retval;
00554 }
00555 
00556 /** GATMonitorable_Impl_FireEvent
00557  *
00558  *  The function GATMonitorable_Impl_FireEvent fires the given event to all
00559  *  registered metric listeners.
00560  *
00561  *  @param monitorable The GATMonitorable to use for calling the registered
00562  *        metric listeners.
00563  *  @param metric The metric, which describes the event fired.
00564  *  @param event The event to fire.
00565  *
00566  *  @return An error code
00567  */
00568 GATResult 
00569 GATMonitorable_Impl_FireEvent(GATMonitorable_Impl_const monitorable,
00570   GATMetric metric, GATMetricEvent event)
00571 {
00572   GATResult retval = GAT_INVALID_HANDLE;
00573   if (NULL != monitorable)
00574   {
00575     if (NULL == metric || NULL == event)
00576     {
00577       retval = GAT_INVALID_PARAMETER;
00578     }
00579     else
00580     {
00581       GATObject_const object = NULL;
00582       
00583       retval = GATTable_Get_GATObject(monitorable->metrics, metric, &object);
00584       if (GAT_SUCCESS == retval)
00585       {
00586         /* find the listener data inside the appropriate list */
00587         GATList_GATMetricListenerData_const list = 
00588           GATObject_ToGATList_GATMetricListenerData_const(object);
00589         GATList_GATMetricListenerData_Iterator it = 
00590           GATList_GATMetricListenerData_Begin(list);
00591         GATList_GATMetricListenerData_Iterator end = 
00592           GATList_GATMetricListenerData_End(list);
00593           
00594         for (/**/; it != end; it = GATList_GATMetricListenerData_Next(it))
00595         {
00596           GATMetricListenerData *data = GATList_GATMetricListenerData_Get(it);
00597           if (NULL == data)
00598           {
00599             retval = GAT_FAIL;    /* this is completely unexpected */
00600             break;
00601           }
00602           
00603           if (NULL != data->listener)
00604           {
00605             /* handle event like metrics only */
00606             retval = data->listener(data->data, event);
00607             if (GAT_SUCCESS != retval)
00608             {
00609               break;
00610             }
00611           }
00612         }
00613       }
00614     }
00615   }
00616   return retval;
00617 }
00618 
00619 /** int GATMonitorable_Equals(GATMonitorable_const lhs, GATMonitorable_const rhs, GATBool *isequal)
00620  *  @brief Compares two GATTable objects
00621  *
00622  *  The function @c GATMonitorable_Equals compares two file objects of type 
00623  *  @c #GATTable.
00624  *
00625  *  @param lhs The first file object to compare
00626  *  @param rhs The second file object to compare
00627  *  @param isequal The pointer to the GATBool variable, which should receive 
00628  *        the result if the comparison
00629  *
00630  *  @return An error code.
00631  */
00632 GATResult 
00633 GATMonitorable_Impl_Equals(GATMonitorable_Impl_const lhs, 
00634   GATMonitorable_Impl_const rhs, GATBool *isequal)
00635 {
00636   GATResult retval = GAT_INVALID_HANDLE;
00637   if (NULL != lhs && NULL != rhs)
00638   {
00639     /* two GATMonitorable_Impl are equal, if its embedded tables are equal */
00640     retval = GATTable_Equals(lhs->metrics, rhs->metrics, isequal);
00641   }
00642   return retval;
00643 }
00644 
00645 /** int GATMonitorable_Clone(GATMonitorable_const filehandle, GATTable *new_file)
00646  *  @brief Clone the given GATTable
00647  *
00648  *  The function @c GATMonitorable_Clone generates a (deep) copy of the given
00649  *  GATTable. 
00650  *
00651  *  @param monitorable The object to clone
00652  *  @param new_file The pointer, through which the result is to be 
00653  *        returned.
00654  *
00655  *  @return An error type.
00656  */
00657 GATResult 
00658 GATMonitorable_Impl_Clone(GATMonitorable_Impl_const monitorable, 
00659   GATMonitorable_Impl *new_object)
00660 {
00661   GATResult retval = GAT_INVALID_HANDLE;
00662   if (NULL != monitorable)
00663   {
00664     GATMonitorable_Impl new_monitorable = 
00665       (GATMonitorable_Impl) malloc (sizeof(struct GATMonitorable_Impl_S));
00666 
00667     if (NULL == new_monitorable)
00668     {
00669       retval = GAT_MEMORYFAILURE;
00670     }
00671     else
00672     {
00673       new_monitorable->GATObject__vtable = &GATMonitorable_Impl__vtable;
00674       new_monitorable->GATMonitorable_Impl__vtable = 
00675         &GATMonitorable_Impl_IMonitorable__vtable;
00676       retval = GATTable_Clone(monitorable->metrics, &new_monitorable->metrics);
00677       if (GAT_SUCCESS != retval)
00678       {
00679         free(new_monitorable);
00680       }
00681       else
00682       {
00683         if (NULL != new_object)
00684         {
00685           *new_object = new_monitorable;
00686         }
00687         else
00688         {
00689           retval = GAT_INVALID_PARAMETER;
00690         }
00691       }
00692     }
00693   }
00694   return retval;
00695 }
00696 
00697 /* Local functions */
00698 
00699 /** int GATMonitorable_GetType(GATMonitorable_const file)
00700  *  @brief Return the type of the GATTable
00701  *
00702  *  The function @c GATMonitorable_GetType always returns GATType_GATTable. 
00703  *
00704  *  @param object The object to inspect
00705  *
00706  *  @return returns always @c #GATType_GATTable.
00707  */
00708 static GATType 
00709 GATMonitorable_Impl_GetType(GATMonitorable_Impl_const monitorable)
00710 {
00711   GAT_UNUSED_PARAMETER(monitorable);
00712   return GATType_GATMonitorable_Impl;
00713 }
00714 
00715 /** int GATMonitorable_GetInterface(GATMonitorable_const table, GATInterface iftype, void const **ifp)
00716  *  @brief Get an interface supported by a GATList
00717  *
00718  *  The function GATMonitorable_GetInterface allows to get a pointer to an 
00719  *  additional interface supported by this GATList.
00720  *
00721  *  @param monitorable The object to be asked for the new interface.
00722  *  @param iftype The interface the object is to be asked for.
00723  *  @param ifp The pointer, through which the result is to be returned.
00724  *
00725  *  @return An error type.
00726  */
00727 static GATResult 
00728 GATMonitorable_Impl_GetInterface(GATMonitorable_Impl_const monitorable, 
00729   GATInterface iftype, void const **ifp)
00730 {
00731   GATResult retval = GAT_INVALID_PARAMETER;
00732   if (NULL != monitorable || NULL != ifp)
00733   {
00734     *ifp = NULL;
00735     if (GATInterface_IMonitorable == iftype)
00736     {
00737       *ifp = (void const *) &monitorable->GATMonitorable_Impl__vtable;
00738       retval = GAT_SUCCESS;
00739     }
00740     else
00741     {
00742       retval = GAT_NO_INTERFACE;
00743     }
00744   }
00745   return retval;
00746 }
00747 
00748 static 
00749 GATuint32 GATMonitorable_Impl_GetKeySize(GATTable_const table, 
00750   void const *key)
00751 {
00752   GAT_UNUSED_PARAMETER(table);
00753   GAT_UNUSED_PARAMETER(key);
00754   return (GATuint32) GATMetric_i_GetTypeSize();
00755 }
00756   
00757 static 
00758 GATBool GATMonitorable_Impl_EqualKeys(GATTable_const table, 
00759   void const *key1, void const *key2)
00760 {
00761   GATBool retval = GATFalse;
00762   
00763   GAT_UNUSED_PARAMETER(table);
00764   
00765   GATMetric_Equals((GATMetric)key1, (GATMetric)key2, &retval);
00766   return retval;
00767 }
00768   
00769 static GATResult
00770 GATMonitorable_Impl_CloneKey(GATTable_const table, void const *src, void **dest)
00771 {
00772   GATResult retval = GAT_FAIL;
00773   GATMetric new_metric = NULL;
00774   
00775   GAT_UNUSED_PARAMETER(table);
00776 
00777   return GATMetric_Clone((GATMetric)src, (GATMetric *)dest);
00778 }
00779 
00780 static void
00781 GATMonitorable_Impl_DestroyKey(GATTable_const monitorable, void **key)
00782 {
00783   GATMetric_Destroy((GATMetric *)key);
00784 }
00785 
00786 static unsigned long 
00787 GATMonitorable_Impl_HashKey(GATTable_const monitorable, void const *key)
00788 {
00789   char const *name = GATMetric_GetName((GATMetric)key);
00790 /*int c = *((int8_t *) name)++;*/
00791   int8_t* tmp = (int8_t *) name;
00792   int8_t  c   = *tmp++;
00793   GATuint32 i = 0;
00794   GATuint32 key_size = strlen (name) + 1;
00795   unsigned long hash = 0;
00796   
00797 /*                              c = *((int8_t *) name)++           */
00798   for (/**/; i < key_size; ++i, tmp = (int8_t *) name, c = *tmp++)
00799   {
00800     hash = c + (hash << 6) + (hash << 16) - hash;
00801   }
00802   return hash;
00803 }
00804