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; break;
106  case SEEK_CUR:
107  i = offset + fw->ip; break;
108  case SEEK_END:
109  i = offset + fw->cnt; break;
110  }
111  if (i >= 0 && i <= fw->cnt) {
112  fw->ip = i;
113  }else{
114  errno = EINVAL;
115  r = -1;
116  }
117  }else{
118  errno = EBADF;
119  r = -1;
120  }
121  return r;
122 }
123 
124 int nrn_fw_getc(NrnFILEWrap* fw){
125  int c = EOF;
126  if (fw->f) {
127  c = getc(fw->f);
128  }else if (fw->buf) {
129  if (fw->ip < fw->cnt) {
130  c = (int)fw->buf[fw->ip++];
131  }
132  }
133  return c;
134 }
135 
136 int nrn_fw_ungetc(int c, NrnFILEWrap* fw){
137  int e = EOF;
138  if (fw->f) {
139  e = ungetc(c, fw->f);
140  }else if (fw->buf) {
141  if (fw->ip > 0) {
142  fw->buf[--fw->ip] = (unsigned char)c;
143  e = c;
144  }
145  }
146  return e;
147 }
148 
149 static int nrn_vsscanf(const char *str, const char** rs, const char *format, va_list args);
150 
151 int nrn_fw_fscanf(NrnFILEWrap* fw, const char* fmt, ...){
152  int i = 0;
153  va_list ap;
154  va_start(ap, fmt);
155  if (fw->f) {
156  i = vfscanf(fw->f, fmt, ap);
157  }else if (fw->buf) {
158  const char* rs;
159  i = nrn_vsscanf(fw->buf + fw->ip, &rs, fmt, ap);
160  fw->ip = (unsigned char*)rs - fw->buf;
161  }
162  va_end(ap);
163  return i;
164 }
165 
166 NrnFILEWrap* nrn_fw_read(const char* path, const char* mode){
167  NrnFILEWrap* fw = (NrnFILEWrap*)0;
168  size_t sz = 0;
169  int isz = -1;
170  unsigned char* buf = (char*)0;
171  if (nrnmpi_myid == 0) {
172  FILE* f = fopen(path, mode);
173  if (f) {
174  struct stat bs;
175  nrn_assert(!fstat(fileno(f), &bs));
176  sz = bs.st_size;
177  isz = sz;
178  if (sz > 0) {
179  buf = (unsigned char*)emalloc(sz+2);
180  nrn_assert(fread(buf, 1, sz, f) == sz);
181  }
182  fclose(f);
183 #if 1
184  printf("load %s %d\n", path, isz);
185 #endif
186  }
187  }
188  if (nrnmpi_numprocs > 1) {
189  nrnmpi_int_broadcast(&isz, 1, 0);
190  if (nrnmpi_myid > 0) {
191  if (isz > 0) {
192  sz = isz;
193  buf = (unsigned char*)emalloc(sz+2);
194  }
195  }
196  if (isz > 0) {
197  nrnmpi_char_broadcast(buf, isz, 0);
198  }
199  }
200  if (isz >= 0) {
201  fw = nrn_fw_wrap((FILE*)0);
202  fw->cnt = sz;
203  buf[sz] = '\0';
204  fw->buf = (unsigned char*)buf;
205  }
206  return fw;
207 }
208 
209 #include "nrn_vsscanf.cpp"
210 
211 #endif /* USE_NRNFILEWRAP */
#define nrn_assert(ex)
Definition: nrnassrt.h:35
#define nrn_fw_set_stdin()
Definition: nrnfilewrap.h:45
#define nrn_fw_getc(fw)
Definition: nrnfilewrap.h:48
#define nrn_fw_wrap(f)
Definition: nrnfilewrap.h:41
#define nrn_fw_delete(fw)
Definition: nrnfilewrap.h:42
static void nrnmpi_char_broadcast(char *, int, int)
Definition: ocbbs.cpp:61
#define e
Definition: passive0.cpp:24
int nrnmpi_numprocs
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
#define nrn_fw_fopen
Definition: nrnfilewrap.h:46
#define nrn_fw_fscanf
Definition: nrnfilewrap.h:50
#define printf
Definition: mwprefix.h:26
int
Definition: nrnmusic.cpp:71
#define cnt
Definition: spt2queue.cpp:19
errno
Definition: system.cpp:98
char * emalloc(unsigned n)
Definition: list.cpp:189
#define nrn_fw_fseek
Definition: nrnfilewrap.h:47
static char * format
Definition: matrixio.c:386
int nrnmpi_myid
#define nrn_fw_fclose
Definition: nrnfilewrap.h:44
#define i
Definition: md1redef.h:12
#define c
char buf[512]
Definition: init.cpp:13
FILE * fopen()
int nrn_xopen_broadcast_
Definition: hoc_init.cpp:272
#define nrn_fw_ungetc(c, fw)
Definition: nrnfilewrap.h:49
#define NrnFILEWrap
Definition: nrnfilewrap.h:39