Salome HOME
Get relevant changes from V7_dev branch (copyright update, adm files etc)
[tools/medcoupling.git] / src / ParaMEDMEMTest / MPI2Connector.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "MPI2Connector.hxx"
21
22 #include <iostream>
23 #include <cstring>
24
25 #ifndef WIN32
26 #include <unistd.h>
27 #endif
28
29 MPI2Connector::MPI2Connector()
30 {
31   MPI_Comm_size( MPI_COMM_WORLD, &_nb_proc );
32   MPI_Comm_rank( MPI_COMM_WORLD, &_num_proc );
33 }
34
35 MPI2Connector::~MPI2Connector()
36 {
37 }
38
39 MPI_Comm MPI2Connector::remoteMPI2Connect(const std::string& service)
40 {
41   int i;
42   char port_name[MPI_MAX_PORT_NAME];
43   char port_name_clt[MPI_MAX_PORT_NAME];
44   std::ostringstream msg;
45   MPI_Comm icom;
46
47   if( service.size() == 0 )
48     {
49       msg << "[" << _num_proc << "] You have to give a service name !";
50       std::cerr << msg.str().c_str() << std::endl;
51       throw std::exception();
52     }
53
54   _srv = false;
55
56   MPI_Barrier(MPI_COMM_WORLD);
57
58   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
59   if( _num_proc == 0 )
60     { 
61       /* rank 0 try to be a server. If service is already published, try to be a cient */
62       MPI_Open_port(MPI_INFO_NULL, port_name); 
63       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
64         {
65           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
66           MPI_Close_port( port_name );
67         }
68       else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )
69         {
70           _srv = true;
71           _port_name = port_name;
72           std::cerr << "[" << _num_proc << "] service " << service << " available at " << port_name << std::endl;
73         }      
74       else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
75         {
76           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
77           MPI_Close_port( port_name );
78         }
79       else
80         {
81           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
82           std::cerr << msg.str().c_str() << std::endl;
83           throw std::exception();
84         }
85     }
86   else
87     {
88       i=0;
89       /* Waiting rank 0 publish name and try to be a client */
90       while ( i != TIMEOUT  ) 
91         {
92           sleep(1);
93           if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
94             {
95               std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
96               break;
97             }
98           i++;
99         }
100       if(i==TIMEOUT)
101         {
102           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
103           std::cerr << msg.str().c_str() << std::endl;
104           throw std::exception();
105         }
106     }
107   MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_ARE_FATAL);
108   
109   /* If rank 0 is server, all processes call MPI_Comm_accept */
110   /* If rank 0 is not server, all processes call MPI_Comm_connect */
111   int srv = (int)_srv;
112   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
113   _srv = (bool)srv;
114   if ( _srv )
115     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
116   else
117     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
118
119   /* create global communicator: servers have low index in global communicator*/
120   MPI_Intercomm_merge(icom,!_srv,&_gcom);
121
122   /* only rank 0 can be server for unpublish name */
123   if(_num_proc != 0) _srv = false;
124
125   return _gcom;
126
127 }
128
129 void MPI2Connector::remoteMPI2Disconnect(const std::string& service)
130 {
131   std::ostringstream msg;
132
133   if( service.size() == 0 )
134     {
135       msg << "[" << _num_proc << "] You have to give a service name !";
136       std::cerr << msg.str().c_str() << std::endl;
137       throw std::exception();
138     }
139
140   MPI_Comm_disconnect( &_gcom ); 
141   if ( _srv )
142     {
143
144       char port_name[MPI_MAX_PORT_NAME];
145       strcpy(port_name,_port_name.c_str());
146
147       MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
148       std::cerr << "[" << _num_proc << "] " << service << ": close port " << _port_name << std::endl;
149       MPI_Close_port( port_name ); 
150     }
151   
152 }
153