GridLab
Grid Application Toolkit

A simple API for Grid Applications
GAT

Menu



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

GATStatus.c

Go to the documentation of this file.
00001 /** @file GATStatus.c
00002  * Source file for the GATStatus class.
00003  *
00004  * The GATStatus class provides a set of routines to maintain a flexible and
00005  * uniform way to store, retrieve and manage errors and related information,
00006  * which occured during a call to the GAT API.
00007  *
00008  * An instance of this class represents an error or an information message 
00009  * from a GAT operation or from an underlying adaptor. instances of this class 
00010  * are used to provide an audit trail which the application user can use to 
00011  * trace the sequence of events which happened in any particular GAT operation; 
00012  * this may then be used by the application, adaptor or service developers or 
00013  * providers to debug problems.
00014  * Since the GAT Engine and adaptors may do several independent operations each 
00015  * of which may have associated errors or status messages, a GATStatus instance 
00016  * forms a node in a tree of GATStatus instances, rather than the more normal 
00017  * parent-child process of a try-catch type error mechanism.
00018  *
00019  * @date Tue Sep 30 2003
00020  *
00021  * @version $Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATStatus.c,v 1.29 2004/05/12 18:56:01 hartmutkaiser Exp $
00022  *
00023  *  Copyright (C) Hartmut Kaiser
00024  *  This file is part of the GAT Engine.
00025  *  Contributed by Hartmut Kaiser <hartmutkaiser [at] t-online [dot] de>.
00026  *
00027  *  Use, modification and distribution is subject to the Gridlab Software
00028  *  License. (See accompanying file GLlicense.txt or copy at
00029  *  http://www.gridlab.org/GLlicense.txt)
00030  */
00031  
00032 #if defined(sccs)
00033 static const char *rcsid = "$Header: /export/cvs-gridlab/wp-1/Codes/GATEngine/C-reference/src/GATStatus.c,v 1.29 2004/05/12 18:56:01 hartmutkaiser Exp $";
00034 #endif
00035 
00036 #include <assert.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <stdio.h>
00040 
00041 #include "GATInternal.h"
00042 #include "GATType.h"
00043 #include "GATErrors.h"
00044 #include "GATObject.h"
00045 #include "GATContext.h"
00046 #include "GATStatus.h"
00047 #include "GATXdsWrapper.h"
00048 #include "GATList.h"
00049 #include "GATSelf.h"
00050 
00051 /* 
00052  *  Define the type specific interface functions for the GATList_GATStatus list 
00053  */
00054 GATLIST_IMPLEMENT(extern, GATStatus, GATList_GATStatus, GATType_GATStatus)
00055 
00056 /*
00057  *  Define the vtable for this object
00058  */
00059 GATOBJECT_DEFINE_VTABLE(GATStatus);
00060 GATSERIALISABLE_DEFINE_VTABLE(GATStatus);
00061 
00062 /*
00063  *  Declare the converters to/from GATObject
00064  */
00065 GATOBJECT_DEFINE_CONVERTERS(GATStatus);
00066 GATOBJECT_DEFINE_CONVERTERS_QUALIFIED(extern, GATList_GATStatus,
00067   GATType_GATList);
00068 
00069 /*
00070  *  The GATStatus_S structure holds the internal representation of a GATStatus 
00071  *  instance.
00072  */
00073 struct GATStatus_S {
00074   GATStatus_vtable *GATObject__vtable;   /* the vtable of this structure */
00075   GATStatus_ISerialisable_vtable *GATSerialisable__vtable;
00076 
00077   GATBool isdirty;
00078   GATResult statuscode;         /* the actual error/status code */
00079   char filename[FILENAME_MAX];  /* file name, where the status was created */
00080   GATuint32 linenumber;               /* line number, where the status was created */
00081   GATList_String messages;      /* a list of related message */
00082   GATStatus_const parent;       /* the parent GATStatus, may be 0 (zero) */ 
00083   GATList_GATStatus children;   /* a list of attached GATStatus children */
00084 };
00085 
00086 /* Static function prototypes */
00087 static GATResult
00088   GATStatus_DeSerialise_Create(GATContext context, GATObject stream, 
00089     GATResult code, GATList_String messages, GATList_GATStatus children, 
00090     char const *filename, GATuint32 lineno, GATStatus *new_object);
00091 
00092 static GATResult
00093   GATStatus_SetParent(GATStatus status, GATStatus_const parent);
00094 
00095 static void
00096   GATStatus_TraceLevel(FILE *fp, GATStatus_const status, int level);
00097 
00098 /* file scope variables */
00099 static GATStatus_vtable GATStatus__vtable = {
00100   GATStatus_GetType,
00101   GATStatus_Destroy,
00102   GATStatus_Equals,
00103   GATStatus_Clone,
00104   GATStatus_GetInterface
00105 };
00106 
00107 static GATStatus_ISerialisable_vtable 
00108   GATStatus_ISerialisable__vtable = 
00109 {
00110   GATStatus_Serialise,
00111   GATStatus_DeSerialise,
00112   GATStatus_GetIsDirty,
00113 };
00114 
00115 /* External functions */
00116 
00117 /** GATStatus_Register_GATSerialisable
00118  *  The GATStatus_Register_GATSerialisable function registers the serialization
00119  *  vtable with the GAT engine to allow generic object creation.
00120  *  This function is called by the GAT engine, there is no need to use it 
00121  *  directly.
00122  */
00123 GATResult GATStatus_Register_GATSerialisable(void)
00124 {
00125   return GATObject_Register_GATSerialisable(GATType_GATStatus, 
00126     &GATStatus_ISerialisable__vtable);
00127 }
00128 
00129 /* Helper API for GATStatus based error diagnostics and error propagation */
00130 
00131 /** GATCreateStatus
00132  *
00133  *  The function GATCreateStatus is a helper function used for creating and
00134  *  assigning a GATStatus object to the function local GATStatus. It is used 
00135  *  for newly diagnosed errors.
00136  *  
00137  *  @param name The function name of the function, where the error/diagnostic
00138  *        occured.
00139  *  @param status The function local status object to which the newly created
00140  *        error/diagnostic should be added.
00141  *  @param code The GATResult code of the error/diagnostic to be added.
00142  *  @param context The GATContext to which the GATStatus to be propagated is 
00143  *        associated with.
00144  *  
00145  *  @return The provided GATResult code from the code parameter.
00146  */
00147 GATResult 
00148 GATCreateStatus(char const *name, GATStatus *status, GATResult result_code, 
00149   GATContext context, char const *filename, GATuint32 lineno)
00150 {
00151   GATResult retval = GAT_SUCCESS;
00152   if (GAT_FAILED(result_code))
00153   {
00154     if (NULL != name && NULL != status)
00155     {
00156       if (NULL == *status)
00157       {
00158         *status = GATStatus_Create(name, filename, lineno);
00159       }
00160       
00161       if (NULL != *status)
00162       {
00163         GATStatus new_status = NULL;
00164         if (GAT_SUCCESS != GATContext_GetCurrentStatus(context, &new_status) || 
00165             NULL == new_status)
00166         {
00167           new_status = GATStatus_Create_Code(result_code, filename, lineno);
00168           if (NULL == new_status)
00169           {
00170             retval = GAT_MEMORYFAILURE;
00171           }
00172         }
00173         
00174         if (NULL != new_status)
00175         {
00176           retval = GATStatus_AddChild(*status, new_status);
00177           if (GAT_SUCCESS == retval)
00178           {
00179             retval = result_code;
00180           }
00181           GATStatus_Destroy(&new_status);
00182         }
00183       }
00184       else
00185       {
00186         retval = GAT_MEMORYFAILURE;
00187       }
00188     }
00189     else
00190     {
00191       retval = GAT_INVALID_PARAMETER;
00192     }
00193   }
00194   else
00195   {
00196     retval = result_code;
00197   }
00198   return retval;
00199 }
00200 
00201 /** GATPropagateStatus
00202  *
00203  *  The function GATPropagateStatus is used for taking the current status from
00204  *  the given context and append it to the function local GATStatus. It is used
00205  *  for error/diagnostics propagation purposes.
00206  *
00207  *  @param name The function name of the function, where the error/diagnostic
00208  *        occured.
00209  *  @param status The function local status object to which the newly created
00210  *        error/diagnostic should be added.
00211  *  @param code The GATResult code of the error/diagnostic to be added.
00212  *  @param context The GATContext to which the GATStatus to be propagated is 
00213  *        associated with.
00214  *  
00215  *  @return The provided GATResult code from the code parameter.
00216  */
00217 GATResult 
00218 GATPropagateStatus(char const *name, GATStatus *status, GATResult result_code, 
00219   GATContext context)
00220 {
00221   /* This function is depreciated and was completely replaced by the 
00222      GATCreateStatus function */
00223   return GATCreateStatus(name, status, result_code, context, NULL, 0);
00224 }
00225 
00226 /* GATStatus API */
00227 
00228 /** GATStatus GATStatus_Create(char const *message)
00229  *  @brief Create a new GATStatus object
00230  *
00231  *  The function @c GATStatus_Create creates a new GATStatus object and 
00232  *  associates with it the given message. The status code stored internally is 
00233  *  initialized to @c #GAT_SUCCESS.
00234  *
00235  *  @param message The message to associate initially with the newly created 
00236  *        GATStatus.
00237  *
00238  *  @return Returns a handle to the newly created GATStatus object.
00239  *        returns 0 (zero) if an error occurs.
00240  */
00241 GATStatus 
00242 GATStatus_Create(char const *message, char const *filename, GATuint32 lineno)
00243 {
00244   GATStatus status = (GATStatus) malloc(sizeof(struct GATStatus_S));
00245   if (NULL != status) 
00246   {
00247     status->GATObject__vtable = &GATStatus__vtable;
00248     status->GATSerialisable__vtable = &GATStatus_ISerialisable__vtable;
00249     
00250     status->isdirty = GATFalse;
00251     status->statuscode = GAT_SUCCESS;
00252     status->parent = NULL;
00253     status->children = NULL;   /* list of children is created lazily */
00254     if (NULL != filename)
00255     {
00256       strncpy(status->filename, filename, FILENAME_MAX);
00257       status->filename[FILENAME_MAX-1] = '\0';
00258     }
00259     else
00260     {
00261       status->filename[0] = '\0';
00262     }
00263     status->linenumber = lineno;
00264     status->messages = GATList_String_Create();
00265     if (NULL != status->messages)
00266     {
00267       GATList_String_Iterator end = GATList_String_End(status->messages);
00268       GATList_String_Iterator new_msg = 
00269         GATList_String_Insert(status->messages, end, message);
00270       
00271       if (NULL == new_msg)
00272       {
00273         GATList_String_Destroy(&status->messages);
00274         free(status);
00275         status = NULL;
00276       }
00277     }
00278   }
00279   return status;
00280 }
00281 
00282 /** GATStatus GATStatus_Create_Code(GATResult code)
00283  *  @brief Create a new GATStatus object
00284  *
00285  *  The function @c GATStatus_Create_Code creates a new GATStatus object and 
00286  *  associates with it the given status code. 
00287  *
00288  *  @param code The status code to associate initially with the newly created 
00289  *        GATStatus.
00290  *
00291  *  @return Returns a handle to the newly created GATStatus object.
00292  *        returns 0 (zero) if an error occurs.
00293  */
00294 GATStatus GATStatus_Create_Code(GATResult code, char const *filename, 
00295   GATuint32 lineno)
00296 {
00297   GATStatus status = (GATStatus) malloc(sizeof(struct GATStatus_S));
00298   if (NULL != status) 
00299   {
00300     status->GATObject__vtable = &GATStatus__vtable;
00301     status->GATSerialisable__vtable = &GATStatus_ISerialisable__vtable;
00302     
00303     status->isdirty = GATFalse;
00304     status->statuscode = code;
00305     status->parent = NULL;
00306     status->children = NULL;         /* list of children is created lazily */
00307     if (NULL != filename)
00308     {
00309       strncpy(status->filename, filename, FILENAME_MAX);
00310       status->filename[FILENAME_MAX-1] = '\0';
00311     }
00312     else
00313     {
00314       status->filename[0] = '\0';
00315     }
00316     status->linenumber = lineno;
00317     status->messages = GATList_String_Create();
00318 
00319     if (NULL == status->messages)
00320     {
00321       GATStatus_Destroy(&status);
00322     }
00323   }
00324   return status;
00325 }
00326 
00327 /** void GATStatus_Destroy(GATStatus *status)
00328  *  @brief Delete an existing GATStatus object
00329  *
00330  *  The function GATStatus_Destroy destroys this GATStatus object and all of
00331  *  the contained data (such as the GATStatus list of children and the list
00332  *  of attached message strings).
00333  *
00334  *  @param status The GATStatus object to be destroyed. If this parameter is 0 
00335  *        (zero) the function does nothing, but returns @c #GAT_SUCCESS.
00336  */
00337 void 
00338 GATStatus_Destroy(GATStatus *status)
00339 {
00340   if (NULL != status && NULL != *status) 
00341   {
00342     GATList_String_Destroy(&(*status)->messages);
00343     GATList_GATStatus_Destroy(&(*status)->children);
00344     free(*status);
00345     *status = NULL;
00346   }
00347 }
00348 
00349 /** GATType GATStatus_GetType(GATStatus_const status)
00350  *  @brief Return the type of the GATStatus
00351  *
00352  *  The function @c GATStatus_GetType always returns GATType_GATStatus. 
00353  *
00354  *  @param object The object to inspect
00355  *
00356  *  @return Returns always @c #GATType_GATStatus.
00357  */
00358 GATType GATStatus_GetType(GATStatus_const status)
00359 {
00360   GAT_UNUSED_PARAMETER(status);
00361   return GATType_GATStatus;
00362 }
00363 
00364 /** int GATStatus_Clone(GATStatus_const status, GATStatus *new_status)
00365  *  @brief Clones a GATStatus object.
00366  *
00367  *  The function GATStatus_Clone makes a exact copy of the given @c #GATStatus
00368  *  object.
00369  *
00370  *  @param status The object to clone
00371  *  @param new_Status The pointer, through which the result is to be 
00372  *        returned.
00373  *
00374  *  @return An error type.
00375  */
00376 GATResult GATStatus_Clone(GATStatus_const status, GATStatus *new_object)
00377 {
00378   GATResult retval = GAT_INVALID_PARAMETER;
00379   if (NULL != status && NULL != new_object)
00380   {
00381     GATStatus new_status = (GATStatus) malloc(sizeof(struct GATStatus_S));
00382     if (NULL == new_status)
00383     {
00384       retval = GAT_MEMORYFAILURE;
00385     }
00386     else
00387     {
00388       new_status->GATObject__vtable = &GATStatus__vtable;
00389       new_status->GATSerialisable__vtable = &GATStatus_ISerialisable__vtable;
00390       
00391       new_status->isdirty = status->isdirty;
00392       new_status->statuscode = status->statuscode;
00393       new_status->parent = status->parent;
00394       new_status->children = NULL;
00395       new_status->messages = NULL;
00396       strcpy(new_status->filename, status->filename);
00397       new_status->linenumber = status->linenumber;
00398       
00399       retval = GATList_String_Clone(status->messages, &new_status->messages);
00400       if (GAT_SUCCESS == retval && NULL != status->children)
00401       {
00402         GATList_GATStatus_Iterator it = GATList_GATStatus_Begin(status->children);
00403         GATList_GATStatus_Iterator end = GATList_GATStatus_End(status->children);
00404         for (/**/; it != end; it = GATList_GATStatus_Next(it))
00405         {
00406           retval = GATStatus_AddChild(new_status, *GATList_GATStatus_Get(it));
00407           if (GAT_SUCCESS != retval)
00408           {
00409             break;
00410           }
00411         }
00412       }
00413     }
00414     
00415     if (GAT_SUCCESS != retval)
00416     {
00417       GATStatus_Destroy(&new_status);
00418     }
00419     
00420     *new_object = new_status;
00421   }
00422   return retval;
00423 }
00424 
00425 /** int GATStatus_Equals(GATStatus_const lhs, GATStatus_const rhs, GATBool *isequal)
00426  *  @brief Compare two GATStatus objects
00427  *
00428  *  The function GATStatus_Equals compares the two given GATStatus objects and 
00429  *  returns the outcome of this comparision.
00430  *
00431  *  @param lhs The first list to compare
00432  *  @param rhs The second list to compare
00433  *  @param isequal The pointer to the GATBool variable, which should receive 
00434  *        the result if the comparision
00435  *
00436  *  @return An error code.
00437  */
00438 GATResult GATStatus_Equals(GATStatus_const lhs, GATStatus_const rhs, 
00439   GATBool *isequal)
00440 {
00441   GATResult retval = GAT_INVALID_PARAMETER;
00442   if (NULL != lhs && NULL != rhs && NULL != isequal)
00443   {
00444     *isequal = GATTrue;
00445     if (lhs->statuscode != rhs->statuscode || 
00446         strcmp(lhs->filename, rhs->filename) ||
00447         lhs->linenumber != rhs->linenumber)
00448     {
00449       *isequal = GATFalse;
00450     }
00451     else 
00452     {
00453       retval = GATList_String_Equals(lhs->messages, rhs->messages, isequal);
00454       if (GAT_SUCCESS == retval && GATTrue == *isequal)
00455       {
00456         if (NULL != lhs->children && NULL != rhs->children)
00457         {
00458           retval = GATList_GATStatus_Equals(lhs->children, rhs->children, 
00459             isequal);
00460         }
00461         else if (NULL == lhs->children && NULL == rhs->children)
00462         {
00463           *isequal = GATTrue;
00464           retval = GAT_SUCCESS;
00465         }
00466         else
00467         {
00468           *isequal = GATFalse;
00469           retval = GAT_SUCCESS;
00470         }
00471       }
00472     }
00473   }
00474   return retval;
00475 }
00476 
00477 /** GATResult GATStatus_GetInterface(GATStatus_const file, GATInterface iftype, void const **ifp)
00478  *  @brief Get an interface supported by a GATObject
00479  *
00480  *  The function GATStatus_GetInterface allows to get a pointer to an 
00481  *  additional interface supported by this GATStatus.
00482  *
00483  *  @param object The object to be asked for the new interface.
00484  *  @param iftype The interface the object is to be asked for.
00485  *  @param ifp The pointer, through which the result is to be returned.
00486  *
00487  *  @return An error type.
00488  */
00489 GATResult 
00490 GATStatus_GetInterface(GATStatus_const object, GATInterface iftype, 
00491   void const **ifp)
00492 {
00493   GATResult retval = GAT_INVALID_PARAMETER;
00494 
00495   if (NULL != ifp)
00496   {
00497     *ifp = NULL;
00498     if (GATInterface_ISerialisable == iftype)
00499     {
00500       *ifp = (void const *) &object->GATSerialisable__vtable;
00501       retval = GAT_SUCCESS;
00502     }
00503     else
00504     {
00505       retval = GAT_NO_INTERFACE;
00506     }
00507   }
00508   return retval;
00509 }
00510 
00511 /* GATAdvertiseable API */
00512 
00513 /** GATResult GATStatus_Serialise(GATStatus object, GATObject stream, GATBool clear_dirty)
00514  *  @brief Serialise a GATStatus object
00515  *
00516  *  The function GATStatus_Serialise serialises the given GATStatus object into the
00517  *  given stream. 
00518  *
00519  *  @param object The GATStatus object to serialise.
00520  *  @param stream The stream interface to use for the serialisation.
00521  *  @param clear_dirty If the clear_dirty parameter is set to GATTrue, the 
00522  *        internal dirty flag of this object is to be reset (no used here)
00523  *
00524  *  @return An error code.
00525  */
00526 GATResult 
00527 GATStatus_Serialise(GATStatus object, GATObject stream, GATBool clear_dirty)
00528 {
00529   GATResult retval = GAT_INVALID_HANDLE;
00530   if (NULL != object)
00531   {
00532     retval = GATXds_SerialiseObject(GATStatus_ToGATObject(object), stream, 
00533       clear_dirty, 0, "uint32 uint32 object object string uint32",
00534       GATSTATUS_VERSION1, object->statuscode, 
00535       object->messages, clear_dirty, object->children, clear_dirty,
00536       object->filename, object->linenumber);
00537     
00538     if (GAT_SUCCEEDED(retval) && clear_dirty)
00539     {
00540       object->isdirty = GATFalse;
00541     }
00542   }
00543   return retval;
00544 }
00545 
00546 /** GATStatus_VersionCallback
00547  *
00548  *  The function GATStatus_VersionCallback is used as a callback function
00549  *  during the de-serialisation of a GATStatus. It should be provided to test,
00550  *  whether the de-serialised version matches the expected version.
00551  *
00552  *  @param version The version number, which was de-serialised from the stream.
00553  *
00554  *  @return This function should return GATTrue, if the version matches the 
00555  *        expected value (version is valid), GATFalse otherwise.
00556  *
00557  *  @remark This function is called from the GAT engine, there is no need to 
00558  *        call it directly.
00559  */
00560 static GATBool
00561 GATStatus_VersionCallback(GATuint32 version)
00562 {
00563   GATBool retval = GATFalse;
00564   if ((version & ~GATSTATUS_MINOR_MASK) <= GATSTATUS_LASTVERSION)
00565   {
00566     retval = GATTrue;
00567   }
00568   return retval;
00569 }
00570 
00571 /** GATStatus_DeSerialiseCallback
00572  *
00573  *  The function GATStatus_DeSerialiseCallback is used as a callback function
00574  *  during the de-serialisation of a GATStatus. It should be provided for the
00575  *  instantiation of the new GATStatus object based on the already de-serialised 
00576  *  data items and the de-serialisation of the associated CPI provider data for 
00577  *  the given object.
00578  *
00579  *  @param context The GAT context to be used for object construction.
00580  *  @param stream The stream interface to use for the serialisation.
00581  *  @param object The pointer to the variable, which should receive the newly 
00582  *        constructed object.
00583  *  @param version The version of the saved data read from the input stream.
00584  *  @param args This parameter is the pointer to the va_list containing 
00585  *        pointers to the already de-serialised data items accordingly to the
00586  *        format string, provided during the call to the 
00587  *        GATStatus_DeSerialise function.
00588  *
00589  *  @return An error code.
00590  *
00591  *  @remark This function is called from the GAT engine, there is no need to 
00592  *        call it directly.
00593  */
00594 static GATResult 
00595 GATStatus_DeSerialiseCallback(GATContext context, GATObject stream, 
00596   GATObject *new_object, GATuint32 version, va_list args)
00597 {
00598   /* the version was eaten already */
00599 
00600   GATuint32 *code = va_arg(args, GATuint32 *);
00601   GATList_String *messages = va_arg(args, GATList_String *);
00602   GATList_GATStatus *children = va_arg(args, GATList_GATStatus *);
00603   char const **filename = va_arg(args, char const **);
00604   GATuint32 *lineno = va_arg(args, GATuint32 *);
00605   
00606   GATStatus object = NULL;
00607   
00608   /* construct the new object */
00609   GATResult retval = GATStatus_DeSerialise_Create(context, stream, *code,
00610     *messages, *children, *filename, *lineno, &object);
00611   if (GAT_SUCCESS == retval)
00612   {
00613     if (NULL != object)
00614     {
00615       *new_object = GATStatus_ToGATObject(object);
00616     }
00617     else
00618     {
00619       GATStatus_Destroy(&object);
00620       retval = GAT_INVALID_PARAMETER;
00621     }
00622   }
00623   return retval;
00624 }
00625 
00626 /** GATStatus GATStatus_DeSerialise(GATContext context, GATObject stream, GATBool clear_dirty)
00627  *  @brief De-serialise a GATStatus object
00628  *
00629  *  The function GATStatus_DeSerialise de-serialises a streamed GATStatus object  
00630  *  from the given stream  It constructs a new instance of the de-serialised 
00631  *  object.
00632  *
00633  *  @param context The GAT context to be used for object construction.
00634  *  @param stream The stream interface to use for the serialisation.
00635  *  @param result The pointer to a variable, which receives the status code of
00636  *        the operation.
00637  *
00638  *  @return The newly constructed GATStatus object.
00639  */
00640 GATStatus 
00641 GATStatus_DeSerialise(GATContext context, GATObject stream, GATResult *result)
00642 {
00643   GAT_USES_STATUS(context, "GATStatus_DeSerialise");
00644   GATObject object = NULL;     /* the new object will be created here */
00645   
00646   /* we must provide all instance data items to be de-serialised for this
00647      GATStatus object accordingly to the provided format string */
00648   GATuint32 version = 0;
00649   
00650   GATResult code = 0;         /* the actual error/status code */
00651   GATList_String messages = NULL; 
00652   GATList_GATStatus children = NULL;
00653   char *filename = NULL;
00654   GATuint32 lineno = 0;
00655   
00656   /* read the data */
00657   GAT_CREATE_STATUS(GATXds_DeSerialiseObject(context, stream, 
00658     GATStatus_DeSerialiseCallback, GATStatus_VersionCallback, &object, 
00659     "uint32 uint32 object object string uint32", &version, &code, &messages, 
00660     &children, &filename, &lineno));
00661 
00662   free(filename);
00663   GATList_String_Destroy(&messages);
00664   GATList_GATStatus_Destroy(&children);
00665 
00666   if (NULL != result)
00667   { 
00668     *result = GAT_RETURN_STATUS();
00669   }
00670   else
00671   {
00672     GAT_STORE_STATUS();
00673   }
00674   return GATObject_ToGATStatus(object);
00675 }
00676 
00677 /** GATStatus_GetIsDirty
00678  *  
00679  *  The function GATStatus_GetIsDirty retrieves the status of the dirty flag of 
00680  *  this GATStatus object.
00681  *
00682  *  @param file The GATStatus object to inspect for its dirty status.
00683  *  @param isdirty The pointer to a variable, which receives the dirty status.
00684  *
00685  *  @return An error code.
00686  */
00687 GATResult GATStatus_GetIsDirty(GATStatus_const object, GATBool *isdirty)
00688 {
00689   GATResult retval = GAT_INVALID_HANDLE;
00690   if (NULL != object)
00691   {
00692     if (NULL != isdirty)
00693     {
00694       *isdirty = object->isdirty;
00695       retval = GAT_SUCCESS;
00696     }
00697     else
00698     {
00699       retval = GAT_INVALID_PARAMETER;
00700     }
00701   }  
00702   return retval;
00703 }
00704 
00705 
00706 /* GATStatus API functions */
00707 
00708 /** int GATStatus_SetStatusCode(GATStatus status, int code)
00709  *  @brief Set the statuscode to be associated with the GATStatus object
00710  *
00711  *  The function GATStatus_SetStatusCode associates a new status code with
00712  *  the GATStatus object under inspection.
00713  *
00714  *  @param status The GATStatus object, which associated status code
00715  *        should be set.
00716  *  @param code The new status code to be associated with the GATStatus
00717  *        object.
00718  *
00719  *  @return Returns @c #GAT_SUCCESS if the given status parameter is a
00720  *        valid GATStatus object. If the given parameter was
00721  *        not a valid GATStatus object, then @c #GAT_INVALID_HANDLE
00722  *        is returned.
00723  */
00724 GATResult 
00725 GATStatus_SetStatusCode(GATStatus status, int code)
00726 {
00727   GATResult result = GAT_INVALID_HANDLE;
00728   if (NULL != status)
00729   {
00730     status->statuscode = code;
00731     result = GAT_SUCCESS;
00732   }
00733   return result;
00734 }
00735 
00736 /** int GATStatus_GetStatusCode(GATStatus status)
00737  *  @brief Get the statuscode associated with the GATStatus object
00738  *
00739  *  The function GATStatus_GetStatusCode returns the statuscode, which
00740  *  was associated with the GATSTatus object with a call of the
00741  *  @c #GATStatus_SetStatusCode function.
00742  *
00743  *  @param status The GATStatus object, which associated status code
00744  *        should be returned.
00745  *
00746  *  @return The statuscode associated with the GATStatus object. If the
00747  *        GATStatus under inspection was not a valid GATStatus (but not
00748  *        equal zero), then @c #GAT_INVALID_HANDLE is returned.
00749  */
00750 GATResult 
00751 GATStatus_GetStatusCode(GATStatus_const status)
00752 {
00753   GATResult result = GAT_INVALID_HANDLE;
00754   if (NULL != status)
00755   {
00756     result = status->statuscode;
00757   }
00758   return result;
00759 }
00760 
00761 /** int GATStatus_AddChild(GATStatus status, GATStatus child)
00762  *  @brief Adds a child to the list of children
00763  *
00764  *  The function GATStatus_AddChild adds a GATStatus to the list of
00765  *  children of this status object. Please note, that there is no test
00766  *  to avoid cyclic hierarchies, so you'll have ensure, that a GATStatus
00767  *  object is @b not inserted into a GATStatus hierarchy twice.
00768  *
00769  *  @param status The GATStatus object, which should get the child added.
00770  *  @param child The GATStatus object to be added as the child.
00771  *
00772  *  @returns The function returns @c #GAT_SUCCESS, if the child was
00773  *        successfully added to the list of children. If the status
00774  *        parameter wasn't a valid GATStatus object, then the value
00775  *        @c #GAT_INVALID_HANDLE is returned.
00776  */
00777 GATResult 
00778 GATStatus_AddChild(GATStatus status, GATStatus child)
00779 {
00780   GATResult result = GAT_INVALID_HANDLE;
00781   if (NULL != status && NULL != child)
00782   {
00783     if (NULL == status->children)
00784     {
00785       /* no children attached so far, create the list */
00786       status->children = GATList_GATStatus_Create();
00787       if (NULL == status->children)
00788       {
00789         result = GAT_MEMORYFAILURE;
00790       }
00791     }
00792 
00793     /* if there isn't a valid child list at this point, then something went
00794        wrong */
00795     if (NULL != status->children)
00796     {
00797       /* add the given GATStatus as the last child to this */
00798       GATList_GATStatus_Iterator end = GATList_GATStatus_End(status->children);
00799       GATList_GATStatus_Iterator item =
00800         GATList_GATStatus_Insert(status->children, end, child);
00801 
00802       if (NULL != item)
00803       {
00804         /* set back pointer to the parent */
00805         GATStatus new_child = *GATList_GATStatus_Get(item);
00806         new_child->parent = status;
00807         result = GAT_SUCCESS;
00808       }
00809     }
00810   }
00811   return result;
00812 }
00813 
00814 /** GATList_GATStatus_const GATStatus_GetChildren(GATStatus status)
00815  *  @brief Get the list of associated children
00816  *
00817  *  The function GATStatus_GetChildren returns the list of children
00818  *  associated with the given GATStatus.
00819  *
00820  *  @param status The GATStatus object, for which the list of children is to
00821  *        be returned.
00822  *
00823  *  @return The function returns the handle of a GATList_GATStatus object,
00824  *        which holds the GATStatus objects associated as children. If the
00825  *        status parameter does not represent a valid GATStatus object or if
00826  *        there aren't any associated children, then 0 (zero) is returned.
00827  */
00828 GATList_GATStatus_const 
00829 GATStatus_GetChildren(GATStatus_const status)
00830 {
00831   GATList_GATStatus result = NULL;
00832   if (NULL != status)
00833   {
00834     result = status->children;
00835   }
00836   return result;
00837 }
00838 
00839 /** int GATStatus_AddMessage(GATStatus status, char const *message)
00840  *  @brief Add a message to the GATStatus object
00841  *
00842  *  The function GATStatus_AddMessage adds a message to the list of
00843  *  messages associated with this GATStatus object.
00844  *
00845  *  @param status The GATStatus object the message has to be
00846  *        associated with.
00847  *  @param message The character string to be associated with the
00848  *        GATStatus object. Note, that actually a copy of this string
00849  *        is stored inside the GATStatus object.
00850  *
00851  *  @return If the message was added successfully to the list of associated 
00852  *        messages of this GATSTatus, the function will return @c #GAT_SUCCESS.
00853  *        If the status parameter does not represent a valid GATStatus object
00854  *        the function returns @c #GAT_INVALID_HANDLE.
00855  */
00856 GATResult 
00857 GATStatus_AddMessage(GATStatus status, char const *message)
00858 {
00859   GATResult result = GAT_INVALID_HANDLE;
00860   if (NULL != status)
00861   {
00862     GATList_String_Iterator item = GATList_String_Insert(
00863       status->messages, GATList_String_End(status->messages), message);
00864 
00865     result = (NULL == item) ? GAT_MEMORYFAILURE : GAT_SUCCESS;
00866   }
00867   return result;
00868 }
00869 
00870 /** GATList_String_const GATStatus_GetMessages(GATStatus status)
00871  *  @brief get the list of associated messages
00872  *
00873  *  The function GATStatus_GetMessages returns the list of associated messages.
00874  *
00875  *  @param status The GATStatus object, for which the list of messages is to
00876  *        be returned.
00877  *
00878  *  @return The function returns the handle of a GATList_String object,
00879  *        which holds the messages associated with this object. If the
00880  *        status parameter does not represent a valid GATStatus object, 
00881  *        then 0 (zero) is returned.
00882  */
00883 GATList_String_const 
00884 GATStatus_GetMessages(GATStatus_const status)
00885 {
00886   GATList_String result = NULL;
00887   if (NULL != status)
00888   {
00889     result = status->messages;
00890   }
00891   return result;
00892 }
00893 
00894 /** GATStatus GATStatus_GetParent(GATStatus status)
00895  *  @brief Get the parent status of this GATStatus object
00896  *  
00897  *  The function GATStatus_GetParent returns the GATStatus object, which is the 
00898  *  direct parent of this status object. This is meaningful especially because,
00899  *  different GATStatus objects may be organized in a hierarchical way.
00900  *
00901  *  @param status The GATStatus object, for which the direct parent is to be 
00902  *        returned
00903  *
00904  *  @return The function returns the GATStatus, which is stored as the direct 
00905  *        parent of this status object. If the status parameter does not 
00906  *        represent a valid GATStatus object, then 0 (zero) is returned.
00907  */
00908 GATStatus_const 
00909 GATStatus_GetParent(GATStatus_const status)
00910 {
00911   GATStatus_const result = NULL;
00912   if (NULL != status)
00913   {
00914     result = status->parent;
00915   }
00916   return result;
00917 }
00918 
00919 /** GATStatus_Trace
00920  *  
00921  *  The function GATStatus_Trace prints out to stderr the content of the given
00922  *  GATStatus object.
00923  *
00924  *  @param status The object for which to print the error information.
00925  */
00926 void
00927 GATStatus_Trace(GATStatus_const status)
00928 {
00929   if (NULL != status) 
00930   {
00931     fprintf(stderr, "GAT error backtrace:\n");
00932     GATStatus_TraceLevel(stderr, status, 0);
00933     fprintf(stderr, "\n");
00934     fflush(stderr);
00935   }
00936 }
00937 
00938 
00939 /* Local functions */
00940 
00941 /** GATStatus_DeSerialise_Create
00942  *
00943  *  The function GATStatus_DeSerialise_Create creates a new GATStatus object.
00944  *
00945  *  @param context The GAT context to use for creation of the GATStatus object.
00946  *  @param stream The object from which the adaptor should read the streamed
00947  *        instance data.
00948  *  @param code The status code of the new  object.
00949  *  @param messages The list of messages associated with the new created object.
00950  *  @param children The list of child GATStatus objects associated with the
00951  *        new object.
00952  *  @param new_object The pointer to the variable, which should receive the 
00953  *        newly constructed GATStatus object.
00954  *
00955  *  @return An error code.
00956  */
00957 static GATResult 
00958 GATStatus_DeSerialise_Create(GATContext context, GATObject stream, 
00959   GATResult code, GATList_String messages, GATList_GATStatus children, 
00960   char const *filename, GATuint32 lineno, GATStatus *object)
00961 {
00962   GAT_USES_STATUS(context, "GATStatus_DeSerialise_Create");
00963 
00964   GATStatus new_object = (GATStatus) malloc(sizeof(struct GATStatus_S));
00965   if(NULL != new_object)
00966   {
00967     memset(new_object, 0, sizeof(struct GATStatus_S));
00968     new_object->GATObject__vtable = &GATStatus__vtable;
00969     new_object->GATSerialisable__vtable = &GATStatus_ISerialisable__vtable;
00970     
00971     new_object->isdirty = GATFalse;
00972     new_object->statuscode = code;
00973     
00974     strcpy(new_object->filename, filename);
00975     new_object->linenumber = lineno;
00976     
00977     GAT_CREATE_STATUS(GATList_String_Clone(messages, &new_object->messages));
00978     
00979     /* set the new object as the parent for the childlist */
00980     if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()) && NULL != children) 
00981     {
00982       GAT_CREATE_STATUS(GATList_GATStatus_Clone(children, &new_object->children));
00983       
00984       if (NULL != new_object->children)
00985       {
00986         GATList_GATStatus_Iterator it = GATList_GATStatus_Begin(new_object->children);
00987         GATList_GATStatus_Iterator end = GATList_GATStatus_End(new_object->children);
00988           
00989         for (/**/; it != end && GAT_SUCCEEDED(GAT_CURRENT_STATUS()); 
00990             it = GATList_GATStatus_Next(it))
00991         {
00992           GATStatus *child = GATList_GATStatus_Get(it);
00993           GAT_CREATE_STATUS_IF(NULL == child, GAT_FAIL);
00994           GAT_CREATE_STATUS(GATStatus_SetParent(new_object, *child));
00995         }
00996       }
00997     }
00998   }
00999   else
01000   {
01001     GAT_CREATE_STATUS(GAT_MEMORYFAILURE);
01002   }  
01003   
01004   if (GAT_SUCCEEDED(GAT_CURRENT_STATUS()))
01005   {
01006     if (NULL != new_object)
01007     {
01008       *object = new_object;
01009     }
01010     else
01011     {
01012       GATStatus_Destroy(&new_object);
01013       GAT_CREATE_STATUS(GAT_INVALID_PARAMETER);
01014     }
01015   }
01016   else
01017   {
01018     GATStatus_Destroy(&new_object);
01019   }
01020   return GAT_RETURN_STATUS();
01021 }
01022 
01023 /** GATStatus_SetParent
01024  *
01025  *  
01026  */
01027 static GATResult
01028 GATStatus_SetParent(GATStatus status, GATStatus_const parent)
01029 {
01030   GATResult retval = GAT_INVALID_HANDLE;
01031   if (NULL != status)
01032   {
01033     status->parent = parent;
01034     retval = GAT_SUCCESS;
01035   }
01036   return retval;
01037 }
01038 
01039 /** GATStatus_TraceLevel
01040  *  
01041  */
01042 static void
01043 GATStatus_TraceLevel(FILE *fp, GATStatus_const status, int level)
01044 {
01045   int code = GATStatus_GetStatusCode(status);
01046   char fmt[32];
01047   char buffer[4096];
01048   GATuint32 written = 0;
01049   GATResult retval = GAT_SUCCESS;
01050   
01051   if (GAT_SUCCESS != code)
01052   {
01053     retval = GATSelf_ResolveErrorMessage(code, buffer, sizeof(buffer), &written);
01054   }
01055   
01056   /* prepare indentation format string */  
01057   memset(fmt, 0, sizeof(fmt));
01058   sprintf(fmt, "%%%d.%ds", level, level);
01059 
01060   /* print out the status code */
01061   if (GAT_SUCCESS != code)
01062   {
01063     fprintf(fp, fmt, "");    /* indent */
01064     if (strlen(status->filename) > 0)
01065     {
01066       fprintf(fp, "Statuscode: 0x%x (%s) at (%s): %d\n", code, 
01067         GAT_SUCCEEDED(retval) ? buffer : "unknown status code", 
01068         status->filename, status->linenumber);
01069     }
01070     else
01071     {
01072       fprintf(fp, "Statuscode: 0x%x (%s)\n", code, 
01073         GAT_SUCCEEDED(retval) ? buffer : "unknown status code");
01074     }
01075   }
01076   
01077   /* print out all attached messages */
01078   {
01079     GATList_String_const messages = GATStatus_GetMessages(status);
01080     GATList_String_Iterator msg = GATList_String_Begin(messages);
01081     GATList_String_Iterator msg_end = GATList_String_End(messages);
01082     int i;
01083     GATBool first = GATTrue;
01084     
01085     for (i = 0; msg != msg_end; msg = GATList_String_Next(msg), ++i)
01086     {
01087       fprintf(fp, fmt, "");   /* indent */
01088       if (GAT_SUCCESS == code && GATTrue == first)
01089       {
01090         /* this is the routine name */
01091         fprintf(fp, "Routine: %s\n", GATList_String_Get(msg));
01092         first = GATFalse;
01093       }
01094       else
01095       {
01096         fprintf(fp, " %s\n", GATList_String_Get(msg));
01097       }
01098     }
01099   }
01100       
01101   /* print out the information for all attached children */  
01102   {
01103     GATList_GATStatus_const children = GATStatus_GetChildren(status);
01104     if (NULL != children)
01105     {
01106       GATList_GATStatus_Iterator it = GATList_GATStatus_Begin(children);
01107       GATList_GATStatus_Iterator end = GATList_GATStatus_End(children);
01108       int j;
01109       
01110       for (j = 0; it != end; it = GATList_GATStatus_Next(it), ++j)
01111       {
01112         GATStatus child = *GATList_GATStatus_Get(it);
01113 
01114         /* ensure the consistency of the hierarchy */
01115         assert(GATStatus_GetParent(child) == status);
01116 
01117         /* print out all the information of this child */        
01118         GATStatus_TraceLevel(fp, child, level + 1);
01119       }
01120     }  
01121   }
01122 }
01123