# MEDversionedApi.cxx

Aller à la documentation de ce fichier.

    00001 /*  This file is part of MED.
    00002  *
    00003  *  COPYRIGHT (C) 1999 - 2012  EDF R&D, CEA/DEN
    00004  *  MED is free software: you can redistribute it and/or modify
    00005  *  it under the terms of the GNU Lesser General Public License as published by
    00006  *  the Free Software Foundation, either version 3 of the License, or
    00007  *  (at your option) any later version.
    00008  *
    00009  *  MED is distributed in the hope that it will be useful,
    00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012  *  GNU Lesser General Public License for more details.
    00013  *
    00014  *  You should have received a copy of the GNU Lesser General Public License
    00015  *  along with MED.  If not, see <http://www.gnu.org/licenses/>.
    00016  */
    00017
    00018 #include "MEDversionedApi.hxx"
    00019
    00020 extern "C" {
    00021 #include "med_config.h"
    00022 }
    00023
    00024 #include "med_versioned.h"
    00025 #include <med_utils.h>
    00026
    00027 using namespace std;
    00028
    00029 static MED_VERSIONED_API & MedVersionedApi=MED_VERSIONED_API::Instance();
    00030
    00031 MED_VERSIONED_API& MED_VERSIONED_API::Instance() {
    00032   static MED_VERSIONED_API obj;
    00033   return obj;
    00034 }
    00035
    00036 void MED_VERSIONED_API::f77ApiIsSet() {
    00037   //SSCRUTE ("initMedVersionedApiF thing");
    00038   _f77ApiIsSet=true;
    00039 }
    00040
    00041 // Le mécanisme de driver permet de faire évoluer la représentation des informations
    00042 // dans les fichiers MED nouvellement crées en restant
    00043 // capable de lire/écrire des fichiers MED avec des représentations antérieures.
    00044 // Cela permet donc une compatibilité ascendante en lecture/écriture des fichiers.
    00045 //
    00046 // 1) Les modifications d'implémentations d'une routine qui rendent impossible/incohérent
    00047 // la lecture d'anciens fichiers avec les nouvelles modifications du modèle interne necessitent
    00048 // le versionement de la routine dans cette table.
    00049 //
    00050 // 2) Les modifications d'implémentations d'une routine qui rendent impossible/incohérent
    00051 // la lecture de nouveaux fichiers avec les anciennes bibliothèques doivent également faire
    00052 // l'objet d'un  versionement dans cette table et non juste une modification dans les versions existantes.
    00053 //
    00054 // Ex : L'implémentation de MEDchampEcr entre 232 et 233 pour l'écriture des champs aux noeuds par maille.
    00055 //    La nouvelle bibliothèque est capable de lire les anciens fichiers qui ne contiennent pas cette fonctionnalité.
    00056 //    Cependant les anciennes bibliothèques ne sont pas capable de relire un fichier produit en 233 même
    00057 //    si l'utilisateur veut ignorer la lecture de tels champs. En effet, MEDnChamp et MEDchampInfo nous indiqueront
    00058 //    la présence de champs qui seront illisible pour l'ancienne implémentation de l'API !
    00059 //
    00060 // Ceci permet à la nouvelle bibliothèque (233) qui lit un fichier 232 de se comporter comme la bibliothèque 232
    00061 // et éviter toute corrompuption du modèle 232.
    00062 // Dans l'exemple précedent, si cette fonctionnalité n'avait pas eu d'impact sur le comportement
    00063 // de MEDnChamp et MEDchampInfo en 232, il n'aurait pas été necessaire de versionner cette routine.
    00064 // La seule protection possible pour les bibliothèques antérieures est de refuser la lecture de fichier MED dont le mineur
    00065 // est supérieur à celui de la bibliothèque courante. (l'exemple précédent est versionné sur le release au lieu du mineur,
    00066 // la règle de versionement MED n'a pas été respectée).
    00067 //
    00068 // Les routines versionnées dont les numéros n'existent pas dans la version courante de la bibliothèque
    00069 // n'ont pas étés modifiées depuis la version de la bibliothèque qui correspond à leur numéro de versionement.
    00070 // Lorsque les routines wrappers (MEDchampEcr pour MEDchampEcr231,MEDchampEcr232,MEDchampEcr233) demandent leur implémentation
    00071 // à getVersionedApi en fonction de la version avec laquelle le fichier traité à été crée, la première implémentation
    00072 // dont le numéro de versionement est inférieur ou égal à celui du fichier est renvoyé.
    00073 // getVersionedApi gère les ruptures de compatibilité globale de bibliothèques (ex : on ne relit
    00074 // pas de fichiers < 220 avec les biblioth�ques 2.3.x.
    00075 // Dans ce mécanisme, il est également necessaire de se protéger d'une lecture de fichier dont le mineur du numéro
    00076 // de version serait supérieur à celui de la bibliothèque.
    00077
    00078
    00079 //
    00080 // ******** POLITIQUE DE VERSIONEMENT DE LA BIBLIOTHEQUE MED ******
    00081 //
    00082 // Le versionement de la bibliothèque MED dans le fichier Makefile.am n'indique rien
    00083 // sur la compatibilité/incompatibilité descendante.
    00084 // Seule la capacité des anciens programmes à utiliser cette nouvelle bibliothèque dynamique est indiquée (ce qui
    00085 // sera toujours le cas avec le système de driver si l'API utilisateur ne change pas (sauf ajout)).
    00086 // Si l'API utilisateur change, le versionement libtool indique l'incompatibilité des anciens programmes à utiliser
    00087 // la nouvelle biblioth�que. Le numéro de version majeur de la bibliothèque devrait également être incrémenté.
    00088 // Si une nouvelle version majeure d'hdf est utilisée et qu'elle est incompatible avec l'ancienne le numéro majeur devrait
    00089 // être également augmenté.
    00090 //
    00091 // Si le numéro de version mineur de la bibliothèque avec laquelle le fichier a été crée est supèrieur à celui de la
    00092 // version de bibliothèque utilisée la bibliothèque doit renvoyer une erreur.
    00093 //
    00094 // Ceci implique qu'un ajout dans la table de versionement suppose l'incrément du numéro mineur de
    00095 // la bibliothèque pour plus de lisiblité par les utilisateurs quand à l'incompatibilité descendante :
    00096 // Une version de numéro mineur antérieur à celui de la bibliotèque MED courante ne pourra relire un fichier nouvellement
    00097 // crée par cette nouvelle version. Celà suppose également que les numéros de versions dont seuls la partie
    00098 // release change ne devrait pas apparaitre dans cette table. Ils correspondent à des corrections de BUG
    00099 // qui n'entrainent pas une incompatibilité descendante.
    00100 //
    00101 // Ceci n'a pas toujours été respecté, ex1: 231, 232, 233
    00102 // Par contre, ex2: 233 peut relire du 234
    00103 //
    00104 //
    00105 // En résumé le versionement dans MED doit fonctionner de la manière suivante à partir de la 2.3.4 :
    00106 //
    00107 // -  x.y.z+1 indique qu'il s'agit d'une correction de BUG qui n'engendre pas d'évolution du modèle
    00108 // ni d'incompatibilité de lecture de fichier avec x.y.z. Aucune nouvelle routine ne doit apparaître
    00109 // dans la table de versionement. Les programmes compilés avec medx.y.z peuvent utiliser medx.y.z+1 sans
    00110 // recompilation. Il y a donc compatibilité ascendante et descendante entre x.y.z  et x.y.z+1
    00111 //
    00112 // - x.y+1.z indique qu'il s'agit d'une correction de BUG et/ou évolution qui engendre soit une évolution
    00113 // du modèle interne ou une incohérence avec l'utilisation de l'implémentation medx.y.z pour un fichier x.y+1.z.
    00114 //  L'API de la bibliothèque ne change pas. Le système de driver permet la compatibilité ascendante.
    00115 //  Il n'est pas necessaire de recompiler les programmes pour bénéficier de cette nouvelle version
    00116 //  de la bibliothèque. Il n'y a pas de compatibilité descendante entre x.y+1.z x.y.z
    00117 //
    00118 // - x+1.y.z indique que l'API MED a changé ou que la version d'HDF utilisée n'est pas compatible
    00119 //   avec celle de x.y.z. La documentation indique si les drivers permettent d'assurer la compatibilité
    00120 //   ascendante. Il n'y a pas de compatibilité descendante avec x.y.z. Les programmes doivent être recompilés
    00121 //   et certainement modifiés pour fonctionner avec x+1.Y.z
    00122 //
    00123
    00124
    00125
    00126 // REM : Ce container singleton est complété par les symboles fortran
    00127 //       à l'appel de edfouv(...) dans la partie fortran de la bibliothèque.
    00128 //       La méthode  f77ApiIsSet est alors appelée.
    00129 //
    00130 MED_VERSIONED_API::MED_VERSIONED_API() : map<keyType,
    00131                                              MedFuncType>(),
    00132                                          _f77ApiIsSet(false)
    00133 {
    00134   map<keyType,MedFuncType > &
    00135     table  = ( map<keyType,
    00136                MedFuncType > & ) *this ;
    00137    table[ "MEDchampEcr231" ]           = MEDchampEcr231 ;
    00138    table[ "MEDchampEcr232" ]           = MEDchampEcr232 ;
    00139    table[ "MEDchampEcr233" ]           = MEDchampEcr233 ;
    00140    table[ "MEDjointCr231" ]            = MEDjointCr231 ;
    00141    table[ "MEDjointCr232" ]            = MEDjointCr232 ;
    00142    table[ "MEDfamCr231" ]              = MEDfamCr231 ;
    00143    table[ "MEDfamCr232" ]              = MEDfamCr232 ;
    00144    table[ "_MEDdatasetNumEcrire231" ]  = _MEDdatasetNumEcrire231 ;
    00145    table[ "_MEDdatasetNumEcrire232" ]  = _MEDdatasetNumEcrire232 ;
    00146    table[ "_MEDdatasetNumLire231" ]    = _MEDdatasetNumLire231 ;
    00147    table[ "_MEDdatasetNumLire232" ]    = _MEDdatasetNumLire232 ;
    00148 }
    00149
    00150
    00151 MedFuncType MED_VERSIONED_API::operator[]( const keyType & c ) const
    00152 {
    00153   map<keyType,MedFuncType > &table = (map<keyType,
    00154                                    MedFuncType >&)*this ;
    00155
    00156   map<keyType,MedFuncType >::iterator it = table.find( c );
    00157   if ( it == table.end() ) return (MedFuncType) NULL;
    00158   return (*it).second;
    00159 }
    00160
    00161
    00162 extern "C" {
    00163   MedFuncType getVersionedApi(const char * const keycharpart,
    00164                               const char * const keynumpart) {
    00165     return MedVersionedApi[std::string(keycharpart)+std::string(keynumpart)];
    00166   }
    00167
    00168   void f77ApiIsSet(void * obj) {
    00169     static_cast<MED_VERSIONED_API*>(obj)->f77ApiIsSet();
    00170   }
    00171 }