GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATFile.c

Go to the documentation of this file.
00001 /** @file GATTable.c
00002  * Main file for the GATFile class.
00003  * 
00004  * A GATFile is an abstract representation of a physical file.
00005  * 
00006  * @date Wed Sep 24 2003
00007  * 
00008  * @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATFile.c,v 1.61 2004/04/20 12:33:22 hartmutkaiser Exp $
00009  *
00010  *  Copyright (C) Tom Goodale
00011  *  Copyright (C) Hartmut Kaiser
00012  *  This file is part of the GAT Engine.
00013  *  Contributed by Tom Goodale <goodale@aei.mpg.de> and
00014  *    Hartmut Kaiser <hartmutkaiser [at] t-online [dot] de>.
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/GATFile.c,v 1.61 2004/04/20 12:33:22 hartmutkaiser Exp $";
00022 
00023 /* System Header Files */
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <assert.h>
00029 
00030 /* GAT Header Files */
00031 #include "GAT.h"
00032 #include "GATRegistry.h"
00033 
00034 #include "GATInternal.h"
00035 #include "GATFileCPI.h"
00036 #include "GATMetricEvent.h"
00037 #include "GATXdsWrapper.h"
00038 
00039 /* define the vtable types */
00040 GATOBJECT_DEFINE_VTABLE(GATFile);
00041 GATSERIALISABLE_DEFINE_VTABLE(GATFile);
00042 GATMONITORABLE_DEFINE_VTABLE(GATFile);
00043 
00044 /* Declare the converters to/from GATObject */
00045 GATOBJECT_DEFINE_CONVERTERS(GATFile);
00046 
00047 /* Macros */
00048 
00049 /* Structures, unions and enums */
00050 struct GATFile_S
00051 {
00052   /* supported interfaces */
00053   GATFile_vtable *GATObject__vtable;
00054   GATFile_ISerialisable_vtable *GATSerialisable__vtable;
00055   GATFile_IMonitorable_vtable *GATMonitorable__vtable;
00056   
00057   /* instance data */
00058   GATFileCPI_Instance data; /* instance data of the corresponding CPI object */
00059   GATFileCPI cpi;         /* CPI object to use for all subsequent operations */
00060   GATFileCPIList cpilist; /* CPI list of appropriate CPI objects */
00061 };
00062 
00063 /* Static function prototypes */
00064 static GATResult
00065 GATFile_DeSerialise_Create(GATContext context, GATObject stream, 
00066   char const *name, GATFile *new_file);
00067 
00068 static GATResult
00069 GATFile_GetCPIInstanceData(GATFile file, void **data);
00070 
00071 /* File scope variables */
00072 static GATFile_vtable GATFile__vtable = {
00073   GATFile_GetType,
00074   GATFile_Destroy,
00075   GATFile_Equals,
00076   GATFile_Clone,
00077   GATFile_GetInterface,
00078   GATFile_GetCPIInstanceData,
00079 };
00080 
00081 static GATFile_ISerialisable_vtable GATFile_ISerialisable__vtable = {
00082   GATFile_Serialise,
00083   GATFile_DeSerialise,
00084   GATFile_GetIsDirty
00085 };
00086 
00087 static GATFile_IMonitorable_vtable  GATFile_IMonitorable__vtable = {
00088   GATFile_AddMetricListener,
00089   GATFile_RegisterPolling,
00090   GATFile_RemoveRegisteredMetric,
00091   GATFile_GetMetrics
00092 };
00093 
00094 /* External functions */
00095 
00096 /** GATFile_Register_GATSerialisable
00097  *  The GATFile_Register_GATSerialisable function registers the serialization
00098  *  vtable with the GAT engine to allow generic object creation.
00099  *  This function is called by the GAT engine, there is no need to use it 
00100  *  directly.
00101  */
00102 GATResult GATFile_Register_GATSerialisable(void)
00103 {
00104   return GATObject_Register_GATSerialisable(GATType_GATFile, 
00105     &GATFile_ISerialisable__vtable);
00106 }
00107 
00108 /** GATFile_Create
00109  *  The  GATFile constructor.
00110  *  This is the constructor for GATFile objects.
00111  *
00112  * @return A new GATFile
00113  */
00114 GATFile 
00115 GATFile_Create(GATContext context, GATLocation_const location,
00116   GATPreferences_const preferences)
00117 {
00118   GAT_STATUS_APIENTRY(context, "GATFile_Create");
00119   
00120   GATFile new_file = (GATFile) malloc(sizeof(struct GATFile_S));  
00121   if(NULL != new_file)
00122   {
00123     memset(new_file, 0, sizeof(struct GATFile_S));
00124     new_file->GATObject__vtable = &GATFile__vtable;
00125     new_file->GATSerialisable__vtable = &GATFile_ISerialisable__vtable;
00126     new_file->GATMonitorable__vtable = &GATFile_IMonitorable__vtable;
00127     
00128     new_file->data.context = context;
00129     new_file->data.isdirty = GATFalse;
00130     new_file->data.source = GATFile_ToGATObject_const(new_file);
00131     
00132     GAT_CREATE_STATUS(GATLocation_Clone(location, &new_file->data.location));
00133     
00134     /* find a CPI object, which can handle the file at the given location */
00135     if (GAT_SUCCEEDED(GAT_CURRENT_STATUS())) 
00136     {
00137       GATRegistry_const registry = GATContext_internal_GetRegistry(context);
00138       
00139       /* use default preferences, if appropriate */
00140       if (NULL == preferences)
00141       {
00142         preferences = GATContext_GetPreferences(context);
00143       }
00144       new_file->cpilist = GATRegistry_FindGATFileCPI(registry, preferences);
00145       
00146       if (NULL == new_file->cpilist)
00147       {
00148         GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00149       }
00150       else 
00151       {
00152         /* create a new instance of the CPI provider */
00153         GATBool found_cpi = GATFalse;
00154         GATFileCPIList current = NULL;
00155         for(current = new_file->cpilist; NULL != current; current = current->next)
00156         {
00157           GAT_CREATE_STATUS(GATFileCPI_CreateInstance(current->cpi, 
00158             &new_file->data));
00159           if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00160           {
00161             new_file->cpi = current->cpi;
00162             found_cpi = GATTrue;
00163             break;
00164           }
00165         }
00166 
00167         /* no available CPI object can handle this */
00168         if (GATFalse == found_cpi)
00169         {
00170           GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
00171         }
00172         else
00173         {
00174           /* now, initialise the monitoring framework with the help of the
00175              CPI provider found */
00176           GATList_GATMetric metrics = NULL;
00177           GATResult retval = GATFileCPI_GetMetrics(new_file->cpi, 
00178             &new_file->data, &metrics);            
00179 
00180           if (GAT_SUCCEEDED(retval))
00181           {
00182             new_file->data.monitorable = GATMonitorable_Impl_Create(metrics);
00183             if (NULL == new_file->data.monitorable)
00184             {
00185               GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00186             }
00187             GATList_GATMetric_Destroy(&metrics);
00188           }
00189           else if (GAT_NOTIMPL == retval)
00190           {
00191             retval = GAT_SUCCESS;   /* no monitoring supported here */
00192           }
00193           else
00194           {
00195             GAT_CREATE_STATUS(retval);
00196           }
00197 
00198           /* register this object with the engine */
00199           GAT_CREATE_STATUS(GATRegistry_AddGATFileToCPIList(context, 
00200             new_file->cpi, new_file));
00201         }
00202       }
00203     }
00204   }
00205   else
00206   {
00207     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00208   }
00209 
00210   /* error handling */
00211   if (GAT_FAILED(GAT_CURRENT_STATUS()))
00212   {
00213     GATFile_Destroy(&new_file);
00214   }
00215   
00216   GAT_STORE_STATUS();
00217   return new_file;
00218 }
00219 
00220 /** GATFile_Create_Name
00221  *  The  GATFile constructor.
00222  *  This is the constructor for GATFile objects.
00223  *
00224  *  @return A new GATFile
00225  */
00226 GATFile 
00227 GATFile_Create_Name(GATContext context, char const *name,
00228   GATPreferences preferences)
00229 {
00230   GATFile file = NULL;
00231   GATLocation location = GATLocation_Create(name);
00232   if (NULL != location)
00233   {
00234     file = GATFile_Create(context, location, preferences);
00235     GATLocation_Destroy(&location);
00236   }
00237   else
00238   {
00239     GAT_STATUS_APIENTRY(context, "GATFile_Create_Name");
00240     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00241     GAT_STORE_STATUS();
00242   }
00243   return file;
00244 }
00245 
00246 /** GATFile_Destroy
00247  *  The GATFile destructor.
00248  *  This is the destructor for GATFile objects.
00249  *
00250  * @param this An old GATFile
00251  */
00252 void GATFile_Destroy(GATFile *file)
00253 {
00254   if(NULL != file && NULL != *file)
00255   {
00256     GATMonitorable_Impl_Destroy(&(*file)->data.monitorable);
00257     if (NULL != (*file)->cpi)
00258     {
00259       GATRegistry_RemoveGATFileFromCPIList((*file)->data.context, (*file)->cpi, 
00260         *file);
00261       GATFileCPI_DestroyInstance((*file)->cpi, &(*file)->data);
00262     }
00263     GATLocation_Destroy(&(*file)->data.location);
00264     GATFileCPIList_Destroy((*file)->cpilist);
00265     free(*file);
00266     *file = NULL;
00267   }
00268 }
00269 
00270 /** int GATFile_GetType(GATFile_const file)
00271  *  @brief Return the type of the GATFile
00272  *
00273  *  The function @c GATFile_GetType always returns GATType_GATFile. 
00274  *
00275  *  @param object The object to inspect
00276  *
00277  *  @return returns always @c #GATType_GATFile.
00278  */
00279 GATType GATFile_GetType(GATFile_const file)
00280 {
00281   GAT_UNUSED_PARAMETER(file);
00282   return GATType_GATFile;
00283 }
00284 
00285 /** int GATFile_Clone(GATFile_const filehandle, GATFile *new_file)
00286  *  @brief Clone the given GATFile
00287  *
00288  *  The function @c GATFile_Clone generates a (deep) copy of the given
00289  *  GATFile. 
00290  *
00291  *  @param filehandle The object to clone
00292  *  @param new_file The pointer, through which the result is to be 
00293  *        returned.
00294  *
00295  *  @return An error type.
00296  */
00297 GATResult GATFile_Clone(GATFile_const filehandle, GATFile *new_object)
00298 {
00299   if (NULL != filehandle)
00300   {
00301     GAT_USES_STATUS(filehandle->data.context, "GATFile_Clone");
00302     
00303     if (NULL != new_object)
00304     {
00305       struct GATFile_S const *file = filehandle;
00306       GATFile new_file = (GATFile) malloc(sizeof(struct GATFile_S));
00307       
00308       *new_object = NULL;
00309       if (NULL == new_file)
00310       {
00311         GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00312       }
00313       else
00314       {
00315         memset(new_file, 0, sizeof(struct GATFile_S));
00316         new_file->GATObject__vtable = &GATFile__vtable;
00317         new_file->GATSerialisable__vtable = &GATFile_ISerialisable__vtable;
00318         new_file->GATMonitorable__vtable = &GATFile_IMonitorable__vtable;
00319         
00320         new_file->data.context = file->data.context;
00321         new_file->data.isdirty = GATFalse;
00322         new_file->data.source = GATFile_ToGATObject_const(new_file);
00323         new_file->cpilist = GATRegistry_CloneGATFileCPIList(file->cpilist);
00324         
00325         if (NULL == new_file->cpilist)
00326         {
00327           GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00328         }
00329         GAT_CREATE_STATUS(GATLocation_Clone(file->data.location, 
00330           &new_file->data.location));
00331         
00332         if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00333         {
00334           /* re-find the cpi to use */
00335           GATFileCPIList current = file->cpilist;
00336           GATFileCPIList new_current = new_file->cpilist;
00337           
00338           for (/**/; NULL != current; 
00339                current = current->next, new_current = new_current->next)
00340           {
00341             if (current->cpi == file->cpi)
00342             {
00343               new_file->cpi = new_current->cpi;
00344               break;
00345             }
00346           }
00347           assert(NULL != new_file->cpi);
00348           
00349           /* clone the instance data */
00350           GAT_CREATE_STATUS(GATFileCPI_CloneInstance(file->cpi, &file->data, 
00351             &new_file->data));
00352 
00353           /* clone the monitoring data */
00354           if (NULL != file->data.monitorable)
00355           {
00356             GAT_CREATE_STATUS(GATMonitorable_Impl_Clone(file->data.monitorable, 
00357               &new_file->data.monitorable));
00358           }
00359             
00360           /* register this object with the engine */
00361           GAT_CREATE_STATUS(GATRegistry_AddGATFileToCPIList(
00362             new_file->data.context, new_file->cpi, new_file));
00363         }
00364       }
00365 
00366       /* destroy the newly allocated object, if some error occured */
00367       if (GAT_FAILED(GAT_CURRENT_STATUS()))
00368       {
00369         GATFile_Destroy(&new_file);
00370       }
00371       else
00372       {
00373         /* return the new object */
00374         *new_object = new_file;
00375       }
00376     }
00377     else
00378     {
00379       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00380     }
00381     
00382     return GAT_RETURN_STATUS();
00383   }
00384   return GAT_INVALID_HANDLE;
00385 }
00386 
00387 /** int GATFile_Equals(GATFile_const lhs, GATFile_const rhs, GATBool *isequal)
00388  *  @brief Compares two GATFile objects
00389  *
00390  *  The function @c GATFile_Equals compares two file objects of type 
00391  *  @c #GATFile.
00392  *
00393  *  @param lhs The first file object to compare
00394  *  @param rhs The second file object to compare
00395  *  @param isequal The pointer to the GATBool variable, which should receive 
00396  *        the result if the comparision
00397  *
00398  *  @return An error code.
00399  */
00400 GATResult 
00401 GATFile_Equals(GATFile_const lhs, GATFile_const rhs, GATBool *isequal)
00402 {
00403   if (NULL != lhs && NULL != rhs)
00404   {
00405     GAT_STATUS_APIENTRY(lhs->data.context, "GATFile_Equals");
00406     if (NULL != isequal)
00407     {
00408       GAT_CREATE_STATUS(GATLocation_Equals(lhs->data.location, 
00409         rhs->data.location, isequal));
00410       if (GATTrue == *isequal)
00411       {
00412         GAT_CREATE_STATUS(GATFileCPI_EqualsInstance(lhs->cpi, &lhs->data, 
00413           &rhs->data, isequal));
00414       }
00415     }
00416     else
00417     {
00418       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00419     }
00420     return GAT_RETURN_STATUS();
00421   }
00422   return GAT_INVALID_HANDLE;
00423 }
00424 
00425 /** int GATFile_GetInterface(GATFile_const file, GATInterface iftype, void const **ifp)
00426  *  @brief Get an interface supported by a GATObject
00427  *
00428  *  The function GATFile_GetInterface allows to get a pointer to an 
00429  *  additional interface supported by this GATFile.
00430  *
00431  *  @param object The object to be asked for the new interface.
00432  *  @param iftype The interface the object is to be asked for.
00433  *  @param ifp The pointer, through which the result is to be returned.
00434  *
00435  *  @return An error type.
00436  */
00437 GATResult 
00438 GATFile_GetInterface(GATFile_const file, GATInterface iftype, void const **ifp)
00439 {
00440   if (NULL != file)
00441   {
00442     GAT_STATUS_APIENTRY(file->data.context, "GATFile_GetInterface");
00443     
00444     if (NULL != ifp)
00445     {
00446       if (GATInterface_ISerialisable == iftype || 
00447           GATInterface_IAdvertisable == iftype)
00448       {
00449         *ifp = (void const *) &file->GATSerialisable__vtable;
00450       }
00451       else if (GATInterface_IMonitorable == iftype && NULL != file->data.monitorable)
00452       {
00453         *ifp = (void const *) &file->GATMonitorable__vtable;
00454       }
00455       else
00456       {
00457         *ifp = NULL;
00458         GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00459       }
00460     }
00461     else
00462     {
00463       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00464     }
00465     
00466     return GAT_RETURN_STATUS();
00467   }
00468   return GAT_INVALID_HANDLE;
00469 }
00470 
00471 /** GATFile_GetLocation
00472  *  This method returns the Location of this File
00473  *
00474  *  @return The Location of this File
00475  */
00476 GATLocation_const 
00477 GATFile_GetLocation(GATFile_const file)
00478 {
00479   if (NULL != file)
00480   {
00481     return file->data.location;
00482   }
00483   return 0;
00484 }
00485 
00486 /** GATFile_Copy
00487  *  @brief Copy a file from one location to another.
00488  *
00489  *  The function GATFile_Copy copies the given file to another location. For 
00490  *  this it tries to call through its CPI's all matching adapters registered 
00491  *  for the file CPI. 
00492  *
00493  *  @param this The file to be copied to the new location
00494  *  @param targetLocation The location the file has to be copied to.
00495  *
00496  *  @return An error code
00497  */
00498 GATResult 
00499 GATFile_Copy(GATFile_const file, GATLocation_const targetLocation,
00500   GATFileMode mode)
00501 {
00502   if (NULL != file)
00503   {
00504     GAT_STATUS_APIENTRY(file->data.context, "GATFile_Copy");
00505     GAT_CREATE_STATUS(GATFileCPI_Copy(file->cpi, &file->data, targetLocation, 
00506       mode));
00507     return GAT_RETURN_STATUS();
00508   }
00509   return GAT_INVALID_HANDLE;
00510 }
00511 
00512 /** GATFile_Move
00513  *  @brief Move a file from one location to another.
00514  *
00515  *  The function GATFile_Move moves the given file to another location. For 
00516  *  this it tries to call through its CPI's all matching adapters registered 
00517  *  for the file CPI. 
00518  *
00519  *  @param this The file to be moved to the new location
00520  *  @param targetLocation The location the file has to be moved to.
00521  *
00522  *  @return An error code
00523  */
00524 GATResult 
00525 GATFile_Move(GATFile_const file, GATLocation_const targetLocation,
00526   GATFileMode mode)
00527 {
00528   if (NULL != file)
00529   {
00530     GAT_STATUS_APIENTRY(file->data.context, "GATFile_Move");
00531     GAT_CREATE_STATUS(GATFileCPI_Move(file->cpi, &file->data, targetLocation, 
00532       mode));
00533     return GAT_RETURN_STATUS();
00534   }
00535   return GAT_INVALID_HANDLE;
00536 }
00537 
00538 /** GATFile_Delete
00539  *  @brief Delete a file.
00540  *
00541  *  The function GATFile_Delete deletes the given file. For 
00542  *  this it tries to call through its CPI's all matching adapters registered 
00543  *  for the file CPI. 
00544  *
00545  *  @param this The file to be moved to the new location
00546  *
00547  *  @return An error code
00548  */
00549 GATResult 
00550 GATFile_Delete(GATFile_const file)
00551 {
00552   if (NULL != file)
00553   {
00554     GAT_STATUS_APIENTRY(file->data.context, "GATFile_Delete");
00555     GAT_CREATE_STATUS(GATFileCPI_Delete(file->cpi, &file->data));
00556     return GAT_RETURN_STATUS();
00557   }
00558   return GAT_INVALID_HANDLE;
00559 }
00560 
00561 /** GATFile_IsReadable
00562  *  @brief Check the file attributes for the readable flag
00563  *
00564  *  The function GATFile_IsReadable checks the file attributes of the given 
00565  *  file and returns, whether it is readable.
00566  *
00567  *  @param this The file to be inspected for its readability attribute.
00568  *
00569  *  @return If the inspected file is readable, the function returns 
00570  *        @c #GAT_SUCCESS, if it is not readable, @c #GAT_FALSE is returned.
00571  *        Otherwise the function returns any of the possible errorcodes.
00572  */
00573 GATResult 
00574 GATFile_IsReadable(GATFile_const file)
00575 {
00576   if (NULL != file)
00577   {
00578     GAT_STATUS_APIENTRY(file->data.context, "GATFile_IsReadable");
00579     GAT_CREATE_STATUS(GATFileCPI_IsReadable(file->cpi, &file->data));
00580     return GAT_RETURN_STATUS();
00581   }
00582   return GAT_INVALID_HANDLE;
00583 }
00584 
00585 /** GATFile_IsWritable
00586  *  @brief Check the file attributes for the writable flag
00587  *
00588  *  The function GATFile_IsWritable checks the file attributes of the given 
00589  *  file and returns, whether it is writable.
00590  *
00591  *  @param this The file to be inspected for its writability attribute.
00592  *
00593  *  @return If the inspected file is writable, the function returns 
00594  *        @c #GAT_SUCCESS, if it is not writable, @c #GAT_FALSE is returned.
00595  *        Otherwise the function returns any of the possible errorcodes.
00596  */
00597 GATResult 
00598 GATFile_IsWritable(GATFile_const file)
00599 {
00600   if (NULL != file)
00601   {
00602     GAT_STATUS_APIENTRY(file->data.context, "GATFile_IsWritable");
00603     GAT_CREATE_STATUS(GATFileCPI_IsWritable(file->cpi, &file->data));
00604     return GAT_RETURN_STATUS();
00605   }
00606   return GAT_INVALID_HANDLE;
00607 }
00608 
00609 /** GATFile_GetLength
00610  *  @brief Returns the size of the given file
00611  *
00612  *  The function GATFile_GetLength returns the file size of the given size  
00613  *  measured in bytes.
00614  *
00615  *  @param this The file to be inspected for its size.
00616  *  @param length The pointer to the variable, where the length of the file is
00617  *        to be returned to.
00618  *
00619  *  @return An error code
00620  */
00621 GATResult 
00622 GATFile_GetLength(GATFile_const file, unsigned long *length)
00623 {
00624   if (NULL != file)
00625   {
00626     GAT_STATUS_APIENTRY(file->data.context, "GATFile_GetLength");
00627     GAT_CREATE_STATUS(GATFileCPI_GetLength(file->cpi, &file->data, length));
00628     return GAT_RETURN_STATUS();
00629   }
00630   return GAT_INVALID_HANDLE;
00631 }
00632 
00633 /** GATFile_LastWriteTime
00634  *  @brief Returns the time of last modification of the given file
00635  *
00636  *  The function GATFile_LastWriteTime returns the time of last modification of
00637  *  the inspected file.
00638  *
00639  *  @param this The file to be inspected for its modification time.
00640  *  @param lw_time The pointer to the variable, where the last write time is 
00641  *      to returned to.
00642  *
00643  *  @return An error code
00644  */
00645 GATResult 
00646 GATFile_LastWriteTime(GATFile_const file, GATTime *lw_time)
00647 {
00648   if (NULL != file)
00649   {
00650     GAT_STATUS_APIENTRY(file->data.context, "GATFile_LastWriteTime");
00651     GAT_CREATE_STATUS(GATFileCPI_LastWriteTime(file->cpi, &file->data, lw_time));
00652     return GAT_RETURN_STATUS();
00653   }
00654   return GAT_INVALID_HANDLE;
00655 }
00656 
00657 
00658 /* GATMonitorable */
00659 
00660 /** GATFile_AddMetricListener
00661  *
00662  *  The function GATFile_AddMetricListener adds the passed instance of a 
00663  *  GATMetricListener to the list of GATMetricListeners which are notified of 
00664  *  fired GATMetricEvents of the type described by the provided GATMetric 
00665  *  instance.
00666  *
00667  *  @param file The GATFile instance to add the GATMetricListener to.
00668  *  @param listener The GTAMetricListener to call, when the corresponding 
00669  *        GATMetricEvent is fired.
00670  *  @param listener_data The client supplied data, which will be passed through
00671  *        to the GATMetricListener.
00672  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00673  *        to the GATMetricListener.
00674  *  @param cookie The returned value should be used to remove the 
00675  *        GATMetricListener from this GATMonitorable.
00676  *
00677  *  @return An error code.
00678  */ 
00679 GATResult GATFile_AddMetricListener(GATFile file, GATMetricListener listener,
00680   void *listener_data, GATMetric metric, GATuint32 *cookie)
00681 {
00682   if (NULL != file)
00683   {
00684     GAT_STATUS_APIENTRY(file->data.context, "GATFile_AddMetricListener");
00685     
00686     if (NULL != file->data.monitorable)
00687     {
00688       GAT_CREATE_STATUS(GATMonitorable_Impl_AddMetricListener(
00689         file->data.monitorable, listener, listener_data, metric, cookie));
00690     } 
00691     else
00692     { 
00693       /* this may happen, if the adaptor has not registered any GATMetrics */
00694       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00695     }
00696     
00697     return GAT_RETURN_STATUS();
00698   }
00699   return GAT_INVALID_HANDLE;
00700 }
00701 
00702 /** GATFile_RegisterPolling
00703  *
00704  *  The function GATFile_RegisterPolling registers a continuous 
00705  *  metric with the given GATFile instance.
00706  *
00707  *  @param file The GATFile instance to register the metric with.
00708  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00709  *        to the GATMetricListener. This metric instance must be of type
00710  *        GATMeasurementType_Continuous, otherwise an error is returned.
00711  *  @param event The pointer to a variable, which should receive the resulting
00712  *        GATMetricEvent. The GATMetricEvent instance should be freed by the 
00713  *        caller when it isn't used anymore.
00714  *  @param cookie The returned value should be used to remove the 
00715  *        GATMetricListener from this GATFile.
00716  *
00717  *  @return An error code.
00718  */ 
00719 GATResult 
00720 GATFile_RegisterPolling(GATFile file, GATMetric metric, GATMetricEvent *event, 
00721   GATuint32 *cookie)
00722 {
00723   if (NULL != file)
00724   {
00725     GAT_STATUS_APIENTRY(file->data.context, "GATFile_RegisterPolling");
00726     
00727     if (NULL != file->data.monitorable)
00728     {
00729       GAT_CREATE_STATUS(GATMonitorable_Impl_RegisterPolling(file->data.monitorable, 
00730         metric, 0, cookie));
00731 
00732       /* ask the CPI provider to return the corresponding metric event */
00733       GAT_CREATE_STATUS(GATFileCPI_GetMetricEvent(file->cpi, &file->data, 
00734         metric, event));
00735 
00736       if (GAT_FAILED(GAT_CURRENT_STATUS()) && NULL != cookie && 0 != *cookie)
00737       {
00738         GATMonitorable_Impl_RemoveRegisteredMetric(file->data.monitorable,
00739           metric, *cookie);
00740         *cookie = 0;
00741       }
00742     } 
00743     else
00744     { 
00745       /* this may happen, if the adaptor has not registered any GATMetrics */
00746       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00747     }
00748     
00749     return GAT_RETURN_STATUS();
00750   }
00751   return GAT_INVALID_HANDLE;
00752 }
00753 
00754 /** GATFile_RemoveRegisteredMetric
00755  *
00756  *  The function GATFile_RemoveRegisteredMetric removes a GATMetricListener, 
00757  *  which was previously registered with GATFile_AddMetricListener.
00758  *
00759  *  @param file The GATFile instance to remove the GATMetricListener from.
00760  *  @param metric The GATMetric instance describing the GATMetricEvent to pass
00761  *        to the GATMetricListener.
00762  *  @param cookie This value identifies the GATMetricListener to remove, it 
00763  *        was returned from the corresponding GATMonitorable_AddMetricListener 
00764  *        or GATMonitorable_MetricRegisterPolling functions.
00765  *  
00766  *  @return An error code.
00767  */
00768 GATResult GATFile_RemoveRegisteredMetric(GATFile file, GATMetric metric, 
00769   GATuint32 cookie)
00770 {
00771   if (NULL != file)
00772   {
00773     GAT_STATUS_APIENTRY(file->data.context, "GATFile_RemoveRegisteredMetric");
00774     
00775     if (NULL != file->data.monitorable)
00776     {
00777       GAT_CREATE_STATUS(GATMonitorable_Impl_RemoveRegisteredMetric(
00778         file->data.monitorable, metric, cookie));
00779     } 
00780     else
00781     { 
00782       /* this may happen, if the adaptor has not registered any GATMetrics */
00783       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00784     }
00785     
00786     return GAT_RETURN_STATUS();
00787   }
00788   return GAT_INVALID_HANDLE;
00789 }
00790 
00791 /** GATFile_GetMetrics
00792  *
00793  *  The function GATFile_GetMetrics returns a list of metrics supported by this
00794  *  GATFile.
00795  *
00796  *  @param file The GATFile instance, for which the supported metrics should be 
00797  *        returned.
00798  *  @param metrics The pointer to the variable, which receives the resulting 
00799  *        list of metrics.
00800  *
00801  *  @return An error code.
00802  */
00803 GATResult GATFile_GetMetrics(GATFile_const file, GATList_GATMetric *metrics)
00804 {
00805   if (NULL != file)
00806   {
00807     GAT_STATUS_APIENTRY(file->data.context, "GATFile_GetMetrics");
00808     
00809     if (NULL != file->data.monitorable)
00810     {
00811       GAT_CREATE_STATUS(GATMonitorable_Impl_GetMetrics(file->data.monitorable, 
00812         metrics));
00813     } 
00814     else
00815     { 
00816       /* this may happen, if the adaptor has not registered any GATMetrics */
00817       GAT_CREATE_STATUS(GAT_NO_INTERFACE);
00818     }
00819     
00820     return GAT_RETURN_STATUS();
00821   }
00822   return GAT_INVALID_HANDLE;
00823 }
00824 
00825 
00826 /* GATAdvertiseable API */
00827 
00828 /** GATFileCPI_SerialiseCallback
00829  *
00830  *  The function GATFileCPI_SerialiseCallback is used as a callback function 
00831  *  for the serialisation of a GATFile object. It should be provided to 
00832  *  serialise the associated CPI provider data for the given object.
00833  *
00834  *  @param object The object to serialise. This is the same as the object 
00835  *        passed as the first parameter to the function GATXds_SerialiseObject.
00836  *  @param stream The stream interface to use for the serialisation.
00837  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
00838  *        internal dirty flag of this object is to be reset (no used here)
00839  *
00840  *  @return An error code.
00841  *
00842  *  @remark This function is called from the GAT engine, there is no need to 
00843  *        call it directly.
00844  */
00845 static GATResult 
00846 GATFileCPI_SerialiseCallback(GATObject object, GATObject stream, 
00847   GATBool clear_dirty)
00848 {
00849   GATFile file = GATObject_ToGATFile(object);
00850   if (NULL != file)
00851   {
00852     GAT_USES_STATUS(file->data.context, "GATFileCPI_SerialiseCallback");
00853     
00854     GAT_CREATE_STATUS(GATFileCPI_Serialise(file->cpi, &file->data, stream,
00855       clear_dirty));
00856 
00857     if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()) && GATTrue == clear_dirty)
00858     {
00859       file->data.isdirty = GATFalse;
00860     }
00861     
00862     return GAT_RETURN_STATUS();
00863   }
00864   return GAT_INVALID_HANDLE;
00865 }
00866 
00867 /** int GATFile_Serialise(GATFile file, GATObject stream, GATBool clear_dirty)
00868  *  @brief Serialise a GATFile object
00869  *
00870  *  The function GATFile_Serialise serialises the given GATFIle object into the
00871  *  given stream. 
00872  *
00873  *  @param file The GATFile object to serialise.
00874  *  @param stream The stream interface to use for the serialisation.
00875  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
00876  *        internal dirty flag of this object is to be reset (no used here)
00877  *
00878  *  @return An error code.
00879  */
00880 GATResult 
00881 GATFile_Serialise(GATFile file, GATObject stream, GATBool clear_dirty)
00882 {
00883   if (NULL != file)
00884   {
00885     GAT_USES_STATUS(file->data.context, "GATFile_Serialise");
00886     
00887     /* FIXME: serialise the location directly, when GATLocation is fully
00888               implemented */
00889     char *name = GATLocation_ToString(GATFile_GetLocation(file));
00890     
00891     if (NULL != name)
00892     {
00893       GAT_CREATE_STATUS(GATXds_SerialiseObject(GATFile_ToGATObject(file), 
00894         stream, clear_dirty, GATFileCPI_SerialiseCallback, "uint32 string",
00895         GATFILE_VERSION1, name));
00896         
00897       free(name);
00898     }
00899     else
00900     {
00901       GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
00902     }
00903     
00904     return GAT_RETURN_STATUS();
00905   }
00906   return GAT_INVALID_HANDLE;
00907 }
00908 
00909 /** GATFileCPI_VersionCallback
00910  *
00911  *  The function GATFileCPI_VersionCallback is used as a callback function
00912  *  during the de-serialisation of a GATFile. It should be provided to test,
00913  *  whether the de-serialised version matches the expected version.
00914  *
00915  *  @param version The version number, which was de-serialised from the stream.
00916  *
00917  *  @return This function should return GATTrue, if the version matches the 
00918  *        expected value (version is valid), GATFalse otherwise.
00919  *
00920  *  @remark This function is called from the GAT engine, there is no need to 
00921  *        call it directly.
00922  */
00923 static GATBool
00924 GATFileCPI_VersionCallback(GATuint32 version)
00925 {
00926   GATBool retval = GATFalse;
00927   if ((version & ~GATFILE_MINOR_MASK) <= GATFILE_LASTVERSION)
00928   {
00929     retval = GATTrue;
00930   }
00931   return retval;
00932 }
00933 
00934 /** GATFileCPI_DeSerialiseCallback
00935  *
00936  *  The function GATFileCPI_DeSerialiseCallback is used as a callback function
00937  *  during the de-serialisation of a GATFile. It should be provided for the
00938  *  instantiation of the new GATFile object based on the already de-serialised 
00939  *  data items and the de-serialisation of the associated CPI provider data for 
00940  *  the given object.
00941  *
00942  *  @param context The GAT context to be used for object construction.
00943  *  @param stream The stream interface to use for the serialisation.
00944  *  @param object The pointer to the variable, which should receive the newly 
00945  *        constructed object.
00946  *  @param version The version of the saved data read from the input stream.
00947  *  @param args This parameter is the pointer to the va_list containing 
00948  *        pointers to the already de-serialised data items accordingly to the
00949  *        format string, provided during the call to the 
00950  *        GATFile_DeSerialise function.
00951  *
00952  *  @return An error code.
00953  *
00954  *  @remark This function is called from the GAT engine, there is no need to 
00955  *        call it directly.
00956  */
00957 static GATResult
00958 GATFileCPI_DeSerialiseCallback(GATContext context, GATObject stream, 
00959   GATObject *object, GATuint32 version, va_list args)
00960 {
00961   GAT_USES_STATUS(context, "GATFileCPI_DeSerialiseCallback");
00962   
00963   /* the version was eaten already */
00964   /* FIXME: serialise/de-serialise the location directly, when GATLocation is
00965             fully implemented */
00966   /*GATLocation *location = va_arg(args, GATLocation *);*/
00967   char const **name = va_arg(args, char const **);
00968   GATFile file = NULL;
00969   
00970   /* construct the new object */
00971   GAT_CREATE_STATUS(GATFile_DeSerialise_Create(context, stream, *name, &file));
00972 
00973   GAT_UNUSED_PARAMETER(version); 
00974   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
00975   {
00976     if (NULL != object)
00977     {
00978       *object = GATFile_ToGATObject(file);
00979     }
00980     else
00981     {
00982       GATFile_Destroy(&file);
00983       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
00984     }
00985   }
00986   
00987   return GAT_RETURN_STATUS();
00988 }
00989 
00990 /** GATFile GATFile_DeSerialise(GATContext context, GATObject stream, GATBool clear_dirty)
00991  *  @brief De-serialise a GATFile object
00992  *
00993  *  The function GATFile_DeSerialise de-serialises a streamed GATFile object  
00994  *  from the given stream  It constructs a new instance of the de-serialised 
00995  *  object.
00996  *
00997  *  @param context The GAT context to be used for object construction.
00998  *  @param stream The stream interface to use for the serialisation.
00999  *  @param result The pointer to a variable, which receives the status code of
01000  *        the operation.
01001  *
01002  *  @return The newly constructed GATFile object.
01003  */
01004 GATFile 
01005 GATFile_DeSerialise(GATContext context, GATObject stream, GATResult *result)
01006 {
01007   GAT_USES_STATUS(context, "GATFile_DeSerialise");
01008   
01009   GATObject object = NULL;     /* the new object will be created here */
01010   GATFile file = NULL;
01011   
01012   /* we must provide all instance data items to be de-serialised for this
01013      GATFile object accordingly to the provided format string */
01014   GATuint32 version = 0;
01015 
01016   /* FIXME: de-serialise the location directly, when GATLocation is fully 
01017             implemented */
01018 /*  GATLocation location = NULL; */
01019   char *name = NULL;
01020 
01021   /* read the data */
01022   GAT_CREATE_STATUS(GATXds_DeSerialiseObject(context, stream, 
01023     GATFileCPI_DeSerialiseCallback, GATFileCPI_VersionCallback, &object, 
01024     "uint32 string", &version, &name));
01025 
01026 /*  GATLocation_Destroy(&location);*/
01027   free(name);
01028 
01029   file = GATObject_ToGATFile(object);
01030   if (NULL == file)
01031   {
01032     GAT_CREATE_STATUS(GAT_BAD_OBJECT_CONVERSION);
01033   }
01034   
01035   if (GAT_FAILED(GAT_CURRENT_STATUS()))
01036   {
01037     GATObject_Destroy(&object);
01038     file = NULL;
01039   }
01040   
01041   if (NULL != result)
01042   { 
01043     *result = GAT_CURRENT_STATUS();
01044   }
01045   
01046   GAT_STORE_STATUS();
01047   return file;
01048 }
01049 
01050 /** GATFile_GetIsDirty
01051  *  
01052  *  The function GATFile_GetIsDirty retrieves the status of the dirty flag of 
01053  *  this GATFile object.
01054  *
01055  *  @param file The GATFile object to inspect for its dirty status.
01056  *  @param isdirty The pointer to a variable, which receives the dirty status.
01057  *
01058  *  @return An error code.
01059  */
01060 GATResult GATFile_GetIsDirty(GATFile_const file, GATBool *isdirty)
01061 {
01062   if (NULL != file)
01063   {
01064     GAT_STATUS_APIENTRY(file->data.context, "GATFile_GetIsDirty");
01065     
01066     if (NULL != isdirty)
01067     {
01068       *isdirty = file->data.isdirty;
01069     }
01070     else
01071     {
01072       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
01073     }
01074     
01075     return GAT_RETURN_STATUS();
01076   }  
01077   return GAT_INVALID_HANDLE;
01078 }
01079 
01080 /* Local functions */
01081 
01082 /** GATFile_DeSerialise_Create
01083  *
01084  *  The function GATFile_DeSerialise_Create creates a new GATFile object and
01085  *  tries to find a CPI provider to associate with this file object. The CPI
01086  *  provider is selected by testing, which adapter is able to handle the 
01087  *  streamed instance data of the original CPI provider.
01088  *
01089  *  @param context The GAT context to use for creation of the GATFile object.
01090  *  @param stream The object from which the adaptor should read the streamed
01091  *        instance data.
01092  *  @param name This is the URI of the file to reconstruct.
01093  *  @param new_object The pointer to the variable, which should receive the 
01094  *        newly constructed GATFile object.
01095  *
01096  *  @return An error code.
01097  */
01098 static GATResult
01099 GATFile_DeSerialise_Create(GATContext context, GATObject stream, 
01100   char const *name, GATFile *new_object)
01101 {
01102   GAT_USES_STATUS(context, "GATFile_DeSerialise_Create");
01103   
01104   GATFile new_file = (GATFile) malloc(sizeof(struct GATFile_S));
01105 
01106   if(NULL != new_file)
01107   {
01108     memset(new_file, 0, sizeof(struct GATFile_S));
01109     new_file->GATObject__vtable = &GATFile__vtable;
01110     new_file->GATSerialisable__vtable = &GATFile_ISerialisable__vtable;
01111     new_file->GATMonitorable__vtable = &GATFile_IMonitorable__vtable;
01112     
01113     new_file->data.context = context;
01114     new_file->data.isdirty = GATFalse;
01115     new_file->data.source = GATFile_ToGATObject_const(new_file);
01116     
01117     /* find a CPI object, which can handle the data at the given stream 
01118        location */
01119     {
01120       GATRegistry_const registry = GATContext_internal_GetRegistry(context);
01121       GATPreferences_const preferences = NULL;
01122             
01123       /* use default preferences, if appropriate */
01124       if (NULL == preferences)
01125       {
01126         preferences = GATContext_GetPreferences(context);
01127       }
01128 
01129       new_file->data.location = GATLocation_Create(name);
01130       new_file->cpilist = GATRegistry_FindGATFileCPI(registry, preferences);
01131       if (NULL == new_file->cpilist)
01132       {
01133         GAT_CREATE_STATUS(GAT_NO_REGISTERED_CPI);
01134       }
01135       else if (NULL != new_file->data.location)
01136       {
01137         /* find out the current stream position */
01138         GATuint32 offset = 0;
01139         GATBool found_cpi = GATFalse;
01140         GATFileCPIList current = NULL;
01141         
01142         GAT_CREATE_STATUS(GATStreamable_Seek(stream, GATOrigin_Current, 0, &offset));
01143         if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01144         {
01145           /* create new instance data of the CPI provider */
01146           for(current = new_file->cpilist; NULL != current; current = current->next)
01147           {
01148             /* try, whether this cpi can handle the input */
01149             GAT_CREATE_STATUS(GATFileCPI_DeSerialise(current->cpi, stream, 
01150               &new_file->data));
01151             if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01152             {
01153               new_file->cpi = current->cpi;
01154               found_cpi = GATTrue;
01155               break;
01156             }
01157             
01158             /* reset stream pointer to the beginning of the CPI instance data */
01159             GAT_CREATE_STATUS(GATStreamable_Seek(stream, GATOrigin_Set, offset, 0));
01160           }
01161         }
01162         
01163         /* no available CPI object can handle this */
01164         if (GATFalse == found_cpi)
01165         {
01166           GAT_CREATE_STATUS(GAT_NO_MATCHING_CPI);
01167         }
01168         else
01169         {
01170           /* try to re-init the monitoring support, since the adaptor found may
01171              support another set of GATMetric's, than the original one. */
01172           GATList_GATMetric metrics = NULL;
01173 
01174           GATResult retval = GATFileCPI_GetMetrics(new_file->cpi, &new_file->data, 
01175             &metrics);
01176           
01177           if (GAT_SUCCEEDED(retval))
01178           {
01179             new_file->data.monitorable = GATMonitorable_Impl_Create(metrics);
01180             if (NULL == new_file->data.monitorable)
01181             {
01182               GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
01183             }
01184             GATList_GATMetric_Destroy(&metrics);
01185           }
01186           else if (GAT_NOTIMPL != retval) /* not impl: no monitoring supported here */
01187           {
01188             GAT_CREATE_STATUS(retval);   
01189           }
01190           else
01191           {
01192             retval = GAT_SUCCESS;
01193           }
01194           
01195           if (GAT_SUCCEEDED(retval))
01196           {
01197             GAT_CREATE_STATUS(GATRegistry_AddGATFileToCPIList(new_file->data.context, 
01198               new_file->cpi, new_file));
01199           }
01200         }
01201       }
01202     }
01203   }
01204   else
01205   {
01206     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
01207   }
01208   
01209   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01210   {
01211     if (NULL != new_object)
01212     {
01213       *new_object = new_file;
01214     }
01215     else
01216     {
01217       GATFile_Destroy(&new_file);
01218       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
01219     }
01220   }
01221   else
01222   {
01223     GATFile_Destroy(&new_file);
01224   }
01225   
01226   return GAT_RETURN_STATUS();
01227 }
01228 
01229 /*  GATFile_GetCPIInstanceData
01230  *  
01231  *  The function GATFile_GetCPIInstanceData returns the CPI instance data, 
01232  *  associated with the given GATFile object.
01233  *
01234  *  @param file The object, for which to return the CPI instance data.
01235  *  @param data The pointer to the variable, which should receive the
01236  *        resulting CPI instance data.
01237  *
01238  *  @return An error code.
01239  */
01240 static GATResult
01241 GATFile_GetCPIInstanceData(GATFile file, void **data)
01242 {
01243   if (NULL != file)
01244   {
01245     GAT_USES_STATUS(file->data.context, "GATFile_GetCPIInstanceData");
01246     
01247     if (NULL != data)
01248     {
01249       *data = (void *)&file->data;
01250     }
01251     else
01252     {
01253       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
01254     }
01255     
01256     return GAT_RETURN_STATUS();
01257   }
01258   return GAT_INVALID_HANDLE;
01259 }
01260