Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
rcdaq_server.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file rcdaq_server.cc
1 
2 #include "rcdaq_rpc.h"
3 #include "rcdaq_actions.h"
4 
5 #include "parseargument.h"
6 #include "rcdaq.h"
7 #include "daq_device.h"
8 #include "rcdaq_plugin.h"
9 #include "all.h"
10 
11 
12 #include <iostream>
13 #include <sstream>
14 #include <iomanip>
15 #include <fstream>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <dlfcn.h>
19 
20 #include <rpc/pmap_clnt.h>
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include "pthread.h"
26 #include "signal.h"
27 
28 #include <sys/file.h>
29 #include <errno.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 
33 
34 #include <vector>
35 
36 
37 #include <set>
38 #include <iostream>
39 
40 using namespace std;
41 
42 static pthread_mutex_t M_output;
43 
44 std::vector<RCDAQPlugin *> pluginlist;
45 
46 static unsigned long my_servernumber = 0;
47 
48 extern "C" void rcdaq_1(struct svc_req *rqstp, SVCXPRT *transp);
49 
50 static int pid_fd = 0;
51 
52 
53 void sig_handler(int i)
54 {
55  if (pid_fd)
56  {
58  unlink (pidfilename);
59  }
60  exit(0);
61 }
62 
63 
64 
65 
66 //-------------------------------------------------------------
67 
68 
70 {
71  pluginlist.push_back(p);
72 }
73 
75 {
76  // do nothing for now
77  // we need to implement this once we add unloading of plugins
78  // as a feature (don't see why at this point)
79 }
80 
81 int daq_load_plugin( const char *sharedlib, std::ostream& os)
82 {
83  void * v = dlopen(sharedlib, RTLD_GLOBAL | RTLD_NOW | RTLD_NOLOAD);
84  if (v)
85  {
86  std::cout << "Plugin "
87  << sharedlib << " already loaded" << std::endl;
88  os << "Plugin "
89  << sharedlib << " already loaded" << std::endl;
90  return 0;
91  }
92 
93  void * voidpointer = dlopen(sharedlib, RTLD_GLOBAL | RTLD_NOW);
94  if (!voidpointer)
95  {
96  std::cout << "Loading of the plugin "
97  << sharedlib << " failed: " << dlerror() << std::endl;
98  os << "Loading of the plugin "
99  << sharedlib << " failed: " << dlerror() << std::endl;
100  return -1;
101 
102  }
103  os << "Plugin " << sharedlib << " successfully loaded" << std::endl;
104  cout << "Plugin " << sharedlib << " successfully loaded" << std::endl;
105  return 0;
106 
107 }
108 
109 //-------------------------------------------------------------
110 
111 // for certain flags we add some info to the status output
112 // with this routine. It is called from daq_status.
113 
114 int daq_status_plugin (const int flag, std::ostream& os )
115 {
116 
117  // in case we do have plugins, list them
118  // if not, we just say "no plugins loded"
119  if ( pluginlist.size() )
120  {
121  os << " List of loaded Plugins:" << endl;
122  }
123  else
124  {
125  os << " No Plugins loaded" << endl;
126  }
127 
128 
129  std::vector<RCDAQPlugin *>::iterator it;
130 
131  for ( it=pluginlist.begin(); it != pluginlist.end(); ++it)
132  {
133  os << " ";
134  (*it)->identify(os, flag);
135  }
136  return 0;
137 }
138 
139 //-------------------------------------------------------------
140 
141 
142 shortResult * r_create_device_1_svc(deviceblock *db, struct svc_req *rqstp)
143 {
144  static shortResult result, error;
145  static char e_string[512];
146  static char r_string[512];
147  error.str = e_string;
148  result.str = r_string;
149  strcpy ( r_string, " ");
150 
151  if ( daq_running() )
152  {
153  strcpy(e_string, "Run is active\n");
154  error.content = 1;
155  error.what = 0;
156  error.status = -1;
157  return &error;
158  }
159 
160  strcpy(e_string, "Device needs at least 2 parameters\n");
161  error.content = 1;
162  error.what = 0;
163  error.status = -1;
164 
165  result.status = 0;
166  result.what = 0;
167  result.content= 0;
168 
169 
170  int eventtype;
171  int subid;
172 
173 
174  if ( db->npar < 3)
175  {
176  strcpy(r_string, "Device needs at least 2 parameters\n");
177  return &error;
178  }
179 
180 
181  strcpy(r_string, "Wrong number of parameters\n");
182 
183  // and we decode the event type and subid
184  eventtype = get_value ( db->argv1); // event type
185  subid = get_value ( db->argv2); // subevent id
186 
187 
188  // now we will see what device we are supposed to set up.
189  // we first check if it is one of our built-in ones, such as
190  // device_random, or device_file or so.
191 
192 
193  if ( strcasecmp(db->argv0,"device_random") == 0 )
194  {
195 
196  // this happens to be the most complex contructor part
197  // so far since there are a few variants, 2-6 parameters
198  switch ( db->npar)
199  {
200  case 3:
201  add_readoutdevice ( new daq_device_random( eventtype,
202  subid ));
203  break;
204 
205  case 4:
206  add_readoutdevice ( new daq_device_random( eventtype,
207  subid,
208  get_value ( db->argv3)));
209  break;
210 
211  case 5:
212  add_readoutdevice ( new daq_device_random( eventtype,
213  subid,
214  get_value ( db->argv3),
215  get_value ( db->argv4)));
216  break;
217 
218  case 6:
219  add_readoutdevice ( new daq_device_random( eventtype,
220  subid,
221  get_value ( db->argv3),
222  get_value ( db->argv4),
223  get_value ( db->argv5)));
224  break;
225 
226  case 7:
227  add_readoutdevice ( new daq_device_random( eventtype,
228  subid,
229  get_value ( db->argv3),
230  get_value ( db->argv4),
231  get_value ( db->argv5),
232  get_value ( db->argv6)));
233  break;
234 
235  default:
236  return &error;
237  break;
238  }
239 
240  return &result;
241  }
242 
243  if ( strcasecmp(db->argv0,"device_deadtime") == 0 )
244  {
245 
246  // this happens to be the most complex contructor part
247  // so far since there are a few variants, 2-6 parameters
248  switch ( db->npar)
249  {
250  case 3:
251  add_readoutdevice ( new daq_device_deadtime( eventtype,
252  subid ));
253  break;
254 
255  case 4: // plus number of ticks
256  add_readoutdevice ( new daq_device_deadtime( eventtype,
257  subid,
258  get_value ( db->argv3)));
259  break;
260 
261  case 5: // plus number of words
262  add_readoutdevice ( new daq_device_deadtime( eventtype,
263  subid,
264  get_value ( db->argv3),
265  get_value ( db->argv4)));
266  break;
267 
268  case 6: // plus trigger flag
269  add_readoutdevice ( new daq_device_deadtime( eventtype,
270  subid,
271  get_value ( db->argv3),
272  get_value ( db->argv4),
273  get_value ( db->argv5)));
274  break;
275 
276  default:
277  return &error;
278  break;
279  }
280 
281  return &result;
282  }
283 
284 
285  else if ( strcasecmp(db->argv0,"device_file") == 0 )
286  {
287 
288  if ( db->npar < 4) return &error;
289 
290  if ( db->npar >= 5)
291  {
292  // we give the size in kbytes but we want it in words
293  int s = 1024*(get_value(db->argv4)+3)/4;
294  if ( s < 4*1024) s = 4*1024; // this is the default size
295  add_readoutdevice ( new daq_device_file( eventtype,
296  subid,
297  db->argv3,
298  0, // no delete
299  s ) );
300  return &result;
301  }
302  else
303  {
304 
305  add_readoutdevice ( new daq_device_file( eventtype,
306  subid,
307  db->argv3));
308  return &result;
309  }
310 
311  }
312  // --------------------------------------------------------------------------
313  // although this logic is very similar to device_file, since the consequences
314  // of a misplaced parameter are so severe, we make a new device
315  else if ( strcasecmp(db->argv0,"device_file_delete") == 0 )
316  {
317 
318  if ( db->npar < 4) return &error;
319 
320  if ( db->npar >= 5)
321  {
322  // we give the size in kbytes but we want it in words
323  int s = 1024*(get_value(db->argv4)+3)/4;
324  if ( s < 4*1024) s = 4*1024; // this is the default size
325  add_readoutdevice ( new daq_device_file( eventtype,
326  subid,
327  db->argv3,
328  1, // we add the delete flag
329  s ) );
330  return &result;
331  }
332  else
333  {
334 
335  add_readoutdevice ( new daq_device_file( eventtype,
336  subid,
337  db->argv3,
338  1) );
339  return &result;
340  }
341 
342  }
343 
344 
345  // --------------------------------------------------------------------------
346 
347 
348  else if ( strcasecmp(db->argv0,"device_filenumbers") == 0 )
349  {
350 
351  if ( db->npar < 4) return &error;
352 
353  if ( db->npar >= 5)
354  {
355  int s = 1024*(get_value(db->argv4)+3)/4;
356  if ( s < 256) s = 256; // this is the default size
357 
358  add_readoutdevice ( new daq_device_filenumbers( eventtype,
359  subid,
360  db->argv3,
361  0, // no delete
362  s));
363  return &result;
364  }
365  else
366  {
367 
368  add_readoutdevice ( new daq_device_filenumbers( eventtype,
369  subid,
370  db->argv3));
371  return &result;
372  }
373 
374  }
375 
376  // --------------------------------------------------------------------------
377 
378 
379  else if ( strcasecmp(db->argv0,"device_filenumbers_delete") == 0 )
380  {
381 
382  if ( db->npar < 4) return &error;
383 
384  if ( db->npar >= 5)
385  {
386  int s = 1024*(get_value(db->argv4)+3)/4;
387  if ( s < 256) s = 256; // this is the default size
388 
389  add_readoutdevice ( new daq_device_filenumbers( eventtype,
390  subid,
391  db->argv3,
392  1, // we add the delete flag
393  s));
394  return &result;
395  }
396  else
397  {
398 
399  add_readoutdevice ( new daq_device_filenumbers( eventtype,
400  subid,
401  db->argv3,
402  1) );
403  return &result;
404  }
405 
406  }
407 
408 
409  else if ( strcasecmp(db->argv0,"device_command") == 0 )
410  {
411 
412  if ( db->npar < 4) return &error;
413 
414  if ( db->npar >= 5)
415  {
416  int s = (get_value(db->argv4)+3)/4;
417  if ( s < 1280) s = 1280; // this is the default size
418  add_readoutdevice ( new daq_device_file( eventtype,
419  subid,
420  db->argv3,
421  get_value(db->argv4) ) );
422  return &result;
423  }
424  else
425  {
426 
427  add_readoutdevice ( new daq_device_command( eventtype,
428  subid,
429  db->argv3));
430  return &result;
431  }
432 
433  }
434  else if ( strcasecmp(db->argv0,"device_rtclock") == 0 )
435  {
436 
437  add_readoutdevice ( new daq_device_rtclock( eventtype,
438  subid));
439 
440  return &result;
441  }
442 
443 
444  // nada, it was none of the built-in ones if we arrive here.
445 
446  // we now go through through the list of plugins and see if any one of
447  // our plugins can make the device.
448 
449  // there are three possibilities:
450  // 1) the plugin can make the device, all done. In that case, return = 0
451  // 2) the plugin can make the device but the parameters are wrong, return = 1
452  // 3) the plugin dosn not knwo about tha device, we keep on going... return = 2
453 
454  // we keep doing that until we either find a plugin that knows the device or we run
455  // out of plugins
456 
457  std::vector<RCDAQPlugin *>::iterator it;
458 
459  int status;
460  for ( it=pluginlist.begin(); it != pluginlist.end(); ++it)
461  {
462  status = (*it)->create_device(db);
463  // in both of the following cases we are done here:
464  if (status == 0) return &result; // sucessfully created
465  else if ( status == 1) return &error; // it's my device but wrong params
466  // in all other cases we continue and try the next plugin
467  }
468 
469  result.content=1;
470  strcpy(r_string, "Unknown device");
471  return &result;
472 
473 }
474 
475 //-------------------------------------------------------------
476 
477 shortResult * r_action_1_svc(actionblock *ab, struct svc_req *rqstp)
478 {
479 
480  static shortResult result;
481 
482  static std::ostringstream outputstream;
483  static unsigned int currentmaxresultlength = 10*2048;
484  static char *resultstring = new char[currentmaxresultlength+1];
485 
486  // to avoid a race condition with the asynchronous
487  // begin or "end requested" feature, wait here...
490 
491 
492  if ( outputstream.str().size() > currentmaxresultlength )
493  {
494  currentmaxresultlength = outputstream.str().size();
495  std::cout << __LINE__<< " " << __FILE__
496  << " *** warning: extended result string to " << currentmaxresultlength << std::endl;
497  delete [] resultstring;
498  resultstring = new char[currentmaxresultlength+1];
499  }
500 
501 
502  pthread_mutex_lock(&M_output);
503  result.str=resultstring;
504  strcpy(resultstring," ");
505  result.content = 0;
506  result.what = 0;
507  result.status = 0;
508 
509  outputstream.str("");
510 
511  switch ( ab->action)
512  {
513 
514  case DAQ_SYNC:
515  pthread_mutex_unlock(&M_output);
516 
517  return &result;
518  break;
519 
520  case DAQ_BEGIN:
521  result.status = daq_begin ( ab->ipar[0], outputstream);
522  outputstream.str().copy(resultstring,outputstream.str().size());
523  resultstring[outputstream.str().size()] = 0;
524  result.str = resultstring;
525  result.content = 1;
526  pthread_mutex_unlock(&M_output);
527  return &result;
528  break;
529 
530  case DAQ_BEGIN_IMMEDIATE:
531  result.status = daq_begin_immediate ( ab->ipar[0], outputstream);
532  outputstream.str().copy(resultstring,outputstream.str().size());
533  resultstring[outputstream.str().size()] = 0;
534  result.str = resultstring;
535  result.content = 1;
536  pthread_mutex_unlock(&M_output);
537  return &result;
538  break;
539 
540  case DAQ_END:
541  result.status = daq_end_interactive(outputstream);
542  outputstream.str().copy(resultstring,outputstream.str().size());
543  resultstring[outputstream.str().size()] = 0;
544  result.str = resultstring;
545  result.content = 1;
546  pthread_mutex_unlock(&M_output);
547  return &result;
548  break;
549 
550  case DAQ_END_IMMEDIATE:
551  result.status = daq_end_immediate(outputstream);
552  outputstream.str().copy(resultstring,outputstream.str().size());
553  resultstring[outputstream.str().size()] = 0;
554  result.str = resultstring;
555  result.content = 1;
556  pthread_mutex_unlock(&M_output);
557  return &result;
558  break;
559 
560  case DAQ_RUNNUMBERFILE:
561  daq_set_runnumberfile(ab->spar, ab->ipar[0]);
562  break;
563 
564  case DAQ_SETRUNNUMBERAPP:
565  daq_set_runnumberApp(ab->spar, ab->ipar[0]);
566  break;
567 
568  case DAQ_SETFILERULE:
569  daq_set_filerule(ab->spar);
570  break;
571 
572  case DAQ_SETNAME:
573  daq_set_name(ab->spar);
574  break;
575 
576 #ifdef HAVE_MOSQUITTO_H
577 
578  case DAQ_SET_MQTT_HOST:
579  result.status = daq_set_mqtt_host(ab->spar, ab->ipar[0], outputstream);
580  if ( result.status)
581  {
582  outputstream.str().copy(resultstring,outputstream.str().size());
583  resultstring[outputstream.str().size()] = 0;
584  result.str = resultstring;
585  result.content = 1;
586  }
587  pthread_mutex_unlock(&M_output);
588  return &result;
589  break;
590 
591 
592  case DAQ_GET_MQTT_HOST:
593  result.status = daq_get_mqtt_host(outputstream);
594  outputstream.str().copy(resultstring,outputstream.str().size());
595  resultstring[outputstream.str().size()] = 0;
596  result.str = resultstring;
597  result.content = 1;
598  pthread_mutex_unlock(&M_output);
599  return &result;
600  break;
601 #endif
602 
603  case DAQ_SETRUNTYPE:
604  result.status = daq_setruntype(ab->spar,outputstream);
605  if ( result.status)
606  {
607  outputstream.str().copy(resultstring,outputstream.str().size());
608  resultstring[outputstream.str().size()] = 0;
609  result.str = resultstring;
610  result.content = 1;
611  }
612  pthread_mutex_unlock(&M_output);
613  return &result;
614  break;
615 
616  case DAQ_GETRUNTYPE:
617  result.status = daq_getruntype(ab->ipar[0], outputstream);
618  outputstream.str().copy(resultstring,outputstream.str().size());
619  resultstring[outputstream.str().size()] = 0;
620  result.str = resultstring;
621  result.content = 1;
622  pthread_mutex_unlock(&M_output);
623  return &result;
624  break;
625 
626  case DAQ_DEFINERUNTYPE:
627  daq_define_runtype(ab->spar, ab->spar2);
628  break;
629 
630  case DAQ_LISTRUNTYPES:
631  result.status = daq_list_runtypes(ab->ipar[0], outputstream);
632  outputstream.str().copy(resultstring,outputstream.str().size());
633  resultstring[outputstream.str().size()] = 0;
634  result.str = resultstring;
635  result.content = 1;
636  pthread_mutex_unlock(&M_output);
637  return &result;
638  break;
639 
640  case DAQ_GETNAME:
641  result.status = daq_get_name(outputstream);
642  outputstream.str().copy(resultstring,outputstream.str().size());
643  resultstring[outputstream.str().size()] = 0;
644  result.str = resultstring;
645  result.content = 1;
646  pthread_mutex_unlock(&M_output);
647  return &result;
648  break;
649 
650 
651  case DAQ_OPEN:
652  result.status = daq_open(outputstream);
653  if (result.status)
654  {
655  outputstream.str().copy(resultstring,outputstream.str().size());
656  resultstring[outputstream.str().size()] = 0;
657  result.str = resultstring;
658  result.content = 1;
659  }
660  pthread_mutex_unlock(&M_output);
661  return &result;
662  break;
663 
664  case DAQ_SET_SERVER:
665  result.status = daq_set_server(ab->spar, ab->ipar[0], outputstream);
666  if (result.status)
667  {
668  outputstream.str().copy(resultstring,outputstream.str().size());
669  resultstring[outputstream.str().size()] = 0;
670  result.str = resultstring;
671  result.content = 1;
672  }
673  pthread_mutex_unlock(&M_output);
674  return &result;
675  break;
676 
677  case DAQ_CLOSE:
678  result.status = daq_close(outputstream);
679  if (result.status)
680  {
681  outputstream.str().copy(resultstring,outputstream.str().size());
682  resultstring[outputstream.str().size()] = 0;
683  result.str = resultstring;
684  result.content = 1;
685  }
686  pthread_mutex_unlock(&M_output);
687  return &result;
688  break;
689 
690  case DAQ_SET_COMPRESSION:
691  result.status = daq_set_compression ( ab->ipar[0], outputstream);
692  outputstream.str().copy(resultstring,outputstream.str().size());
693  resultstring[outputstream.str().size()] = 0;
694  result.str = resultstring;
695  result.content = 1;
696  pthread_mutex_unlock(&M_output);
697  return &result;
698  break;
699 
700 
701 
702  case DAQ_FAKETRIGGER:
703  result.status = daq_fake_trigger (ab->ipar[0], ab->ipar[1]);
704  break;
705 
706  case DAQ_LISTREADLIST:
707  result.status = daq_list_readlist(outputstream);
708  outputstream.str().copy(resultstring,outputstream.str().size());
709  resultstring[outputstream.str().size()] = 0;
710  result.str = resultstring;
711  result.content = 1;
712  pthread_mutex_unlock(&M_output);
713  return &result;
714  break;
715 
716  case DAQ_CLEARREADLIST:
717  result.status = daq_clear_readlist(outputstream);
718  outputstream.str().copy(resultstring,outputstream.str().size());
719  resultstring[outputstream.str().size()] = 0;
720  result.str = resultstring;
721  result.content = 1;
722  pthread_mutex_unlock(&M_output);
723  return &result;
724  break;
725 
726  case DAQ_STATUS:
727  result.status = daq_status(ab->ipar[0], outputstream);
728  outputstream.str().copy(resultstring,outputstream.str().size());
729  resultstring[outputstream.str().size()] = 0;
730  result.str = resultstring;
731  result.content = 1;
732  pthread_mutex_unlock(&M_output);
733  return &result;
734  break;
735 
736  case DAQ_SETMAXEVENTS:
737  result.status = daq_setmaxevents ( ab->ipar[0], outputstream);
738  if (result.status)
739  {
740  outputstream.str().copy(resultstring,outputstream.str().size());
741  resultstring[outputstream.str().size()] = 0;
742  result.str = resultstring;
743  result.content = 1;
744  }
745  pthread_mutex_unlock(&M_output);
746  return &result;
747  break;
748 
749  case DAQ_SETMAXVOLUME:
750  result.status = daq_setmaxvolume ( ab->ipar[0], outputstream);
751  if (result.status)
752  {
753  outputstream.str().copy(resultstring,outputstream.str().size());
754  resultstring[outputstream.str().size()] = 0;
755  result.str = resultstring;
756  result.content = 1;
757  }
758  pthread_mutex_unlock(&M_output);
759  return &result;
760  break;
761 
762  case DAQ_ROLLOVERLIMIT:
763  result.status = daq_setrolloverlimit ( ab->ipar[0], outputstream);
764  if (result.status)
765  {
766  outputstream.str().copy(resultstring,outputstream.str().size());
767  resultstring[outputstream.str().size()] = 0;
768  result.str = resultstring;
769  result.content = 1;
770  }
771  pthread_mutex_unlock(&M_output);
772  return &result;
773  break;
774 
776  result.status = daq_setmaxbuffersize ( ab->ipar[0], outputstream);
777  if (result.status)
778  {
779  outputstream.str().copy(resultstring,outputstream.str().size());
780  resultstring[outputstream.str().size()] = 0;
781  result.str = resultstring;
782  result.content = 1;
783  }
784  pthread_mutex_unlock(&M_output);
785  return &result;
786  break;
787 
789  result.status = daq_setadaptivebuffering ( ab->ipar[0], outputstream);
790  if (result.status)
791  {
792  outputstream.str().copy(resultstring,outputstream.str().size());
793  resultstring[outputstream.str().size()] = 0;
794  result.str = resultstring;
795  result.content = 1;
796  }
797  pthread_mutex_unlock(&M_output);
798  return &result;
799  break;
800 
801 
802  case DAQ_ELOG:
803  daq_set_eloghandler( ab->spar, ab->ipar[0], ab->spar2);
804  break;
805 
806  case DAQ_LOAD:
807  result.status = daq_load_plugin( ab->spar, outputstream );
808  if (result.status)
809  {
810  outputstream.str().copy(resultstring,outputstream.str().size());
811  resultstring[outputstream.str().size()] = 0;
812  result.str = resultstring;
813  result.content = 1;
814  }
815  pthread_mutex_unlock(&M_output);
816  return &result;
817  break;
818 
819  case DAQ_WEBCONTROL:
820  result.status = daq_webcontrol ( ab->ipar[0], outputstream);
821  outputstream.str().copy(resultstring,outputstream.str().size());
822  resultstring[outputstream.str().size()] = 0;
823  result.str = resultstring;
824  result.content = 1;
825  pthread_mutex_unlock(&M_output);
826  return &result;
827  break;
828 
829  case DAQ_GETLASTFILENAME:
830  result.status = daq_getlastfilename ( outputstream);
831  if ( result.status )
832  {
833  pthread_mutex_unlock(&M_output);
834  result.content = 0;
835  return &result;
836  }
837  outputstream.str().copy(resultstring,outputstream.str().size());
838  resultstring[outputstream.str().size()] = 0;
839  result.str = resultstring;
840  result.content = 1;
841  pthread_mutex_unlock(&M_output);
842  return &result;
843  break;
844 
846  result.what = daq_getlastevent_number ( outputstream);
847  outputstream.str().copy(resultstring,outputstream.str().size());
848  resultstring[outputstream.str().size()] = 0;
849  result.str = resultstring;
850  result.content = 1;
851  result.status = 0;
852  pthread_mutex_unlock(&M_output);
853  return &result;
854  break;
855 
856  case DAQ_SETEVENTFORMAT:
857  result.status = daq_setEventFormat ( ab->ipar[0], outputstream);
858  if (result.status)
859  {
860  outputstream.str().copy(resultstring,outputstream.str().size());
861  resultstring[outputstream.str().size()] = 0;
862  result.str = resultstring;
863  result.content = 1;
864  }
865  pthread_mutex_unlock(&M_output);
866  return &result;
867  break;
868 
870  result.status = daq_setRunControlMode ( ab->ipar[0], outputstream);
871  if (result.status)
872  {
873  outputstream.str().copy(resultstring,outputstream.str().size());
874  resultstring[outputstream.str().size()] = 0;
875  result.str = resultstring;
876  result.content = 1;
877  }
878  pthread_mutex_unlock(&M_output);
879  return &result;
880  break;
881 
883  result.status = daq_getRunControlMode (outputstream);
884  outputstream.str().copy(resultstring,outputstream.str().size());
885  resultstring[outputstream.str().size()] = 0;
886  result.str = resultstring;
887  result.content = 1;
888  pthread_mutex_unlock(&M_output);
889  return &result;
890  break;
891 
892  default:
893  strcpy(resultstring, "Unknown action");
894  result.content = 1;
895  result.status = 1;
896  break;
897 
898  }
899 
900  pthread_mutex_unlock(&M_output);
901  return &result;
902 
903 
904 }
905 
906 shortResult * r_shutdown_1_svc(void *x, struct svc_req *rqstp)
907 {
908 
909  static shortResult result;
910 
911  static std::ostringstream outputstream;
912 
913  static char resultstring[256];
914 
915  pthread_mutex_lock(&M_output);
916 
917 
918  result.content = 0;
919  result.what = 0;
920  result.status = 0;
921 
922  outputstream.str("");
923 
924  result.str = (char *) outputstream.str().c_str();
925 
926  result.status = daq_shutdown ( my_servernumber, RCDAQ_VERS, pid_fd, outputstream);
927  cout << "daq_shutdown status = " << result.status << endl;
928  if (result.status)
929  {
930  outputstream.str().copy(resultstring,outputstream.str().size());
931  resultstring[outputstream.str().size()] = 0;
932  result.str = resultstring;
933  result.content = 1;
934  }
935  pthread_mutex_unlock(&M_output);
936  return &result;
937 
938 }
939 
940 //-------------------------------------------------------------
941 
942 
943 int
944 main (int argc, char **argv)
945 {
946 
947  int servernumber = 0;
948 
949  mode_t mask = umask(0);
950  int i = mkdir ( "/tmp/rcdaq", 0777);
951  if ( i && errno != EEXIST)
952  {
953  std::cerr << "Error accessing the lock directory /tmp/rcdaq" << std::endl;
954  return 2;
955  }
956 
957  umask(mask);
958 
959  if ( argc > 1)
960  {
961  servernumber = get_value(argv[1]);
962  }
963 
965 
966  sprintf (pidfilename, "/tmp/rcdaq/rcdaq_%d", servernumber);
967 
968  pid_fd = open(pidfilename, O_CREAT | O_RDWR, 0666);
969  if ( pid_fd < 0)
970  {
971 
972  ifstream pidfile = ifstream(pidfilename);
973  if ( pidfile.is_open())
974  {
975  int ipid;
976  pidfile >> ipid;
977  std::cerr << "Another server is already running, PID= " << ipid << std::endl;
978  return 2;
979  }
980 
981  std::cerr << "Error creating the lock file" << std::endl;
982  return 2;
983  }
984 
985  int rc = flock(pid_fd, LOCK_EX | LOCK_NB);
986  if(rc)
987  {
988  if (errno == EWOULDBLOCK)
989  {
990  ifstream pidfile = ifstream(pidfilename);
991  if ( pidfile.is_open())
992  {
993  int ipid;
994  pidfile >> ipid;
995  std::cerr << "Another server is already running, PID= " << ipid << std::endl;
996  return 3;
997  }
998 
999  std::cerr << "Another server is already running" << std::endl;
1000  return 3;
1001  }
1002  }
1003 
1004  // we write out pid in here, for good measure
1005  char pid[64];
1006  int x = sprintf(pid,"%d\n", getpid());
1007  write (pid_fd, pid, x);
1008 
1009 
1010  std::cout << "Server number is " << servernumber << std::endl;
1011 
1012  signal(SIGKILL, sig_handler);
1013  signal(SIGTERM, sig_handler);
1014  signal(SIGINT, sig_handler);
1015 
1016 
1017  pthread_mutex_init(&M_output, 0);
1018 
1019  rcdaq_init( servernumber, M_output);
1020 
1021  my_servernumber = RCDAQ+servernumber; // remember who we are for later
1022 
1023  SVCXPRT *transp;
1024 
1025  pmap_unset (my_servernumber, RCDAQ_VERS);
1026 
1027  transp = svctcp_create(RPC_ANYSOCK, 0, 0);
1028  if (transp == NULL) {
1029  fprintf (stderr, "%s", "cannot create tcp service.");
1030  exit(1);
1031  }
1032  if (!svc_register(transp, my_servernumber, RCDAQ_VERS, rcdaq_1, IPPROTO_TCP)) {
1033  fprintf (stderr, "%s", "unable to register (RCDAQ+servernumber, RCDAQ_VERS, tcp).");
1034  exit(1);
1035  }
1036 
1037  // char hostname[1024];
1038  // gethostname(hostname, 1024);
1039  // daq_set_name(hostname);
1040 
1041  svc_run ();
1042  fprintf (stderr, "%s", "svc_run returned");
1043  exit (1);
1044  /* NOTREACHED */
1045 }
1046