NAMD
common.C
Go to the documentation of this file.
1 
7 /*
8  global functions as declared in common.h
9 */
10 
11 #if !defined(WIN32) || defined(__CYGWIN__)
12 #include <unistd.h>
13 #endif
14 #include <errno.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <ctype.h>
19 
20 #include "common.h"
21 #include "Node.h"
22 #include "SimParameters.h"
23 #include "InfoStream.h"
24 
25 #include "charm++.h"
26 
27 #ifdef WIN32
28 #include <io.h>
29 #define access(PATH,MODE) _access(PATH,00)
30 #define NOCOMPRESSED
31 #endif
32 
33 #ifdef USESTDIOSTUBS
34 
35 // On the ASCI-Red, these functions have prototypes that don't match
36 // the standard, so I'll override them
37 
38 int write(int fd, const void* buf, int count)
39 {
40  return write(fd,(void*)buf,(size_t)count);
41 }
42 
43 int stat(const char* fn, struct stat* buf)
44 {
45  return stat((char*)fn, buf);
46 }
47 
48 #endif
49 
50 
51 const char *NAMD_version_string() {
52  return NAMD_VERSION; // macro defined in toplevel Makefile
53 }
54 
55 // Query for Tcl-style version numbering in NAMD
56 void NAMD_version(int *major, int *minor, int *patchLevel, int *releaseType)
57 {
58  int NAMD_major = 0;
59  int NAMD_minor = 0;
60  int NAMD_patchLevel = 0;
61  int NAMD_releaseType = NAMD_UNKNOWN_RELEASE;
62 
63  // have to parse the version string to determine numbers
64  const char *vstr = NAMD_version_string();
65  char dot[4] = ""; // expect to read "."
66  char release[8] = ""; // expect to read "" or "."
67  // or "alpha" or "beta" or "final" or "release"
68  char extra[4] = ""; // bad version string if we read an extra character
69  int n = sscanf(vstr, "%d%3[^0-9]%d%7[^0-9]%d%c",
70  &NAMD_major, dot, &NAMD_minor, release, &NAMD_patchLevel, extra);
71  if (n < 3 || n > 5) {
72  NAMD_bug("Unable to parse NAMD_VERSION from Makefile");
73  }
74  if (n >= 4) {
75  if (strcmp(release, "a") == 0 || strcmp(release, "alpha") == 0) {
76  NAMD_releaseType = NAMD_ALPHA_RELEASE;
77  }
78  else if (strcmp(release, "b") == 0 || strcmp(release, "beta") == 0) {
79  NAMD_releaseType = NAMD_BETA_RELEASE;
80  }
81  else if (strcmp(release, ".") == 0 ||
82  strcmp(release, "final") == 0 ||
83  strcmp(release, "release") == 0 ||
84  strcmp(release, "patch") == 0) {
85  NAMD_releaseType = NAMD_FINAL_RELEASE;
86  }
87  else {
88  NAMD_bug("Unable to parse NAMD_VERSION from Makefile");
89  }
90  }
91  else {
92  NAMD_releaseType = NAMD_FINAL_RELEASE;
93  }
94  // now return values to caller
95  if (major != NULL) *major = NAMD_major;
96  if (minor != NULL) *minor = NAMD_minor;
97  if (patchLevel != NULL) *patchLevel = NAMD_patchLevel;
98  if (releaseType != NULL) *releaseType = NAMD_releaseType;
99 }
100 
101 
102 int NAMD_gcd(int a, int b)
103 {
104  if(a == 0 || b == 0) return 0;
105  else if(a == b) return a;
106  else if(a > b) return NAMD_gcd(a-b,b);
107  return NAMD_gcd(a, b-a);
108 }
109 
110 // make a duplicate of a string
111 char *NAMD_stringdup(const char *s) {
112  char *rs;
113 
114  if(!s)
115  return NULL;
116 
117  rs = new char[strlen(s) + 1];
118  strcpy(rs,s);
119 
120  return rs;
121 }
122 
123 
124 // signal all nodes, it's time to quit
125 void NAMD_quit(const char *err_msg)
126 {
127  if ( ! err_msg ) err_msg = "(unknown error)";
128  CkPrintf("EXITING: %s\n", err_msg);
129  fflush(stdout);
130  char repstr[24] = "";
131  if (CmiNumPartitions() > 1
132  || Node::Object()->simParameters->CUDASOAintegrateMode) {
133  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
134  // CkAbort ensures that all replicas die
135  CkAbort("%sEXITING: %s\n", repstr, err_msg);
136  }
137  CkError("%sEXITING: %s\n", repstr, err_msg);
138 #if CHARM_VERSION < 61000
139  CkExit();
140 #else
141  CkExit(0);
142 #endif
143 }
144 
145 
146 // signal all nodes, it's time to quit
147 void NAMD_die(const char *err_msg)
148 {
149  if ( ! err_msg ) err_msg = "(unknown error)";
150  CkPrintf("FATAL ERROR: %s\n", err_msg);
151  fflush(stdout);
152  char repstr[24] = "";
153  if (CmiNumPartitions() > 1 ||
154  (Node::Object()->simParameters != 0 &&
155  Node::Object()->simParameters->CUDASOAintegrateMode)) {
156  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
157  // CkAbort ensures that all replicas die
158  CkAbort("%sFATAL ERROR: %s\n", repstr, err_msg);
159  }
160  CkError("%sFATAL ERROR: %s\n", repstr, err_msg);
161 #if CHARM_VERSION < 61000
162  CkExit();
163 #else
164  CkExit(1);
165 #endif
166 }
167 
168 
169 // signal all nodes, it's time to quit
170 void NAMD_err(const char *err_msg)
171 {
172  if ( ! err_msg ) err_msg = "(unknown error)";
173  const char *sys_err_msg = strerror(errno);
174  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
175  CkPrintf("FATAL ERROR: %s: %s\n", err_msg, sys_err_msg);
176  fflush(stdout);
177  char repstr[24] = "";
178  if (CmiNumPartitions() > 1 ||
179  (Node::Object()->simParameters != 0 &&
180  Node::Object()->simParameters->CUDASOAintegrateMode)) {
181  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
182  // CkAbort ensures that all replicas die
183  CkAbort("%sFATAL ERROR: %s: %s\n", repstr, err_msg, sys_err_msg);
184  }
185  CkError("%sFATAL ERROR: %s: %s\n", repstr, err_msg, sys_err_msg);
186 #if CHARM_VERSION < 61000
187  CkExit();
188 #else
189  CkExit(1);
190 #endif
191 }
192 
193 
194 // signal all nodes, it's time to quit and it's our own damn fault
195 void NAMD_bug(const char *err_msg)
196 {
197  if ( ! err_msg ) err_msg = "(unknown error)";
198  const char *bug_msg =
199  "FATAL ERROR: See http://www.ks.uiuc.edu/Research/namd/bugreport.html";
200  CkPrintf("FATAL ERROR: %s\n%s\n",err_msg, bug_msg);
201  fflush(stdout);
202  char repstr[24] = "";
203  if (CmiNumPartitions() > 1 ||
204  (Node::Object()->simParameters != 0 &&
205  Node::Object()->simParameters->CUDASOAintegrateMode)) {
206  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
207  // CkAbort ensures that all replicas die
208  CkAbort("%sFATAL ERROR: %s\n%s\n", repstr, err_msg, bug_msg);
209  }
210  CkError("%sFATAL ERROR: %s\n%s\n", repstr, err_msg, bug_msg);
211 #if CHARM_VERSION < 61000
212  CkExit();
213 #else
214  CkExit(2);
215 #endif
216 }
217 
218 
219 int NAMD_file_exists(const char *filename) {
220  int rval;
221  do {
222  rval = access(filename, F_OK);
223  } while ( rval != 0 && errno == EINTR );
224  if ( rval != 0 && errno != ENOENT ) {
225  const char *sys_err_msg = strerror(errno);
226  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
227  iout << iERROR << "Error on checking file "
228  << filename << ": " << sys_err_msg << "\n" << endi;
229  fflush(stdout);
230  }
231  return ! rval;
232 }
233 
234 // move filename to filename.BAK
235 void NAMD_backup_file(const char *filename, const char *extension)
236 {
237  if (NAMD_file_exists(filename)) {
238  if ( ! extension ) extension = ".BAK";
239  char *backup = new char[strlen(filename)+strlen(extension)+1];
240  strcpy(backup, filename);
241  strcat(backup, extension);
242 #if defined(WIN32) && !defined(__CYGWIN__)
243  if ( remove(backup) ) if ( errno != ENOENT ) {
244  char *sys_err_msg = strerror(errno);
245  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
246  iout << iERROR << "Error on removing file "
247  << backup << ": " << sys_err_msg << "\n" << endi;
248  fflush(stdout);
249  }
250 #endif
251  while ( rename(filename,backup) )
252  {
253  if ( errno == EINTR ) continue;
254  const char *sys_err_msg = strerror(errno);
255  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
256  iout << iERROR << "Error on renaming file " << filename
257  << " to " << backup << ": " << sys_err_msg << "\n" << endi;
258  fflush(stdout);
259  if ( errno == EXDEV ) continue;
260  break;
261  // char errmsg[256];
262  // sprintf(errmsg, "Error on renaming file %s to %s",filename,backup);
263  // NAMD_err(errmsg);
264  }
265  delete [] backup;
266  }
267 }
268 
269 // same as open, only does error checking internally
270 int NAMD_open_text(const char *fname, int append) {
271  int fd;
272 
273  // open the file and die if the open fails
274 #ifdef WIN32
275  while ( (fd = _open(fname, O_WRONLY|(append?O_APPEND:O_EXCL)|O_CREAT|O_TEXT,_S_IREAD|_S_IWRITE)) < 0) {
276 #else
277 #ifdef NAMD_NO_O_EXCL
278  while ( (fd = open(fname, O_WRONLY|(append?O_APPEND:O_TRUNC)|O_CREAT,
279 #else
280  while ( (fd = open(fname, O_WRONLY|(append?O_APPEND:O_EXCL)|O_CREAT,
281 #endif
282  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
283 #endif
284  if ( errno != EINTR ) {
285  char errmsg[1024];
286  sprintf(errmsg, "Unable to open text file %s", fname);
287  NAMD_err(errmsg);
288  }
289  }
290 
291  return fd;
292 }
293 
294 // same as write, only does error checking internally
295 void NAMD_write(int fd, const char *buf, size_t count, const char *fname) {
296  while ( count ) {
297 #if defined(WIN32) && !defined(__CYGWIN__)
298  long retval = _write(fd,buf,count);
299 #else
300  ssize_t retval = write(fd,buf,count);
301 #endif
302  if ( retval < 0 && errno == EINTR ) retval = 0;
303  if ( retval < 0 ) {
304  char errmsg[1024];
305  sprintf(errmsg, "Error on writing to file %s", fname);
306  NAMD_err(errmsg);
307  }
308  if ( retval > count ) NAMD_bug("extra bytes written in NAMD_write()");
309  buf += retval;
310  count -= retval;
311  }
312 }
313 
314 // same as close, only does error checking internally
315 void NAMD_close(int fd, const char *fname) {
316 #ifdef WIN32
317  while ( _close(fd) ) {
318 #else
319  while ( close(fd) ) {
320 #endif
321  if ( errno != EINTR ) {
322  char errmsg[1024];
323  sprintf(errmsg, "Error on closing file %s", fname);
324  NAMD_err(errmsg);
325  }
326  }
327 }
328 
329 
330 /***************************************************************************
331  Fopen(char *Filename, char *mode): similar to fopen(filename,mode) except
332  it checks for compressed file names too.
333  For example: Fopen("config");
334  This will first look for the filename "config" (and return "r" file handle
335  if it is found).
336  Then it will look for "config.Z" (and run "zcat config.Z", returning
337  a file handle to the uncompressed data if found).
338  Then it will look for "config.gz" (and run "gzip -d -c config.gz", returning
339  a file handle to the uncompressed data if found).
340  ***************************************************************************/
341 FILE *Fopen (const char *filename, const char *mode)
342 {
343  struct stat buf;
344  // check if basic filename exists (and not a directory)
345 
346 #if defined(NOCOMPRESSED)
347  if (!stat(filename,&buf))
348  {
349  FILE *rval;
350  while ( ! (rval = fopen(filename,mode)) ) {
351  if ( errno != EINTR ) break;
352  }
353  return(rval);
354  }
355 #else
356  if (!stat(filename,&buf))
357  {
358  if (!S_ISDIR(buf.st_mode)) {
359  FILE *rval;
360  while ( ! (rval = fopen(filename,mode)) ) {
361  if ( errno != EINTR ) break;
362  }
363  return(rval);
364  }
365  }
366  // check for a compressed file
367  char *realfilename;
368  char *command;
369  FILE *fout;
370  command = (char *)malloc(strlen(filename)+25);
371  // check for .Z (unix compress)
372  sprintf(command,"zcat %s.Z",filename);
373  realfilename = command+5;
374  iout << "Command = " << command << "\n" << endi;
375  iout << "Filename.Z = " << realfilename << "\n" << endi;
376  if (!stat(realfilename,&buf))
377  {
378  if (!S_ISDIR(buf.st_mode))
379  {
380  fout = popen(command,mode);
381  // on HP-UX, the first character(s) out of pipe may be
382  // garbage! (Argh!)
383  int C;
384  do
385  {
386  C = fgetc(fout);
387  // iout << "C is " << C << "\n" << endi;
388  if (isalnum(C) || isspace(C))
389  {
390  ungetc(C,fout);
391  C = -1; // outta loop
392  }
393  } while(C != -1);
394  free(command);
395  return(fout);
396  }
397  }
398  // check for .gz (gzip)
399  sprintf(command,"gzip -d -c %s.gz",filename);
400  realfilename = command+11;
401  iout << "Command = " << command << "\n" << endi;
402  iout << "Filename.gz = " << realfilename << "\n" << endi;
403  if (!stat(realfilename,&buf))
404  {
405  if (!S_ISDIR(buf.st_mode))
406  {
407  fout = popen(command,mode);
408  // on HP-UX, the first character(s) out of pipe may be
409  // garbage! (Argh!)
410  int C;
411  do
412  {
413  C = fgetc(fout);
414  // iout << "C is " << C << "\n" << endi;
415  if (isalnum(C) || isspace(C))
416  {
417  ungetc(C,fout);
418  C = -1; // outta loop
419  }
420  } while(C != -1);
421  free(command);
422  return(fout);
423  }
424  }
425  free(command);
426 #endif /* !defined(NOCOMPRESSED) */
427 
428  return(NULL);
429 } /* Fopen() */
430 
431 /***************************************************************************
432  Fclose(FILE *fout): similar to fclose(fout) except it first checks if the
433  file handle fout is a named pipe.
434  ***************************************************************************/
435 int Fclose (FILE *fout)
436 {
437  int rc = -1;
438 #if !defined(NOCOMPRESSED)
439  rc = pclose(fout);
440 #endif
441  if (rc == -1) // stream not associated with a popen()
442  {
443  rc = fclose(fout);
444  }
445  return rc;
446 } /* Fclose() */
447 
448 
static Node * Object()
Definition: Node.h:86
void NAMD_err(const char *err_msg)
Definition: common.C:170
int NAMD_open_text(const char *fname, int append)
Definition: common.C:270
void NAMD_quit(const char *err_msg)
Definition: common.C:125
void NAMD_write(int fd, const char *buf, size_t count, const char *fname)
Definition: common.C:295
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
const char * NAMD_version_string()
Definition: common.C:51
int NAMD_file_exists(const char *filename)
Definition: common.C:219
#define iout
Definition: InfoStream.h:51
int NAMD_gcd(int a, int b)
Definition: common.C:102
char * NAMD_stringdup(const char *s)
Definition: common.C:111
void NAMD_bug(const char *err_msg)
Definition: common.C:195
void NAMD_close(int fd, const char *fname)
Definition: common.C:315
FILE * Fopen(const char *filename, const char *mode)
Definition: common.C:341
void NAMD_die(const char *err_msg)
Definition: common.C:147
void NAMD_backup_file(const char *filename, const char *extension)
Definition: common.C:235
int Fclose(FILE *fout)
Definition: common.C:435
std::ostream & iERROR(std::ostream &s)
Definition: InfoStream.C:83
void NAMD_version(int *major, int *minor, int *patchLevel, int *releaseType)
Definition: common.C:56