cis_config
PsiInterface.h
1 #include <fcntl.h> /* For O_* constants */
2 #include <sys/stat.h> /* For mode constants */
3 #include <sys/msg.h>
4 #include <sys/types.h>
5 #include <sys/sem.h>
6 #include <sys/shm.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <regex.h>
14 #include <../dataio/AsciiFile.h>
15 #include <../dataio/AsciiTable.h>
16 
17 
19 #define PSI_MSG_MAX LINE_SIZE_MAX
20 
21 #define PSI_MSG_EOF "EOF!!!"
22 
23 #define _psiTrackChannels 256
24 
25 static char * _psiChannelNames[_psiTrackChannels];
27 static unsigned _psiChannelsUsed = 0;
28 
29 
30 //==============================================================================
42 //==============================================================================
43 
53 static inline
54 void psiLog(const char* prefix, const char* fmt, va_list ap) {
55  fprintf(stdout, "%s: %d: ", prefix, getpid());
56  vfprintf(stdout, fmt, ap);
57  fprintf(stdout, "\n");
58 };
59 
67 static inline
68 void psiInfo(const char* fmt, ...) {
69  va_list ap;
70  va_start(ap, fmt);
71  psiLog("INFO", fmt, ap);
72  va_end(ap);
73 };
74 
82 static inline
83 void psiDebug(const char* fmt, ...) {
84  va_list ap;
85  va_start(ap, fmt);
86  psiLog("DEBUG", fmt, ap);
87  va_end(ap);
88 };
89 
97 static inline
98 void psiError(const char* fmt, ...) {
99  va_list ap;
100  va_start(ap, fmt);
101  psiLog("ERROR", fmt, ap);
102  va_end(ap);
103 };
104 
105 #define error psiError
106 #ifdef PSI_DEBUG
107  #if PSI_DEBUG == INFO
108  #define info psiInfo
109  #define debug while (0) psiDebug
110  #elif PSI_DEBUG == DEBUG
111  #define debug psiInfo
112  #define info psiDebug
113  #else
114  #define debug while (0) psiDebug
115  #define info while (0) psiInfo
116  #endif
117 #else
118  #define debug while (0) psiDebug
119  #define info while (0) psiInfo
120 #endif
121 
122 //==============================================================================
143 //==============================================================================
144 
156 static inline
157 int psi_mq(char *name, const char *yamlName){
158  // Look up registered name
159  char *qid = getenv(name);
160  // Fail if the driver did not declare the channel
161  if (qid == NULL) {
162  error("psi_mq: Channel %s not registered, model/YAML mismatch (yaml=%s)\n",
163  name, yamlName);
164  // Check if opposite channel exists
165  char nm_opp[512];
166  strcpy(nm_opp, yamlName);
167  if (strcmp(name+strlen(yamlName), "_IN") == 0)
168  strcat(nm_opp, "_OUT");
169  else
170  strcat(nm_opp, "_IN");
171  qid = getenv(nm_opp);
172  if (qid != NULL) {
173  error("psi_mq: Directed channel %s exists, but requested channel %s does not\n",
174  nm_opp, name);
175  }
176  return -1;
177  }
178  // Fail if trying to re-use the same channel twice
179  for (unsigned i =0; i < _psiChannelsUsed; i++ ){
180  if (0 == strcmp(_psiChannelNames[i], name)){
181  error("Attempt to re-use channel %s", name);
182  return -1;
183  }
184  }
185  // Fail if > _psiTrackChannels channels used
186  if (_psiChannelsUsed >= _psiTrackChannels) {
187  error("Too many channels in use, max: %d\n", _psiTrackChannels);
188  return -1;
189  }
190  _psiChannelNames[_psiChannelsUsed++] = qid;
191  int qkey = atoi(qid);
192  int fid = msgget(qkey, 0600);
193  return fid;
194 };
195 
201 static inline
202 int is_eof(const char *buf) {
203  if (strcmp(buf, PSI_MSG_EOF) == 0)
204  return 1;
205  else
206  return 0;
207 };
208 
212 typedef struct msgbuf_t {
213  long mtype;
214  char data[PSI_MSG_MAX];
215 } msgbuf_t;
216 
221 typedef struct psiInput_t {
222  int _handle;
223  const char *_name;
224  char *_fmt;
225  int _nfmt;
226 } psiInput_t;
227 
232 typedef struct psiOutput_t {
233  int _handle;
234  const char *_name;
235  char *_fmt;
236  int _nfmt;
237 } psiOutput_t;
238 
247 static inline
248 psiOutput_t psiOutput(const char *name){
249  char nm[512];
250  strcpy(nm, name);
251  strcat(nm, "_OUT");
252  psiOutput_t ret;
253  ret._name = name;
254  ret._fmt = 0;
255  ret._nfmt = 0;
256  ret._handle = psi_mq(nm, name);
257  return ret;
258 };
259 
268 static inline
269 psiInput_t psiInput(const char *name){
270  char nm[512];
271  strcpy(nm, name);
272  strcat(nm, "_IN");
273  psiInput_t ret;
274  ret._handle = psi_mq(nm, name);
275  ret._name = name;
276  ret._fmt = 0;
277  ret._nfmt = 0;
278  return ret;
279 };
280 
282 static inline
283 psiOutput_t psi_output(const char *name){
284  return psiOutput(name);
285 };
286 
288 static inline
289 psiInput_t psi_input(const char *name){
290  return psiInput(name);
291 };
292 
303 static inline
304 psiOutput_t psiOutputFmt(const char *name, char *fmtString){
305  psiOutput_t ret = psiOutput(name);
306  ret._fmt = fmtString;
307  ret._nfmt = count_formats(fmtString);
308  return ret;
309 };
310 
321 static inline
322 psiInput_t psiInputFmt(const char *name, char *fmtString){
323  psiInput_t ret = psiInput(name);
324  ret._fmt = fmtString;
325  ret._nfmt = count_formats(fmtString);
326  return ret;
327 };
328 
337 static inline
338 int psi_output_nmsg(psiOutput_t psiQ) {
339  int rc;
340  struct msqid_ds buf;
341  int num_messages;
342  rc = msgctl(psiQ._handle, IPC_STAT, &buf);
343  if (rc != 0) {
344  error("psi_output_nmsg: Could not access queue.");
345  return -1;
346  }
347  num_messages = buf.msg_qnum;
348  return num_messages;
349 };
350 
359 static inline
360 int psi_input_nmsg(psiInput_t psiQ) {
361  int rc;
362  struct msqid_ds buf;
363  int num_messages;
364  rc = msgctl(psiQ._handle, IPC_STAT, &buf);
365  if (rc != 0) {
366  error("psi_input_nmsg: Could not access queue.");
367  return -1;
368  }
369  num_messages = buf.msg_qnum;
370  return num_messages;
371 };
372 
382 static inline
383 int psi_send(psiOutput_t psiQ, char *data, int len){
384  debug("psi_send(%s): %d bytes", psiQ._name, len);
385  if (len > PSI_MSG_MAX) {
386  error("psi_send(%s): message too large for single packet (PSI_MSG_MAX=%d, len=%d)",
387  psiQ._name, PSI_MSG_MAX, len);
388  return -1;
389  }
390  msgbuf_t t;
391  t.mtype = 1;
392  memcpy(t.data, data, len);
393  int ret = -1;
394  while (1) {
395  ret = msgsnd(psiQ._handle, &t, len, IPC_NOWAIT);
396  debug("psi_send(%s): msgsnd returned %d", psiQ._name, ret);
397  if (ret == 0) break;
398  if (ret == EAGAIN) {
399  debug("psi_send(%s): msgsnd, sleep", psiQ._name);
400  usleep(250*1000);
401  } else {
402  error("psi_send: msgsend(%d, %p, %d, IPC_NOWAIT) ret(%d), errno(%d): %s",
403  psiQ._handle, &t, len, ret, errno, strerror(errno));
404  ret = -1;
405  break;
406  }
407  }
408  debug("psi_send(%s): returning %d", psiQ._name, ret);
409  return ret;
410 };
411 
422 static inline
423 int psi_recv(psiInput_t psiQ, char *data, int len){
424  debug("psi_recv(%s)", psiQ._name);
425  msgbuf_t t;
426  t.mtype=1;
427  int ret = -1;
428  while (1) {
429  ret = msgrcv(psiQ._handle, &t, len, 0, IPC_NOWAIT);
430  if (ret == -1 && errno == ENOMSG) {
431  debug("psi_recv(%s): no input, sleep", psiQ._name);
432  usleep(250*1000);
433  } else {
434  debug("psi_recv(%s): received input: %d bytes, ret=%d",
435  psiQ._name, strlen(t.data), ret);
436  break;
437  }
438  }
439  if (ret > 0){
440  memcpy(data, t.data, ret);
441  data[ret] = '\0';
442  } else {
443  debug("psi_recv: msgrecv(%d, %p, %d, 0, IPC_NOWAIT: %s", psiQ._handle, &t, len, strerror(errno));
444  ret = -1;
445  }
446 
447  debug("psi_recv(%s): returns %d bytes\n", psiQ._name, ret);
448  return ret;
449 };
450 
462 static inline
463 int psi_send_nolimit(psiOutput_t psiQ, char *data, int len){
464  debug("psi_send_nolimit(%s): %d bytes", psiQ._name, len);
465  int ret = -1;
466  int msgsiz = 0;
467  char msg[PSI_MSG_MAX];
468  sprintf(msg, "%ld", (long)(len));
469  ret = psi_send(psiQ, msg, strlen(msg));
470  if (ret != 0) {
471  debug("psi_send_nolimit(%s): sending size of payload failed.", psiQ._name);
472  return ret;
473  }
474  int prev = 0;
475  while (prev < len) {
476  if ((len - prev) > PSI_MSG_MAX)
477  msgsiz = PSI_MSG_MAX;
478  else
479  msgsiz = len - prev;
480  ret = psi_send(psiQ, data + prev, msgsiz);
481  if (ret != 0) {
482  debug("psi_send_nolimit(%s): send interupted at %d of %d bytes.",
483  psiQ._name, prev, len);
484  break;
485  }
486  prev += msgsiz;
487  debug("psi_send_nolimit(%s): %d of %d bytes sent",
488  psiQ._name, prev, len);
489  }
490  if (ret == 0)
491  debug("psi_send_nolimit(%s): %d bytes completed", psiQ._name, len);
492  return ret;
493 };
494 
508 static inline
509 int psi_recv_nolimit(psiInput_t psiQ, char **data, int len0){
510  debug("psi_recv_nolimit(%s)", psiQ._name);
511  long len = 0;
512  int ret = -1;
513  int msgsiz = 0;
514  char msg[PSI_MSG_MAX];
515  int prev = 0;
516  ret = psi_recv(psiQ, msg, PSI_MSG_MAX);
517  if (ret < 0) {
518  debug("psi_recv_nolimit(%s): failed to receive payload size.", psiQ._name);
519  return -1;
520  }
521  ret = sscanf(msg, "%ld", &len);
522  if (ret != 1) {
523  debug("psi_recv_nolimit(%s): failed to parse payload size (%s)",
524  psiQ._name, msg);
525  return -1;
526  }
527  // Reallocate data if necessary
528  if (len > len0) {
529  *data = (char*)realloc(*data, len);
530  }
531  ret = -1;
532  while (prev < len) {
533  if ((len - prev) > PSI_MSG_MAX)
534  msgsiz = PSI_MSG_MAX;
535  else
536  msgsiz = len - prev;
537  ret = psi_recv(psiQ, (*data) + prev, msgsiz);
538  if (ret < 0) {
539  debug("psi_recv_nolimit(%s): recv interupted at %d of %d bytes.",
540  psiQ._name, prev, len);
541  break;
542  }
543  prev += ret;
544  debug("psi_recv_nolimit(%s): %d of %d bytes received",
545  psiQ._name, prev, len);
546  }
547  if (ret > 0) {
548  debug("psi_recv_nolimit(%s): %d bytes completed", psiQ._name, prev);
549  return prev;
550  } else {
551  return -1;
552  }
553 };
554 
555 
556 //==============================================================================
574 //==============================================================================
575 
585 static inline
586 int vpsiSend(psiOutput_t psiQ, va_list ap) {
587  char buf[PSI_MSG_MAX];
588  int ret = vsnprintf(buf, PSI_MSG_MAX, psiQ._fmt, ap);
589  debug("vpsiSend(%s): vsnprintf returns %d", psiQ._name, ret);
590  if (ret < 0) {
591  error("vpsiSend(%s): vsnprintf encoding error", psiQ._name);
592  return -1;
593  } else if (ret > PSI_MSG_MAX) {
594  error("vpsiSend(%s): encoded message too large. (PSI_MSG_MAX=%d, len=%d)",
595  psiQ._name, PSI_MSG_MAX, ret);
596  return -1;
597  }
598  ret = psi_send(psiQ, buf, ret);
599  debug("vpsiSend(%s): psi_send returns %d", psiQ._name, ret);
600  return ret;
601 };
602 
614 static inline
615 int vpsiRecv(psiInput_t psiQ, va_list ap) {
616  char buf[PSI_MSG_MAX];
617  int ret = psi_recv(psiQ, buf, PSI_MSG_MAX);
618  if (ret < 0) {
619  error("vpsiRecv(%s): Error receiving.", psiQ._name);
620  return -1;
621  }
622  debug("vpsiRecv(%s): psi_recv returns %d: %s", psiQ._name, ret, buf);
623  if (is_eof(buf)) {
624  debug("vpsiRecv(%s): EOF received.\n", psiQ._name);
625  return -1;
626  }
627  int sret = vsscanf(buf, psiQ._fmt, ap);
628  if (sret != psiQ._nfmt) {
629  error("vpsiRecv(%s): vsscanf filled %d variables, but there are %d formats",
630  psiQ._name, sret, psiQ._nfmt);
631  return -1;
632  }
633  debug("vpsiRecv(%s): vsscanf returns %d", psiQ._name, sret);
634  return ret;
635 };
636 
646 static inline
647 int psiSend(psiOutput_t psiQ, ...){
648  va_list ap;
649  va_start(ap, psiQ);
650  int ret = vpsiSend(psiQ, ap);
651  va_end(ap);
652  return ret;
653 };
654 
666 static inline
667 int psiRecv(psiInput_t psiQ, ...){
668  va_list ap;
669  va_start(ap, psiQ);
670  int ret = vpsiRecv(psiQ, ap);
671  va_end(ap);
672  return ret;
673 };
674 
685 static inline
686 int vpsiSend_nolimit(psiOutput_t psiQ, va_list ap) {
687  char *buf = (char*)malloc(PSI_MSG_MAX);
688  int ret = vsnprintf(buf, PSI_MSG_MAX, psiQ._fmt, ap);
689  if (ret < 0) {
690  error("vpsiSend_nolimit(%s): vsnprintf encoding error", psiQ._name);
691  free(buf);
692  return -1;
693  } else if (ret > PSI_MSG_MAX) {
694  buf = (char*)realloc(buf, ret+1);
695  ret = vsnprintf(buf, ret, psiQ._fmt, ap);
696  }
697  debug("vpsiSend_nolimit(%s): vsnprintf returns %d", psiQ._name, ret);
698  ret = psi_send_nolimit(psiQ, buf, ret);
699  debug("vpsiSend_nolimit(%s): psi_send_nolimit returns %d", psiQ._name, ret);
700  free(buf);
701  return ret;
702 };
703 
715 static inline
716 int vpsiRecv_nolimit(psiInput_t psiQ, va_list ap) {
717  char *buf = (char*)malloc(PSI_MSG_MAX);
718  int ret = psi_recv_nolimit(psiQ, &buf, PSI_MSG_MAX);
719  if (ret < 0) {
720  error("vpsiRecv_nolimit(%s): Error receiving.", psiQ._name);
721  free(buf);
722  return -1;
723  }
724  debug("vpsiRecv_nolimit(%s): psi_recv returns %d", psiQ._name, ret);
725  if (is_eof(buf)) {
726  debug("vpsiRecv(%s): EOF received.\n", psiQ._name);
727  return -1;
728  }
729  int sret = vsscanf(buf, psiQ._fmt, ap);
730  if (sret != psiQ._nfmt) {
731  error("vpsiRecv_nolimit(%s): vsscanf filled %d variables, but there are %d formats",
732  psiQ._name, sret, psiQ._nfmt);
733  free(buf);
734  return -1;
735  }
736  debug("vpsiRecv_nolimit(%s): vsscanf returns %d", psiQ._name, ret);
737  free(buf);
738  return ret;
739 };
740 
751 static inline
752 int psiSend_nolimit(psiOutput_t psiQ, ...) {
753  va_list ap;
754  va_start(ap, psiQ);
755  int ret = vpsiSend_nolimit(psiQ, ap);
756  va_end(ap);
757  return ret;
758 };
759 
771 static inline
772 int psiRecv_nolimit(psiInput_t psiQ, ...) {
773  va_list ap;
774  va_start(ap, psiQ);
775  int ret = vpsiRecv_nolimit(psiQ, ap);
776  va_end(ap);
777  return ret;
778 };
779 
780 
781 //==============================================================================
819 //==============================================================================
820 
826 typedef struct psiRpc_t {
829  char *_inFmt;
830  char *_outFmt;
831 } psiRpc_t;
832 
844 static inline
845 psiRpc_t psiRpc(const char *outName, char *outFormat,
846  const char *inName, char *inFormat){
847  psiRpc_t rpc;
848  rpc._inFmt = inFormat;
849  rpc._outFmt = outFormat;
850  rpc._input = psiInputFmt(inName, inFormat);
851  rpc._output = psiOutputFmt(outName, outFormat);
852  return rpc;
853 };
854 
865 static inline
866 psiRpc_t psiRpcClient(const char *name, char *outFormat, char *inFormat){
867  psiRpc_t rpc = psiRpc(name, outFormat, name, inFormat);
868  return rpc;
869 };
870 
881 static inline
882 psiRpc_t psiRpcServer(const char *name, char *inFormat, char *outFormat){
883  psiRpc_t rpc = psiRpc(name, outFormat, name, inFormat);
884  return rpc;
885 };
886 
897 static inline
898 int vrpcSend(psiRpc_t rpc, va_list ap) {
899  int ret = vpsiSend_nolimit(rpc._output, ap);
900  return ret;
901 };
902 
916 static inline
917 int vrpcRecv(psiRpc_t rpc, va_list ap) {
918  int ret = vpsiRecv_nolimit(rpc._input, ap);
919  return ret;
920 };
921 
932 static inline
933 int rpcSend(psiRpc_t rpc, ...){
934  va_list ap;
935  va_start(ap, rpc);
936  int ret = vrpcSend(rpc, ap);
937  va_end(ap);
938  return ret;
939 };
940 
954 static inline
955 int rpcRecv(psiRpc_t rpc, ...){
956  va_list ap;
957  va_start(ap, rpc);
958  int ret = vrpcRecv(rpc, ap);
959  va_end(ap);
960  return ret;
961 };
962 
976 static inline
977 int vrpcCall(psiRpc_t rpc, va_list ap) {
978  int ret;
979 
980  // pack the args and call
981  ret = vpsiSend_nolimit(rpc._output, ap);
982  if (ret < 0) {
983  printf("vrpcCall: vpsiSend_nolimit error: ret %d: %s\n", ret, strerror(errno));
984  return -1;
985  }
986 
987  // unpack the messages into the remaining variable arguments
988  va_list op;
989  va_copy(op, ap);
990  ret = vpsiRecv_nolimit(rpc._input, op);
991  va_end(op);
992 
993  return ret;
994 };
995 
1009 static inline
1010 int rpcCall(psiRpc_t rpc, ...){
1011  int ret;
1012  va_list ap;
1013  va_start(ap, rpc);
1014  ret = vrpcCall(rpc, ap);
1015  va_end(ap);
1016  return ret;
1017 };
1018 
1019 
1020 //==============================================================================
1059 //==============================================================================
1060 
1064 typedef struct psiAsciiFileOutput_t {
1065  int _valid;
1066  const char *_name;
1067  int _type;
1071 
1075 typedef struct psiAsciiFileInput_t {
1076  int _valid;
1077  const char *_name;
1078  int _type;
1082 
1092 static inline
1093 psiAsciiFileOutput_t psiAsciiFileOutput(const char *name, int dst_type) {
1095  int ret;
1096  out._name = name;
1097  out._type = dst_type;
1098  out._valid = 1;
1099  if (dst_type == 0) {
1100  out._file = asciiFile(name, "w", NULL, NULL);
1101  ret = af_open(&(out._file));
1102  if (ret != 0) {
1103  error("psiAsciiFileOutput: Could not open %s", name);
1104  out._valid = 0;
1105  }
1106  } else {
1107  out._psi = psiOutput(name);
1108  out._file = asciiFile(name, "0", NULL, NULL);
1109  }
1110  return out;
1111 };
1112 
1122 static inline
1123 psiAsciiFileInput_t psiAsciiFileInput(const char *name, int src_type) {
1124  psiAsciiFileInput_t out;
1125  int ret;
1126  out._name = name;
1127  out._type = src_type;
1128  out._valid = 1;
1129  if (src_type == 0) { // Direct file interface
1130  out._file = asciiFile(name, "r", NULL, NULL);
1131  ret = af_open(&(out._file));
1132  if (ret != 0) {
1133  error("psiAsciiFileInput: Could not open %s", name);
1134  out._valid = 0;
1135  }
1136  } else {
1137  out._psi = psiInput(name);
1138  out._file = asciiFile(name, "0", NULL, NULL);
1139  }
1140  return out;
1141 };
1142 
1148 static inline
1149 int af_send_eof(psiAsciiFileOutput_t t) {
1150  char buf[PSI_MSG_MAX] = PSI_MSG_EOF;
1151  int ret = psi_send(t._psi, buf, strlen(buf));
1152  return ret;
1153 };
1154 
1164 static inline
1165 int af_recv_line(psiAsciiFileInput_t t, char *line, size_t n) {
1166  int ret;
1167  if (t._type == 0) {
1168  ret = af_readline_full(t._file, &line, &n);
1169  } else {
1170  ret = psi_recv(t._psi, line, n);
1171  if (ret > 0) {
1172  if (is_eof(line))
1173  ret = -1;
1174  }
1175  }
1176  return ret;
1177 };
1178 
1185 static inline
1186 int af_send_line(psiAsciiFileOutput_t t, char *line) {
1187  int ret;
1188  if (t._type == 0) {
1189  ret = af_writeline_full(t._file, line);
1190  } else {
1191  ret = psi_send(t._psi, line, strlen(line));
1192  }
1193  return ret;
1194 };
1195 
1200 static inline
1201 void cleanup_pafi(psiAsciiFileInput_t *t) {
1202  af_close(&((*t)._file));
1203 };
1204 
1209 static inline
1210 void cleanup_pafo(psiAsciiFileOutput_t *t) {
1211  af_close(&((*t)._file));
1212 };
1213 
1214 
1215 //==============================================================================
1300 //==============================================================================
1301 
1305 typedef struct psiAsciiTableOutput_t {
1306  int _valid;
1307  const char *_name;
1308  int _type;
1312 
1316 typedef struct psiAsciiTableInput_t {
1317  int _valid;
1318  const char *_name;
1319  int _type;
1323 
1334 static inline
1335 psiAsciiTableOutput_t psiAsciiTableOutput(const char *name, char *format_str,
1336  int dst_type) {
1338  int ret;
1339  out._valid = 1;
1340  out._name = name;
1341  out._type = dst_type;
1342  if (dst_type == 0) {
1343  out._table = asciiTable(name, "w", format_str,
1344  NULL, NULL, NULL);
1345  ret = at_open(&(out._table));
1346  if (ret != 0) {
1347  error("psiAsciiTableOutput: Could not open %s", name);
1348  out._valid = 0;
1349  } else {
1350  at_writeformat(out._table);
1351  }
1352  } else {
1353  out._psi = psiOutput(name);
1354  ret = psi_send(out._psi, format_str, strlen(format_str));
1355  if (ret != 0) {
1356  error("psiAsciiTableOutput: Failed to receive format string.");
1357  out._valid = 0;
1358  } else {
1359  out._table = asciiTable(name, "0", format_str,
1360  NULL, NULL, NULL);
1361  out._psi._fmt = format_str;
1362  out._psi._nfmt = count_formats(out._psi._fmt);
1363  }
1364  }
1365  return out;
1366 };
1367 
1376 static inline
1377 psiAsciiTableInput_t psiAsciiTableInput(const char *name, int src_type) {
1379  int ret;
1380  out._valid = 1;
1381  out._name = name;
1382  out._type = src_type;
1383  if (src_type == 0) { // Direct file interface
1384  out._table = asciiTable(name, "r", NULL,
1385  NULL, NULL, NULL);
1386  ret = at_open(&(out._table));
1387  if (ret != 0) {
1388  error("psiAsciiTableInput: Could not open %s", name);
1389  out._valid = 0;
1390  }
1391  } else {
1392  out._psi = psiInput(name);
1393  out._psi._fmt = (char*)malloc(PSI_MSG_MAX);
1394  ret = psi_recv(out._psi, out._psi._fmt, PSI_MSG_MAX);
1395  if (ret < 0) {
1396  error("psiAsciiTableInput: Failed to receive format string.");
1397  out._valid = 0;
1398  } else {
1399  out._psi._nfmt = count_formats(out._psi._fmt);
1400  out._table = asciiTable(name, "0", out._psi._fmt,
1401  NULL, NULL, NULL);
1402  }
1403  }
1404  return out;
1405 };
1406 
1414 static inline
1415 int at_psi_send(psiAsciiTableOutput_t t, char *data, int len){
1416  return psi_send_nolimit(t._psi, data, len);
1417 };
1418 
1428 static inline
1429 int at_psi_recv(psiAsciiTableInput_t t, char **data, int len){
1430  return psi_recv_nolimit(t._psi, data, len);
1431 };
1432 
1438 static inline
1439 int at_send_eof(psiAsciiTableOutput_t t) {
1440  char buf[PSI_MSG_MAX] = PSI_MSG_EOF;
1441  int ret = psi_send_nolimit(t._psi, buf, strlen(buf));
1442  return ret;
1443 };
1444 
1451 static inline
1452 int vsend_row(psiAsciiTableOutput_t t, va_list ap) {
1453  int ret;
1454  if (t._type == 0) {
1455  ret = at_vwriteline(t._table, ap);
1456  if (ret > 0)
1457  ret = 0;
1458  else
1459  ret = -1;
1460  } else {
1461  ret = vpsiSend_nolimit(t._psi, ap);
1462  }
1463  return ret;
1464 };
1465 
1474 static inline
1475 int vrecv_row(psiAsciiTableInput_t t, va_list ap) {
1476  int ret;
1477  if (t._type == 0) {
1478  ret = at_vreadline(t._table, ap);
1479  } else {
1480  ret = vpsiRecv_nolimit(t._psi, ap);
1481  }
1482  return ret;
1483 };
1484 
1491 static inline
1492 int at_send_row(psiAsciiTableOutput_t t, ...) {
1493  int ret;
1494  va_list ap;
1495  va_start(ap, t);
1496  ret = vsend_row(t, ap);
1497  va_end(ap);
1498  return ret;
1499 };
1500 
1509 static inline
1510 int at_recv_row(psiAsciiTableInput_t t, ...) {
1511  int ret;
1512  va_list ap;
1513  va_start(ap, t);
1514  ret = vrecv_row(t, ap);
1515  va_end(ap);
1516  return ret;
1517 };
1518 
1527 static inline
1528 int vsend_array(psiAsciiTableOutput_t t, int nrows, va_list ap) {
1529  int ret;
1530  if (t._type == 0) {
1531  printf("Not currently implemented.\n");
1532  ret = -1;
1533  } else {
1534  char *data = NULL;
1535  ret = at_varray_to_bytes(t._table, &data, nrows, ap);
1536  /* printf("Sending %d: ", ret); */
1537  /* fwrite(data, ret, 1, stdout); */
1538  /* printf("\n"); */
1539  if (ret >= 0) {
1540  ret = psi_send_nolimit(t._psi, data, ret);
1541  } else {
1542  char buf[10] = "";
1543  psi_send(t._psi, buf, 0);
1544  }
1545  free(data);
1546  }
1547  return ret;
1548 };
1549 
1557 static inline
1558 int vrecv_array(psiAsciiTableInput_t t, va_list ap) {
1559  int ret;
1560  if (t._type == 0) {
1561  printf("Not currently implemented.\n");
1562  ret = -1;
1563  } else {
1564  int data_siz = 10*t._table.row_siz;
1565  char *data = (char*)malloc(data_siz);
1566  ret = psi_recv_nolimit(t._psi, &data, data_siz);
1567  /* printf("Received: "); */
1568  /* fwrite(data, ret, 1, stdout); */
1569  /* printf("\n"); */
1570  if (ret >= 0) {
1571  ret = at_vbytes_to_array(t._table, data, ret, ap);
1572  }
1573  }
1574  return ret;
1575 };
1576 
1585 static inline
1586 int at_send_array(psiAsciiTableOutput_t t, int nrows, ...) {
1587  int ret;
1588  va_list ap;
1589  va_start(ap, nrows);
1590  ret = vsend_array(t, nrows, ap);
1591  va_end(ap);
1592  return ret;
1593 };
1594 
1602 static inline
1603 int at_recv_array(psiAsciiTableInput_t t, ...) {
1604  int ret;
1605  va_list ap;
1606  va_start(ap, t);
1607  ret = vrecv_array(t, ap);
1608  va_end(ap);
1609  return ret;
1610 };
1611 
1616 static inline
1617 void cleanup_pati(psiAsciiTableInput_t *t) {
1618  if ((*t)._type != 0)
1619  free((*t)._psi._fmt);
1620  at_close(&((*t)._table));
1621  at_cleanup(&((*t)._table));
1622 };
1623 
1628 static inline
1629 void cleanup_pato(psiAsciiTableOutput_t *t) {
1630  at_close(&((*t)._table));
1631  at_cleanup(&((*t)._table));
1632 };
1633 
int row_siz
Size of an entire row in bytes.
Definition: AsciiTable.h:94
int _nfmt
Number of fields expected from format string.
Definition: PsiInterface.h:236
int _type
0 if _name is a local table, 1 if it is a message queue.
Definition: PsiInterface.h:1319
int _handle
Queue handle.
Definition: PsiInterface.h:233
psiInput_t _psi
Associated input handler for input channel.
Definition: PsiInterface.h:1080
psiOutput_t _psi
Associated output handler for queues.
Definition: PsiInterface.h:1310
long mtype
Message buffer type.
Definition: PsiInterface.h:213
const char * _name
Path to local table or name of message queue.
Definition: PsiInterface.h:1318
Message buffer structure.
Definition: PsiInterface.h:212
asciiFile_t _file
Associated output handler for local files.
Definition: PsiInterface.h:1068
int _handle
Queue handle.
Definition: PsiInterface.h:222
int _type
0 for local file, 1 for output channel.
Definition: PsiInterface.h:1067
psiInput_t _psi
Associated input handler for queues.
Definition: PsiInterface.h:1321
const char * _name
Path to local file or name of input channel.
Definition: PsiInterface.h:1077
asciiTable_t _table
Associated output handler for local tables.
Definition: PsiInterface.h:1309
const char * _name
Queue name.
Definition: PsiInterface.h:223
char * _outFmt
Format string used for output queue.
Definition: PsiInterface.h:830
int _nfmt
Number of fields expected from format string.
Definition: PsiInterface.h:225
Structure for handling output to an ASCII table.
Definition: PsiInterface.h:1305
char * _fmt
Format for formatting queue messages.
Definition: PsiInterface.h:235
Remote Procedure Call (RPC) structure. Contains information required to coordinate sending/receiving ...
Definition: PsiInterface.h:826
int _valid
Indicates if the structure was succesfully initialized.
Definition: PsiInterface.h:1076
char * _inFmt
Format string used for input queue.
Definition: PsiInterface.h:829
const char * _name
Path to local table or name of message queue.
Definition: PsiInterface.h:1307
int _valid
Success or failure of initializing the structure.
Definition: PsiInterface.h:1317
Output queue structure. Contains information on an output queue.
Definition: PsiInterface.h:232
psiInput_t _input
Input queue structure.
Definition: PsiInterface.h:827
char * _fmt
Format for interpreting queue messages.
Definition: PsiInterface.h:224
Input queue structure. Contains information on an input queue.
Definition: PsiInterface.h:221
Structure for handling input from an ASCII table.
Definition: PsiInterface.h:1316
char data[PSI_MSG_MAX]
Buffer for the message.
Definition: PsiInterface.h:214
int _type
0 if _name is a local table, 1 if it is a message queue.
Definition: PsiInterface.h:1308
const char * _name
Queue name.
Definition: PsiInterface.h:234
Structure of information for output to a file line by line.
Definition: PsiInterface.h:1064
Structure containing information about an ASCII text file.
Definition: AsciiFile.h:13
psiOutput_t _psi
Associated output handler for output channel.
Definition: PsiInterface.h:1069
int _valid
Success or failure of initializing the structure.
Definition: PsiInterface.h:1306
Structure of information for input from a file line by line.
Definition: PsiInterface.h:1075
asciiTable_t _table
Associated input handler for local tables.
Definition: PsiInterface.h:1320
Structure containing information about an ASCII table.
Definition: AsciiTable.h:87
int _type
0 for local file, 1 for input channel.
Definition: PsiInterface.h:1078
const char * _name
Path to local file or name of output channel.
Definition: PsiInterface.h:1066
asciiFile_t _file
Associated input handler for local files.
Definition: PsiInterface.h:1079
int _valid
Indicates if the structure was succesfully initialized.
Definition: PsiInterface.h:1065
psiOutput_t _output
Output queue structure.
Definition: PsiInterface.h:828