14 #include <../dataio/AsciiFile.h> 15 #include <../dataio/AsciiTable.h> 19 #define PSI_MSG_MAX LINE_SIZE_MAX 21 #define PSI_MSG_EOF "EOF!!!" 23 #define _psiTrackChannels 256 25 static char * _psiChannelNames[_psiTrackChannels];
27 static unsigned _psiChannelsUsed = 0;
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");
68 void psiInfo(
const char* fmt, ...) {
71 psiLog(
"INFO", fmt, ap);
83 void psiDebug(
const char* fmt, ...) {
86 psiLog(
"DEBUG", fmt, ap);
98 void psiError(
const char* fmt, ...) {
101 psiLog(
"ERROR", fmt, ap);
105 #define error psiError 107 #if PSI_DEBUG == INFO 109 #define debug while (0) psiDebug 110 #elif PSI_DEBUG == DEBUG 111 #define debug psiInfo 112 #define info psiDebug 114 #define debug while (0) psiDebug 115 #define info while (0) psiInfo 118 #define debug while (0) psiDebug 119 #define info while (0) psiInfo 157 int psi_mq(
char *name,
const char *yamlName){
159 char *qid = getenv(name);
162 error(
"psi_mq: Channel %s not registered, model/YAML mismatch (yaml=%s)\n",
166 strcpy(nm_opp, yamlName);
167 if (strcmp(name+strlen(yamlName),
"_IN") == 0)
168 strcat(nm_opp,
"_OUT");
170 strcat(nm_opp,
"_IN");
171 qid = getenv(nm_opp);
173 error(
"psi_mq: Directed channel %s exists, but requested channel %s does not\n",
179 for (
unsigned i =0; i < _psiChannelsUsed; i++ ){
180 if (0 == strcmp(_psiChannelNames[i], name)){
181 error(
"Attempt to re-use channel %s", name);
186 if (_psiChannelsUsed >= _psiTrackChannels) {
187 error(
"Too many channels in use, max: %d\n", _psiTrackChannels);
190 _psiChannelNames[_psiChannelsUsed++] = qid;
191 int qkey = atoi(qid);
192 int fid = msgget(qkey, 0600);
202 int is_eof(
const char *buf) {
203 if (strcmp(buf, PSI_MSG_EOF) == 0)
256 ret.
_handle = psi_mq(nm, name);
274 ret.
_handle = psi_mq(nm, name);
284 return psiOutput(name);
290 return psiInput(name);
304 psiOutput_t psiOutputFmt(
const char *name,
char *fmtString){
306 ret.
_fmt = fmtString;
307 ret.
_nfmt = count_formats(fmtString);
322 psiInput_t psiInputFmt(
const char *name,
char *fmtString){
324 ret.
_fmt = fmtString;
325 ret.
_nfmt = count_formats(fmtString);
342 rc = msgctl(psiQ.
_handle, IPC_STAT, &buf);
344 error(
"psi_output_nmsg: Could not access queue.");
347 num_messages = buf.msg_qnum;
364 rc = msgctl(psiQ.
_handle, IPC_STAT, &buf);
366 error(
"psi_input_nmsg: Could not access queue.");
369 num_messages = buf.msg_qnum;
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);
392 memcpy(t.
data, data, len);
395 ret = msgsnd(psiQ.
_handle, &t, len, IPC_NOWAIT);
396 debug(
"psi_send(%s): msgsnd returned %d", psiQ.
_name, ret);
399 debug(
"psi_send(%s): msgsnd, sleep", psiQ.
_name);
402 error(
"psi_send: msgsend(%d, %p, %d, IPC_NOWAIT) ret(%d), errno(%d): %s",
403 psiQ.
_handle, &t, len, ret, errno, strerror(errno));
408 debug(
"psi_send(%s): returning %d", psiQ.
_name, ret);
423 int psi_recv(
psiInput_t psiQ,
char *data,
int len){
424 debug(
"psi_recv(%s)", psiQ.
_name);
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);
434 debug(
"psi_recv(%s): received input: %d bytes, ret=%d",
440 memcpy(data, t.
data, ret);
443 debug(
"psi_recv: msgrecv(%d, %p, %d, 0, IPC_NOWAIT: %s", psiQ.
_handle, &t, len, strerror(errno));
447 debug(
"psi_recv(%s): returns %d bytes\n", psiQ.
_name, ret);
463 int psi_send_nolimit(
psiOutput_t psiQ,
char *data,
int len){
464 debug(
"psi_send_nolimit(%s): %d bytes", psiQ.
_name, len);
467 char msg[PSI_MSG_MAX];
468 sprintf(msg,
"%ld", (
long)(len));
469 ret = psi_send(psiQ, msg, strlen(msg));
471 debug(
"psi_send_nolimit(%s): sending size of payload failed.", psiQ.
_name);
476 if ((len - prev) > PSI_MSG_MAX)
477 msgsiz = PSI_MSG_MAX;
480 ret = psi_send(psiQ, data + prev, msgsiz);
482 debug(
"psi_send_nolimit(%s): send interupted at %d of %d bytes.",
483 psiQ.
_name, prev, len);
487 debug(
"psi_send_nolimit(%s): %d of %d bytes sent",
488 psiQ.
_name, prev, len);
491 debug(
"psi_send_nolimit(%s): %d bytes completed", psiQ.
_name, len);
509 int psi_recv_nolimit(
psiInput_t psiQ,
char **data,
int len0){
510 debug(
"psi_recv_nolimit(%s)", psiQ.
_name);
514 char msg[PSI_MSG_MAX];
516 ret = psi_recv(psiQ, msg, PSI_MSG_MAX);
518 debug(
"psi_recv_nolimit(%s): failed to receive payload size.", psiQ.
_name);
521 ret = sscanf(msg,
"%ld", &len);
523 debug(
"psi_recv_nolimit(%s): failed to parse payload size (%s)",
529 *data = (
char*)realloc(*data, len);
533 if ((len - prev) > PSI_MSG_MAX)
534 msgsiz = PSI_MSG_MAX;
537 ret = psi_recv(psiQ, (*data) + prev, msgsiz);
539 debug(
"psi_recv_nolimit(%s): recv interupted at %d of %d bytes.",
540 psiQ.
_name, prev, len);
544 debug(
"psi_recv_nolimit(%s): %d of %d bytes received",
545 psiQ.
_name, prev, len);
548 debug(
"psi_recv_nolimit(%s): %d bytes completed", psiQ.
_name, prev);
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);
591 error(
"vpsiSend(%s): vsnprintf encoding error", psiQ.
_name);
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);
598 ret = psi_send(psiQ, buf, ret);
599 debug(
"vpsiSend(%s): psi_send returns %d", psiQ.
_name, ret);
616 char buf[PSI_MSG_MAX];
617 int ret = psi_recv(psiQ, buf, PSI_MSG_MAX);
619 error(
"vpsiRecv(%s): Error receiving.", psiQ.
_name);
622 debug(
"vpsiRecv(%s): psi_recv returns %d: %s", psiQ.
_name, ret, buf);
624 debug(
"vpsiRecv(%s): EOF received.\n", psiQ.
_name);
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",
633 debug(
"vpsiRecv(%s): vsscanf returns %d", psiQ.
_name, sret);
650 int ret = vpsiSend(psiQ, ap);
670 int ret = vpsiRecv(psiQ, ap);
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);
690 error(
"vpsiSend_nolimit(%s): vsnprintf encoding error", psiQ.
_name);
693 }
else if (ret > PSI_MSG_MAX) {
694 buf = (
char*)realloc(buf, ret+1);
695 ret = vsnprintf(buf, ret, psiQ.
_fmt, ap);
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);
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);
720 error(
"vpsiRecv_nolimit(%s): Error receiving.", psiQ.
_name);
724 debug(
"vpsiRecv_nolimit(%s): psi_recv returns %d", psiQ.
_name, ret);
726 debug(
"vpsiRecv(%s): EOF received.\n", psiQ.
_name);
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",
736 debug(
"vpsiRecv_nolimit(%s): vsscanf returns %d", psiQ.
_name, ret);
755 int ret = vpsiSend_nolimit(psiQ, ap);
775 int ret = vpsiRecv_nolimit(psiQ, ap);
845 psiRpc_t psiRpc(
const char *outName,
char *outFormat,
846 const char *inName,
char *inFormat){
850 rpc.
_input = psiInputFmt(inName, inFormat);
851 rpc.
_output = psiOutputFmt(outName, outFormat);
866 psiRpc_t psiRpcClient(
const char *name,
char *outFormat,
char *inFormat){
867 psiRpc_t rpc = psiRpc(name, outFormat, name, inFormat);
882 psiRpc_t psiRpcServer(
const char *name,
char *inFormat,
char *outFormat){
883 psiRpc_t rpc = psiRpc(name, outFormat, name, inFormat);
898 int vrpcSend(
psiRpc_t rpc, va_list ap) {
899 int ret = vpsiSend_nolimit(rpc.
_output, ap);
917 int vrpcRecv(
psiRpc_t rpc, va_list ap) {
918 int ret = vpsiRecv_nolimit(rpc.
_input, ap);
936 int ret = vrpcSend(rpc, ap);
958 int ret = vrpcRecv(rpc, ap);
977 int vrpcCall(
psiRpc_t rpc, va_list ap) {
981 ret = vpsiSend_nolimit(rpc.
_output, ap);
983 printf(
"vrpcCall: vpsiSend_nolimit error: ret %d: %s\n", ret, strerror(errno));
990 ret = vpsiRecv_nolimit(rpc.
_input, op);
1014 ret = vrpcCall(rpc, ap);
1097 out.
_type = dst_type;
1099 if (dst_type == 0) {
1100 out.
_file = asciiFile(name,
"w", NULL, NULL);
1101 ret = af_open(&(out.
_file));
1103 error(
"psiAsciiFileOutput: Could not open %s", name);
1107 out.
_psi = psiOutput(name);
1108 out.
_file = asciiFile(name,
"0", NULL, NULL);
1127 out.
_type = src_type;
1129 if (src_type == 0) {
1130 out.
_file = asciiFile(name,
"r", NULL, NULL);
1131 ret = af_open(&(out.
_file));
1133 error(
"psiAsciiFileInput: Could not open %s", name);
1137 out.
_psi = psiInput(name);
1138 out.
_file = asciiFile(name,
"0", NULL, NULL);
1150 char buf[PSI_MSG_MAX] = PSI_MSG_EOF;
1151 int ret = psi_send(t.
_psi, buf, strlen(buf));
1168 ret = af_readline_full(t.
_file, &line, &n);
1170 ret = psi_recv(t.
_psi, line, n);
1189 ret = af_writeline_full(t.
_file, line);
1191 ret = psi_send(t.
_psi, line, strlen(line));
1202 af_close(&((*t)._file));
1211 af_close(&((*t)._file));
1341 out.
_type = dst_type;
1342 if (dst_type == 0) {
1343 out.
_table = asciiTable(name,
"w", format_str,
1345 ret = at_open(&(out.
_table));
1347 error(
"psiAsciiTableOutput: Could not open %s", name);
1350 at_writeformat(out.
_table);
1353 out.
_psi = psiOutput(name);
1354 ret = psi_send(out.
_psi, format_str, strlen(format_str));
1356 error(
"psiAsciiTableOutput: Failed to receive format string.");
1359 out.
_table = asciiTable(name,
"0", format_str,
1382 out.
_type = src_type;
1383 if (src_type == 0) {
1384 out.
_table = asciiTable(name,
"r", NULL,
1386 ret = at_open(&(out.
_table));
1388 error(
"psiAsciiTableInput: Could not open %s", name);
1392 out.
_psi = psiInput(name);
1393 out.
_psi.
_fmt = (
char*)malloc(PSI_MSG_MAX);
1396 error(
"psiAsciiTableInput: Failed to receive format string.");
1416 return psi_send_nolimit(t.
_psi, data, len);
1430 return psi_recv_nolimit(t.
_psi, data, len);
1440 char buf[PSI_MSG_MAX] = PSI_MSG_EOF;
1441 int ret = psi_send_nolimit(t.
_psi, buf, strlen(buf));
1455 ret = at_vwriteline(t.
_table, ap);
1461 ret = vpsiSend_nolimit(t.
_psi, ap);
1478 ret = at_vreadline(t.
_table, ap);
1480 ret = vpsiRecv_nolimit(t.
_psi, ap);
1496 ret = vsend_row(t, ap);
1514 ret = vrecv_row(t, ap);
1531 printf(
"Not currently implemented.\n");
1535 ret = at_varray_to_bytes(t.
_table, &data, nrows, ap);
1540 ret = psi_send_nolimit(t.
_psi, data, ret);
1543 psi_send(t.
_psi, buf, 0);
1561 printf(
"Not currently implemented.\n");
1565 char *data = (
char*)malloc(data_siz);
1566 ret = psi_recv_nolimit(t.
_psi, &data, data_siz);
1571 ret = at_vbytes_to_array(t.
_table, data, ret, ap);
1589 va_start(ap, nrows);
1590 ret = vsend_array(t, nrows, ap);
1607 ret = vrecv_array(t, ap);
1618 if ((*t)._type != 0)
1619 free((*t)._psi._fmt);
1620 at_close(&((*t)._table));
1621 at_cleanup(&((*t)._table));
1630 at_close(&((*t)._table));
1631 at_cleanup(&((*t)._table));
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 _handle
Queue handle.
Definition: PsiInterface.h:233
psiOutput_t _psi
Associated output handler for queues.
Definition: PsiInterface.h:1310
long mtype
Message buffer type.
Definition: PsiInterface.h:213
Message buffer structure.
Definition: PsiInterface.h:212
asciiFile_t _file
Associated output handler for local files.
Definition: PsiInterface.h:1068
int _type
0 for local file, 1 for output channel.
Definition: PsiInterface.h:1067
asciiTable_t _table
Associated output handler for local tables.
Definition: PsiInterface.h:1309
char * _outFmt
Format string used for output queue.
Definition: PsiInterface.h:830
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
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
Output queue structure. Contains information on an output queue.
Definition: PsiInterface.h:232
psiInput_t _input
Input queue structure.
Definition: PsiInterface.h:827
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 containing information about an ASCII table.
Definition: AsciiTable.h:87
const char * _name
Path to local file or name of output channel.
Definition: PsiInterface.h:1066
int _valid
Indicates if the structure was succesfully initialized.
Definition: PsiInterface.h:1065
psiOutput_t _output
Output queue structure.
Definition: PsiInterface.h:828