source: pcp/src/opt.c@ c510a7

Last change on this file since c510a7 was c510a7, checked in by Frederik Heber <heber@…>, 17 years ago

char lengths of 255 and MAXDUMMYSTRING replaced with define MAXSTRINGSIZE in molecuilder and pcp

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