NEURON
bbsclimpi.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include "../nrnpython/nrnpython_config.h"
3 #include <nrnmpi.h>
4 #include "bbsconf.h"
5 #ifdef NRNMPI // to end of file
6 #include <errno.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <InterViews/resource.h>
11 #include "oc2iv.h"
12 #include "bbs.h"
13 #include "bbsrcli.h"
14 #include "bbssrv.h"
15 
16 extern void nrnmpi_int_broadcast(int*, int, int);
17 
18 #define debug 0
19 
20 #if defined(USE_PYTHON)
21 extern int (*p_nrnpython_start)(int);
22 #endif
23 
24 #if defined(HAVE_STL)
25 #if defined(HAVE_SSTREAM) // the standard ...
26 #include <map>
27 #else
28 #include <pair.h>
29 #include <map.h>
30 #endif
31 
32 struct ltint {
33  bool operator()(int i, int j) const {
34  return i < j;
35  }
36 };
37 
38 class KeepArgs: public std::map<int, bbsmpibuf*, ltint> {};
39 
40 #endif
41 
42 int BBSClient::sid_;
43 
45  sendbuf_ = nil;
46  recvbuf_ = nil;
47  request_ = nrnmpi_newbuf(100);
48  nrnmpi_ref(request_);
49 #if defined(HAVE_STL)
50  keepargs_ = new KeepArgs();
51 #endif
53 }
54 
56  nrnmpi_unref(sendbuf_);
57  nrnmpi_unref(recvbuf_);
58  nrnmpi_unref(request_);
59 #if defined(HAVE_STL)
60  delete keepargs_;
61 #endif
62 }
63 
64 void BBSClient::perror(const char* s) {
65  printf("BBSClient error: %s\n", s);
66 }
67 
68 void BBSClient::upkbegin() {
69  nrnmpi_upkbegin(recvbuf_);
70 }
71 
72 char* BBSClient::getkey() {
73  return nrnmpi_getkey(recvbuf_);
74 }
75 
76 int BBSClient::getid() {
77  return nrnmpi_getid(recvbuf_);
78 }
79 
80 int BBSClient::upkint() {
81  return nrnmpi_upkint(recvbuf_);
82 }
83 
84 double BBSClient::upkdouble() {
85  return nrnmpi_upkdouble(recvbuf_);
86 }
87 
88 void BBSClient::upkvec(int n, double* x) {
89  nrnmpi_upkvec(n, x, recvbuf_);
90 }
91 
92 char* BBSClient::upkstr() {
93  return nrnmpi_upkstr(recvbuf_); // do not forget to free(string)
94 }
95 
96 char* BBSClient::upkpickle(size_t* n) {
97  return nrnmpi_upkpickle(n, recvbuf_); // do not forget to free(string)
98 }
99 
100 void BBSClient::pkbegin() {
101  if (!sendbuf_) {
102  sendbuf_ = nrnmpi_newbuf(100);
103  nrnmpi_ref(sendbuf_);
104  }
105  nrnmpi_pkbegin(sendbuf_);
106 }
107 
108 void BBSClient::pkint(int i) {
109  nrnmpi_pkint(i, sendbuf_);
110 }
111 
112 void BBSClient::pkdouble(double x) {
113  nrnmpi_pkdouble(x, sendbuf_);
114 }
115 
116 void BBSClient::pkvec(int n, double* x) {
117  nrnmpi_pkvec(n, x, sendbuf_);
118 }
119 
120 void BBSClient::pkstr(const char* s) {
121  nrnmpi_pkstr(s, sendbuf_);
122 }
123 
124 void BBSClient::pkpickle(const char* s, size_t n) {
125  nrnmpi_pkpickle(s, n, sendbuf_);
126 }
127 
128 void BBSClient::post(const char* key) {
129 #if debug
130  printf("%d BBSClient::post |%s|\n", nrnmpi_myid_bbs, key);
131  fflush(stdout);
132 #endif
133  nrnmpi_enddata(sendbuf_);
134  nrnmpi_pkstr(key, sendbuf_);
135  nrnmpi_bbssend(sid_, POST, sendbuf_);
136  nrnmpi_unref(sendbuf_);
137  sendbuf_ = nil;
138 }
139 
140 void BBSClient::post_todo(int parentid) {
141 #if debug
142  printf("%d BBSClient::post_todo for %d\n", nrnmpi_myid_bbs, parentid);
143  fflush(stdout);
144 #endif
145  nrnmpi_enddata(sendbuf_);
146  nrnmpi_pkint(parentid, sendbuf_);
147  nrnmpi_bbssend(sid_, POST_TODO, sendbuf_);
148  nrnmpi_unref(sendbuf_);
149  sendbuf_ = nil;
150 }
151 
152 void BBSClient::post_result(int id) {
153 #if debug
154  printf("%d BBSClient::post_result %d\n", nrnmpi_myid_bbs, id);
155  fflush(stdout);
156 #endif
157  nrnmpi_enddata(sendbuf_);
158  nrnmpi_pkint(id, sendbuf_);
159  nrnmpi_bbssend(sid_, POST_RESULT, sendbuf_);
160  nrnmpi_unref(sendbuf_);
161  sendbuf_ = nil;
162 }
163 
164 int BBSClient::get(const char* key, int type) {
165 #if debug
166  printf("%d BBSClient::get |%s| type=%d\n", nrnmpi_myid_bbs, key, type);
167  fflush(stdout);
168 #endif
169  nrnmpi_pkbegin(request_);
170  nrnmpi_enddata(request_);
171  nrnmpi_pkstr(key, request_);
172  return get(type);
173 }
174 
175 int BBSClient::get(int key, int type) {
176 #if debug
177  printf("%d BBSClient::get %d type=%d\n", nrnmpi_myid_bbs, key, type);
178  fflush(stdout);
179 #endif
180  nrnmpi_pkbegin(request_);
181  nrnmpi_enddata(request_);
182  nrnmpi_pkint(key, request_);
183  return get(type) - 1; // sent id+1 so cannot be mistaken for QUIT
184 }
185 
186 int BBSClient::get(int type) { // blocking
187  fflush(stdout);
188  fflush(stderr);
189  double ts = time();
190  nrnmpi_unref(recvbuf_);
191  recvbuf_ = nrnmpi_newbuf(100);
192  nrnmpi_ref(recvbuf_);
193  int msgtag = nrnmpi_bbssendrecv(sid_, type, request_, recvbuf_);
194  errno = 0;
195  wait_time_ += time() - ts;
196 #if debug
197  printf("%d BBSClient::get return msgtag=%d\n", nrnmpi_myid_bbs, msgtag);
198  fflush(stdout);
199 #endif
200  if (msgtag == QUIT) {
201  done();
202  }
203  return msgtag;
204 }
205 
206 bool BBSClient::look_take(const char* key) {
207 #if debug
208  printf("%d BBSClient::look_take %s\n", nrnmpi_myid_bbs, key);
209 #endif
210  int type = get(key, LOOK_TAKE);
211  bool b = (type == LOOK_TAKE_YES);
212  if (b) {
213  upkbegin();
214  }
215  return b;
216 }
217 
218 bool BBSClient::look(const char* key) {
219 #if debug
220  printf("%d BBSClient::look %s\n", nrnmpi_myid_bbs, key);
221 #endif
222  int type = get(key, LOOK);
223  bool b = (type == LOOK_YES);
224  if (b) {
225  upkbegin();
226  }
227  return b;
228 }
229 
230 void BBSClient::take(const char* key) { // blocking
231  int bufid;
232  get(key, TAKE);
233  upkbegin();
234 }
235 
237  int type = get(0, LOOK_TAKE_TODO);
238  if (type) {
239  upkbegin();
240  }
241  return type;
242 }
243 
244 int BBSClient::take_todo() {
245  int type;
246  char* rs;
247  size_t n;
248  while ((type = get(0, TAKE_TODO)) == CONTEXT) {
249  upkbegin();
250  upkint(); // throw away userid
251  upkint(); // throw away info in reserved second slot for worker_id
252 #if debug
253  printf("%d execute context\n", nrnmpi_myid_bbs);
254  fflush(stdout);
255 #endif
256  rs = execute_helper(&n, -1);
257  if (rs) {
258  delete[] rs;
259  }
260  }
261  upkbegin();
262  return type;
263 }
264 
265 int BBSClient::look_take_result(int pid) {
266  int type = get(pid, LOOK_TAKE_RESULT);
267  if (type) {
268  upkbegin();
269  }
270  return type;
271 }
272 
273 void BBSClient::save_args(int userid) {
274 #if defined(HAVE_STL)
275  nrnmpi_ref(sendbuf_);
276  keepargs_->insert(std::pair<const int, bbsmpibuf*>(userid, sendbuf_));
277 
278 #endif
280 }
281 
282 void BBSClient::return_args(int userid) {
283 #if defined(HAVE_STL)
284  KeepArgs::iterator i = keepargs_->find(userid);
285  nrnmpi_unref(recvbuf_);
286  recvbuf_ = nil;
287  if (i != keepargs_->end()) {
288  recvbuf_ = (*i).second;
289  nrnmpi_ref(recvbuf_);
290  keepargs_->erase(i);
291  upkbegin();
293  }
294 #endif
295 }
296 
297 void BBSClient::done() {
298 #if defined(USE_PYTHON)
299  extern void (*p_nrnpython_finalize)();
300 #endif
301 #if debug
302  printf("%d BBSClient::done\n", nrnmpi_myid_bbs);
303  fflush(stdout);
304 #endif
306  if (nrnmpi_myid == 0) {
307  int info[2];
308  info[0] = -2;
309  info[1] = -1;
310  // printf("%d broadcast %d %d\n", nrnmpi_myid_world, info[0], info[1]);
311  nrnmpi_int_broadcast(info, 2, 0);
312  }
313  }
314 #if defined(USE_PYTHON)
315  if (p_nrnpython_start) {
316  (*p_nrnpython_start)(0);
317  }
318 #endif
319  BBSImpl::done();
321 #if defined(USE_PYTHON)
322  if (p_nrnpython_finalize) {
323  (*p_nrnpython_finalize)();
324  }
325 #endif
326  exit(0);
327 }
328 
329 void BBSClient::start() {
330  char* client = 0;
331  int tid;
332  int n;
333  if (started_) {
334  return;
335  }
336 #if debug
337  printf("%d BBSClient start\n", nrnmpi_myid_bbs);
338  fflush(stdout);
339 #endif
340  BBSImpl::start();
341  sid_ = 0;
342 #if 0
343  { // a worker
344  is_master_ = false;
345  nrnmpi_pkbegin(request_);
346  nrnmpi_enddata(request_);
347  nrn_assert(get(HELLO) == HELLO);
348  return;
349  }
350 #endif
351 }
352 
353 #endif // NRNMPI
#define nil
Definition: enter-scope.h:36
#define POST_TODO
Definition: bbssrv.h:14
#define LOOK_TAKE_RESULT
Definition: bbssrv.h:17
#define TAKE
Definition: bbssrv.h:8
#define TAKE_TODO
Definition: bbssrv.h:18
#define LOOK_TAKE
Definition: bbssrv.h:7
#define LOOK
Definition: bbssrv.h:6
#define POST_RESULT
Definition: bbssrv.h:15
#define POST
Definition: bbssrv.h:5
#define HELLO
Definition: bbssrv.h:13
#define QUIT
Definition: bbssrv.h:4
#define LOOK_YES
Definition: bbssrv.h:9
#define LOOK_TAKE_TODO
Definition: bbssrv.h:16
#define CONTEXT
Definition: bbssrv.h:19
#define LOOK_TAKE_YES
Definition: bbssrv.h:11
short type
Definition: cabvars.h:9
virtual void post_todo(int parentid)
virtual char * upkstr()
virtual void start()
virtual void perror(const char *)
virtual int look_take_result(int pid)
virtual void take(const char *)
virtual void upkvec(int, double *)
virtual void pkpickle(const char *, size_t)
virtual void pkvec(int, double *)
virtual void return_args(int)
virtual int upkint()
virtual void save_args(int)
virtual void post(const char *)
static int sid_
Definition: bbsrcli.h:52
virtual void pkbegin()
virtual bool look_take(const char *)
virtual int take_todo()
int get(const char *key, int type)
virtual char * upkpickle(size_t *)
virtual void pkint(int)
virtual double upkdouble()
virtual int look_take_todo()
virtual bool look(const char *)
virtual void done()
virtual void pkdouble(double)
virtual void post_result(int id)
KeepArgs * keepargs_
Definition: bbsrcli.h:53
virtual void pkstr(const char *)
virtual ~BBSClient()
int working_id_
Definition: bbsimpl.h:54
static bool is_master_
Definition: bbsimpl.h:60
virtual void return_args(int userid)
Definition: ocbbs.cpp:1385
char * execute_helper(size_t *, int id, bool exec=true)
Definition: ocbbs.cpp:1215
static bool started_
Definition: bbsimpl.h:61
double wait_time_
Definition: bbsimpl.h:55
virtual double time()
Definition: bbs.cpp:133
virtual void start()
Definition: bbs.cpp:506
virtual void done()
Definition: bbs.cpp:487
void(* p_nrnpython_finalize)()
void
#define i
Definition: md1redef.h:12
static double map(void *v)
Definition: mlinedit.cpp:47
#define printf
Definition: mwprefix.h:26
static List * info
#define nrn_assert(ex)
Definition: nrnassrt.h:53
int const size_t const size_t n
Definition: nrngsl.h:11
size_t j
void nrnmpi_terminate()
Definition: nrnmpi.cpp:180
int nrnmpi_myid
int nrnmpi_numprocs_world
int nrnmpi_numprocs
int nrnmpi_numprocs_bbs
int nrnmpi_myid_bbs
int(* p_nrnpython_start)(int)
static double userid(void *v)
Definition: ocbbs.cpp:227
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
#define key
Definition: spt2queue.cpp:20