Automatic commit of irc logs
[matches/MCTX3420.git] / server / main.c
1 /**
2  * @file main.c
3  * @brief main and its helper functions, signal handling and cleanup functions
4  */
5
6 // --- Custom headers --- //
7 #include "common.h"
8 #include "options.h"
9 #include "sensor.h"
10 #include "actuator.h"
11 #include "control.h"
12 #include "pin_test.h"
13 #include "bbb_pin_defines.h"
14
15 // --- Standard headers --- //
16 #include <syslog.h> // for system logging
17 #include <signal.h> // for signal handling
18
19
20 #ifdef REALTIME_VERSION
21 #include <time.h>
22 #include <sched.h>
23 #include <sys/mman.h>
24 #include <sys/utsname.h>
25 #endif //REALTIME_VERSION
26
27 // --- Variable definitions --- //
28 Options g_options; // options passed to program through command line arguments
29
30 // --- Function definitions --- //
31
32 /**
33  * Parse command line arguments, initialise g_options
34  * @param argc - Number of arguments
35  * @param argv - Array of argument strings
36  */
37 void ParseArguments(int argc, char ** argv)
38 {
39         g_options.program = argv[0]; // program name
40         g_options.verbosity = LOGDEBUG; // default log level
41         // Set the main directory
42         //if (getcwd(g_options.root_dir, sizeof(g_options.root_dir)) == NULL)
43         //      Fatal("Couldn't get current working directory - %s", strerror(errno));
44
45         clock_gettime(CLOCK_MONOTONIC, &(g_options.start_time)); // Start time
46
47
48         g_options.auth_method = AUTH_NONE;  // Don't use authentication
49         g_options.auth_uri = ""; // 
50         g_options.ldap_base_dn = "";
51         g_options.experiment_dir = ".";
52         
53         for (int i = 1; i < argc; ++i)
54         {
55                 if (argv[i][0] != '-')
56                         Fatal("Unexpected argv[%d] - %s", i, argv[i]);
57
58                 if (i+1 >= argc || argv[i+1][0] == '-')
59                         Fatal("No argument following switch %s", argv[i]);
60                 
61                 if (strlen(argv[i]) > 2)
62                         Fatal("Human readable switches are not supported.");
63
64                 char * end = NULL;
65                 switch (argv[i][1])
66                 {
67                         // Set program verbosity
68                         case 'v':
69                                 g_options.verbosity = strtol(argv[++i], &end, 10);
70                                 break;
71                         // Enable/Disable pin test
72                         case 'p':
73                                 g_options.enable_pin = !(strtol(argv[++i], &end, 10));
74                                 break;
75                         // LDAP URI
76                         case 'A':
77                                 g_options.auth_uri = argv[++i];
78                                 break;
79                         // LDAP DN
80                         case 'd':
81                                 g_options.ldap_base_dn = argv[++i];
82                                 break;
83                         case 'e':
84                         // Experiments directory
85                                 g_options.experiment_dir = argv[++i];
86                                 break;
87                         default:
88                                 Fatal("Unrecognised switch %s", argv[i]);
89                                 break;
90                 }
91
92                 if (end != NULL && *end != '\0')
93                         Fatal("argv[%d] -%c requires an integer (got \"%s\" instead)", i-1, argv[i-1][0], argv[i]);
94         }       
95
96         Log(LOGDEBUG, "Verbosity: %d", g_options.verbosity);
97         Log(LOGDEBUG, "Pin Module Enabled: %d", g_options.enable_pin);
98         Log(LOGDEBUG, "Auth URI: %s", g_options.auth_uri);
99         Log(LOGDEBUG, "LDAP Base DN: %s", g_options.ldap_base_dn);
100         //Log(LOGDEBUG, "Root directory: %s", g_options.root_dir);
101         Log(LOGDEBUG, "Experiment directory: %s", g_options.experiment_dir);
102
103         if (!DirExists(g_options.experiment_dir))
104         {
105                 Fatal("Experiment directory '%s' does not exist.", g_options.experiment_dir);
106         }
107
108         if (g_options.auth_uri[0] != '\0')
109         {
110                 //HACK...
111                 if (PathExists(g_options.auth_uri))
112                         g_options.auth_method = AUTH_SHADOW;
113                 else
114                         g_options.auth_method = AUTH_LDAP;
115         }
116         
117 }
118
119 /**
120  * Cleanup before the program exits
121  */
122 void Cleanup()
123 {
124         Log(LOGDEBUG, "Begin cleanup.");
125         Sensor_Cleanup();
126         Actuator_Cleanup();
127         Log(LOGDEBUG, "Finish cleanup.");
128 }
129
130
131 #ifdef REALTIME_VERSION
132
133 #define MAX_SAFE_STACK (8*1024)
134 #define NSEC_PER_SEC (1000000000)
135
136 void stack_prefault()
137 {
138         unsigned char dummy[MAX_SAFE_STACK];
139         memset(dummy, 0, MAX_SAFE_STACK);
140         return;
141 }
142
143 bool is_realtime()
144 {
145         struct utsname u;
146         bool crit1 = 0;
147         bool crit2 = 0;
148         FILE * f;
149         uname(&u);
150         crit1 = (strcasestr(u.version, "PREEMPT RT") != NULL);
151         if (crit1 && ((f = fopen("/sys/kernel/realtime", "r")) != NULL))
152         {
153                 int flag;
154                 crit2 = ((fscanf(f, "%d", &flag) == 1) && (flag == 1));
155                 fclose(f);
156         }
157         return (crit1 && crit2);
158 }
159
160 #endif //REALTIME_VERSION
161
162 /**
163  * Main entry point; start worker threads, setup signal handling, wait for threads to exit, exit
164  * @param argc - Num args
165  * @param argv - Args
166  * @returns 0 on success, error code on failure
167  * NOTE: NEVER USE exit(3)! Instead call Thread_QuitProgram
168  */
169 int main(int argc, char ** argv)
170 {
171
172         // Open log before calling ParseArguments (since ParseArguments may call the Log functions)
173         openlog("mctxserv", LOG_PID | LOG_PERROR, LOG_USER);
174
175         ParseArguments(argc, argv); // Setup the g_options structure from program arguments
176
177         Log(LOGINFO, "Server started");
178
179
180         
181         #ifdef REALTIME_VERSION
182         
183         if (is_realtime())
184         {
185                 Log(LOGDEBUG, "Running under realtime kernel");
186         }
187         else
188         {
189                 Fatal("Not running under realtime kernel");
190         }
191         struct sched_param param;
192         param.sched_priority = 49;
193         if (sched_setscheduler(0, SCHED_FIFO, &param) < 0)
194                 Fatal("sched_setscheduler failed - %s", strerror(errno));
195         if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
196                 Fatal("mlockall failed - %s", strerror(errno));
197         stack_prefault();
198         #endif //REALTIME_VERSION
199
200         
201
202         Pin_Init();
203         
204         // Try and start things
205         
206         //const char *ret;
207         //if ((ret = Control_SetMode(CONTROL_START, "test")) != NULL)
208         //      Fatal("Control_SetMode failed with '%s'", ret);
209         
210
211         // run request thread in the main thread
212         FCGI_RequestLoop(NULL);
213
214         
215         Control_SetMode(CONTROL_STOP, NULL);
216         //if ((ret = Control_SetMode(CONTROL_STOP, "test")) != NULL)
217         //      Fatal("Control_SetMode failed with '%s'", ret);
218         
219         //Sensor_StopAll();
220         //Actuator_StopAll();
221
222         Pin_Close();
223
224         Cleanup();
225         return 0;
226 }
227
228

UCC git Repository :: git.ucc.asn.au