26 clock_gettime(CLOCK_REALTIME, &tsp);
28 return ((
double)tsp.tv_sec) + ((double)tsp.tv_nsec)/1e9;
37 fc->input_handler = 0;
38 fc->server_response = 0;
42 fc->last_atime_out = 0;
43 fc->last_atime_in = 0;
49 if(fc->server_response) free(fc->server_response);
53 fc->server_response = (
char *)malloc(buffsz*
sizeof(
char));
55 if(fc->server_response)
return 0;
58 ERRMSG(
"server_response malloc failed in setup_fifo_channel.");
63 int set_fifo_channel(fifo_channel *fc,
const char *fin,
const char *fout,
int (*inp_hand)(fifo_channel *),
void * adata)
65 if(fc->infname) free(fc->infname);
66 fc->infname = (
char *)malloc((strlen(fin)+1)*
sizeof(char));
69 ERRMSG(
"infname malloc failed in set_fifo_channel.");
73 if(fc->outfname) free(fc->outfname);
74 fc->outfname = (
char *)malloc((strlen(fout)+1)*
sizeof(char));
77 ERRMSG(
"outfname malloc failed in set_fifo_channel.");
81 strncpy(fc->infname, fin, (strlen(fin)+1));
82 strncpy(fc->outfname, fout, (strlen(fout)+1));
84 fc->input_handler = inp_hand;
98 if(mkfifo(fc->infname, S_IRUSR | S_IWUSR) !=0)
102 ERRMSG(
"Error creating input fifo.");
107 if(mkfifo(fc->outfname, S_IRUSR | S_IWUSR) !=0 )
111 ERRMSG(
"Error creating output fifo.");
128 ERRMSG(
"Error opening input fifo.");
137 nbytes = read(fc->fd_in, rbuff, 10);
138 while(nbytes > 0) nbytes = read(fc->fd_in, rbuff, 10);
153 ERRMSG(
"Error opening input fifo.");
159 nbytes = read(fc->fd_in, rbuff, 10);
160 while(nbytes > 0) nbytes = read(fc->fd_in, rbuff, 10);
173 ERRMSG(
"Error opening output fifo.");
187 ERRMSG(
"Error opening output fifo.");
200 ERRMSG(
"Fifo channel output not connected.");
206 ERRMSG(
"Output buffer to large.");
210 fc->server_response[0] =
'\0';
211 fc->seqmsg = fc->server_response;
213 nbytes = write(fc->fd_out, com, comlen+1);
225 ERRMSG(
"Fifo channel output not connected.");
231 ERRMSG(
"Output buffer to large.");
235 fc->server_response[0] =
'\0';
236 fc->seqmsg = fc->server_response;
238 memcpy(wbuff, com, comlen+1);
239 memcpy(wbuff+comlen+1, seqmsg, 6);
241 nbytes = write(fc->fd_out, wbuff, comlen+7);
248 int nbytes, totbytes;
257 ERRMSG(
"Fifo channel input not connected.");
264 nbytes = read(fc->fd_in, rbuffer,
RWBUFF_SZ);
270 while(nbytes > 0 && nbytes+totbytes < fc->sr_sz-1)
272 memcpy(fc->server_response + totbytes, rbuffer, nbytes);
277 nbytes = read(fc->fd_in, rbuffer,
RWBUFF_SZ);
282 if(nbytes < 0 && errno != EAGAIN)
287 if(totbytes + nbytes >= fc->sr_sz-1)
289 ERRMSG(
"input exceeded max server response size (fc->sr_sz). fifo read truncated.");
294 fc->server_response[totbytes] =
'\0';
296 slen = strlen(fc->server_response);
298 fc->seqmsg = &(fc->server_response[slen+1]);
311 else fc->seqmsg = fc->server_response;
320 fl.l_whence = SEEK_SET;
325 if(fcntl(fc->fd_out, F_GETLK, &fl) < 0)
return 1;
327 if(fl.l_type == F_UNLCK)
return 0;
360 fl->
fifo_ch = (fifo_channel *)malloc(nch*
sizeof(fifo_channel));
364 ERRMSG(
"Error allocating fifo_list memory.");
384 for(i = 0; i < fl->
nchan; i++)
388 snprintf(errmsg,
ERRMSG_SZ,
"Error opening input fifo channel %i (%s)", i, fl->
fifo_ch[i].infname);
401 for(i = 0; i < fl->
nchan; i++)
405 snprintf(errmsg,
ERRMSG_SZ,
"Error opening output fifo channel %i (%s)", i, fl->
fifo_ch[i].outfname);
420 for(i = 0; i < fl->
nchan; i++)
426 snprintf(errmsg,
ERRMSG_SZ,
"Error opening input fifo channel %i (%s)", i, fl->
fifo_ch[i].infname);
440 for(i = 0; i < fl->
nchan; i++)
444 snprintf(errmsg,
ERRMSG_SZ,
"Error opening output fifo channel %i (%s)", i, fl->
fifo_ch[i].outfname);
460 for(i = 0; i < fl->
maxfile+1; i++)
465 for(i =0; i < fl->
nchan; i++)
474 for(i=0;i<fl->
nchan;i++)
481 for(i=0; i < fl->
rq_sz; i++)
486 fl->read_queue_nextpos = 0;
521 for(i=0;i<fl->
nchan; i++)
523 if(fl->
fifo_ch[i].input_handler)
525 fcntl(fl->
fifo_ch[i].fd_in, F_SETSIG, RTSIGIO);
529 fcntl(fl->
fifo_ch[i].fd_in, F_SETSIG, RTSIGIGN);
536 void catch_fifo_pending_reads(
int signum __attribute__((unused)), siginfo_t *siginf,
void *ucont __attribute__((unused)))
545 if(siginf->si_code == POLL_IN)
556 ERRMSG(
"Condition met. RT Signal queue wraparound.");
570 ERRMSG(
"Standard SIGIO caught. RT Signal queue overflow.");
595 if(fl->
fifo_ch[i].input_handler)
615 fd = open(fname, O_RDWR| O_NONBLOCK);
618 snprintf(errmsg,
ERRMSG_SZ,
"Error opening fifo %s. Error = %s", fname, strerror(errno));
624 fcntl(fd, F_SETOWN, getpid());
625 fcntl(fd, F_SETFL, 0);
626 fcntl(fd, F_SETFL, O_ASYNC | O_RDWR | O_NONBLOCK);
631 fl.l_whence = SEEK_SET;
636 if(fcntl(fd, F_SETLK, &fl) < 0)
638 snprintf(errmsg,
ERRMSG_SZ,
"Error getting exclusive lock on %s. Error = %s. Closing file.", fname, strerror(errno));
656 fd = open(fname, O_RDWR | O_NONBLOCK);
659 snprintf(errmsg,
ERRMSG_SZ,
"Error opening fifo %s. Error = %s", fname, strerror(errno));
663 if(fd >=0 && !nolock)
666 fl.l_whence = SEEK_SET;
674 if(fcntl(fd, F_SETLK, &fl) < 0)
676 snprintf(errmsg,
ERRMSG_SZ,
"Error getting exclusive lock on %s. Error = %s. Closing file.", fname, strerror(errno));
int fifo_list_do_pending_read(fifo_list *fl)
Runs through the pending reads, dispatching each handler in turn.
int open_fifo_channel_in(fifo_channel *fc)
Opens the input fifo channel for async reading with an exculsive lock.
#define ERRMSG_SZ
The size of the errmsg buffers.
int check_if_in_locked(fifo_channel *fc)
Checks if the output fifo of the channel is locked.
int connect_fifo_list_nolock(fifo_list *fl)
Open each fifo in the list, without exclusive locks.
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
int setup_fifo_channel(fifo_channel *fc, size_t buffsz)
Allocate the server_response buffer.
int nchan
The number of channels.
int setup_fifo_list(fifo_list *fl, int nch)
Setup a fifo_list.
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
int init_fifo_channel(fifo_channel *fc)
Initializes the fifo_channel structure.
fd_set fds
the fd_set for the async SIGIO handler
int rq_sz
Size of the read_queue.
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
int * read_queue
Circular buffer which contains the fifo_ch index to read next.
int open_fifo_channel_in_nolock(fifo_channel *fc)
Opens the input fifo channel for async reading without an exculsive lock.
int set_fifo_channel(fifo_channel *fc, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of the fifo_channel.
int write_fifo_channel_seqmsg(fifo_channel *fc, const char *com, int comlen, char *seqmsg)
Write data to the output channel, including a sequence message.
#define ERRMSG(msg)
Error reporting macro. If not using the function __error_message(msg) then use stderr.
A structure to hold a list of fifo_channels.
int wopen_nonblock(char *fname, int nolock)
Open a file for non-blocking writes.
int open_fifo_channel_out_nolock(fifo_channel *fc)
Opens the output fifo channel for non-blocking writing without an exclusive lock. ...
fifo_channel * fifo_ch
An array of fifo_channels.
int open_fifo_channel_out(fifo_channel *fc)
Opens the output fifo channel for non-blocking writing with an exclusive lock.
int * pending_reads
An array, with same index as fifo_ch, which tracks number of pending reads on each channel...
void catch_fifo_response_list(int signum)
A SIGIO handler, which uses global_fifo_list to call the appropriate handler.
int maxfile
the maximum file descriptor for the SIGIO handler to worry about.
int init_fifo_list_pending_reads(fifo_list *fl)
Populates the fd_to_fifo_ch_index array.
int ropen_async(char *fname, int nolock)
Open a file for non-blocking asynchronous reads.
void catch_fifo_pending_reads(int signum, siginfo_t *siginf, void *ucont)
A handler for a R/T SIGIO, which just updates the pending reads meta data but does no actual signal h...
int RTSIGIO_overflow
flag indicating that the signal queue has overflown.
int set_fifo_list_rtsig(fifo_list *fl)
Change from SIGIO to real time signals.
int connect_fifo_list(fifo_list *fl)
Open each fifo in the list, with exclusive lock on the input fifo.
int init_fifo_list(fifo_list *fl)
Initialize the fifo_list.
int create_fifos(fifo_channel *fc)
Creates the fifos if they don't already exist.
Declarations for linux fifo utilities.
int * fd_to_fifo_ch_index
Array mapping a file descriptor to an index in the fifo_ch array.
void catch_fifo_standard_sigio(int signum)
A handler for normal SIGIO when we should have gotten the R/T SIGIO, implying signal queue overflow...
double get_currt()
Returns time since the Unix epoch in double precision seconds.
int read_queue_pos
The current position in the read_queue.
int tot_pending_reads
The total number of pending reads.
#define RWBUFF_SZ
The size of the i/o buffer.
int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of one channel in the list.