| 1 | /**************************************************************\
 | 
|---|
| 2 | 
 | 
|---|
| 3 |   drsdaq
 | 
|---|
| 4 | 
 | 
|---|
| 5 |   Main program for data acquisition, starts threads for console input.
 | 
|---|
| 6 |   
 | 
|---|
| 7 |   Original program by S. Commichau.
 | 
|---|
| 8 |   
 | 
|---|
| 9 |   Oliver Grimm, May 2010
 | 
|---|
| 10 |  
 | 
|---|
| 11 | \**************************************************************/
 | 
|---|
| 12 | 
 | 
|---|
| 13 | #define LOCKFILE "/tmp/CT3_DAQ_LOCK"
 | 
|---|
| 14 | 
 | 
|---|
| 15 | #include <stdio.h>
 | 
|---|
| 16 | #include <signal.h>
 | 
|---|
| 17 | #include <readline/readline.h>
 | 
|---|
| 18 | #include <readline/history.h>
 | 
|---|
| 19 | 
 | 
|---|
| 20 | #include "DAQReadout.h"
 | 
|---|
| 21 | 
 | 
|---|
| 22 | // Function prototypes
 | 
|---|
| 23 | void CrashHandler(int);
 | 
|---|
| 24 | void ExitFunction();
 | 
|---|
| 25 | 
 | 
|---|
| 26 | // ================
 | 
|---|
| 27 | //   Main program
 | 
|---|
| 28 | // ================
 | 
|---|
| 29 | //
 | 
|---|
| 30 | // Several unlikely system call failures are handled via throwing an exception.
 | 
|---|
| 31 | 
 | 
|---|
| 32 | int main() {
 | 
|---|
| 33 | 
 | 
|---|
| 34 |   char str[MAX_COM_SIZE], *Command;
 | 
|---|
| 35 |   int LockDescriptor;
 | 
|---|
| 36 | 
 | 
|---|
| 37 |   // Assure only one instance of program runs (lock creator written to log file)
 | 
|---|
| 38 |   // Lock file deleted by destructor
 | 
|---|
| 39 |   if((LockDescriptor = open(LOCKFILE,O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1) {
 | 
|---|
| 40 |     if(errno==EEXIST) {
 | 
|---|
| 41 |       printf("Error: Lock file already existing\n");
 | 
|---|
| 42 |       snprintf(str, sizeof(str), "paste %s -s -d ' '",LOCKFILE);
 | 
|---|
| 43 |       system(str);
 | 
|---|
| 44 |     }
 | 
|---|
| 45 |     else printf("Could not create lock file %s (%s)\n", LOCKFILE, strerror(errno));
 | 
|---|
| 46 |     exit(EXIT_FAILURE);
 | 
|---|
| 47 |   }
 | 
|---|
| 48 |   close(LockDescriptor);
 | 
|---|
| 49 |   sprintf(str,"echo Created >%s; date >>%s; echo by $USER@$HOSTNAME >>%s",LOCKFILE,LOCKFILE,LOCKFILE);
 | 
|---|
| 50 |   system(str);
 | 
|---|
| 51 | 
 | 
|---|
| 52 |   // Readline library uses getc() (allows interruption by signal)
 | 
|---|
| 53 |   rl_getc_function = getc;
 | 
|---|
| 54 | 
 | 
|---|
| 55 |   // writev() in DAQ thread needs to be able to write at least 3 chunks
 | 
|---|
| 56 |   if(IOV_MAX < 2) {
 | 
|---|
| 57 |         printf("Fatal error: IOV_MAX is less than 2, cannot use writev() to write event data.\n");
 | 
|---|
| 58 |         exit(EXIT_FAILURE);
 | 
|---|
| 59 |   }
 | 
|---|
| 60 |      
 | 
|---|
| 61 |   system("clear");
 | 
|---|
| 62 |   printf("\n*** DRS readout (built %s, %s, revision %s) *** \n\n",__DATE__, __TIME__, REVISION);
 | 
|---|
| 63 | 
 | 
|---|
| 64 |   // Set exit function
 | 
|---|
| 65 |   atexit(&ExitFunction);
 | 
|---|
| 66 | 
 | 
|---|
| 67 |   // Construct main instance (static ensures destructor is called with exit())
 | 
|---|
| 68 |   static DAQReadout M;
 | 
|---|
| 69 | 
 | 
|---|
| 70 |   // Set signal handlers
 | 
|---|
| 71 |   signal(SIGILL, &CrashHandler);
 | 
|---|
| 72 |   signal(SIGABRT, &CrashHandler);
 | 
|---|
| 73 |   signal(SIGFPE, &CrashHandler);
 | 
|---|
| 74 |   signal(SIGSEGV, &CrashHandler);
 | 
|---|
| 75 |   signal(SIGBUS, &CrashHandler);
 | 
|---|
| 76 | 
 | 
|---|
| 77 |   // Command loop
 | 
|---|
| 78 |   while (!M.ExitRequest) {
 | 
|---|
| 79 |     // Assemble prompt
 | 
|---|
| 80 |     if (M.NumBoards == 0) snprintf(M.Prompt,sizeof(M.Prompt),"\rDAQ> "); 
 | 
|---|
| 81 |     else if (M.FirstBoard == M.LastBoard) snprintf(M.Prompt,sizeof(M.Prompt),"\rDAQ|B%d> ",M.FirstBoard); 
 | 
|---|
| 82 |     else snprintf(M.Prompt,sizeof(M.Prompt),"\rDAQ|B%d-%d> ",M.FirstBoard,M.LastBoard); 
 | 
|---|
| 83 | 
 | 
|---|
| 84 |     // Read Command
 | 
|---|
| 85 |     Command = readline(M.Prompt);
 | 
|---|
| 86 |     if (Command == NULL) continue;
 | 
|---|
| 87 |     if(strlen(Command)>0) add_history(Command);
 | 
|---|
| 88 | 
 | 
|---|
| 89 |     // Process command
 | 
|---|
| 90 |         DimClient::sendCommand(SERVER_NAME"/Command", Command);
 | 
|---|
| 91 |     free(Command);
 | 
|---|
| 92 |   }
 | 
|---|
| 93 | }
 | 
|---|
| 94 | 
 | 
|---|
| 95 | 
 | 
|---|
| 96 | // Remove lock file before running default signal code
 | 
|---|
| 97 | void CrashHandler(int Signal) {
 | 
|---|
| 98 | 
 | 
|---|
| 99 |   remove(LOCKFILE);
 | 
|---|
| 100 |   printf("Caught signal number %d. Removed lockfile and performing standard signal action. Good luck.\n",Signal);
 | 
|---|
| 101 |   signal(Signal, SIG_DFL);
 | 
|---|
| 102 |   raise(Signal);
 | 
|---|
| 103 | }
 | 
|---|
| 104 | 
 | 
|---|
| 105 | // This function will be implicitly called by exit()
 | 
|---|
| 106 | void ExitFunction() {
 | 
|---|
| 107 | 
 | 
|---|
| 108 |   if (remove(LOCKFILE) == -1) {
 | 
|---|
| 109 |     printf("Could not remove lock file %s (%s)\n", LOCKFILE, strerror(errno));
 | 
|---|
| 110 |   }
 | 
|---|
| 111 | }
 | 
|---|