]> SALOME platform Git repositories - modules/kernel.git/blob - src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx
Salome HOME
merge from branch BR_V5_DEV
[modules/kernel.git] / src / DSC / DSC_User / Datastream / Calcium / CalciumCxxInterface.hxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : CalciumCxxInterface.hxx
23 //  Author : Eric Fayolle (EDF)
24 //  Module : KERNEL
25 // Modified by : $LastChangedBy$
26 // Date        : $LastChangedDate: 2007-03-01 13:27:58 +0100 (jeu, 01 mar 2007) $
27 // Id          : $Id$
28 //
29 #ifndef _CALCIUM_CXXINTERFACE_HXX_
30 #define _CALCIUM_CXXINTERFACE_HXX_
31
32 #include <string>
33 #include <vector>
34 #include <iostream>
35 #include "Superv_Component_i.hxx"
36 #include "CalciumException.hxx"
37 #include "CalciumTypes.hxx"
38 #include "CalciumGenericUsesPort.hxx"
39 #include "Copy2UserSpace.hxx"
40 #include "Copy2CorbaSpace.hxx"
41 #include "CalciumPortTraits.hxx"
42
43 #include <stdio.h>
44
45 //#define _DEBUG_
46
47 template <typename T1, typename T2>
48 struct IsSameType {
49   static const bool value = false;
50 };
51 template <typename T1>
52 struct IsSameType<T1,T1> {
53   static const bool value = true;
54 };
55
56
57 #include <boost/type_traits/remove_all_extents.hpp>
58
59 namespace CalciumInterface {
60   
61   /********************* INTERFACE DE DECONNEXION *****************/
62
63   static inline void
64   ecp_cd (Superv_Component_i & component, std::string & instanceName)
65   { 
66     /* TODO : Trouver le nom de l'instance SALOME*/
67     if (instanceName.empty()) instanceName="UNDEFINED";
68
69   }
70
71   static void
72   ecp_fin (Superv_Component_i & component, bool provideLastGivenValue)
73   { 
74     std::vector<std::string> usesPortNames;
75     std::vector<std::string>::const_iterator it;
76     component.get_uses_port_names(usesPortNames);    
77     
78     //Récupérer le type de réel du port est un peu difficile
79     //car l'interface ne donne aucune indication
80
81     //     uses_port *myUsesPort;
82     calcium_uses_port* myCalciumUsesPort;
83       
84     for (it=usesPortNames.begin(); it != usesPortNames.end(); ++it) {
85       try {
86
87         myCalciumUsesPort= 
88           component.Superv_Component_i::get_port< calcium_uses_port >((*it).c_str());
89
90 //      component.Superv_Component_i::get_port(myUsesPort,(*it).c_str());
91 //      calcium_uses_port* myCalciumUsesPort=
92 //        dynamic_cast<calcium_uses_port*>(myUsesPort);
93
94 #ifdef _DEBUG_
95         std::cerr << "-------- CalciumInterface(ecp_fin) MARK 1 -|"<< *it <<"|----"<< 
96           //      typeid(myUsesPort).name() <<"-------------" <<
97           typeid(myCalciumUsesPort).name() <<"-------------" << std::endl;
98 #endif
99         
100 //      if ( !myCalciumUsesPort )
101 //        throw Superv_Component_i::BadCast(LOC(OSS()<<"Impossible de convertir le port "
102 //                                              << *it << " en port de type calcium_uses_port." ));
103
104         myCalciumUsesPort->disconnect(provideLastGivenValue);
105
106       } catch ( const Superv_Component_i::BadCast & ex) {
107 #ifdef _DEBUG_
108         std::cerr << ex.what() << std::endl;
109 #endif
110         throw (CalciumException(CalciumTypes::CPTPVR,ex));
111       } catch ( const DSC_Exception & ex) {
112 #ifdef _DEBUG_
113         std::cerr << ex.what() << std::endl;
114 #endif
115         // Exception venant de SupervComponent :
116         //   PortNotDefined(CPNMVR), PortNotConnected(CPLIEN)  
117         // ou du port uses : Dsc_Exception
118         // On continue à traiter la deconnexion des autres ports uses
119       } catch (...) {
120         throw (CalciumException(CalciumTypes::CPATAL,"Exception innatendue"));
121         // En fonction du mode de gestion des erreurs throw;
122       }
123     }
124   }
125
126
127   /********************* INTERFACES DE DESALLOCATION  *****************/
128
129   // Uniquement appelé par l'utilisateur s'il utilise la 0 copie
130   //   ( pointeur de données data==NULL à l'appel de ecp_lecture )
131   // Une désallocation aura lieu uniquement si un buffer intermédiaire
132   // était necessaire (type utilisateur et corba diffférent)
133   // La propriété du buffer est rendue à CORBA sinon  
134   template <typename T1, typename T2> static void
135   ecp_free ( T1 * dataPtr )
136   {
137     typedef typename ProvidesPortTraits<T2>::PortType     PortType;
138     typedef typename PortType::DataManipulator            DataManipulator;
139     typedef typename DataManipulator::Type                DataType; // Attention != T1
140     typedef typename DataManipulator::InnerType           InnerType;
141
142     DeleteTraits<IsSameType<T1,InnerType>::value, DataManipulator >::apply(dataPtr);
143   }
144
145   template <typename T1> static void
146   ecp_free ( T1 * dataPtr )
147   {
148     ecp_free<T1,T1> ( dataPtr );
149   }
150
151
152   /********************* INTERFACES DE LECTURE *****************/
153
154
155   // T1 est le type de données
156   // T2 est un <nom> de type Calcium permettant de sélectionner le port CORBA correspondant 
157   // T1 et T2 sont dissociés pour discriminer le cas des nombres complexes
158   //  -> Les données des nombres complexes sont de type float mais
159   //     le port à utiliser est le port cplx
160   template <typename T1, typename T2 > static void
161   ecp_lecture ( Superv_Component_i & component,
162                int    const  & dependencyType,
163                double        & ti,
164                double const  & tf,
165                long          & i,
166                const std::string  & nomVar, 
167                size_t          bufferLength,
168                size_t        & nRead, 
169                T1            * &data )
170   {
171
172     assert(&component);
173
174     typedef typename ProvidesPortTraits<T2>::PortType     PortType;
175     typedef typename PortType::DataManipulator            DataManipulator;
176     typedef typename DataManipulator::Type                CorbaDataType; // Attention != T1
177     typedef typename DataManipulator::InnerType           InnerType;
178     CalciumTypes::DependencyType _dependencyType=               
179       static_cast<CalciumTypes::DependencyType>(dependencyType);
180     
181     CorbaDataType     corbaData;
182
183 #ifdef _DEBUG_
184     std::cerr << "-------- CalciumInterface(ecp_lecture) MARK 1 ------------------" << std::endl;
185 #endif
186
187     if (nomVar.empty())
188       throw CalciumException(CalciumTypes::CPNMVR,
189                                 LOC("Le nom de la variable est <nul>"));
190     PortType * port;
191 #ifdef _DEBUG_
192     std::cout << "-------- CalciumInterface(ecp_lecture) MARK 2 ------------------" << std::endl;
193 #endif
194
195     try {
196       port  = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
197 #ifdef _DEBUG_
198       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 3 ------------------" << std::endl;
199 #endif
200     } catch ( const Superv_Component_i::PortNotDefined & ex) {
201 #ifdef _DEBUG_
202       std::cerr << ex.what() << std::endl;
203 #endif
204       throw (CalciumException(CalciumTypes::CPNMVR,ex));
205     } catch ( const Superv_Component_i::PortNotConnected & ex) {
206 #ifdef _DEBUG_
207       std::cerr << ex.what() << std::endl;;
208 #endif
209       throw (CalciumException(CalciumTypes::CPLIEN,ex)); 
210       // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
211     } catch ( const Superv_Component_i::BadCast & ex) {
212 #ifdef _DEBUG_
213       std::cerr << ex.what() << std::endl;
214 #endif
215       throw (CalciumException(CalciumTypes::CPTPVR,ex));
216     }
217   
218     // mode == mode du port 
219     CalciumTypes::DependencyType portDependencyType = port->getDependencyType();
220
221     if ( portDependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
222       throw CalciumException(CalciumTypes::CPIT,
223                              LOC(OSS()<<"Le mode de dépendance de la variable " 
224                                  << nomVar << " est indéfini."));
225
226     if ( ( portDependencyType != _dependencyType ) && 
227          ( _dependencyType != CalciumTypes::SEQUENCE_DEPENDENCY ) ) 
228       throw CalciumException(CalciumTypes::CPITVR,
229                              LOC(OSS()<<"Le mode de dépendance de la variable " 
230                                  << nomVar << ": " << portDependencyType 
231                                  << " ne correspond pas au mode demandé."));
232
233   
234     if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
235       corbaData = port->get(ti,tf, 0);
236 #ifdef _DEBUG_
237       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 5 ------------------" << std::endl;
238 #endif
239     } 
240     else if ( _dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
241       corbaData = port->get(0, i);
242 #ifdef _DEBUG_
243       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 6 ------------------" << std::endl;
244 #endif
245     } else {
246       // Lecture en séquence
247 #ifdef _DEBUG_
248       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 7 ------------------" << std::endl;
249 #endif
250       corbaData = port->next(ti,i);
251     }
252  
253 #ifdef _DEBUG_
254     std::cout << "-------- CalciumInterface(ecp_lecture) MARK 8 ------------------" << std::endl;
255 #endif
256     size_t corbaDataSize = DataManipulator::size(corbaData);
257 #ifdef _DEBUG_
258     std::cout << "-------- CalciumInterface(ecp_lecture) corbaDataSize : " << corbaDataSize << std::endl;
259 #endif
260    
261     // Vérifie si l'utilisateur demande du 0 copie
262     if ( data == NULL ) {
263       if ( bufferLength != 0 ) {
264         MESSAGE("bufferLength devrait valoir 0 pour l'utilisation du mode sans copie (data==NULL)");
265       }
266       nRead = corbaDataSize;
267       // Si les types T1 et InnerType sont différents, il faudra effectuer tout de même une recopie
268       if (!IsSameType<T1,InnerType>::value) data = new T1[nRead];
269 #ifdef _DEBUG_
270       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 9 ------------------" << std::endl;
271 #endif
272       // On essaye de faire du 0 copy si les types T1 et InnerType sont les mêmes.
273       // Copy2UserSpace : 
274       // La raison d'être du foncteur Copy2UserSpace est que le compilateur n'acceptera
275       // pas une expresion d'affectation sur des types incompatibles même 
276       // si cette expression se trouve dans une branche non exécuté d'un test
277       // sur la compatibilité des types.
278       // En utilisant le foncteur Copy2UserSpace, seul la spécialisation en adéquation
279       // avec la compatibilité des types sera compilée 
280       Copy2UserSpace< IsSameType<T1,InnerType>::value, DataManipulator >::apply(data,corbaData,nRead);
281 #ifdef _DEBUG_
282       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 10 ------------------" << std::endl;
283 #endif
284       // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
285       // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
286       // DataManipulator::delete_data(corbaData); 
287       // ni DataManipulator::getPointer(corbaData,true); qui détruit la sequence lorsque l'on
288       // prend la propriété du buffer
289       //  old : Dans les deux cas la structure CORBA n'est plus utile 
290       //  old : Si !IsSameType<T1,InnerType>::value l'objet CORBA est détruit avec son contenu
291       //  old : Dans l'autre cas seul la coquille CORBA est détruite 
292       //  L'utilisateur devra appeler ecp_free qui déterminera s'il est necessaire
293       //  de désallouer un buffer intermédiaire ( types différents) ou de rendre la propriété
294    } else {
295       nRead = std::min < size_t > (corbaDataSize,bufferLength);
296 #ifdef _DEBUG_
297       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 11 ------------------" << std::endl;
298 #endif
299       Copy2UserSpace<false, DataManipulator >::apply(data,corbaData,nRead);
300       DataManipulator::copy(corbaData,data,nRead);
301     
302 #ifdef _DEBUG_
303       std::cout << "-------- CalciumInterface(ecp_lecture) MARK 12 ------------------" << std::endl;
304 #endif
305       // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
306       // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
307       // DataManipulator::delete_data(corbaData);
308    }
309 #ifdef _DEBUG_
310     std::cout << "-------- CalciumInterface(ecp_lecture), Valeur de data : " << std::endl;
311     std::copy(data,data+nRead,std::ostream_iterator<T1>(std::cout," "));
312     std::cout << "Ptr :" << data << std::endl;
313
314     std::cout << "-------- CalciumInterface(ecp_lecture) MARK 13 ------------------" << std::endl;
315 #endif
316  
317   
318     return;
319   }
320
321   // T1 est le type de données
322   template <typename T1 > static void
323   ecp_lecture ( Superv_Component_i & component,
324                int    const      & dependencyType,
325                double            & ti,
326                double const      & tf,
327                long              & i,
328                const std::string & nomVar, 
329                size_t              bufferLength,
330                size_t            & nRead, 
331                T1                * &data )
332   {
333     ecp_lecture<T1,T1> (component,dependencyType,ti,tf,
334                         i,nomVar,bufferLength,nRead,data);
335   
336   }
337
338   /********************* INTERFACES D'ECRITURE *****************/
339
340   // T1 : DataType
341   // T2 : PortType
342   template <typename T1, typename T2> static void
343   ecp_ecriture ( Superv_Component_i & component,
344                  int    const      & dependencyType,
345                  double const      & t,
346                  long   const      & i,
347                  const std::string & nomVar, 
348                  size_t              bufferLength,
349                  T1                  const  & data ) 
350   {
351     
352     assert(&component);
353
354     //typedef typename StarTrait<TT>::NonStarType                    T;
355     typedef typename boost::remove_all_extents< T2 >::type           T2_without_extent;
356     typedef typename boost::remove_all_extents< T1 >::type           T1_without_extent;
357
358     typedef typename UsesPortTraits    <T2_without_extent>::PortType UsesPortType;
359     typedef typename ProvidesPortTraits<T2_without_extent>::PortType ProvidesPortType;// pour obtenir un manipulateur de données
360     typedef typename ProvidesPortType::DataManipulator               DataManipulator;
361     // Verifier que l'on peut définir UsesPortType::DataManipulator
362     //    typedef typename PortType::DataManipulator            DataManipulator;
363     typedef typename DataManipulator::Type                           CorbaDataType; // Attention != T1
364     typedef typename DataManipulator::InnerType                      InnerType;
365     
366     T1_without_extent const & _data = data;
367
368     CalciumTypes::DependencyType _dependencyType=               
369       static_cast<CalciumTypes::DependencyType>(dependencyType);
370
371 #ifdef _DEBUG_
372     std::cerr << "-------- CalciumInterface(ecriture) MARK 1 ------------------" << std::endl;
373 #endif
374     if ( nomVar.empty() ) throw CalciumException(CalciumTypes::CPNMVR,
375                                                     LOC("Le nom de la variable est <nul>"));
376     UsesPortType * port;
377 #ifdef _DEBUG_
378     std::cout << "-------- CalciumInterface(ecriture) MARK 2 ------------------" << std::endl;
379 #endif
380
381     try {
382       port  = component.Superv_Component_i::get_port< UsesPortType > (nomVar.c_str());
383 #ifdef _DEBUG_
384       std::cout << "-------- CalciumInterface(ecriture) MARK 3 ------------------" << std::endl;
385 #endif
386     } catch ( const Superv_Component_i::PortNotDefined & ex) {
387 #ifdef _DEBUG_
388       std::cerr << ex.what() << std::endl;
389 #endif
390       throw (CalciumException(CalciumTypes::CPNMVR,ex));
391     } catch ( const Superv_Component_i::PortNotConnected & ex) {
392 #ifdef _DEBUG_
393       std::cerr << ex.what() << std::endl;;
394 #endif
395       throw (CalciumException(CalciumTypes::CPLIEN,ex)); 
396       // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
397     } catch ( const Superv_Component_i::BadCast & ex) {
398 #ifdef _DEBUG_
399       std::cerr << ex.what() << std::endl;
400 #endif
401       throw (CalciumException(CalciumTypes::CPTPVR,ex));
402     }
403  
404     // mode == mode du port 
405     // On pourrait créer la méthode CORBA dans le mode de Couplage CALCIUM.
406     // et donc ajouter cette cette méthode uniquement dans l'IDL calcium !
407
408 //     CalciumTypes::DependencyType portDependencyType;
409 //     try {
410 //       portDependencyType = port->getDependencyType();
411 //       std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
412 //     } catch ( const DSC_Exception & ex ) {
413 //       std::cerr << ex.what() << std::endl;;
414 //       throw (CalciumException(CalciumTypes::CPIT,ex));
415 //     }
416
417     if ( _dependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
418       throw CalciumException(CalciumTypes::CPIT,
419                                 LOC(OSS()<<"Le mode de dépendance demandé pour la variable " 
420                                     << nomVar << " est indéfini."));
421
422     if ( _dependencyType == CalciumTypes::SEQUENCE_DEPENDENCY )
423       throw CalciumException(CalciumTypes::CPIT,
424                                 LOC(OSS()<<"Le mode de dépendance SEQUENCE_DEPENDENCY pour la variable " 
425                                     << nomVar << " est impossible en écriture."));
426
427     // Il faudrait que le port provides génère une exception si le mode donnée n'est pas
428     // le bon. La seule façon de le faire est d'envoyer -1 en temps si on n'est en itération
429     // et vice-versa pour informer les provides port du mode dans lequel on est. Sinon il faut
430     // modifier l'interface IDL pour y ajouter un mode de dépendance !
431     // ---->
432 //     if ( portDependencyType != _dependencyType ) 
433 //       throw CalciumException(CalciumTypes::CPITVR,
434 //                              LOC(OSS()<<"Le mode de dépendance de la variable " 
435 //                                  << nomVar << " ne correspond pas au mode demandé."));
436
437   
438     if ( bufferLength < 1 )
439       throw CalciumException(CalciumTypes::CPNTNULL,
440                                 LOC(OSS()<<"Le buffer a envoyer est de taille nulle "));
441
442
443 #ifdef _DEBUG_
444     std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
445 #endif
446     CorbaDataType corbaData;
447
448     
449     // Si les types Utilisateurs et CORBA sont différents
450     // il faut effectuer une recopie sinon on utilise directement le
451     // buffer data pour constituer la séquence
452     // TODO : 
453     // - Attention en mode asynchrone il faudra eventuellement
454     //   faire une copie des données même si elles sont de même type.
455     // - OLD : En cas de collocalisation (du port provide et du port uses)
456     //   OLD : il est necessaire d'effectuer une recopie du buffer car la
457     //   OLD : séquence est envoyée au port provide par une référence sur 
458     //   OLD : la séquence locale. Or la méthode put récupère le buffer directement
459     //   OLD : qui est alors le buffer utilisateur. Il pourrait alors arriver que :
460     //   OLD :   * Le recepteur efface le buffer emetteur
461     //   OLD :   * Le port lui-même efface le buffer de l'utilisateur !
462     //   OLD : Cette copie est effectuée dans GenericPortUses::put 
463     //   OLD : en fonction de la collocalisation ou non.
464     // - OLD :En cas de connection multiples d'un port uses distant vers plusieurs port provides
465     //   OLD : collocalisés les ports provides partagent la même copie de la donnée ! 
466     //   OLD : Il faut effectuer une copie dans le port provides.
467     //   OLD : Cette copie est effectuée dans GenericPortUses::put 
468     //   OLD : en fonction de la collocalisation ou non.
469     Copy2CorbaSpace<IsSameType<T1_without_extent,InnerType>::value, DataManipulator >::apply(corbaData,_data,bufferLength);
470  
471     //TODO : GERER LES EXCEPTIONS ICI : ex le port n'est pas connecté
472     if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
473       try
474       {
475         port->put(*corbaData,t, -1); 
476       }
477       catch ( const DSC_Exception & ex) 
478       {
479         throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
480       }
481       //Le -1 peut être traité par le cst DataIdContainer et transformé en 0 
482       //Etre obligé de mettre une étoile ds (*corbadata) va poser des pb pour les types <> seq
483 #ifdef _DEBUG_
484       std::cout << "-------- CalciumInterface(ecriture) MARK 5 ------------------" << std::endl;
485 #endif
486     } 
487     else if ( _dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
488       try
489       {
490         port->put(*corbaData,-1, i);
491       }
492       catch ( const DSC_Exception & ex) 
493       {
494         throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
495       }
496 #ifdef _DEBUG_
497       std::cout << "-------- CalciumInterface(ecriture) MARK 6 ------------------" << std::endl;
498 #endif
499     } 
500
501     
502 #ifdef _DEBUG_
503     std::cout << "-------- CalciumInterface(ecriture), Valeur de corbaData : " << std::endl;
504     for (int i = 0; i < corbaData->length(); ++i)
505       std::cout << "-------- CalciumInterface(ecriture), corbaData[" << i << "] = " << (*corbaData)[i] << std::endl;
506 #endif
507     
508     //    if ( !IsSameType<T1,InnerType>::value ) delete corbaData;
509     // Supprime l'objet CORBA avec eventuellement les données qu'il contient (cas de la recopie)
510     delete corbaData;
511
512 #ifdef _DEBUG_
513     std::cout << "-------- CalciumInterface(ecriture) MARK 7 ------------------" << std::endl;
514 #endif
515    
516     return;
517   };
518   
519   template <typename T1> static void
520   ecp_ecriture ( Superv_Component_i & component,
521                  int    const  & dependencyType,
522                  double const  & t,
523                  long   const  & i,
524                  const std::string  & nomVar, 
525                  size_t bufferLength,
526                  T1 const & data ) {
527     ecp_ecriture<T1,T1> (component,dependencyType,t,i,nomVar,bufferLength,data); 
528   };
529
530 };
531
532 #endif