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) { delete [] rs; }
258  }
259  upkbegin();
260  return type;
261 }
262 
263 int BBSClient::look_take_result(int pid) {
264  int type = get(pid, LOOK_TAKE_RESULT);
265  if (type) {
266  upkbegin();
267  }
268  return type;
269 }
270 
271 void BBSClient::save_args(int userid) {
272 #if defined(HAVE_STL)
273  nrnmpi_ref(sendbuf_);
274  keepargs_->insert(
275  std::pair<const int, bbsmpibuf* >(userid, sendbuf_)
276  );
277 
278 #endif
279  post_todo(working_id_);
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();
292  BBSImpl::return_args(userid);
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]; info[0] = -2; info[1] = -1;
308 //printf("%d broadcast %d %d\n", nrnmpi_myid_world, info[0], info[1]);
309  nrnmpi_int_broadcast(info, 2, 0);
310  }
311  }
312 #if defined(USE_PYTHON)
313  if (p_nrnpython_start) { (*p_nrnpython_start)(0);}
314 #endif
315  BBSImpl::done();
317 #if defined(USE_PYTHON)
318  if (p_nrnpython_finalize) { (*p_nrnpython_finalize)(); }
319 #endif
320  exit(0);
321 }
322 
323 void BBSClient::start() {
324  char* client = 0;
325  int tid;
326  int n;
327  if (started_) { return; }
328 #if debug
329 printf("%d BBSClient start\n", nrnmpi_myid_bbs);
330 fflush(stdout);
331 #endif
332  BBSImpl::start();
333  sid_ = 0;
334 #if 0
335  { // a worker
336  is_master_ = false;
337  nrnmpi_pkbegin(request_);
338  nrnmpi_enddata(request_);
339  nrn_assert(get(HELLO) == HELLO);
340  return;
341  }
342 #endif
343 }
344 
345 #endif //NRNMPI
virtual void pkpickle(const char *, size_t)
static double userid(void *v)
Definition: ocbbs.cpp:225
#define nrn_assert(ex)
Definition: nrnassrt.h:35
short type
Definition: cabvars.h:10
#define TAKE
Definition: bbssrv.h:8
virtual int look_take_result(int pid)
virtual bool look(const char *)
virtual void done()
Definition: bbs.cpp:484
virtual char * upkpickle(size_t *)
int nrnmpi_numprocs_world
virtual double upkdouble()
#define CONTEXT
Definition: bbssrv.h:19
int nrnmpi_myid_bbs
void
virtual void start()
Definition: bbs.cpp:500
virtual void post_result(int id)
void nrnmpi_terminate()
Definition: nrnmpi.cpp:180
int nrnmpi_numprocs_bbs
#define LOOK_TAKE_RESULT
Definition: bbssrv.h:17
int get(const char *key, int type)
virtual bool look_take(const char *)
static List * info
virtual ~BBSClient()
static double map(void *v)
Definition: mlinedit.cpp:46
virtual int upkint()
virtual int look_take_todo()
static double done(void *v)
Definition: ocbbs.cpp:280
virtual void take(const char *)
virtual void pkbegin()
void(* p_nrnpython_finalize)()
int const size_t const size_t n
Definition: nrngsl.h:12
int nrnmpi_numprocs
_CONST char * s
Definition: system.cpp:74
virtual void return_args(int)
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
virtual void pkdouble(double)
virtual void return_args(int userid)
Definition: ocbbs.cpp:1308
#define printf
Definition: mwprefix.h:26
int(* p_nrnpython_start)(int)
int
Definition: nrnmusic.cpp:71
virtual char * upkstr()
virtual void upkvec(int, double *)
static int sid_
Definition: bbsrcli.h:51
#define TAKE_TODO
Definition: bbssrv.h:18
#define key
Definition: spt2queue.cpp:20
virtual void done()
errno
Definition: system.cpp:98
size_t j
#define POST_TODO
Definition: bbssrv.h:14
virtual void save_args(int)
#define nil
Definition: enter-scope.h:36
virtual void post(const char *)
#define LOOK_TAKE
Definition: bbssrv.h:7
virtual void post_todo(int parentid)
#define HELLO
Definition: bbssrv.h:13
virtual void start()
#define POST
Definition: bbssrv.h:5
virtual void pkint(int)
#define LOOK_TAKE_YES
Definition: bbssrv.h:11
#define LOOK_TAKE_TODO
Definition: bbssrv.h:16
int nrnmpi_myid
virtual void perror(const char *)
virtual int take_todo()
#define i
Definition: md1redef.h:12
virtual void pkstr(const char *)
virtual void pkvec(int, double *)
#define LOOK_YES
Definition: bbssrv.h:9
#define POST_RESULT
Definition: bbssrv.h:15
#define QUIT
Definition: bbssrv.h:4
#define LOOK
Definition: bbssrv.h:6