The VisAO Camera
VisAOApp_base.cpp
Go to the documentation of this file.
1 /************************************************************
2 * VisAOApp_base.cpp
3 *
4 * Author: Jared R. Males (jrmales@email.arizona.edu)
5 *
6 * Definitions for the basic VisAO application, implementing the command fifos
7 *
8 * Developed as part of the Magellan Adaptive Optics system.
9 ************************************************************/
10 
11 /** \file VisAOApp_base.cpp
12  * \author Jared R. Males
13  * \brief Definitions for VisAOApp_base.
14  *
15 */
16 
17 #include "VisAOApp_base.h"
18 
19 
20 
21 namespace VisAO
22 {
23 
24 //std::string global_app_name;
25 
26 
27 //Static fields
28 int VisAOApp_base::control_mode = VisAOApp_base::CMODE_NONE;
29 
31 
33 {
34 
36  com_path_remote[0]='\0';
37  com_path_local[0]='\0';
38  com_path_script[0]='\0';
39  com_path_auto[0]='\0';
40 
41  wait_to = .2;
42 
43  getresuid(&euid_real, &euid_called, &suid);
44  set_euid_called(); //immediately step down to unpriveleged uid.
45  RT_priority = 0;
46 
47  pause_time = 1.0;
48 
49  pthread_mutex_init(&my_mutex, NULL);
50 
51  profile = new VisAO::profiler(1000);
52  use_profiler = 0;
53 
57 
58  signal(RTSIGIGN, SIG_IGN);
59 
60  dataFileOpen = 0;
61  dataFileOpenTime = 0.;
62 
63  data_save_path = "data/syslogs";
64  data_log_time_length = 120.;
65 
66 }
67 
69 {
70  if(dataFileOpen)
71  {
72  dataof.close();
73  dataFileOpen = false;
74  }
75 
76  return;
77 }
78 
80 {
81  errno = 0;
82  if(seteuid(euid_called) < 0)
83  {
84  logss.str("");
85  logss << "Setting effective user id to euid_called (" << euid_called << ") failed. Errno says: " << strerror(errno) << ".";
86  error_report(Logger::LOG_LEV_ERROR, logss.str());
87  return -1;
88  }
89 
90  return 0;
91 }
92 
94 {
95  errno = 0;
96  if(seteuid(euid_real) < 0)
97  {
98  logss.str("");
99  logss << "Setting effective user id to euid_real (" << euid_real << ") failed. Errno says: " << strerror(errno) << ".";
100  error_report(Logger::LOG_LEV_ERROR, logss.str());
101  return -1;
102  }
103 
104  return 0;
105 }
106 
107 
109 {
110  int rv1, rv;
111  struct sched_param schedpar;
112 
113  schedpar.sched_priority = prio;
114 
115  rv1 = set_euid_called(); //Get the maximum privileges available
116 
117  errno = 0;
118 
119  if(prio > 0) rv = sched_setscheduler(0, VISAO_SCHED_POLICY, &schedpar);
120  else rv = sched_setscheduler(0, SCHED_OTHER, &schedpar);
121 
122  if(rv < 0)
123  {
124  logss.str("");
125  logss << "Setting scheduler priority to " << prio << " failed. Errno says: " << strerror(errno) << ". ";
126  error_report(Logger::LOG_LEV_ERROR, logss.str());
127 
128  rv += -1;
129  }
130  else
131  {
132  RT_priority = prio;
133  logss.str("");
134  logss << "Scheduler priority (RT_priority) set to " << RT_priority << ".";
135  log_msg(Logger::LOG_LEV_INFO, logss.str());
136  }
137 
138  rv += rv1 + set_euid_real(); //Go back to regular privileges
139 
140  return rv;
141 
142 }
143 
144 int VisAOApp_base::set_app_name(std::string an)
145 {
146  app_name = an;
147 
148  return 0;
149 }
150 
151 int VisAOApp_base::setup_baseApp(bool usethreads)
152 {
153  int nsub;
154  if(fl.nchan == 0)
155  {
156  error_report(Logger::LOG_LEV_ERROR, "fifo_list not yet setup.");
157  return -1;
158  }
159 
160  if(!usethreads)
161  {
162  nsub = 1;
163  if(com_path_local[0] != '\0')
164  {
165  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_local + "_in").c_str(), (char *)(com_path_local + "_out").c_str(),
166  &com_local_handler, (void *) this);
167  nsub++;
168  }
169  if(com_path_remote[0] != '\0')
170  {
171  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_remote + "_in").c_str(), (char *)(com_path_remote + "_out").c_str(),
172  &com_remote_handler, (void *) this);
173  nsub++;
174  }
175  if(com_path_script[0] != '\0')
176  {
177  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_script + "_in").c_str(), (char *)(com_path_script + "_out").c_str(),
178  &com_script_handler, (void *) this);
179  nsub++;
180  }
181  if(com_path_auto[0] != '\0')
182  {
183  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_auto + "_in").c_str(), (char *)(com_path_auto + "_out").c_str(),
184  &com_auto_handler, (void *) this);
185  nsub++;
186  }
187  }
188  else
189  {
190  nsub = 1;
191  if(com_path_local[0] != '\0')
192  {
193  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_local + "_in").c_str(), (char *)(com_path_local + "_out").c_str(),
194  &com_local_thread_handler, (void *) this);
195  nsub++;
196  }
197  if(com_path_remote[0] != '\0')
198  {
199  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_remote + "_in").c_str(), (char *)(com_path_remote + "_out").c_str(),
200  &com_remote_thread_handler, (void *) this);
201  nsub++;
202  }
203  if(com_path_script[0] != '\0')
204  {
205  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_script + "_in").c_str(), (char *)(com_path_script + "_out").c_str(),
206  &com_script_thread_handler, (void *) this);
207  nsub++;
208  }
209  if(com_path_auto[0] != '\0')
210  {
211  set_fifo_list_channel(&fl, fl.nchan - nsub, RWBUFF_SZ, (char *)(com_path_auto + "_in").c_str(), (char *)(com_path_auto + "_out").c_str(),
212  &com_auto_thread_handler, (void *) this);
213  nsub++;
214  }
215  }
216 
217  return 0;
218 }
219 
220 int VisAOApp_base::setup_baseApp(bool remfifo, bool locfifo, bool scrfifo, bool autfifo, bool usethreads)
221 {
222  if(remfifo)
223  {
224  com_path_remote = com_path + "_com_remote";
225  logss.str("");
226  logss << "Set com_path_remote: " << com_path_remote << ".";
227  log_msg(Logger::LOG_LEV_INFO, logss.str());
228  }
229  if(locfifo)
230  {
231  com_path_local = com_path + "_com_local";
232  logss.str("");
233  logss << "Set com_path_local: " << com_path_local << ".";
234  log_msg(Logger::LOG_LEV_INFO, logss.str());
235  }
236  if(scrfifo)
237  {
238  com_path_script = com_path + "_com_script";
239  logss.str("");
240  logss << "Set com_path_script: " << com_path_script << ".";
241  log_msg(Logger::LOG_LEV_INFO, logss.str());
242  }
243  if(autfifo)
244  {
245  com_path_auto = com_path + "_com_auto";
246  logss.str("");
247  logss << "Set com_path_auto: " << com_path_auto << ".";
248  log_msg(Logger::LOG_LEV_INFO, logss.str());
249  }
250 
251  return setup_baseApp(usethreads);
252 }
253 
254 
255 
257 {
258  return ::setup_fifo_list(&fl, nfifos);
259 }
260 
262 {
263  std::cout << "Connecting fifo list\n";
265 }
266 
268 {
270 }
271 
273 {
274  struct sigaction act;
275  sigset_t sset;
276 
277  act.sa_handler = &catch_fifo_response_list;
278  act.sa_flags = 0;
279  sigemptyset(&sset);
280  act.sa_mask = sset;
281 
282  errno = 0;
283 
284  if(sigaction(SIGIO, &act, 0) < 0)
285  {
286  logss.str("");
287  logss << "Error setting signal handler for SIGIO. Errno says: " << strerror(errno) << ".";
288  error_report(Logger::LOG_LEV_ERROR, logss.str());
289  return -1;
290  }
291 
292  log_msg(Logger::LOG_LEV_INFO, "Installed signal handling for SIGIO");
293 
294  return 0;
295 }
296 
298 {
299  struct sigaction act;
300  sigset_t sset;
301 
303 
304  act.sa_sigaction = &catch_fifo_pending_reads;
305  act.sa_flags = SA_SIGINFO;
306  sigemptyset(&sset);
307  act.sa_mask = sset;
308 
309  errno = 0;
310 
311  if(sigaction(RTSIGIO, &act, 0) < 0)
312  {
313  logss.str("");
314  logss << "Error setting signal handler for RTSIGIO. Errno says: " << strerror(errno) << ".";
315  error_report(Logger::LOG_LEV_ERROR, logss.str());
316  return -1;
317  }
318 
319  log_msg(Logger::LOG_LEV_INFO, "Installed signal handling for RTSIGIO");
320 
321  act.sa_handler = &catch_fifo_standard_sigio;
322  act.sa_flags = 0;
323 
324  errno = 0;
325  if(sigaction(SIGIO, &act, 0) < 0)
326  {
327  logss.str("");
328  logss << "Error setting backup signal handler for SIGIO. Errno says: " << strerror(errno) << ".";
329  error_report(Logger::LOG_LEV_ERROR, logss.str());
330  return -1;
331  }
332 
333  log_msg(Logger::LOG_LEV_INFO, "Installed backup signal handling for SIGIO");
334 
335  signal(RTSIGIGN, SIG_IGN);
336  log_msg(Logger::LOG_LEV_INFO, "Ignoring RTSIGIGN");
337 
338  return 0;
339 }
340 
341 
343 {
344  int rv;
345  if(fl.RTSIGIO_overflow)
346  {
347  //Do something here!
348  rv = -1;
349  error_report(Logger::LOG_LEV_ERROR, "R/T SIGIO overflow.");
350 
351  catch_fifo_response_list(0); //This will go through all current inputs.
352 
353  fl.RTSIGIO_overflow = 0;
354  }
355  while(fl.tot_pending_reads > 0 && !TimeToDie)
356  {
358  }
359  return rv;
360 }
361 
362 int VisAOApp_base::write_fifo_channel(int ch, const char *com, int comlen, std::string * resp)
363 {
364  int rv;
365 
366  //Wait until somebody opens the other end.
367  if(fl.fifo_ch[ch].timeout)
368  {
369  /*struct stat fst;
370  fstat(fl.fifo_ch[ch].fd_out, &fst);
371  if(fl.fifo_ch[ch].last_atime_out == 0) fl.fifo_ch[ch].last_atime_out = fst.st_atime;
372 
373  if(fl.fifo_ch[ch].last_atime_out == fst.st_atime)
374  {
375  *resp = "";
376  return -1;
377  }
378  else
379  {
380  fl.fifo_ch[ch].last_atime_out = 0;
381  }*/
382  //mod time won't clear a timeout due to server slowness.
383  //Have to explicitly try and open the channel until we get the error.
384  int test_fd = wopen_nonblock(fl.fifo_ch[ch].outfname, 0);
385 
386  //std::cout << "test_fd result: " << test_fd << "\n";
387  if(test_fd > 0 )
388  {
389  close(test_fd);
390  return -1;
391  }
392  }
393 
394  rv = ::write_fifo_channel(&fl.fifo_ch[ch], com, comlen);
395 
396  if(rv < 0)
397  {
398  logss.str("");
399  logss << "Error returned from ::write_fifo_channel on channel " << ch << ".";
400  error_report(Logger::LOG_LEV_ERROR, logss.str());
401  return rv;
402  }
403 
404  if(!resp) return rv;
405 
406  return get_fifo_channel_response(resp, ch);
407 }
408 
409 int VisAOApp_base::write_fifo_channel(int ch, const char *com, int comlen, std::string * resp, char *sm)
410 {
411  int rv;
412 
413  //Wait until somebody opens the other end.
414  if(fl.fifo_ch[ch].timeout)
415  {
416  struct stat fst;
417  fstat(fl.fifo_ch[ch].fd_out, &fst);
418  if(fl.fifo_ch[ch].last_atime_out == 0) fl.fifo_ch[ch].last_atime_out = fst.st_atime;
419 
420  if(fl.fifo_ch[ch].last_atime_out == fst.st_atime)
421  {
422  *resp = "";
423  return -1;
424  }
425  else
426  {
427  fl.fifo_ch[ch].last_atime_out = 0;
428  }
429  }
430 
431  rv = ::write_fifo_channel_seqmsg(&fl.fifo_ch[ch], com, comlen, sm);
432 
433  if(rv < 0)
434  {
435  logss.str("");
436  logss << "Error returned from ::write_fifo_channel on channel " << ch << ".";
437  error_report(Logger::LOG_LEV_ERROR, logss.str());
438  return rv;
439  }
440 
441  if(!resp) return rv;
442 
443  return get_fifo_channel_response(resp, ch);
444 }
445 
446 int VisAOApp_base::get_fifo_channel_response(std::string * resp, int ch)
447 {
448  double startT;
449  int nottimedout = 0;
450  startT = get_curr_time();
451 
452  //if(using_signal_thread)
453  if(fl.fifo_ch[ch].input_handler)
454  {
455  //Here the signal handling thread should take care of reading the fifo for us.
456  while((fl.fifo_ch[ch].server_response[0] == '\0') && (get_curr_time() - startT < wait_to) &&!TimeToDie)
457  {
458 
459  sched_yield();
460  usleep(10); //give up the scheduler in case the signal thread is waiting.
461  //So far usleep(1) is too short
462  //usleep(10) works.
463  }
464  }
465  else
466  {
467  //Here we're either blocked or just using the RT signals without the separate thread
468  //so we have to do the work.
469  //std::cerr << "Polling " << get_curr_time() << "\n";
470 
471  pollfd pfd;
472  pfd.fd = fl.fifo_ch[ch].fd_in;
473  pfd.events = POLLIN;
474  pfd.revents = 0;
475 
476  errno = 0;
477  if(fl.fifo_ch[ch].timeout)
478  {
479  nottimedout = poll(&pfd, 1, (int) (.1*wait_to*1000.));
480  }
481  else
482  {
483  nottimedout = poll(&pfd, 1, (int) (wait_to*1000.));
484  }
485  if(nottimedout < 0)
486  {
487  logss.str("");
488  logss << "Poll returned error (not a timeout). errno says: " << strerror(errno) << "\n";
489  error_report(Logger::LOG_LEV_ERROR, logss.str());
490  return -1;
491  }
493 
494  //std::cerr << "Done Polling " << get_curr_time() << "\n";
495  }
496 
497  //Check for timeout
498  if(fl.fifo_ch[ch].server_response[0] == '\0' || !nottimedout)
499  {
500  *resp = "";
501  if(!fl.fifo_ch[ch].timeout)
502  {
503  logss.str("");
504  logss << "FIFO response timeout. wait_to = " << wait_to << "secs.";
505  error_report(Logger::LOG_LEV_ERROR, logss.str());
506  fl.fifo_ch[ch].timeout = 1;
507  struct stat fst;
508  fstat(fl.fifo_ch[ch].fd_out, &fst);
509  fl.fifo_ch[ch].last_atime_out = fst.st_atime;
510  }
511  return -1;
512  }
513 
514  fl.fifo_ch[ch].last_atime_out = 0;
515 
516  //If not a timeout, check if this clears a timeout
517  if(fl.fifo_ch[ch].timeout)
518  {
519  logss.str("");
520  logss << "FIFO response timeout clear.";
521  error_report(Logger::LOG_LEV_ERROR, logss.str());
522  fl.fifo_ch[ch].timeout = 0;
523  }
524 
525  //Ok, now copy and getouta.
526  *resp = fl.fifo_ch[ch].server_response;
527 
528  return 0;
529 
530 }
531 
533 {
534  if(to < 0)
535  {
536  wait_to = 0;
537  error_report(Logger::LOG_LEV_ERROR, "Attempt to set wait_to to negative number.");
538  }
539  else wait_to = to;
540 
541  logss.str("");
542  logss << "Wait timeout (wait_to) set to " << wait_to << " secs.";
543 
544  log_msg(Logger::LOG_LEV_INFO, logss.str());
545 
546  if(to < 0) return -1;
547  else return 0;
548 }
549 
551 {
552  return request_control(ctype, 0);
553 }
554 
555 int VisAOApp_base::request_control(int ctype, bool override)
556 {
557  if(ctype >= control_mode || override)
558  {
559  control_mode = ctype;
560  return control_mode;
561  }
562  else return -1;
563 }
564 
565 std::string VisAOApp_base::__remote_command(std::string com, char *seqmsg)
566 {
567  if(com == "") return "";//ignore spurious SIGIO events
568 
569  //Before we do anything else, check if AUTO
570  if(control_mode == CMODE_AUTO && com[0] != 'X')
571  {
572  return "A\n";
573  }
574 
575  std::string response;
576 
577  //Is this an override to remote control command?
578  if(control_mode > CMODE_REMOTE && com[0] == 'X')
579  {
580  if(com == "XREMOTE")
581  {
582  if(request_control(CMODE_REMOTE, 1) == CMODE_REMOTE) return "REMOTE\n";
583  else return "FAIL\n";
584  }
585  else return "UNKOWN COMMAND:" + com + "\n";
586  }
587 
588  //Is this a request to take remote control in a non-override situation?
589  if(com == "REMOTE" || com == "XREMOTE")
590  {
591  if(control_mode <= CMODE_REMOTE)
592  {
593  if(request_control(CMODE_REMOTE) == CMODE_REMOTE) return "REMOTE\n";
594  else return "FAIL\n";
595  }
596  else
597  {
598  if(control_mode == CMODE_LOCAL) return "L\n";
599  else return "A\n"; // cant' get here.
600  }
601  }
602 
603  //Is this a request to give up remote control?
604  if(control_mode == CMODE_REMOTE && com == "~REMOTE")
605  {
606  if(default_control_mode > -1 && default_control_mode == CMODE_REMOTE)
607  {
609  else return "FAIL\n";
610  }
611  else
612  {
613  if(request_control(CMODE_NONE,1) == CMODE_NONE) return "NONE\n";
614  else return "FAIL\n";
615  }
616  }
617 
618  //If we're here, must be an app specific command
619  return remote_command(com, seqmsg);
620 }
621 
622 std::string VisAOApp_base::remote_command(std::string com)
623 {
624  return "UNKOWN COMMAND: " + com + "\n";
625 }
626 
627 std::string VisAOApp_base::remote_command(std::string com, char *seqmsg __attribute__((unused)))
628 {
629  seqmsg = 0; //just to suppress the unused warning.
630  return remote_command(com);
631 }
632 
633 std::string VisAOApp_base::__local_command(std::string com, char *seqmsg)
634 {
635 
636  if(com == "") return "";//ignore spurious SIGIO events
637 
638  //Before we do anything else, check if AUTO
639  if(control_mode == CMODE_AUTO && com[0] != 'X')
640  {
641  return "A\n";
642  }
643 
644  int pos = com.find_first_of("\n\r", 0);
645  if(pos > -1) com.erase(pos, com.length()-pos);
646 
647  std::string response;
648 
649  //Is this an override to local control command?
650  if(control_mode > CMODE_LOCAL && com[0] == 'X')
651  {
652  if(com == "XLOCAL")
653  {
654  if(request_control(CMODE_LOCAL, 1) == CMODE_LOCAL) return "LOCAL\n";
655  else return "FAIL\n";
656  }
657  else return "UNKOWN COMMAND:" + com + "\n";
658  }
659 
660  //Is this a request to take local control in a non-override situation?
661  if(com == "LOCAL" || com == "XLOCAL")
662  {
663  if(control_mode <= CMODE_LOCAL)
664  {
665  if(request_control(CMODE_LOCAL) == CMODE_LOCAL) return "LOCAL\n";
666  else return "FAIL\n";
667  }
668  else
669  {
670  return "A\n";
671  }
672  }
673 
674  //Is this a request to relinquish local control?
675  if(control_mode == CMODE_LOCAL && com == "~LOCAL")
676  {
677  if(default_control_mode > -1 && default_control_mode != CMODE_LOCAL)
678  {
680  else return "FAIL\n";
681  }
682  else
683  {
684  if(request_control(CMODE_NONE,1) == CMODE_NONE) return "NONE\n";
685  else return "FAIL\n";
686  }
687  }
688 
689  return local_command(com,seqmsg);
690 }
691 
692 std::string VisAOApp_base::local_command(std::string com)
693 {
694  return "UNKOWN COMMAND: " + com + "\n";
695 }
696 
697 std::string VisAOApp_base::local_command(std::string com, char *seqmsg __attribute__((unused)))
698 {
699  seqmsg = 0; //just to suppress the unused warning.
700  return local_command(com);
701 }
702 
703 std::string VisAOApp_base::__script_command(std::string com, char *seqmsg)
704 {
705 
706  if(com == "") return "";//ignore spurious SIGIO events
707 
708  //Before we do anything else, check if AUTO
709  if(control_mode == CMODE_AUTO && com[0] != 'X')
710  {
711  return "A\n";
712  }
713 
714  int pos = com.find_first_of("\n\r", 0);
715  if(pos > -1) com.erase(pos, com.length()-pos);
716 
717  std::string response;
718 
719  //Is this an override to script control command?
720  if(control_mode > CMODE_SCRIPT && com[0] == 'X')
721  {
722  if(com == "XSCRIPT")
723  {
724  if(request_control(CMODE_SCRIPT, 1) == CMODE_SCRIPT) return "SCRIPT\n";
725  else return "FAIL\n";
726  }
727  else return "UNKOWN COMMAND:" + com + "\n";
728  }
729 
730  //Is this a request to take script control in a non-override situation?
731  if(com == "SCRIPT" || com == "XSCRIPT")
732  {
733  if(control_mode <= CMODE_SCRIPT)
734  {
735  if(request_control(CMODE_SCRIPT) == CMODE_SCRIPT) return "SCRIPT\n";
736  else return "FAIL\n";
737  }
738  else
739  {
740  return "A\n";
741  }
742  }
743 
744  //Is this a request to relinquish script control?
745  if(control_mode == CMODE_SCRIPT && com == "~SCRIPT")
746  {
747  if(default_control_mode > -1 && default_control_mode != CMODE_SCRIPT)
748  {
750  else return "FAIL\n";
751  }
752  else
753  {
754  if(request_control(CMODE_NONE,1) == CMODE_NONE) return "NONE\n";
755  else return "FAIL\n";
756  }
757  }
758 
759  return script_command(com,seqmsg);
760 }
761 
762 std::string VisAOApp_base::script_command(std::string com)
763 {
764  return "UNKOWN COMMAND: " + com + "\n";
765 }
766 
767 std::string VisAOApp_base::script_command(std::string com, char *seqmsg __attribute__((unused)))
768 {
769  seqmsg = 0; //just to suppress the unused warning.
770  return script_command(com);
771 }
772 
773 std::string VisAOApp_base::auto_command(std::string com, char *seqmsg)
774 {
775  return post_auto_command(com,seqmsg);
776 }
777 
778 
779 std::string VisAOApp_base::post_auto_command(std::string com, char *seqmsg __attribute__((unused)))
780 {
781 
782  if(com == "") return "";//ignore spurious SIGIO events
783 
784  int pos = com.find_first_of("\n\r", 0);
785  if(pos > -1) com.erase(pos, com.length()-pos);
786 
787 
788  //Is this a request to take auto control?
789  if(com == "AUTO" || com == "XAUTO")
790  {
791  if(control_mode <= CMODE_AUTO)
792  {
793  if(request_control(CMODE_AUTO) == CMODE_AUTO) return "AUTO\n";
794  else return "FAIL\n";
795  }
796  else
797  {
798  return "?\n"; // can't get here.
799  }
800  }
801 
802 
803  //Is this a request to relinquish auto control?
804  if(control_mode == CMODE_AUTO && com == "~AUTO")
805  {
806 
807  if(default_control_mode > -1 && default_control_mode != CMODE_AUTO)
808  {
810  else return "FAIL\n";
811  }
812  else
813  {
814  if(request_control(CMODE_NONE, 1) == CMODE_NONE) return "NONE\n";
815  else return "FAIL\n";
816  }
817  }
818 
819  seqmsg = 0; //to suppress the warning.
820  return "UNKOWN COMMAND: " + com + "\n";
821 }
822 
824 {
825  switch(control_mode)
826  {
827  case CMODE_REMOTE:
828  return "REMOTE";
829  case CMODE_LOCAL:
830  return "LOCAL";
831  case CMODE_SCRIPT:
832  return "SCRIPT";
833  case CMODE_AUTO:
834  return "AUTO";
835  default:
836  return "NONE";
837  }
838 }
839 
841 {
842  switch(control_mode)
843  {
844  case CMODE_REMOTE:
845  return "R\n";
846  case CMODE_LOCAL:
847  return "L\n";
848  case CMODE_SCRIPT:
849  return "S\n";
850  case CMODE_AUTO:
851  return "A\n";
852  default:
853  return "N\n";
854  }
855 }
856 
857 
858 void VisAOApp_base::error_report(int LogLevel, std::string emsg)
859 {
860  std::cerr << get_app_name() << ": " << emsg << "\n";
861  log_msg(LogLevel, emsg);
862 }
863 
864 void VisAOApp_base::log_msg(int LogLevel, std::string lmsg)
865 {
866  std::cout << get_app_name() << ": " << lmsg << " (log level " << LogLevel << ")\n";
867  return;
868 }
869 
870 int VisAOApp_base::start_profiler()
871 {
872  struct sched_param schedpar;
873  schedpar.sched_priority = 0;
874 
875  pthread_t th;
876  pthread_attr_t attr;
877  pthread_attr_init(&attr);
878  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
879  //pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
880  pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
881  pthread_attr_setschedpolicy(&attr, SCHED_OTHER);
882  pthread_attr_setschedparam(&attr, &schedpar);
883 
884  return pthread_create(&th, &attr, &__start_profiler, (void *) profile);
885 }
886 
888 {
889  int rv;
890  size_t sizecheck;
891 
893 
894  if(!rv)
895  {
897  if(statusboard_shmemptr) rv = 0;
898  else rv = -1;
899  }
900 
901  return rv;
902 
903 }
904 
906 {
907  statusboard_shmemkey = mkey;
908  return 0;
909 }
910 
912 {
914  {
916 
917  bsb->control_mode = control_mode;
918 
919  clock_gettime(CLOCK_REALTIME, &bsb->last_update);
920  }
921  return 0;
922 }
923 
924 
925 std::string VisAOApp_base::getDataFileName()
926 {
927  std::string fname;
928  char buffer[21];
929  timeval tv;
930 
931  gettimeofday(&tv, 0);
932  get_visao_filename(buffer, &tv);
933 
934  fname = getenv("VISAO_ROOT");
935  fname += "/";
936  fname += data_save_path;
937  fname += "/";
938  fname += data_file_prefix;
939  fname += "_";
940  fname += buffer;
941  fname += ".txt";
942 
943  return fname;
944 }
945 
946 int VisAOApp_base::checkDataFileOpen()
947 {
948  //Close the file if it has been opened for long enough
949  if(dataFileOpen && (get_curr_time()-dataFileOpenTime > data_log_time_length))
950  {
951  dataof.close();
952  dataFileOpen = false;
953  }
954 
955  if(!dataFileOpen)
956  {
957  std::string fname;
958  fname = getDataFileName();
959  dataof.open(fname.c_str());
960  if(!dataof.good())
961  {
962  Logger::get()->log(Logger::LOG_LEV_ERROR, "Error opening data file. AOsystem data may not be logged correctly");
963  dataFileOpen = false;
964  dataFileOpenTime = 0;
965  return -1;
966  }
967  else
968  {
969  dataFileOpen = true;
970  dataFileOpenTime = get_curr_time();
971  }
972  }
973 
974  return 0;
975 }
976 
977 void VisAOApp_base::dataLogger(timeval tv __attribute__((unused)))
978 {
979  return;
980 }
981 
982 
983 int com_remote_handler(fifo_channel * fc)
984 {
985  std::string tmp, com, response;
986  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
987 
988  read_fifo_channel(fc);
989 
990  com = fc->server_response;
991 
992  //Process each line read
993  while(getnextline(&tmp, &com))
994  {
995  response = vab->__remote_command(tmp,0);
996 
997  write_fifo_channel(fc, (char *)response.c_str(), response.length());
998  }
999 
1000  return 0;
1001 }
1002 
1003 int com_local_handler(fifo_channel * fc)
1004 {
1005  std::string tmp, com, response;
1006  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1007 
1008  read_fifo_channel(fc);
1009 
1010  com = fc->server_response;
1011 
1012  //Process each line read
1013  while(getnextline(&tmp, &com))
1014  {
1015  if(tmp == "")
1016  {
1017  std::cerr << "Fix this bug! " << __FILE__ << " line " << __LINE__ << "\n";
1018  break;
1019  }
1020  response = vab->__local_command(tmp,0);
1021 
1022  write_fifo_channel(fc, (char *)response.c_str(), response.length());
1023  }
1024 
1025  return 0;
1026 }
1027 
1028 int com_script_handler(fifo_channel * fc)
1029 {
1030  std::string tmp, com, response;
1031  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1032 
1033  read_fifo_channel(fc);
1034 
1035  com = fc->server_response;
1036 
1037  //Process each line read
1038  while(getnextline(&tmp, &com))
1039  {
1040  response = vab->__script_command(tmp,0);
1041 
1042  write_fifo_channel(fc, (char *)response.c_str(), response.length());
1043  }
1044 
1045  return 0;
1046 }
1047 
1048 int com_auto_handler(fifo_channel * fc)
1049 {
1050  std::string response;
1051  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1052 
1053  read_fifo_channel(fc);
1054 
1055  //No checking for multiple lines done.
1056  response = vab->auto_command(fc->server_response, fc->seqmsg);
1057 
1058  write_fifo_channel(fc, (char *)response.c_str(), response.length());
1059 
1060  return 0;
1061 }
1062 
1063 int com_remote_thread_handler(fifo_channel * fc)
1064 {
1065  pthread_t th;
1066  pthread_attr_t attr;
1067  pthread_attr_init(&attr);
1068  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1069  pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
1070 
1071  pthread_create(&th, &attr, &__com_remote_thread_handler, (void *) fc);
1072 
1073  return 0;
1074 }
1075 
1077 {
1078  fifo_channel *fc = (fifo_channel *)ptr;
1079  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1080 
1081  pthread_mutex_lock(&vab->my_mutex);
1082 
1083  com_remote_handler(fc);
1084 
1085  pthread_mutex_unlock(&vab->my_mutex);
1086 
1087  return 0;
1088 }
1089 
1090 int com_local_thread_handler(fifo_channel * fc)
1091 {
1092  pthread_t th;
1093  pthread_attr_t attr;
1094  pthread_attr_init(&attr);
1095  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1096  pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
1097 
1098  pthread_create(&th, &attr, &__com_local_thread_handler, (void *) fc);
1099 
1100  return 0;
1101 }
1102 
1104 {
1105  fifo_channel *fc = (fifo_channel *)ptr;
1106  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1107 
1108  pthread_mutex_lock(&vab->my_mutex);
1109 
1110  com_local_handler(fc);
1111 
1112  pthread_mutex_unlock(&vab->my_mutex);
1113 
1114  return 0;
1115 }
1116 
1117 int com_script_thread_handler(fifo_channel * fc)
1118 {
1119  pthread_t th;
1120  pthread_attr_t attr;
1121  pthread_attr_init(&attr);
1122  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1123  pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
1124 
1125  pthread_create(&th, &attr, &__com_script_thread_handler, (void *) fc);
1126  return 0;
1127 }
1128 
1130 {
1131  fifo_channel *fc = (fifo_channel *)ptr;
1132  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1133 
1134  pthread_mutex_lock(&vab->my_mutex);
1135 
1136  com_script_handler(fc);
1137 
1138  pthread_mutex_unlock(&vab->my_mutex);
1139 
1140  return 0;
1141 }
1142 
1143 int com_auto_thread_handler(fifo_channel * fc)
1144 {
1145  pthread_t th;
1146  pthread_attr_t attr;
1147  pthread_attr_init(&attr);
1148  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
1149  pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
1150 
1151  pthread_create(&th, &attr, &__com_auto_thread_handler, (void *) fc);
1152  return 0;
1153 }
1154 
1156 {
1157  fifo_channel *fc = (fifo_channel *)ptr;
1158  VisAOApp_base * vab = (VisAOApp_base *)fc->auxdata;
1159 
1160  pthread_mutex_lock(&vab->my_mutex);
1161 
1162  com_auto_handler(fc);
1163 
1164  pthread_mutex_unlock(&vab->my_mutex);
1165 
1166  return 0;
1167 }
1168 
1169 int getnextline(std::string *comln, std::string * com)
1170 {
1171  std::string tmp;
1172  int pos;
1173 
1174  if(com->length() == 0)
1175  {
1176  return 0;
1177  }
1178  pos = com->find_first_of("\n\r", 0);
1179  if(pos == -1)
1180  {
1181  *comln = *com;
1182  *com = "";
1183  return 1;
1184  }
1185  if(pos < (int)com->length()-1)
1186  {
1187  if((*com)[pos+1] == '\n' || (*com)[pos+1] == '\r') com->erase(pos, 1);
1188  }
1189 
1190  *comln = com->substr(0, pos);
1191  com->erase(0, pos+1);
1192 
1193  return 1;
1194 }
1195 
1196 
1197 void * __start_profiler(void * ptr)
1198 {
1199  ((VisAO::profiler *) ptr)->start();
1200  return 0;
1201 }
1202 
1203 } //namespace VisAO
1204 
virtual ~VisAOApp_base()
Virtual destructor.
int fifo_list_do_pending_read(fifo_list *fl)
Runs through the pending reads, dispatching each handler in turn.
Definition: fifoutils.c:576
std::string control_mode_string()
Convenience function to return the control type string, e.g. "REMOTE".
int connect_fifo_list_nolock(fifo_list *fl)
Open each fifo in the list, without exclusive locks.
Definition: fifoutils.c:415
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
Definition: fifoutils.c:194
void * __com_remote_thread_handler(void *ptr)
The start function for remote handling with a thread.
int nchan
The number of channels.
Definition: fifoutils.h:206
int statusboard_shmemid
The ID of the shared memory block.
int setup_fifo_list(fifo_list *fl, int nch)
Setup a fifo_list.
Definition: fifoutils.c:354
double get_curr_time(void)
Gets the current CLOCK_REALTIME time, returns it in seconds to double precision.
Definition: libvisaoc.c:40
int com_local_handler(fifo_channel *fc)
fifo_channel handler for local commands
int com_remote_thread_handler(fifo_channel *fc)
Thread version of the fifo_channel handler for remote commands.
int com_auto_thread_handler(fifo_channel *fc)
Thread version of the fifo_channel handler for auto commands.
static int default_control_mode
The default control mode.
double wait_to
The timeout for waiting on responses from FIFOs in seconds.
void * __com_auto_thread_handler(void *ptr)
The start function for auto handling with a thread.
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
int setup_sigio()
Setup the SIGIO signal handling.
pthread_mutex_t my_mutex
Mutex used by the threaded versions of the standard command handlers.
std::ostringstream logss
Conveninence string stream for building log messages.
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
virtual void error_report(int LogLevel, std::string emsg)
Report an error. Also calls log_msg.
virtual std::string __local_command(std::string com, char *seqmsg)
Processing for local commands.
int RT_priority
The real-time scheduling priority. Default is 0.
Definition: VisAOApp_base.h:62
int write_fifo_channel_seqmsg(fifo_channel *fc, const char *com, int comlen, char *seqmsg)
Write data to the output channel, including a sequence message.
Definition: fifoutils.c:218
int set_RT_priority(int prio)
Set the real-time priority of the current process.
std::string com_path
The control fifo path base name.
virtual int update_statusboard()
Update the status board.
virtual int setup_baseApp(bool usethreads=false)
Install fifo channels.
int check_fifo_list_RTpending()
Check for pending reads for the fifo list while using the RT signals.
int wopen_nonblock(char *fname, int nolock)
Open a file for non-blocking writes.
Definition: fifoutils.c:649
fifo_channel * fifo_ch
An array of fifo_channels.
Definition: fifoutils.h:207
uid_t euid_real
The real user id of the proces.
Definition: VisAOApp_base.h:58
std::string com_path_local
The path for the local control fifos.
std::string app_name
The name of the application.
Definition: VisAOApp_base.h:82
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
VisAOApp_base()
Default constructor.
#define VISAO_SCHED_POLICY
The real-time scheduling policy used by the VisAO system.
Definition: libvisao.h:27
uid_t euid_called
The user id of the process as called (that is when the constructor gets called).
Definition: VisAOApp_base.h:59
void catch_fifo_response_list(int signum)
A SIGIO handler, which uses global_fifo_list to call the appropriate handler.
std::string com_path_remote
The path for the remote control fifos.
std::string com_path_script
The path for the script control fifos.
virtual std::string __script_command(std::string com, char *seqmsg)
Processing for script commands - not normally overriden.
key_t statusboard_shmemkey
The key used to lookup the shared memory.
virtual std::string auto_command(std::string com, char *seqmsg)
Processing for auto commands - to be overriden.
int getnextline(std::string *comln, std::string *com)
Utility function for parsing command buffers line by line.
int TimeToDie
Global set by SIGTERM.
void catch_fifo_pending_reads(int signum, siginfo_t *siginf, void *ucont)
A handler for a R/T SIGIO, which just updates the pending reads meta data but does no actual signal h...
std::string control_mode_response()
Convenience function to return the control type response string, e.g. "A\n".
int com_script_handler(fifo_channel *fc)
fifo_channel handler for script commands
void * attach_shm(size_t *sz, key_t mkey, int shmemid)
Attach to a shared memory buffer and get its size.
Definition: libvisaoc.c:90
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
The base class for VisAO applications.
Definition: VisAOApp_base.h:48
std::string com_path_auto
The path for the auto control fifos.
int RTSIGIO_overflow
flag indicating that the signal queue has overflown.
Definition: fifoutils.h:223
int get_fifo_channel_response(std::string *resp, int ch)
Check, and wait if neccessary, for data on a fifo channel.
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
virtual std::string remote_command(std::string com)
Called by __remote_command after control state logic.
virtual int request_control(int cmode)
Calls request_control(cmode, 0).
int com_script_thread_handler(fifo_channel *fc)
Thread version of the fifo_channel handler for script commands.
int set_fifo_list_rtsig(fifo_list *fl)
Change from SIGIO to real time signals.
Definition: fifoutils.c:517
int com_local_thread_handler(fifo_channel *fc)
Thread version of the fifo_channel handler for local commands.
int set_app_name(std::string an)
Set the application name.
uid_t suid
The save-set user id of the process.
Definition: VisAOApp_base.h:60
int connect_fifo_list(fifo_list *fl)
Open each fifo in the list, with exclusive lock on the input fifo.
Definition: fifoutils.c:379
virtual void dataLogger(timeval tv)
Log data at intervals.
int set_statusboard_shmemkey(key_t mkey)
Set the status board shared memory key. Does nothing else.
int init_fifo_list(fifo_list *fl)
Initialize the fifo_list.
Definition: fifoutils.c:341
virtual std::string __remote_command(std::string com, char *seqmsg)
Processing for remote commands.
virtual std::string script_command(std::string com)
Called by __script_command after control state logic.
void * __com_script_thread_handler(void *ptr)
The start function for script handling with a thread.
Declarations for VisAOApp_base.
int set_wait_to(double to)
Set the wait timeout for fifo channel responses.
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
virtual std::string get_app_name()
Get the application name.
Definition: VisAOApp_base.h:92
int set_euid_called()
Changes the user id of the process to euid_called.
int connect_fifo_list()
Connect the fifo_list with exclusive locking.
static int control_mode
The current control mode.
int setup_RTsigio()
Setup SIGIO signal handling using realtime signals.
int get_visao_filename(char *buffer, struct timeval *tv)
Writes the standard visao unique filename for a timeval to the buffer.
virtual std::string local_command(std::string com)
Called by __local_command after control state logic.
int com_auto_handler(fifo_channel *fc)
fifo_channel handler for auto commands
int connect_fifo_list_nolock()
Connect the fifo_list without exclusive locking.
void catch_fifo_standard_sigio(int signum)
A handler for normal SIGIO when we should have gotten the R/T SIGIO, implying signal queue overflow...
void * __com_local_thread_handler(void *ptr)
The start function for local handling with a thread.
The namespace of VisAO software.
virtual std::string post_auto_command(std::string com, char *seqmsg=0)
Processing for auto commands - not normally overriden.
virtual void log_msg(int LogLevel, std::string lmsg)
Log a message.
int tot_pending_reads
The total number of pending reads.
Definition: fifoutils.h:215
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
int create_shmem(int *shmemid, key_t mkey, size_t sz)
Create a shared memory buffer.
Definition: libvisaoc.c:49
int set_euid_real()
Changes the user id fo the process to the real user id.
int com_remote_handler(fifo_channel *fc)
fifo_channel handler for remote commands
int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of one channel in the list.
Definition: fifoutils.c:373
int write_fifo_channel(int ch, const char *com, int comlen, std::string *resp)
Write data to a fifo_channel, and get a response if desired.