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