2 #ifndef CISCOMMUNICATION_H_ 3 #define CISCOMMUNICATION_H_ 6 #include <../serialize/serialize.h> 7 #include <comm_header.h> 12 #include <ServerComm.h> 13 #include <ClientComm.h> 14 #include <AsciiFileComm.h> 15 #include <AsciiTableComm.h> 16 #include <DefaultComm.h> 23 static void **vcomms2clean = NULL;
24 static size_t ncomms2clean = 0;
25 static size_t clean_registered = 0;
29 int comm_send_eof(
const comm_t x);
31 int comm_nmsg(
const comm_t x);
40 int free_comm_type(
comm_t *x) {
41 comm_type t = x->
type;
44 ret = free_ipc_comm(x);
45 else if (t == ZMQ_COMM)
46 ret = free_zmq_comm(x);
47 else if (t == RPC_COMM)
48 ret = free_rpc_comm(x);
49 else if (t == SERVER_COMM)
50 ret = free_server_comm(x);
51 else if (t == CLIENT_COMM)
52 ret = free_client_comm(x);
53 else if (t == ASCII_FILE_COMM)
54 ret = free_ascii_file_comm(x);
55 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
56 ret = free_ascii_table_comm(x);
58 cislog_error(
"free_comm_type: Unsupported comm_type %d", t);
73 cislog_debug(
"free_comm(%s)", x->
name);
76 if (_cis_error_flag == 0) {
77 cislog_debug(
"free_comm(%s): Sending EOF", x->
name);
79 while (comm_nmsg(*x) > 0) {
80 cislog_debug(
"free_comm(%s): draining %d messages",
81 x->
name, comm_nmsg(*x));
82 usleep(CIS_SLEEP_TIME);
85 cislog_error(
"free_comm(%s): Error registered", x->
name);
88 ret = free_comm_type(x);
92 if (vcomms2clean[idx] != NULL) {
93 free(vcomms2clean[idx]);
94 vcomms2clean[idx] = NULL;
104 void clean_comms(
void) {
106 cislog_debug(
"atexit begin");
107 for (i = 0; i < ncomms2clean; i++) {
108 if (vcomms2clean[i] != NULL) {
109 free_comm((
comm_t*)(vcomms2clean[i]));
112 if (vcomms2clean != NULL) {
117 #if defined(ZMQINSTALLED) 121 cislog_debug(
"atexit done");
132 int register_comm(
comm_t *x) {
133 if (clean_registered == 0) {
135 clean_registered = 1;
140 void **t_vcomms2clean = (
void**)realloc(vcomms2clean,
sizeof(
void*)*(ncomms2clean + 1));
141 if (t_vcomms2clean == NULL) {
142 cislog_error(
"register_comm(%s): Failed to realloc the comm list.", x->
name);
145 vcomms2clean = t_vcomms2clean;
147 vcomms2clean[ncomms2clean++] = (
void*)x;
158 int new_comm_type(
comm_t *x) {
159 comm_type t = x->
type;
162 flag = new_ipc_address(x);
163 else if (t == ZMQ_COMM)
164 flag = new_zmq_address(x);
165 else if (t == RPC_COMM)
166 flag = new_rpc_address(x);
167 else if (t == SERVER_COMM)
168 flag = new_server_address(x);
169 else if (t == CLIENT_COMM)
170 flag = new_client_address(x);
171 else if (t == ASCII_FILE_COMM)
172 flag = new_ascii_file_address(x);
173 else if (t == ASCII_TABLE_COMM)
174 flag = new_ascii_table_address(x);
175 else if (t == ASCII_TABLE_ARRAY_COMM)
176 flag = new_ascii_table_array_address(x);
178 cislog_error(
"new_comm_type: Unsupported comm_type %d", t);
191 int init_comm_type(
comm_t *x) {
192 comm_type t = x->
type;
195 flag = init_ipc_comm(x);
196 else if (t == ZMQ_COMM)
197 flag = init_zmq_comm(x);
198 else if (t == RPC_COMM)
199 flag = init_rpc_comm(x);
200 else if (t == SERVER_COMM)
201 flag = init_server_comm(x);
202 else if (t == CLIENT_COMM)
203 flag = init_client_comm(x);
204 else if (t == ASCII_FILE_COMM)
205 flag = init_ascii_file_comm(x);
206 else if (t == ASCII_TABLE_COMM)
207 flag = init_ascii_table_comm(x);
208 else if (t == ASCII_TABLE_ARRAY_COMM)
209 flag = init_ascii_table_array_comm(x);
211 cislog_error(
"init_comm_type: Unsupported comm_type %d", t);
214 cislog_debug(
"init_comm_type(%s): Done, flag = %d", x->
name, flag);
229 comm_t new_comm(
char *address,
const char *direction,
const comm_type t,
231 comm_t *ret = new_comm_base(address, direction, t, seri_info);
233 cislog_error(
"new_comm: Could not initialize base.");
234 return empty_comm_base();
237 if (address == NULL) {
238 flag = new_comm_type(ret);
240 flag = init_comm_type(ret);
243 cislog_error(
"new_comm: Failed to initialize new comm address.");
246 if (strlen(ret->name) == 0) {
247 sprintf(ret->name,
"temp.%s", ret->address);
249 flag = register_comm(ret);
251 cislog_error(
"new_comm: Failed to register new comm.");
271 comm_t init_comm(
const char *name,
const char *direction,
const comm_type t,
272 const void *seri_info) {
273 cislog_debug(
"init_comm: Initializing comm.");
275 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
276 _set_abort_behavior(0,_WRITE_ABORT_MSG);
278 comm_t *ret = init_comm_base(name, direction, t, seri_info);
280 cislog_error(
"init_comm(%s): Could not initialize base.", name);
281 return empty_comm_base();
283 int flag = init_comm_type(ret);
285 cislog_error(
"init_comm(%s): Could not initialize comm.", name);
288 flag = register_comm(ret);
290 cislog_error(
"init_comm(%s): Failed to register new comm.", name);
294 cislog_debug(
"init_comm(%s): Initialized comm.", name);
304 int comm_nmsg(
const comm_t x) {
307 cislog_error(
"comm_nmsg: Invalid comm");
310 comm_type t = x.
type;
312 ret = ipc_comm_nmsg(x);
313 else if (t == ZMQ_COMM)
314 ret = zmq_comm_nmsg(x);
315 else if (t == RPC_COMM)
316 ret = rpc_comm_nmsg(x);
317 else if (t == SERVER_COMM)
318 ret = server_comm_nmsg(x);
319 else if (t == CLIENT_COMM)
320 ret = client_comm_nmsg(x);
321 else if (t == ASCII_FILE_COMM)
322 ret = ascii_file_comm_nmsg(x);
323 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
324 ret = ascii_table_comm_nmsg(x);
326 cislog_error(
"comm_nmsg: Unsupported comm_type %d", t);
341 int comm_send_single(
const comm_t x,
const char *data,
const size_t len) {
344 cislog_error(
"comm_send_single: Invalid comm");
347 comm_type t = x.
type;
349 ret = ipc_comm_send(x, data, len);
350 else if (t == ZMQ_COMM)
351 ret = zmq_comm_send(x, data, len);
352 else if (t == RPC_COMM)
353 ret = rpc_comm_send(x, data, len);
354 else if (t == SERVER_COMM)
355 ret = server_comm_send(x, data, len);
356 else if (t == CLIENT_COMM)
357 ret = client_comm_send(x, data, len);
358 else if (t == ASCII_FILE_COMM)
359 ret = ascii_file_comm_send(x, data, len);
360 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
361 ret = ascii_table_comm_send(x, data, len);
363 cislog_error(
"comm_send_single: Unsupported comm_type %d", t);
387 sprintf(head.
id,
"%d", rand());
393 if (x.
type == CLIENT_COMM) {
399 if (serializer->
type == DIRECT_SERI) {
401 }
else if (serializer->
type == FORMAT_SERI) {
404 }
else if (serializer->
type == ARRAY_SERI) {
408 }
else if (serializer->
type == ASCII_TABLE_SERI) {
412 }
else if (serializer->
type == ASCII_TABLE_ARRAY_SERI) {
417 }
else if (serializer->
type == PLY_SERI) {
419 }
else if (serializer->
type == OBJ_SERI) {
424 if (x.
type == SERVER_COMM) {
426 if (res_comm[0] == NULL) {
427 cislog_error(
"comm_send_multipart_header(%s): no response comm registered",
432 x0 = &((*res_comm)[0]);
435 }
else if (x.
type == CLIENT_COMM) {
436 if (!(is_eof(data))) {
437 head = client_response_header(x, head);
444 if (x0->
type == ZMQ_COMM) {
445 char *reply_address = set_reply_send(x0);
446 if (reply_address == NULL) {
447 cislog_error(
"comm_send_multipart_header: Could not set reply address.");
464 int comm_send_multipart(
const comm_t x,
const char *data,
const size_t len) {
466 int headbuf_len = CIS_MSG_BUF;
467 int headlen = 0, ret = -1;
469 cislog_error(
"comm_send_multipart: Invalid comm");
472 comm_t xmulti = empty_comm_base();
474 comm_head_t head = comm_send_multipart_header(x, data, len);
475 if (head.
valid == 0) {
476 cislog_error(
"comm_send_multipart: Invalid header generated.");
479 char *headbuf = (
char*)malloc(headbuf_len);
480 if (headbuf == NULL) {
481 cislog_error(
"comm_send_multipart: Failed to malloc headbuf.");
486 headlen = format_comm_header(head, headbuf, headbuf_len);
488 cislog_error(
"comm_send_multipart: Failed to format header.");
493 if (((
size_t)headlen + len + 1) > (
size_t)headbuf_len) {
494 char *t_headbuf = (
char*)realloc(headbuf, (
size_t)headlen + len + 1);
495 if (t_headbuf == NULL) {
496 cislog_error(
"comm_send_multipart: Failed to realloc headbuf.");
501 headbuf_len = headlen + (int)len + 1;
504 memcpy(headbuf + headlen, data, len);
506 headbuf[headlen] =
'\0';
512 xmulti = new_comm(NULL,
"send", x.
type, NULL);
513 if (!(xmulti.
valid)) {
514 cislog_error(
"comm_send_multipart: Failed to initialize a new comm.");
522 if (xmulti.
type == ZMQ_COMM) {
523 char *reply_address = set_reply_send(&xmulti);
524 if (reply_address == NULL) {
525 cislog_error(
"comm_send_multipart: Could not set worker reply address.");
530 headlen = format_comm_header(head, headbuf, headbuf_len);
532 cislog_error(
"comm_send_multipart: Failed to format header.");
539 ret = comm_send_single(x, headbuf, headlen);
541 cislog_error(
"comm_send_multipart: Failed to send header.");
548 cislog_debug(
"comm_send_multipart(%s): %d bytes completed", x.
name, head.
size);
555 while (prev < head.
size) {
559 msgsiz = head.
size - prev;
560 ret = comm_send_single(xmulti, data + prev, msgsiz);
562 cislog_debug(
"comm_send_multipart(%s): send interupted at %d of %d bytes.",
567 cislog_debug(
"comm_send_multipart(%s): %d of %d bytes sent",
571 cislog_debug(
"comm_send_multipart(%s): %d bytes completed", x.
name, head.
size);
591 int comm_send(
const comm_t x,
const char *data,
const size_t len) {
594 cislog_error(
"comm_send: Invalid comm");
598 cislog_error(
"comm_send(%s): sent_eof not initialized.", x.
name);
605 if (x.
type == CLIENT_COMM) {
610 cislog_debug(
"comm_send(%s): Sending EOF", x.
name);
612 cislog_error(
"comm_send(%s): EOF already sent", x.
name);
618 ret = comm_send_multipart(x, data, len);
620 cislog_debug(
"comm_send(%s): Sending as single message without a header.",
622 ret = comm_send_single(x, data, len);
625 cislog_debug(
"comm_send(%s): sent EOF, ret = %d", x.
name, ret);
638 int comm_send_eof(
const comm_t x) {
640 char buf[100] = CIS_MSG_EOF;
641 ret = comm_send(x, buf, strlen(buf));
658 int comm_recv_single(
const comm_t x,
char **data,
const size_t len,
659 const int allow_realloc) {
662 cislog_error(
"comm_recv_single: Invalid comm");
665 comm_type t = x.
type;
667 ret = ipc_comm_recv(x, data, len, allow_realloc);
668 else if (t == ZMQ_COMM)
669 ret = zmq_comm_recv(x, data, len, allow_realloc);
670 else if (t == RPC_COMM)
671 ret = rpc_comm_recv(x, data, len, allow_realloc);
672 else if (t == SERVER_COMM)
673 ret = server_comm_recv(x, data, len, allow_realloc);
674 else if (t == CLIENT_COMM)
675 ret = client_comm_recv(x, data, len, allow_realloc);
676 else if (t == ASCII_FILE_COMM)
677 ret = ascii_file_comm_recv(x, data, len, allow_realloc);
678 else if ((t == ASCII_TABLE_COMM) || (t == ASCII_TABLE_ARRAY_COMM))
679 ret = ascii_table_comm_recv(x, data, len, allow_realloc);
681 cislog_error(
"comm_recv: Unsupported comm_type %d", t);
697 int comm_recv_multipart(
const comm_t x,
char **data,
const size_t len,
698 const size_t headlen,
const int allow_realloc) {
701 cislog_error(
"comm_recv_multipart: Invalid comm");
705 comm_head_t head = parse_comm_header(*data, headlen);
707 cislog_error(
"comm_recv_multipart(%s): Error parsing header.", x.
name);
714 cislog_debug(
"comm_recv_multipart(%s): Updating serializer type to %d",
717 new_type = DIRECT_SERI;
719 new_type = FORMAT_SERI;
721 new_type = ASCII_TABLE_ARRAY_SERI;
726 new_type = ASCII_TABLE_SERI;
728 new_type = ASCII_TABLE_ARRAY_SERI;
736 ret = update_serializer(x.
serializer, new_type, new_info);
738 cislog_error(
"comm_recv_multipart(%s): Error updating serializer.", x.
name);
743 if ((new_type == ASCII_TABLE_SERI) || (new_type == ASCII_TABLE_ARRAY_SERI)) {
745 ret = at_update(table, x.
name,
"0");
747 cislog_error(
"comm_recv_multipart(%s): Failed to update asciiTable address.",
751 ret = simplify_formats(table->
format_str, CIS_MSG_MAX);
753 cislog_error(
"comm_recv_multipart(%s): Failed to simplify recvd table format.", x.
name);
756 }
else if (new_type == FORMAT_SERI) {
760 cislog_error(
"comm_recv_multipart(%s): Failed to simplify recvd format.", x.
name);
770 cislog_debug(
"comm_recv_multipart(%s): EOF received.", x.
name);
781 if (!(xmulti.
valid)) {
782 cislog_error(
"comm_recv_multipart: Failed to initialize a new comm.");
788 if (xmulti.
type == ZMQ_COMM) {
790 if (reply_socket < 0) {
791 cislog_error(
"comm_recv_multipart: Failed to set worker reply address.");
799 if ((head.
size + 1) > len) {
801 char *t_data = (
char*)realloc(*data, head.
size + 1);
802 if (t_data == NULL) {
803 cislog_error(
"comm_recv_multipart(%s): Failed to realloc buffer",
811 cislog_error(
"comm_recv_multipart(%s): buffer is not large enough",
818 char *pos = (*data) + prev;
819 while (prev < head.
size) {
820 msgsiz = head.
size - prev + 1;
821 ret = comm_recv_single(xmulti, &pos, msgsiz, 0);
823 cislog_debug(
"comm_recv_multipart(%s): recv interupted at %d of %d bytes.",
829 cislog_debug(
"comm_recv_multipart(%s): %d of %d bytes received",
833 cislog_debug(
"comm_recv_multipart(%s): %d bytes completed", x.
name, prev);
857 int comm_recv(
const comm_t x,
char *data,
const size_t len) {
858 int ret = comm_recv_single(x, &data, len, 0);
861 cislog_debug(
"comm_recv(%s): EOF received.", x.
name);
865 ret = comm_recv_multipart(x, &data, len, ret, 0);
868 cislog_error(
"comm_recv_realloc(%s): Failed to receive header or message.",
884 int comm_recv_realloc(
const comm_t x,
char **data,
const size_t len) {
885 int ret = comm_recv_single(x, data, len, 1);
888 cislog_debug(
"comm_recv_realloc(%s): EOF received.", x.
name);
892 ret = comm_recv_multipart(x, data, len, ret, 1);
895 cislog_error(
"comm_recv_realloc(%s): Failed to receive header or message.",
904 int comm_send_nolimit(
const comm_t x,
const char *data,
const size_t len) {
905 return comm_send(x, data, len);
914 int comm_send_nolimit_eof(
const comm_t x) {
917 cislog_error(
"comm_send_nolimit_eof: Invalid comm");
921 cislog_error(
"comm_send_nolimit_eof(%s): sent_eof not initialized.", x.
name);
925 char buf[2048] = CIS_MSG_EOF;
926 ret = comm_send_nolimit(x, buf, strlen(buf));
929 cislog_error(
"comm_send_nolimit_eof(%s): EOF already sent", x.
name);
948 int comm_recv_nolimit(
const comm_t x,
char **data,
const size_t len) {
949 return comm_recv_realloc(x, data, len);
963 int vcommSend(
const comm_t x, va_list ap) {
966 cislog_error(
"vcommSend: Invalid comm");
969 size_t buf_siz = CIS_MSG_BUF;
971 char *buf = (
char*)malloc(buf_siz);
973 cislog_error(
"vcommSend(%s): Failed to alloc buffer", x.
name);
977 if (x.
type == CLIENT_COMM) {
982 ret = serialize(*serializer, &buf, buf_siz, 1, &args_used, ap);
984 cislog_error(
"vcommSend(%s): serialization error", x.
name);
988 ret = comm_send(x, buf, ret);
989 cislog_debug(
"vcommSend(%s): comm_send returns %d", x.
name, ret);
1011 int vcommRecv(
const comm_t x, va_list ap) {
1014 cislog_error(
"vcommRecv: Invalid comm");
1018 size_t buf_siz = CIS_MSG_BUF;
1020 char *buf = (
char*)malloc(buf_siz);
1022 cislog_error(
"vcommSend(%s): Failed to alloc buffer", x.
name);
1025 ret = comm_recv_nolimit(x, &buf, buf_siz);
1031 cislog_debug(
"vcommRecv(%s): comm_recv returns %d: %.10s...", x.
name, ret, buf);
1034 if (x.
type == SERVER_COMM) {
1038 ret = deserialize(*serializer, buf, ret, ap);
1040 cislog_error(
"vcommRecv(%s): error deserializing message (ret=%d)",
1045 cislog_debug(
"vcommRecv(%s): deserialize_format returns %d", x.
name, ret);
1050 #define vcommSend_nolimit vcommSend 1051 #define vcommRecv_nolimit vcommRecv void * handle
Pointer to handle for comm.
Definition: CommBase.h:29
char format_str[LINE_SIZE_MAX]
Format string for rows.
Definition: AsciiTable.h:82
void * info
Pointer to any extra info comm requires.
Definition: CommBase.h:30
Communication structure.
Definition: CommBase.h:23
char address[COMM_ADDRESS_SIZE]
Comm address.
Definition: CommBase.h:26
char zmq_reply_worker[COMMBUFFSIZ]
Reply address for worker socket.
Definition: comm_header.h:35
int is_work_comm
Flag specifying if comm is a temporary work comm.
Definition: CommBase.h:41
Serializer structure.
Definition: SerializeBase.h:19
time_t * last_send
Clock output at time of last send.
Definition: CommBase.h:35
void * info
Pointer to any extra info serializer requires.
Definition: SerializeBase.h:21
int multipart
1 if message is multipart, 0 if it is not.
Definition: comm_header.h:22
size_t bodybeg
Start of body in header.
Definition: comm_header.h:24
size_t maxMsgSize
The maximum message size.
Definition: CommBase.h:32
size_t size_info
Size of allocate space for info.
Definition: SerializeBase.h:22
int * used
Flag specifying if the comm has been used.
Definition: CommBase.h:38
char address[COMMBUFFSIZ]
Address that message will comm in on.
Definition: comm_header.h:21
comm_type type
Comm type.
Definition: CommBase.h:24
int valid
1 if the header is valid, 0 otherwise.
Definition: comm_header.h:25
int is_file
Flag specifying if the comm connects directly to a file.
Definition: CommBase.h:40
int always_send_header
1 if comm should always send a header.
Definition: CommBase.h:33
seri_t * serializer
Serializer for comm messages.
Definition: CommBase.h:31
char zmq_reply[COMMBUFFSIZ]
Reply address for ZMQ sockets.
Definition: comm_header.h:34
char format_str[COMMBUFFSIZ]
Format string for serializer.
Definition: comm_header.h:30
size_t bodysiz
Size of body.
Definition: comm_header.h:23
char direction[COMM_DIR_SIZE]
send or recv for direction messages will go.
Definition: CommBase.h:27
char name[COMM_NAME_SIZE]
Comm name.
Definition: CommBase.h:25
int * sent_eof
Flag specifying if EOF has been sent.
Definition: CommBase.h:36
size_t size
Size of incoming message.
Definition: comm_header.h:20
int valid
1 if communicator initialized, 0 otherwise.
Definition: CommBase.h:28
int * recv_eof
Flag specifying if EOF has been received.
Definition: CommBase.h:37
int as_array
1 if messages will be serialized arrays.
Definition: comm_header.h:33
int serializer_type
Code indicating the type of serializer.
Definition: comm_header.h:29
Structure containing information about an ASCII table.
Definition: AsciiTable.h:80
char id[COMMBUFFSIZ]
Unique ID associated with this message.
Definition: comm_header.h:26
int index_in_register
Index of the comm in the comm register.
Definition: CommBase.h:34
seri_type type
Serializer type.
Definition: SerializeBase.h:20
Header information passed by comms for multipart messages.
Definition: comm_header.h:19