Pakman
pakman_mpi_worker.h
Go to the documentation of this file.
1 #ifndef PAKMAN_MPI_WORKER_H
2 #define PAKMAN_MPI_WORKER_H
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <assert.h>
8 #include <mpi.h>
9 
34 #define PAKMAN_EXIT_SUCCESS 0
35 
37 #define PAKMAN_EXIT_FAILURE 1
38 
39 #ifndef DOXYGEN_SHOULD_SKIP_THIS
40 
41 #define PAKMAN_ROOT 0
42 #define PAKMAN_MANAGER_MSG_TAG 2
43 #define PAKMAN_MANAGER_SIGNAL_TAG 3
44 #define PAKMAN_WORKER_MSG_TAG 5
45 #define PAKMAN_WORKER_ERROR_CODE_TAG 6
46 
47 #define PAKMAN_TERMINATE_WORKER_SIGNAL 0
48 
49 MPI_Comm pakman_get_parent_comm();
50 
51 char* pakman_receive_message(MPI_Comm comm);
52 int pakman_receive_signal(MPI_Comm comm);
53 
54 void pakman_send_message(MPI_Comm comm, const char *message);
55 void pakman_send_error_code(MPI_Comm comm, int error_code);
56 
57 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
58 
80  int argc, char *argv[],
81  int (*simulator)(int argc, char *argv[],
82  const char *input_string, char **p_output_string));
83 
84 #ifndef DOXYGEN_SHOULD_SKIP_THIS
85 
86 MPI_Comm pakman_get_parent_comm()
87 {
88  MPI_Comm parent_comm;
89  MPI_Comm_get_parent(&parent_comm);
90 
91  return parent_comm;
92 }
93 
94 char* pakman_receive_message(MPI_Comm comm)
95 {
96  /* Probe for message */
97  MPI_Status status;
98  MPI_Probe(PAKMAN_ROOT, PAKMAN_MANAGER_MSG_TAG, comm, &status);
99 
100  /* Allocate buffer to receive message */
101  int count;
102  MPI_Get_count(&status, MPI_CHAR, &count);
103  char *buffer = (char *) malloc(count * sizeof(char));
104 
105  /* Receive message */
106  MPI_Recv(buffer, count, MPI_CHAR, PAKMAN_ROOT, PAKMAN_MANAGER_MSG_TAG,
107  comm, MPI_STATUS_IGNORE);
108 
109  return buffer;
110 }
111 
112 int pakman_receive_signal(MPI_Comm comm)
113 {
114  /* Allocate buffer to receive message */
115  int signal;
116 
117  /* Receive message */
118  MPI_Recv(&signal, 1, MPI_INT, PAKMAN_ROOT, PAKMAN_MANAGER_SIGNAL_TAG,
119  comm, MPI_STATUS_IGNORE);
120 
121  return signal;
122 }
123 
124 void pakman_send_message(MPI_Comm comm, const char *message)
125 {
126  /* Count length of output_string, including null-terminating character */
127  size_t count = strlen(message) + 1;
128 
129  /* Send message */
130  MPI_Send(message, count, MPI_CHAR, PAKMAN_ROOT, PAKMAN_WORKER_MSG_TAG,
131  comm);
132 }
133 
134 void pakman_send_error_code(MPI_Comm comm, int error_code)
135 {
136  /* Send error_code */
137  MPI_Send(&error_code, 1, MPI_INT, PAKMAN_ROOT,
138  PAKMAN_WORKER_ERROR_CODE_TAG, comm);
139 }
140 
141 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
142 
144  int argc, char *argv[],
145  int (*simulator)(int argc, char *argv[],
146  const char *input_string, char **p_output_string))
147 {
148  /* Get parent communicator */
149  MPI_Comm parent_comm = pakman_get_parent_comm();
150 
151  /* Check if I was spawned */
152  if (parent_comm == MPI_COMM_NULL)
153  {
154  fputs("Pakman Worker error: MPI Worker was not spawned, exiting...\n",
155  stderr);
156  return PAKMAN_EXIT_FAILURE;
157  }
158 
159  /* Start loop */
160  int continue_loop = 1;
161  while (continue_loop)
162  {
163  /* Probe for message */
164  MPI_Status status;
165  MPI_Probe(PAKMAN_ROOT, MPI_ANY_TAG, parent_comm, &status);
166 
167  /* Check tag */
168  switch (status.MPI_TAG)
169  {
170  case PAKMAN_MANAGER_MSG_TAG:
171  {
172  /* Receive message */
173  char* input_string = pakman_receive_message(parent_comm);
174 
175  /* Run simulation */
176  char *output_string;
177  int error_code = (*simulator)(argc, argv,
178  input_string, &output_string);
179 
180  /* Send output */
181  pakman_send_message(parent_comm, output_string);
182 
183  /* Send error code */
184  pakman_send_error_code(parent_comm, error_code);
185 
186  /* Free input and output strings */
187  free(input_string);
188  free(output_string);
189 
190  break;
191  }
192  case PAKMAN_MANAGER_SIGNAL_TAG:
193  {
194  /* Receive signal */
195  int signal = pakman_receive_signal(parent_comm);
196 
197  /* Check signal */
198  switch (signal)
199  {
200  case PAKMAN_TERMINATE_WORKER_SIGNAL:
201  {
202  /* Set loop condition to false */
203  continue_loop = 0;
204  break;
205  }
206  default:
207  {
208  fputs("Pakman Worker error: signal not recognised, "
209  "exiting...\n", stderr);
210  return PAKMAN_EXIT_FAILURE;
211  }
212  }
213  break;
214  }
215  default:
216  {
217  fputs("Pakman Worker error: tag not recognised, exiting...\n",
218  stderr);
219  return PAKMAN_EXIT_FAILURE;
220  }
221  }
222  }
223 
224  /* Disconnect parent communicator */
225  MPI_Comm_disconnect(&parent_comm);
226 
227  /* Return successful error code */
228  return PAKMAN_EXIT_SUCCESS;
229 }
230 
231 #endif /* PAKMAN_MPI_WORKER_H */
int pakman_run_mpi_worker(int argc, char *argv[], int(*simulator)(int argc, char *argv[], const char *input_string, char **p_output_string))
#define PAKMAN_EXIT_FAILURE
#define PAKMAN_EXIT_SUCCESS