source: pcp/src/opt.c@ 9e831e

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

CallOptions#ReadSrcFile is now enumerated ParseSrcDensities

This is done to distinguish between when only Occ are parsed (i.e. when StructOpt has been done before and now we do perturbed run), all or we pare and minimise subsequently.

  • 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 = DoNotParse;
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.