]> SALOME platform Git repositories - modules/kernel.git/commitdiff
Salome HOME
PR: missing in merge V4_1_1rc2
authorprascle <prascle>
Thu, 21 Feb 2008 16:12:36 +0000 (16:12 +0000)
committerprascle <prascle>
Thu, 21 Feb 2008 16:12:36 +0000 (16:12 +0000)
src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx [new file with mode: 0644]

diff --git a/src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx b/src/DSC/DSC_User/Datastream/Calcium/CalciumCxxInterface.hxx
new file mode 100644 (file)
index 0000000..39565be
--- /dev/null
@@ -0,0 +1,500 @@
+//  Copyright (C) 2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
+// 
+//  This library is free software; you can redistribute it and/or 
+//  modify it under the terms of the GNU Lesser General Public 
+//  License as published by the Free Software Foundation; either 
+//  version 2.1 of the License. 
+// 
+//  This library is distributed in the hope that it will be useful, 
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+//  Lesser General Public License for more details. 
+// 
+//  You should have received a copy of the GNU Lesser General Public 
+//  License along with this library; if not, write to the Free Software 
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
+// 
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//
+//
+//  File   : CalciumCxxInterface.hxx
+//  Author : Eric Fayolle (EDF)
+//  Module : KERNEL
+// Modified by : $LastChangedBy$
+// Date        : $LastChangedDate: 2007-03-01 13:27:58 +0100 (jeu, 01 mar 2007) $
+// Id          : $Id$
+
+#ifndef _CALCIUM_CXXINTERFACE_HXX_
+#define _CALCIUM_CXXINTERFACE_HXX_
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include "Superv_Component_i.hxx"
+#include "CalciumException.hxx"
+#include "CalciumTypes.hxx"
+#include "CalciumGenericUsesPort.hxx"
+#include "Copy2UserSpace.hxx"
+#include "Copy2CorbaSpace.hxx"
+#include "CalciumPortTraits.hxx"
+
+#include <stdio.h>
+
+//#define _DEBUG_
+
+template <typename T1, typename T2>
+struct IsSameType {
+  static const bool value = false;
+};
+template <typename T1>
+struct IsSameType<T1,T1> {
+  static const bool value = true;
+};
+
+
+
+namespace CalciumInterface {
+  
+  /********************* INTERFACE DE DECONNEXION *****************/
+
+  static void
+  ecp_fin (Superv_Component_i & component, bool provideLastGivenValue)
+  { 
+    std::vector<std::string> usesPortNames;
+    std::vector<std::string>::const_iterator it;
+    component.get_uses_port_names(usesPortNames);    
+    
+    //récupérer le type de réel du port est un peu difficile
+    //car l'interface nous donne aucune indication
+
+    //     uses_port *myUsesPort;
+    calcium_uses_port* myCalciumUsesPort;
+      
+    for (it=usesPortNames.begin(); it != usesPortNames.end(); ++it) {
+      try {
+
+       myCalciumUsesPort= 
+         component.Superv_Component_i::get_port< calcium_uses_port >((*it).c_str());
+
+//     component.Superv_Component_i::get_port(myUsesPort,(*it).c_str());
+//     calcium_uses_port* myCalciumUsesPort=
+//       dynamic_cast<calcium_uses_port*>(myUsesPort);
+
+#ifdef _DEBUG_
+       std::cerr << "-------- CalciumInterface(ecp_fin) MARK 1 -|"<< *it <<"|----"<< 
+         //      typeid(myUsesPort).name() <<"-------------" <<
+         typeid(myCalciumUsesPort).name() <<"-------------" << std::endl;
+#endif
+       
+//     if ( !myCalciumUsesPort )
+//       throw Superv_Component_i::BadCast(LOC(OSS()<<"Impossible de convertir le port "
+//                                             << *it << " en port de type calcium_uses_port." ));
+
+       myCalciumUsesPort->disconnect(provideLastGivenValue);
+
+      } catch ( const Superv_Component_i::BadCast & ex) {
+#ifdef _DEBUG_
+       std::cerr << ex.what() << std::endl;
+#endif
+       throw (CalciumException(CalciumTypes::CPTPVR,ex));
+      } catch ( const DSC_Exception & ex) {
+#ifdef _DEBUG_
+       std::cerr << ex.what() << std::endl;
+#endif
+       // Exception venant de SupervComponent :
+       //   PortNotDefined(CPNMVR), PortNotConnected(CPLIEN)  
+       // ou du port uses : Dsc_Exception
+       // On continue à traiter la deconnexion des autres ports uses
+      } catch (...) {
+       throw (CalciumException(CalciumTypes::CPATAL,"Exception innatendue"));
+       // En fonction du mode de gestion des erreurs throw;
+      }
+    }
+  }
+
+
+  /********************* INTERFACES DE DESALLOCATION  *****************/
+
+  // Uniquement appelé par l'utilisateur s'il utilise la 0 copie
+  //   ( pointeur de données data==NULL à l'appel de ecp_lecture )
+  // Une désallocation aura lieu uniquement si un buffer intermédiaire
+  // était necessaire (type utilisateur et corba diffférent)
+  // La propriété du buffer est rendue à CORBA sinon  
+  template <typename T1, typename T2> static void
+  ecp_free ( T1 * dataPtr )
+  {
+    typedef typename ProvidesPortTraits<T2>::PortType     PortType;
+    typedef typename PortType::DataManipulator            DataManipulator;
+    typedef typename DataManipulator::Type                DataType; // Attention != T
+    typedef typename DataManipulator::InnerType           InnerType;
+
+    DeleteTraits<IsSameType<T1,InnerType>::value >::apply(dataPtr);
+  }
+
+  template <typename T1> static void
+  ecp_free ( T1 * dataPtr )
+  {
+    ecp_free<T1,T1> ( dataPtr );
+  }
+
+
+  /********************* INTERFACES DE LECTURE *****************/
+
+  // T1 est le type de données
+  template <typename T1 > static void
+  ecp_lecture ( Superv_Component_i & component,
+              CalciumTypes::DependencyType dependencyType,
+              double        & ti,
+              double const  & tf,
+              long          & i,
+              const string  & nomVar, 
+              size_t          bufferLength,
+              size_t        & nRead, 
+              T1            * &data )
+  {
+    ecp_lecture<T1,T1> (component,dependencyType,ti,tf,
+                       i,nomVar,bufferLength,nRead,data);
+  
+  }
+
+  // T1 est le type de données
+  // T2 est un <nom> de type Calcium permettant de sélectionner le port correspondant 
+  // T1 et T2 sont dissociés pour discriminer le cas des nombres complexes
+  //  -> Les données des nombres complexes sont de type float mais
+  //     le port à utiliser est le port cplx
+  template <typename T1, typename T2 > static void
+  ecp_lecture ( Superv_Component_i & component,
+              CalciumTypes::DependencyType dependencyType,
+              double        & ti,
+              double const  & tf,
+              long          & i,
+              const string  & nomVar, 
+              size_t          bufferLength,
+              size_t        & nRead, 
+              T1            * &data )
+  {
+
+    assert(&component);
+
+    typedef typename ProvidesPortTraits<T2>::PortType     PortType;
+    typedef typename PortType::DataManipulator            DataManipulator;
+    typedef typename DataManipulator::Type                CorbaDataType; // Attention != T1
+    typedef typename DataManipulator::InnerType           InnerType;
+
+    CorbaDataType     corbaData;
+
+#ifdef _DEBUG_
+    std::cerr << "-------- CalciumInterface(ecp_lecture) MARK 1 ------------------" << std::endl;
+#endif
+
+    if (nomVar.empty())
+      throw CalciumException(CalciumTypes::CPNMVR,
+                               LOC("Le nom de la variable est <nul>"));
+    PortType * port;
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecp_lecture) MARK 2 ------------------" << std::endl;
+#endif
+
+    try {
+      port  = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 3 ------------------" << std::endl;
+#endif
+    } catch ( const Superv_Component_i::PortNotDefined & ex) {
+#ifdef _DEBUG_
+      std::cerr << ex.what() << std::endl;
+#endif
+      throw (CalciumException(CalciumTypes::CPNMVR,ex));
+    } catch ( const Superv_Component_i::PortNotConnected & ex) {
+#ifdef _DEBUG_
+      std::cerr << ex.what() << std::endl;;
+#endif
+      throw (CalciumException(CalciumTypes::CPLIEN,ex)); 
+      // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
+    } catch ( const Superv_Component_i::BadCast & ex) {
+#ifdef _DEBUG_
+      std::cerr << ex.what() << std::endl;
+#endif
+      throw (CalciumException(CalciumTypes::CPTPVR,ex));
+    }
+  
+    // mode == mode du port 
+    CalciumTypes::DependencyType portDependencyType = port->getDependencyType();
+
+    if ( portDependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
+      throw CalciumException(CalciumTypes::CPIT,
+                            LOC(OSS()<<"Le mode de dépendance de la variable " 
+                                << nomVar << " est indéfini."));
+
+    if ( ( portDependencyType != dependencyType ) && 
+        ( dependencyType != CalciumTypes::SEQUENCE_DEPENDENCY ) ) 
+      throw CalciumException(CalciumTypes::CPITVR,
+                            LOC(OSS()<<"Le mode de dépendance de la variable " 
+                                << nomVar << ": " << portDependencyType 
+                                << " ne correspond pas au mode demandé."));
+
+  
+    if ( dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
+      corbaData = port->get(ti,tf, 0);
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 5 ------------------" << std::endl;
+#endif
+    } 
+    else if ( dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
+      corbaData = port->get(0, i);
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 6 ------------------" << std::endl;
+#endif
+    } else {
+      // Lecture en séquence
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 7 ------------------" << std::endl;
+#endif
+      corbaData = port->next(ti,i);
+    }
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecp_lecture) MARK 8 ------------------" << std::endl;
+#endif
+    size_t corbaDataSize = DataManipulator::size(corbaData);
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecp_lecture) corbaDataSize : " << corbaDataSize << std::endl;
+#endif
+   
+    // Vérifie si l'utilisateur demande du 0 copie
+    if ( data == NULL ) {
+      if ( bufferLength != 0 ) {
+       MESSAGE("bufferLength devrait valoir 0 pour l'utilisation du mode sans copie (data==NULL)");
+      }
+      nRead = corbaDataSize;
+      // Si les types T et InnerType sont différents, il faudra effectuer tout de même une recopie
+      if (!IsSameType<T1,InnerType>::value) data = new T1[nRead];
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 9 ------------------" << std::endl;
+#endif
+      // On essaye de faire du 0 copy si les types T1 et InnerType sont les mêmes
+      Copy2UserSpace< IsSameType<T1,InnerType>::value >::apply(data,corbaData,nRead);
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 10 ------------------" << std::endl;
+#endif
+      // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
+      // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
+      // DataManipulator::delete_data(corbaData);
+      //  old : Dans les deux cas la structure CORBA n'est plus utile 
+      //  old : Si !IsSameType<T1,InnerType>::value l'objet CORBA est détruit avec son contenu
+      //  old : Dans l'autre cas seul la coquille CORBA est détruite 
+      //  L'utilisateur devra appeler ecp_free (version modifiée) qui déterminera s'il est necessaire
+      //   de désallouer un buffer intermédiaire ( types différents) ou de rendre la propriété
+   } else {
+      nRead = std::min < size_t > (corbaDataSize,bufferLength);
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 11 ------------------" << std::endl;
+#endif
+      Copy2UserSpace<false>::apply(data,corbaData,nRead);
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecp_lecture) MARK 12 ------------------" << std::endl;
+#endif
+      // Attention : Seul CalciumCouplingPolicy via eraseDataId doit décider de supprimer ou non
+      // la donnée corba associée à un DataId ! Ne pas effectuer la desallocation suivante :
+      // DataManipulator::delete_data(corbaData);
+   }
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecp_lecture), Valeur de data : " << std::endl;
+    std::copy(data,data+nRead,std::ostream_iterator<T1>(std::cout," "));
+    std::cout << "Ptr :" << data << std::endl;
+
+    std::cout << "-------- CalciumInterface(ecp_lecture) MARK 13 ------------------" << std::endl;
+#endif
+  
+    return;
+  }
+
+
+  /********************* INTERFACES D'ECRITURE *****************/
+
+  template <typename T1> static void
+  ecp_ecriture ( Superv_Component_i & component,
+                CalciumTypes::DependencyType dependencyType,
+                double const  & t,
+                long   const  & i,
+                const string  & nomVar, 
+                size_t bufferLength,
+                T1  & data ) {
+    ecp_ecriture<T1,T1> (component,dependencyType,t,i,nomVar,bufferLength,data); 
+  }
+
+  template <typename T1, typename T2> static void
+  ecp_ecriture ( Superv_Component_i & component,
+                CalciumTypes::DependencyType dependencyType,
+                double const  & t,
+                long   const  & i,
+                const string  & nomVar, 
+                size_t bufferLength,
+                T1  & data ) 
+  {
+    
+    assert(&component);
+
+    //typedef typename StarTrait<TT>::NonStarType           T;
+    typedef typename UsesPortTraits<T2>::PortType          PortType;
+    typedef typename ProvidesPortTraits<T2>::PortType      ProvidesPortType;
+    typedef typename ProvidesPortType::DataManipulator     DataManipulator;
+    // Verifier que l'on peut définir UsesPortType::DataManipulator
+    //    typedef typename PortType::DataManipulator            DataManipulator;
+    typedef typename DataManipulator::Type                CorbaDataType; // Attention != T1
+    typedef typename DataManipulator::InnerType           InnerType;
+
+#ifdef _DEBUG_
+    std::cerr << "-------- CalciumInterface(ecriture) MARK 1 ------------------" << std::endl;
+#endif
+    if ( nomVar.empty() ) throw CalciumException(CalciumTypes::CPNMVR,
+                                                   LOC("Le nom de la variable est <nul>"));
+    PortType * port;
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecriture) MARK 2 ------------------" << std::endl;
+#endif
+
+    try {
+      port  = component.Superv_Component_i::get_port< PortType > (nomVar.c_str());
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecriture) MARK 3 ------------------" << std::endl;
+#endif
+    } catch ( const Superv_Component_i::PortNotDefined & ex) {
+#ifdef _DEBUG_
+      std::cerr << ex.what() << std::endl;
+#endif
+      throw (CalciumException(CalciumTypes::CPNMVR,ex));
+    } catch ( const Superv_Component_i::PortNotConnected & ex) {
+#ifdef _DEBUG_
+      std::cerr << ex.what() << std::endl;;
+#endif
+      throw (CalciumException(CalciumTypes::CPLIEN,ex)); 
+      // VERIFIER LES CAS DES CODES : CPINARRET, CPSTOPSEQ, CPCTVR, CPLIEN
+    } catch ( const Superv_Component_i::BadCast & ex) {
+#ifdef _DEBUG_
+      std::cerr << ex.what() << std::endl;
+#endif
+      throw (CalciumException(CalciumTypes::CPTPVR,ex));
+    }
+    // mode == mode du port 
+    // On pourrait créer la méthode CORBA dans le mode de Couplage CALCIUM.
+    // et donc ajouter cette cette méthode uniquement dans l'IDL calcium !
+
+//     CalciumTypes::DependencyType portDependencyType;
+//     try {
+//       portDependencyType = port->getDependencyType();
+//       std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
+//     } catch ( const DSC_Exception & ex ) {
+//       std::cerr << ex.what() << std::endl;;
+//       throw (CalciumException(CalciumTypes::CPIT,ex));
+//     }
+
+    if ( dependencyType == CalciumTypes::UNDEFINED_DEPENDENCY )
+      throw CalciumException(CalciumTypes::CPIT,
+                               LOC(OSS()<<"Le mode de dépendance demandé pour la variable " 
+                                   << nomVar << " est indéfini."));
+
+    if ( dependencyType == CalciumTypes::SEQUENCE_DEPENDENCY )
+      throw CalciumException(CalciumTypes::CPIT,
+                               LOC(OSS()<<"Le mode de dépendance SEQUENCE_DEPENDENCY pour la variable " 
+                                   << nomVar << " est impossible en écriture."));
+
+    // Il faudrait que le port provides génère une exception si le mode donnée n'est pas
+    // le bon. La seule façon de le faire est d'envoyer -1 en temps si on n'est en itération
+    // et vice-versa pour informer les provides port du mode dans lequel on est. Sinon il faut
+    // modifier l'interface IDL pour y ajouter un mode de dépendance !
+    // ---->
+//     if ( portDependencyType != dependencyType ) 
+//       throw CalciumException(CalciumTypes::CPITVR,
+//                             LOC(OSS()<<"Le mode de dépendance de la variable " 
+//                                 << nomVar << " ne correspond pas au mode demandé."));
+
+  
+    if ( bufferLength < 1 )
+      throw CalciumException(CalciumTypes::CPNTNULL,
+                               LOC(OSS()<<"Le buffer a envoyer est de taille nulle "));
+
+
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecriture) MARK 4 ------------------" << std::endl;
+#endif
+    CorbaDataType corbaData;
+
+    
+    // Si les types Utilisateurs et CORBA sont différents
+    // il faut effectuer une recopie sinon on utilise directement le
+    // buffer data pour constituer la séquence
+    // TODO : 
+    // - Attention en mode asynchrone il faudra eventuellement
+    //   faire une copie des données même si elles sont de même type.
+    // - OLD : En cas de collocalisation (du port provide et du port uses)
+    //   OLD : il est necessaire d'effectuer une recopie du buffer car la
+    //   OLD : séquence est envoyée au port provide par une référence sur 
+    //   OLD : la séquence locale. Or la méthode put récupère le buffer directement
+    //   OLD : qui est alors le buffer utilisateur. Il pourrait alors arriver que :
+    //   OLD :   * Le recepteur efface le buffer emetteur
+    //   OLD :   * Le port lui-même efface le buffer de l'ulisateur !
+    //   OLD : Cette copie est effectuée dans GenericPortUses::put 
+    //   OLD : en fonction de la collocalisation ou non.
+    // - OLD :En cas de connection multiples d'un port uses distant vers plusieurs port provides
+    //   OLD : collocalisés les ports provides partagent la même copie de la donnée ! 
+    //   OLD : Il faut effectuer une copie dans le port provides.
+    //   OLD : Cette copie est effectuée dans GenericPortUses::put 
+    //   OLD : en fonction de la collocalisation ou non.
+    Copy2CorbaSpace<IsSameType<T1,InnerType>::value >::apply(corbaData,data,bufferLength);
+    //TODO : GERER LES EXCEPTIONS ICI : ex le port n'est pas connecté
+    if ( dependencyType == CalciumTypes::TIME_DEPENDENCY ) {
+      try
+      {
+        port->put(*corbaData,t, -1); 
+      }
+      catch ( const DSC_Exception & ex) 
+      {
+        throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
+      }
+      //Le -1 peut être traité par le cst DataIdContainer et transformé en 0 
+      //Etre obligé de mettre une étoile ds (*corbadata) va poser des pb pour les types <> seq
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecriture) MARK 5 ------------------" << std::endl;
+#endif
+    } 
+    else if ( dependencyType == CalciumTypes::ITERATION_DEPENDENCY ) {
+      try
+      {
+        port->put(*corbaData,-1, i);
+      }
+      catch ( const DSC_Exception & ex) 
+      {
+        throw (CalciumException(CalciumTypes::CPATAL,ex.what()));
+      }
+#ifdef _DEBUG_
+      std::cout << "-------- CalciumInterface(ecriture) MARK 6 ------------------" << std::endl;
+#endif
+    } 
+
+    
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecriture), Valeur de corbaData : " << std::endl;
+    for (int i = 0; i < corbaData->length(); ++i)
+      cout << "-------- CalciumInterface(ecriture), corbaData[" << i << "] = " << (*corbaData)[i] << endl;
+#endif
+    
+    //    if ( !IsSameType<T1,InnerType>::value ) delete corbaData;
+    // Supprime l'objet CORBA avec eventuellement les données qu'il contient (cas de la recopie)
+    delete corbaData;
+
+#ifdef _DEBUG_
+    std::cout << "-------- CalciumInterface(ecriture) MARK 7 ------------------" << std::endl;
+#endif
+   
+    return;
+  }
+
+};
+
+#endif