1 | /** \file opt.c
|
---|
2 | * Option Retrieving and debugger.
|
---|
3 | * This file contains routines that read options from command line GetOptions(),
|
---|
4 | * set the verbosity level SetOutGroup1() and individually for each process
|
---|
5 | * SetOutGroup2() and starting the various debuggers Start_cvd(), Start_dbx(),
|
---|
6 | * Start_ddd(), Start_gdb(), Start_totalview(), Start_ups(), StartDebugger().
|
---|
7 | * And deallocating the debug string FreeDebugStr().
|
---|
8 | *
|
---|
9 | * \date 1998-2000
|
---|
10 | *
|
---|
11 | * $Id: opt.c,v 1.15 2007-02-12 09:44:56 foo Exp $
|
---|
12 | */
|
---|
13 |
|
---|
14 | #ifdef HAVE_CONFIG_H
|
---|
15 | #include <config.h>
|
---|
16 | #endif
|
---|
17 |
|
---|
18 | #include<stdio.h>
|
---|
19 | #include<stdlib.h>
|
---|
20 | #include<string.h>
|
---|
21 | #include<unistd.h>
|
---|
22 | #include<sys/utsname.h>
|
---|
23 | #include"data.h"
|
---|
24 | #include"helpers.h"
|
---|
25 | #include"opt.h"
|
---|
26 |
|
---|
27 | static char *DebugString = NULL; //!< command line option
|
---|
28 | static char *program_name = NULL;//<! copy of argv[0]
|
---|
29 | static int debugger_started = 0; //!< "debugger been started?"-flag (0 - no, 1 - yes)
|
---|
30 |
|
---|
31 | /** Free debug string memory .
|
---|
32 | * Frees memory for DebugString and program_name
|
---|
33 | */
|
---|
34 | static void FreeDebugStr(void) {
|
---|
35 | if (DebugString) Free(DebugString, "FreeDebugStr: DebugString");
|
---|
36 | if (program_name) Free(program_name, "FreeDebugStr: program_name");
|
---|
37 | }
|
---|
38 |
|
---|
39 | /*extern char *optarg;
|
---|
40 | extern int optind;*/
|
---|
41 |
|
---|
42 | /** Reads options from commandline and fills \ref CallOptions.
|
---|
43 | * uses getopt in order to retrieve options from command line, including
|
---|
44 | * most importantly the main paramter file. The rest is just verbosity,
|
---|
45 | * debugging, alarm timer and source file for restarting calculations.\n
|
---|
46 | * Also usage is printed on request
|
---|
47 | *
|
---|
48 | * \param *Call \ref CallOptions structure to be filled
|
---|
49 | * \param argc argument count and ...
|
---|
50 | * \param argv[] .. argument const char array right from command line
|
---|
51 | */
|
---|
52 | void GetOptions(struct CallOptions *Call, int argc, char *const argv[]) {
|
---|
53 | /* parsen der Kommandozeile */
|
---|
54 | int c, errflg = 0;
|
---|
55 |
|
---|
56 | /* defaults setzen */
|
---|
57 | Call->MainParameterFile = NULL;
|
---|
58 | Call->ForcesFile = NULL;
|
---|
59 | Call->debug = 0;
|
---|
60 | Call->nicelevel = 0;
|
---|
61 | Call->Out = 0;
|
---|
62 | Call->alarm = 0;
|
---|
63 | Call->proc[PEPsi] = 0;
|
---|
64 | Call->proc[PEGamma] = 0;
|
---|
65 | Call->ReadSrcFiles = DoNotParse;
|
---|
66 | Call->WriteSrcFiles = 0;
|
---|
67 | Call->AddNFactor = 1;
|
---|
68 |
|
---|
69 | while ((c = getopt(argc, argv, "a:d:D:hn:o:p:m:rvwxF:")) != -1) {
|
---|
70 | switch (c) {
|
---|
71 | case 'a':
|
---|
72 | Call->alarm = abs(atoi(optarg));
|
---|
73 | break;
|
---|
74 | case 'd':
|
---|
75 | if (DebugString) Free(DebugString, "GetOptions: DebugString");
|
---|
76 | Call->debug = 1;
|
---|
77 | DebugString = (char *)Malloc(strlen(optarg)+1, "GetOptions");
|
---|
78 | strcpy(DebugString, optarg);
|
---|
79 | break;
|
---|
80 | case 'D':
|
---|
81 | if (DebugString) Free(DebugString, "GetOptions: DebugString");
|
---|
82 | DebugString = (char *)Malloc(strlen(optarg)+1, "GetOptions");
|
---|
83 | strcpy(DebugString, optarg);
|
---|
84 | Call->debug = 2;
|
---|
85 | break;
|
---|
86 | case 'h':
|
---|
87 | printf("Usage: %s [-hvxrw ] [-a alarmtime] [-d debugstr|-D debugstr] [-n nicelevel] [-m addNfactor]\n","pcp");
|
---|
88 | printf(" [-o verbosity] mainparameterfile\n");
|
---|
89 | printf(" -a alarmtime Sets alarm to alarmtime seconds. Code will finish after\n");
|
---|
90 | printf(" next timestep, writing out the current state.\n");
|
---|
91 | printf(" -d debugstr Starts debugger right away.\n");
|
---|
92 | printf(" -D debugstr Starts debugger when encountering an error.\n");
|
---|
93 | printf(" Valid syntax for debugstr:\n");
|
---|
94 | printf(" 0 sleep for a minute, no debugger\n");
|
---|
95 | printf(" [host[:display][,debugger]] start debugger xterm on host:display\n");
|
---|
96 | printf(" (if DISPLAY is set or for local connection set host to local).\n");
|
---|
97 | printf(" Valid values for debugger are: gdb, dbx, ddd, cvd, totalview, ups.\n");
|
---|
98 | printf(" -h Displays this help page and exits successfully.\n");
|
---|
99 | printf(" -n nicelevel Decreases priority of process.\n");
|
---|
100 | printf(" -o verbosity Sets verbosity level. Deprecated, use -v instead.\n");
|
---|
101 | printf(" Possible values include: 0-5.\n");
|
---|
102 | printf(" -v Increases verbosity level by one. Default value: 0.\n");
|
---|
103 | printf(" -p n,m procs per Gamma-point, procs per psi\n");
|
---|
104 | printf(" No.of PE = n * m\n");
|
---|
105 | printf(" -r Read old src files.\n");
|
---|
106 | printf(" -w Write src files.\n");
|
---|
107 | printf(" -m f Additional NFactor - to fix read srcpsi\n");
|
---|
108 | printf(" -F file Do not calculate Hellmann-Feyman forces but read from file\n");
|
---|
109 | printf("For parallel codes it is necessary to specify the main parameter file\n");
|
---|
110 | printf("with an absolute path.\n");
|
---|
111 | exit(EXIT_SUCCESS);
|
---|
112 | case 'n':
|
---|
113 | Call->nicelevel = abs(atoi(optarg));
|
---|
114 | break;
|
---|
115 | case 'o':
|
---|
116 | Call->Out = abs(atoi(optarg));
|
---|
117 | break;
|
---|
118 | case 'p':
|
---|
119 | if (sscanf(optarg, "%d,%d", &Call->proc[PEPsi], &Call->proc[PEGamma]) < 2)
|
---|
120 | errflg++;
|
---|
121 | if (Call->proc[PEPsi] < 1 || Call->proc[PEGamma] < 1) {
|
---|
122 | fprintf(stderr, "proc[i] must be > 0\n");
|
---|
123 | errflg++;
|
---|
124 | }
|
---|
125 | break;
|
---|
126 | case 'r':
|
---|
127 | Call->ReadSrcFiles++;
|
---|
128 | break;
|
---|
129 | case 'v':
|
---|
130 | Call->Out++;
|
---|
131 | break;
|
---|
132 | case 'w':
|
---|
133 | Call->WriteSrcFiles++;
|
---|
134 | break;
|
---|
135 | case 'm':
|
---|
136 | if (sscanf(optarg, "%d", &Call->AddNFactor) < 1)
|
---|
137 | errflg++;
|
---|
138 | if (Call->AddNFactor <= 1) {
|
---|
139 | fprintf(stderr, "AddNFactor must be > 0\n");
|
---|
140 | errflg++;
|
---|
141 | }
|
---|
142 | break;
|
---|
143 | case '?':
|
---|
144 | errflg++;
|
---|
145 | break;
|
---|
146 | case 'F':
|
---|
147 | fprintf(stderr, "Recognized forces file '%s' with length %ld.\n", optarg, strlen(optarg));
|
---|
148 | Call->ForcesFile = (char *) Malloc((strlen(optarg)+2)*sizeof(char), "GetOptions: CallOptions::*ForcesFile");
|
---|
149 | strcpy(Call->ForcesFile, optarg);
|
---|
150 | fprintf(stderr, "Stored CallOptions->ForcesFile: %s\n", Call->ForcesFile);
|
---|
151 | break;
|
---|
152 | default:
|
---|
153 | fprintf(stderr, "GetOptions: getopt() returned character code O%o !?\n", c);
|
---|
154 | errflg++;
|
---|
155 | }
|
---|
156 | }
|
---|
157 | if (errflg) {
|
---|
158 | fprintf(stderr,"Usage: %s [ OPTIONS ] mainparameterfile\nTry '%s -h' for more information.\n", argv[0], argv[0]);
|
---|
159 | exit(EXIT_FAILURE);
|
---|
160 | }
|
---|
161 | if ( optind < argc - 1)
|
---|
162 | fprintf(stderr, "Warning: more than one file specified\n");
|
---|
163 | for ( ; optind < argc ; optind++) {
|
---|
164 | Call->MainParameterFile = (char *)Malloc(strlen(argv[optind])+1, "GetOptions: MainParameterFile");
|
---|
165 | strcpy(Call->MainParameterFile, argv[optind]);
|
---|
166 | }
|
---|
167 |
|
---|
168 | /* nun auswerten */
|
---|
169 | program_name = (char *)Malloc(strlen(argv[0]) + 1, "GetOptions");
|
---|
170 | strcpy(program_name, argv[0]);
|
---|
171 | if (Call->alarm) alarm(Call->alarm);
|
---|
172 | if (Call->nicelevel) nice(Call->nicelevel);
|
---|
173 | if (!Call->MainParameterFile) {
|
---|
174 | fprintf(stderr, "Did not specify a main parameter file.\n");
|
---|
175 | exit(EXIT_FAILURE);
|
---|
176 | }
|
---|
177 | atexit(FreeDebugStr); /* nachher aufraeumen */
|
---|
178 | }
|
---|
179 |
|
---|
180 | /** Starts DDD Debugger.
|
---|
181 | * Via a system call the debugger is started with certain paramaters
|
---|
182 | * \param *Host hostname (if not specified, then launched via \a pid)
|
---|
183 | * \param *program program name
|
---|
184 | * \param pid Process ID of te program
|
---|
185 | * \return return value of launched debugger
|
---|
186 | */
|
---|
187 | static int Start_ddd(char *Host, char *program, pid_t pid) {
|
---|
188 | char s[MAXSTRINGSIZE];
|
---|
189 | if (Host) sprintf(s, "ddd -display %s %s %ld &", Host, program, (long int)pid);
|
---|
190 | else sprintf(s, "ddd %s %ld &", program, (long int)pid);
|
---|
191 | return system(s);
|
---|
192 | }
|
---|
193 |
|
---|
194 | /** Starts GDB Debugger.
|
---|
195 | * Via a system call the debugger is started with certain paramaters
|
---|
196 | * \param *Host hostname (if not specified, then launched via \a pid)
|
---|
197 | * \param *program program name
|
---|
198 | * \param pid Process ID of te program
|
---|
199 | * \return return value of launched debugger
|
---|
200 | */
|
---|
201 | static int Start_gdb(char *Host, char *program, pid_t pid) {
|
---|
202 | char s[MAXSTRINGSIZE];
|
---|
203 | if (Host) sprintf(s, "xterm -display %s -e gdb %s %ld &", Host, program, (long int)pid);
|
---|
204 | else sprintf(s, "xterm -e gdb %s %ld &", program, (long int)pid);
|
---|
205 | return system(s);
|
---|
206 | }
|
---|
207 |
|
---|
208 | /** Starts DBX Debugger.
|
---|
209 | * Via a system call the debugger is started with certain paramaters
|
---|
210 | * \param *Host hostname (if not specified, then launched via \a pid)
|
---|
211 | * \param *program program name
|
---|
212 | * \param pid Process ID of te program
|
---|
213 | * \return return value of launched debugger
|
---|
214 | */
|
---|
215 | static int Start_dbx(char *Host, char *program, pid_t pid) {
|
---|
216 | char s[MAXSTRINGSIZE];
|
---|
217 | program = program;
|
---|
218 | if (Host) sprintf(s, "xterm -display %s -e dbx -p %ld &", Host, (long int)pid);
|
---|
219 | else sprintf(s, "xterm -e dbx -p %ld &", (long int)pid);
|
---|
220 | return system(s);
|
---|
221 | }
|
---|
222 |
|
---|
223 | /** Starts CVD Debugger.
|
---|
224 | * Via a system call the debugger is started with certain paramaters
|
---|
225 | * \param *Host hostname (if not specified, then launched via \a pid)
|
---|
226 | * \param *program program name
|
---|
227 | * \param pid Process ID of te program
|
---|
228 | * \return return value of launched debugger
|
---|
229 | */
|
---|
230 | static int Start_cvd(char *Host, char *program, pid_t pid) {
|
---|
231 | char s[MAXSTRINGSIZE];
|
---|
232 | program = program;
|
---|
233 | if (Host) sprintf(s, "cvd -pid %ld -display %s &", (long int)pid, Host);
|
---|
234 | else sprintf(s, "cvd -pid %ld &", (long int)pid);
|
---|
235 | return system(s);
|
---|
236 | }
|
---|
237 |
|
---|
238 | /** Starts Totalview Debugger.
|
---|
239 | * Via a system call the debugger is started with certain paramaters
|
---|
240 | * \param *Host hostname (if not specified, then launched via \a pid)
|
---|
241 | * \param *program program name
|
---|
242 | * \param pid Process ID of te program
|
---|
243 | * \return return value of launched debugger
|
---|
244 | */
|
---|
245 | static int Start_totalview(char *Host, char *program, pid_t pid) {
|
---|
246 | char s[MAXSTRINGSIZE];
|
---|
247 | int myrank = 0;
|
---|
248 | MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
|
---|
249 | if (myrank) return 0; /* nur einmal totalview aufrufen */
|
---|
250 | if (Host) sprintf(s, "totalview -display %s -p %ld %s &", Host, (long int)pid, program);
|
---|
251 | else sprintf(s, "totalview -p %ld %s &", (long int)pid, program);
|
---|
252 | return system(s);
|
---|
253 | }
|
---|
254 |
|
---|
255 | /** Starts UPS Debugger.
|
---|
256 | * Via a system call the debugger is started with certain paramaters
|
---|
257 | * \param *Host hostname (if not specified, then launched via \a pid)
|
---|
258 | * \param *program program name
|
---|
259 | * \param pid Process ID of te program
|
---|
260 | * \return return value of launched debugger
|
---|
261 | */
|
---|
262 | static int Start_ups(char *Host, char *program, pid_t pid) {
|
---|
263 | char s[MAXSTRINGSIZE];
|
---|
264 | if (Host) sprintf(s, "ups -display %s %s %ld &", Host, program, (long int)pid);
|
---|
265 | else sprintf(s, "ups %s %ld &", program, (long int)pid);
|
---|
266 | return system(s);
|
---|
267 | }
|
---|
268 |
|
---|
269 | /** Starts debugger.
|
---|
270 | * Tries to start a certain debugger, specified either via command line
|
---|
271 | * or educatedly guessed (having a list of typical ones), waits a minute
|
---|
272 | * in order to let the debugger have time for its pre-activities
|
---|
273 | *
|
---|
274 | * \warning no mallocs in this routine, no \ref Error
|
---|
275 | */
|
---|
276 | void StartDebugger(void) {
|
---|
277 | char Host[MAXSTRINGSIZE] = "", Debugger[MAXSTRINGSIZE] = "";
|
---|
278 | char *host_ptr = Host;
|
---|
279 | int (*Debugger_call) (char *, char *, pid_t);
|
---|
280 | struct utsname op;
|
---|
281 |
|
---|
282 | if (debugger_started || !DebugString)
|
---|
283 | return; /* nicht starten, falls kein -d oder -D, nicht zweimal starten */
|
---|
284 | debugger_started = 1;
|
---|
285 |
|
---|
286 | if (strcmp(DebugString, "0")) {
|
---|
287 | /* debugger soll aus Programm heraus gestartet werden */
|
---|
288 | if (!system(NULL)) {
|
---|
289 | fprintf(stderr,"StartDebugger: No shell available\n");
|
---|
290 | exit(EXIT_FAILURE);
|
---|
291 | }
|
---|
292 | switch (sscanf(DebugString, " %197[a-zA-Z0-9._:-],%199s", Host, Debugger)) {
|
---|
293 | case 2:
|
---|
294 | if (!strcmp(Debugger, "ddd")) Debugger_call = Start_ddd;
|
---|
295 | else if (!strcmp(Debugger, "gdb")) Debugger_call = Start_gdb;
|
---|
296 | else if (!strcmp(Debugger, "dbx")) Debugger_call = Start_dbx;
|
---|
297 | else if (!strcmp(Debugger, "cvd")) Debugger_call = Start_cvd;
|
---|
298 | else if (!strcmp(Debugger, "totalview")) Debugger_call = Start_totalview;
|
---|
299 | else if (!strcmp(Debugger, "ups")) Debugger_call = Start_ups;
|
---|
300 | else {
|
---|
301 | fprintf(stderr, "StartDebugger: debugger %s not supported.\n", Debugger);
|
---|
302 | exit(EXIT_FAILURE);
|
---|
303 | }
|
---|
304 | break;
|
---|
305 | case 0:
|
---|
306 | host_ptr = NULL; /* no -display */
|
---|
307 | case 1:
|
---|
308 | /* try to set debugger smart ;-) */
|
---|
309 | if (uname(&op) == -1) {
|
---|
310 | perror("StartDebugger: uname failed");
|
---|
311 | exit(EXIT_FAILURE);
|
---|
312 | }
|
---|
313 | if (!strncmp(op.sysname, "Linux", 5) || !strncmp(op.sysname, "linux", 5)) Debugger_call = Start_gdb;
|
---|
314 | else if (!strncmp(op.sysname, "IRIX", 4)) Debugger_call = Start_cvd;
|
---|
315 | else if (!strncmp(op.sysname, "sn", 2)) Debugger_call = Start_totalview;
|
---|
316 | else Debugger_call = Start_gdb;
|
---|
317 | break;
|
---|
318 | default:
|
---|
319 | fprintf(stderr, "StartDebugger: could not read debugstring.\n");
|
---|
320 | exit(EXIT_FAILURE);
|
---|
321 | }
|
---|
322 | if (!strcmp(Host, "local")) host_ptr = NULL; /* no -display */
|
---|
323 | else if (!strchr(Host, ':')) strcat(Host, ":0"); /* kein :0 gesetzt */
|
---|
324 | if (Debugger_call(host_ptr, program_name, getpid())) {
|
---|
325 | fprintf(stderr, "StartDebugger: could not start %s on %s\n", Debugger, Host);
|
---|
326 | exit(EXIT_FAILURE);
|
---|
327 | }
|
---|
328 | }
|
---|
329 | sleep(60); /* danach sollte der Debugger gestartet sein */
|
---|
330 | }
|
---|
331 |
|
---|
332 | /** Sets verbosity individually for each group.
|
---|
333 | * Depending on the specified general verbosity \ref CallOptions#Out the array \ref CallOptions#out
|
---|
334 | * is set accordingly
|
---|
335 | *
|
---|
336 | * \sa SetOutGroup2()
|
---|
337 | * \param *Call \ref CallOptions structure containing \ref CallOptions#Out and \ref CallOptions#out
|
---|
338 | */
|
---|
339 | void SetOutGroup1(struct CallOptions *Call) {
|
---|
340 | int i, me;
|
---|
341 | MPI_Comm_rank(MPI_COMM_WORLD, &me); // me is the process number of this one
|
---|
342 | for (i=0; i < MaxOutGroup; i++) Call->out[i] = 0; // resetting all levels
|
---|
343 | if (me == 0) Call->out[MinOut] = 1; // generally (0) does some output
|
---|
344 | switch (Call->Out) {
|
---|
345 | case OutNone:
|
---|
346 | break;
|
---|
347 | case OutNormal:
|
---|
348 | if (me == 0) Call->out[MinOut] = 1;
|
---|
349 | if (me == 0) Call->out[NormalOut] = 1;
|
---|
350 | if (me == 0) Call->out[ValueOut] = 1;
|
---|
351 | break;
|
---|
352 | case OutNormalP:
|
---|
353 | Call->out[MinOut] = 1;
|
---|
354 | Call->out[NormalOut] = 1;
|
---|
355 | if (me == 0) Call->out[ValueOut] = 1;
|
---|
356 | break;
|
---|
357 | case OutMore:
|
---|
358 | if (me == 0) Call->out[MinOut] = 1;
|
---|
359 | if (me == 0) Call->out[NormalOut] = 1;
|
---|
360 | if (me == 0) Call->out[ReadOut] = 1;
|
---|
361 | if (me == 0) Call->out[ValueOut] = 1;
|
---|
362 | break;
|
---|
363 | case OutMoreP:
|
---|
364 | Call->out[MinOut] = 1;
|
---|
365 | Call->out[NormalOut] = 1;
|
---|
366 | Call->out[ReadOut] = 1;
|
---|
367 | Call->out[ValueOut] = 1;
|
---|
368 | break;
|
---|
369 | case OutAll:
|
---|
370 | break;
|
---|
371 | case OutAllP:
|
---|
372 | default:
|
---|
373 | ;
|
---|
374 | }
|
---|
375 | }
|
---|
376 |
|
---|
377 | /** Set the output of various MPI communicating groups.
|
---|
378 | * Groups such as SpinDouble and for fft receive equal output levels
|
---|
379 | * regarding their calculations. Pattern is: "Me being part of the
|
---|
380 | * group? (..==0) Then set level to blabla"
|
---|
381 | *
|
---|
382 | * \sa SetOutGroup1()
|
---|
383 | * \param *P \ref Problem contains the communicators (aka groups)
|
---|
384 | * \param *Call \ref CallOptions contains verbosity level
|
---|
385 | */
|
---|
386 | void SetOutGroup2(struct Problem *P, struct CallOptions *Call) {
|
---|
387 | int i;
|
---|
388 | switch (Call->Out) {
|
---|
389 | case OutNone:
|
---|
390 | break;
|
---|
391 | case OutNormal:
|
---|
392 | if (P->Par.me_comm_ST_Psi == 0) Call->out[LeaderOut] = 1;
|
---|
393 | break;
|
---|
394 | case OutNormalP:
|
---|
395 | if (P->Par.me_comm_ST_Psi == 0) Call->out[LeaderOut] = 1;
|
---|
396 | if (P->Par.me_comm_ST == 0) Call->out[StepLeaderOut] = 1;
|
---|
397 | break;
|
---|
398 | case OutMore:
|
---|
399 | if (P->Par.me_comm_ST_Psi == 0) Call->out[LeaderOut] = 1;
|
---|
400 | if (P->Par.me_comm_ST == 0) Call->out[PsiOut] = 1;
|
---|
401 | if (P->Par.me_comm_ST_Psi == 0) Call->out[StepLeaderOut] = 1;
|
---|
402 | break;
|
---|
403 | case OutMoreP:
|
---|
404 | if (P->Par.my_color_comm_ST_Psi == 0) Call->out[LeaderOut] = 1;
|
---|
405 | if (P->Par.my_color_comm_ST_Psi == 0) Call->out[PsiOut] = 1;
|
---|
406 | if (P->Par.my_color_comm_ST_Psi == 0) Call->out[StepLeaderOut] = 1;
|
---|
407 | break;
|
---|
408 | case OutAll:
|
---|
409 | for (i=0; i < MaxOutGroup; i++) Call->out[i] = 1;
|
---|
410 | break;
|
---|
411 | case OutAllP:
|
---|
412 | default:
|
---|
413 | for (i=0; i < MaxOutGroup; i++) Call->out[i] = 1;
|
---|
414 | }
|
---|
415 | }
|
---|