Salome HOME
Various fixes for test runs - introducing MEDCOUPLING_RESOURCE_DIR env variable
[tools/medcoupling.git] / src / ParaMEDMEMTest / MPI2Connector.cxx
1 // Copyright (C) 2007-2020  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
30 #ifdef OMPI_MAJOR_VERSION 
31 #   if OMPI_MAJOR_VERSION >= 4
32 #      define MPI_ERROR_HANDLER(var) MPI_Comm_set_errhandler(MPI_COMM_WORLD, var)
33 #   else
34 #      define MPI_ERROR_HANDLER(var) MPI_Errhandler_set(MPI_COMM_WORLD, var)
35 #   endif
36 #else  // MPICH and other versions:
37 #   define MPI_ERROR_HANDLER(var) MPI_Errhandler_set(MPI_COMM_WORLD, var)
38 #endif
39
40 MPI2Connector::MPI2Connector()
41 {
42   MPI_Comm_size( MPI_COMM_WORLD, &_nb_proc );
43   MPI_Comm_rank( MPI_COMM_WORLD, &_num_proc );
44 }
45
46 MPI2Connector::~MPI2Connector()
47 {
48 }
49
50 MPI_Comm MPI2Connector::remoteMPI2Connect(const std::string& service)
51 {
52   int i;
53   char port_name[MPI_MAX_PORT_NAME];
54   char port_name_clt[MPI_MAX_PORT_NAME];
55   std::ostringstream msg;
56   MPI_Comm icom;
57
58   if( service.size() == 0 )
59     {
60       msg << "[" << _num_proc << "] You have to give a service name !";
61       std::cerr << msg.str().c_str() << std::endl;
62       throw std::exception();
63     }
64
65   _srv = false;
66
67   MPI_Barrier(MPI_COMM_WORLD);
68   MPI_ERROR_HANDLER(MPI_ERRORS_RETURN);
69   if( _num_proc == 0 )
70     { 
71       /* rank 0 try to be a server. If service is already published, try to be a cient */
72       MPI_Open_port(MPI_INFO_NULL, port_name); 
73       if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
74         {
75           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
76           MPI_Close_port( port_name );
77         }
78       else if ( MPI_Publish_name((char*)service.c_str(), MPI_INFO_NULL, port_name) == MPI_SUCCESS )
79         {
80           _srv = true;
81           _port_name = port_name;
82           std::cerr << "[" << _num_proc << "] service " << service << " available at " << port_name << std::endl;
83         }      
84       else if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
85         {
86           std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
87           MPI_Close_port( port_name );
88         }
89       else
90         {
91           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
92           std::cerr << msg.str().c_str() << std::endl;
93           throw std::exception();
94         }
95     }
96   else
97     {
98       i=0;
99       /* Waiting rank 0 publish name and try to be a client */
100       while ( i != TIMEOUT  ) 
101         {
102           sleep(1);
103           if ( MPI_Lookup_name((char*)service.c_str(), MPI_INFO_NULL, port_name_clt) == MPI_SUCCESS )
104             {
105               std::cerr << "[" << _num_proc << "] I get the connection with " << service << " at " << port_name_clt << std::endl;
106               break;
107             }
108           i++;
109         }
110       if(i==TIMEOUT)
111         {
112           msg << "[" << _num_proc << "] Error on connection with " << service << " at " << port_name_clt;
113           std::cerr << msg.str().c_str() << std::endl;
114           throw std::exception();
115         }
116     }
117   MPI_ERROR_HANDLER(MPI_ERRORS_ARE_FATAL);
118   
119   /* If rank 0 is server, all processes call MPI_Comm_accept */
120   /* If rank 0 is not server, all processes call MPI_Comm_connect */
121   int srv = (int)_srv;
122   MPI_Bcast(&srv,1,MPI_INT,0,MPI_COMM_WORLD);
123   _srv = (bool)srv;
124   if ( _srv )
125     MPI_Comm_accept( port_name, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
126   else
127     MPI_Comm_connect(port_name_clt, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &icom );
128
129   /* create global communicator: servers have low index in global communicator*/
130   MPI_Intercomm_merge(icom,!_srv,&_gcom);
131
132   /* only rank 0 can be server for unpublish name */
133   if(_num_proc != 0) _srv = false;
134
135   return _gcom;
136
137 }
138
139 void MPI2Connector::remoteMPI2Disconnect(const std::string& service)
140 {
141   std::ostringstream msg;
142
143   if( service.size() == 0 )
144     {
145       msg << "[" << _num_proc << "] You have to give a service name !";
146       std::cerr << msg.str().c_str() << std::endl;
147       throw std::exception();
148     }
149
150   MPI_Comm_disconnect( &_gcom ); 
151   if ( _srv )
152     {
153
154       char port_name[MPI_MAX_PORT_NAME];
155       strcpy(port_name,_port_name.c_str());
156
157       MPI_Unpublish_name((char*)service.c_str(), MPI_INFO_NULL, port_name); 
158       std::cerr << "[" << _num_proc << "] " << service << ": close port " << _port_name << std::endl;
159       MPI_Close_port( port_name ); 
160     }
161   
162 }
163