00001 /* This file is part of MED. 00002 * 00003 * COPYRIGHT (C) 1999 - 2015 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 }