Back to index

salome-med  6.5.0
MPI2Connector.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "MPI2Connector.hxx"
00021 
00022 #include <iostream>
00023 #include <cstring>
00024 
00025 MPI2Connector::MPI2Connector()
00026 {
00027   MPI_Comm_size( MPI_COMM_WORLD, &_nb_proc );
00028   MPI_Comm_rank( MPI_COMM_WORLD, &_num_proc );
00029 }
00030 
00031 MPI2Connector::~MPI2Connector()
00032 {
00033 }
00034 
00035 MPI_Comm MPI2Connector::remoteMPI2Connect(const std::string& service)
00036 {
00037   int i;
00038   char port_name[MPI_MAX_PORT_NAME];
00039   char port_name_clt[MPI_MAX_PORT_NAME];
00040   std::ostringstream msg;
00041   MPI_Comm icom;
00042 
00043   if( service.size() == 0 )
00044     {
00045       msg << "[" << _num_proc << "] You have to give a service name !";
00046       std::cerr << msg.str().c_str() << std::endl;
00047       throw std::exception();
00048     }
00049 
00050   _srv = false;
00051 
00052   MPI_Barrier(MPI_COMM_WORLD);
00053 
00054   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
00055   if( _num_proc == 0 )
00056     { 
00057       /* rank 0 try to be a server. If service is already published, try to be a cient */
00058       MPI_Open_port(MPI_INFO_NULL, port_name); 
00059       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
00060         {
00061           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
00062           MPI_Close_port( port_name );
00063         }
00064       else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )
00065         {
00066           _srv = true;
00067           _port_name = port_name;
00068           std::cerr << "[" << _num_proc << "] service " << service << " available at " << port_name << std::endl;
00069         }      
00070       else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
00071         {
00072           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
00073           MPI_Close_port( port_name );
00074         }
00075       else
00076         {
00077           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
00078           std::cerr << msg.str().c_str() << std::endl;
00079           throw std::exception();
00080         }
00081     }
00082   else
00083     {
00084       i=0;
00085       /* Waiting rank 0 publish name and try to be a client */
00086       while ( i != TIMEOUT  ) 
00087         {
00088           sleep(1);
00089           if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
00090             {
00091               std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
00092               break;
00093             }
00094           i++;
00095         }
00096       if(i==TIMEOUT)
00097         {
00098           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
00099           std::cerr << msg.str().c_str() << std::endl;
00100           throw std::exception();
00101         }
00102     }
00103   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
00104   
00105   /* If rank 0 is server, all processes call MPI_Comm_accept */
00106   /* If rank 0 is not server, all processes call MPI_Comm_connect */
00107   int srv = (int)_srv;
00108   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
00109   _srv = (bool)srv;
00110   if ( _srv )
00111     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
00112   else
00113     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
00114 
00115   /* create global communicator: servers have low index in global communicator*/
00116   MPI_Intercomm_merge(icom,!_srv,&_gcom);
00117 
00118   /* only rank 0 can be server for unpublish name */
00119   if(_num_proc != 0) _srv = false;
00120 
00121   return _gcom;
00122 
00123 }
00124 
00125 void MPI2Connector::remoteMPI2Disconnect(const std::string& service)
00126 {
00127   std::ostringstream msg;
00128 
00129   if( service.size() == 0 )
00130     {
00131       msg << "[" << _num_proc << "] You have to give a service name !";
00132       std::cerr << msg.str().c_str() << std::endl;
00133       throw std::exception();
00134     }
00135 
00136   MPI_Comm_disconnect( &_gcom ); 
00137   if ( _srv )
00138     {
00139 
00140       char port_name[MPI_MAX_PORT_NAME];
00141       strcpy(port_name,_port_name.c_str());
00142 
00143       MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
00144       std::cerr << "[" << _num_proc << "] " << service << ": close port " << _port_name << std::endl;
00145       MPI_Close_port( port_name ); 
00146     }
00147   
00148 }
00149