NEURON
nrnfilewrap.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 
3 /*
4 On the BG/P when 128K or more processors are used we need to avoid
5 huge numbers of replicated reads of hoc files. The NrnFileWrap
6 provides a framework for this. In normal circumstances corresponding
7 fopen, fclose , getc, fall through to the FILE functions.
8 Otherwise, the file will be read by rank 0 into a char buffer and
9 broadcast to all the other ranks.
10 */
11 
12 #include <stdarg.h>
13 #include <errno.h>
14 #include <ctype.h>
15 #include <limits.h>
16 #include <unistd.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include "hoc.h"
20 #include "nrnmpi.h"
21 #include "nrnfilewrap.h"
22 
23 extern int nrn_xopen_broadcast_;
24 
25 #if USE_NRNFILEWRAP /* to end of file */
26 
27 static NrnFILEWrap* fwstdin;
28 static NrnFILEWrap* nrn_fw_read(const char* path, const char* mode);
29 
30 NrnFILEWrap* nrn_fw_wrap(FILE* f) {
31  NrnFILEWrap* fw;
32  fw = (NrnFILEWrap*) emalloc(sizeof(NrnFILEWrap));
33  fw->f = f;
34  fw->buf = (char*) 0;
35  fw->ip = 0;
36  fw->cnt = 0;
37  return fw;
38 }
39 
40 void nrn_fw_delete(NrnFILEWrap* fw) {
41  if (fw->buf) {
42  free(fw->buf);
43  }
44  free(fw);
45 }
46 
47 int nrn_fw_fclose(NrnFILEWrap* fw) {
48  int e = 0;
49  if (fw->f) {
50  e = fclose(fw->f);
51  }
52  if (fw->buf) {
53  nrn_fw_delete(fw);
54  }
55  return e;
56 }
57 
59  if (!fwstdin) {
60  fwstdin = nrn_fw_wrap(stdin);
61  }
62  return fwstdin;
63 }
64 
65 NrnFILEWrap* nrn_fw_fopen(const char* path, const char* mode) {
66  NrnFILEWrap* fw = (NrnFILEWrap*) 0;
67  FILE* f;
69  f = fopen(path, mode);
70  if (f) {
71  fw = nrn_fw_wrap(f);
72  }
73  } else {
74  fw = nrn_fw_read(path, mode);
75  }
76  return fw;
77 }
78 
79 int nrn_fw_readaccess(const char* path) {
80  int r;
82  r = access(path, R_OK);
83  } else {
84  if (nrnmpi_myid == 0) {
85  r = access(path, R_OK);
86 #if 0
87  printf("access %s %d\n", path, r);
88 #endif
89  }
90  nrnmpi_int_broadcast(&r, 1, 0);
91  }
92  r = ((r == 0) ? 1 : 0);
93  return r;
94 }
95 
96 int nrn_fw_fseek(NrnFILEWrap* fw, long offset, int whence) {
97  int r = 0;
98  int e = 0;
99  if (fw->f) {
100  r = fseek(fw->f, offset, whence);
101  } else if (fw->buf) {
102  long i = -1;
103  switch (whence) {
104  case SEEK_SET:
105  i = offset;
106  break;
107  case SEEK_CUR:
108  i = offset + fw->ip;
109  break;
110  case SEEK_END:
111  i = offset + fw->cnt;
112  break;
113  }
114  if (i >= 0 && i <= fw->cnt) {
115  fw->ip = i;
116  } else {
117  errno = EINVAL;
118  r = -1;
119  }
120  } else {
121  errno = EBADF;
122  r = -1;
123  }
124  return r;
125 }
126 
127 int nrn_fw_getc(NrnFILEWrap* fw) {
128  int c = EOF;
129  if (fw->f) {
130  c = getc(fw->f);
131  } else if (fw->buf) {
132  if (fw->ip < fw->cnt) {
133  c = (int) fw->buf[fw->ip++];
134  }
135  }
136  return c;
137 }
138 
139 int nrn_fw_ungetc(int c, NrnFILEWrap* fw) {
140  int e = EOF;
141  if (fw->f) {
142  e = ungetc(c, fw->f);
143  } else if (fw->buf) {
144  if (fw->ip > 0) {
145  fw->buf[--fw->ip] = (unsigned char) c;
146  e = c;
147  }
148  }
149  return e;
150 }
151 
152 static int nrn_vsscanf(const char* str, const char** rs, const char* format, va_list args);
153 
154 int nrn_fw_fscanf(NrnFILEWrap* fw, const char* fmt, ...) {
155  int i = 0;
156  va_list ap;
157  va_start(ap, fmt);
158  if (fw->f) {
159  i = vfscanf(fw->f, fmt, ap);
160  } else if (fw->buf) {
161  const char* rs;
162  i = nrn_vsscanf(fw->buf + fw->ip, &rs, fmt, ap);
163  fw->ip = (unsigned char*) rs - fw->buf;
164  }
165  va_end(ap);
166  return i;
167 }
168 
169 NrnFILEWrap* nrn_fw_read(const char* path, const char* mode) {
170  NrnFILEWrap* fw = (NrnFILEWrap*) 0;
171  size_t sz = 0;
172  int isz = -1;
173  unsigned char* buf = (char*) 0;
174  if (nrnmpi_myid == 0) {
175  FILE* f = fopen(path, mode);
176  if (f) {
177  struct stat bs;
178  nrn_assert(!fstat(fileno(f), &bs));
179  sz = bs.st_size;
180  isz = sz;
181  if (sz > 0) {
182  buf = (unsigned char*) emalloc(sz + 2);
183  nrn_assert(fread(buf, 1, sz, f) == sz);
184  }
185  fclose(f);
186 #if 1
187  printf("load %s %d\n", path, isz);
188 #endif
189  }
190  }
191  if (nrnmpi_numprocs > 1) {
192  nrnmpi_int_broadcast(&isz, 1, 0);
193  if (nrnmpi_myid > 0) {
194  if (isz > 0) {
195  sz = isz;
196  buf = (unsigned char*) emalloc(sz + 2);
197  }
198  }
199  if (isz > 0) {
200  nrnmpi_char_broadcast(buf, isz, 0);
201  }
202  }
203  if (isz >= 0) {
204  fw = nrn_fw_wrap((FILE*) 0);
205  fw->cnt = sz;
206  buf[sz] = '\0';
207  fw->buf = (unsigned char*) buf;
208  }
209  return fw;
210 }
211 
212 #include "nrn_vsscanf.cpp"
213 
214 #endif /* USE_NRNFILEWRAP */
#define c
char buf[512]
Definition: init.cpp:13
static char * format
Definition: matrixio.c:386
#define i
Definition: md1redef.h:12
char * emalloc(unsigned n)
Definition: list.cpp:166
#define printf
Definition: mwprefix.h:26
#define nrn_assert(ex)
Definition: nrnassrt.h:53
int nrn_xopen_broadcast_
Definition: hoc_init.cpp:408
#define nrn_fw_wrap(f)
Definition: nrnfilewrap.h:41
#define nrn_fw_fclose
Definition: nrnfilewrap.h:44
#define nrn_fw_set_stdin()
Definition: nrnfilewrap.h:45
#define nrn_fw_delete(fw)
Definition: nrnfilewrap.h:42
#define nrn_fw_getc(fw)
Definition: nrnfilewrap.h:48
#define nrn_fw_fscanf
Definition: nrnfilewrap.h:50
#define nrn_fw_fseek
Definition: nrnfilewrap.h:47
#define NrnFILEWrap
Definition: nrnfilewrap.h:39
#define nrn_fw_fopen
Definition: nrnfilewrap.h:46
#define nrn_fw_ungetc(c, fw)
Definition: nrnfilewrap.h:49
int nrnmpi_myid
int nrnmpi_numprocs
static void nrnmpi_char_broadcast(char *, int, int)
Definition: ocbbs.cpp:61
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
#define e
Definition: passive0.cpp:22
FILE * fopen()
#define cnt
Definition: spt2queue.cpp:19