GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATLogicalFile.c

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