The VisAO Camera
fifoutils.h
Go to the documentation of this file.
1 /************************************************************
2 * fifoutils.h
3 *
4 * Author: Jared R. Males (jrmales@as.arizona.edu)
5 *
6 * Linux fifo utilities, declarations
7 *
8 ************************************************************/
9 
10 /** \file fifoutils.h
11  * \author Jared R. Males
12  * \brief Declarations for linux fifo utilities.
13  *
14 */
15 
16 #ifndef __FIFOUTILS_H__
17 #define __FIFOUTILS_H__
18 
19 #ifdef __cplusplus
20 extern "C"
21 {
22 #endif
23 
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <signal.h>
31 #include <sys/stat.h>
32 
33 #include "profileutils.h"
34 
35 #ifndef MAX_FNAME_SZ
36 ///The maximum allowed filename length
37 #define MAX_FNAME_SZ 256
38 #endif
39 
40 
41 #ifndef RWBUFF_SZ
42 ///The size of the i/o buffer
43 #define RWBUFF_SZ 256
44 #endif
45 
46 #ifndef ERRMSG_SZ
47 ///The size of the errmsg buffers
48 #define ERRMSG_SZ 256
49 #endif
50 
51 #ifndef ERRHAND
52 ///Error reporting macro. If not using the function __error_message(msg) then use stderr.
53 #define ERRMSG(msg) fprintf(stderr, "%s (%s line %i)\n", msg,__FILE__,__LINE__)
54 #else
55 extern void fifo_error_message(const char *, const char *, int);
56 #define ERRMSG(msg) fifo_error_message(msg, __FILE__, __LINE__)
57 #endif
58 
59 
60 #ifndef RTSIGIO
61 #define RTSIGIO (SIGRTMIN+4)
62 #define RTSIGIGN (SIGRTMIN+5)
63 #define RTSIGPING (SIGRTMIN+6)
64 #endif
65 
66 /****************** The basic fifo_channel. *******************************/
67 
68 typedef struct __fifo_channel fifo_channel;
69 
70 /// The basic fifo_channel structure.
71 /** Contains the meta data for a single (both ways) fifo i/o channel.
72  * Holds the file descriptors, the file names, and pointer to the input handler.*/
74 {
75  int fd_out; ///<output file descriptor
76  int fd_in; ///<input file descriptor
77 
78  char * outfname; ///<output file name
79  char * infname; ///<input file name
80 
81  int (*input_handler)(fifo_channel *); ///<the handler for input
82  char * server_response; ///<buffer for the server response after output
83  char * seqmsg; ///< Pointer to a possible sequence message, normally just the \0 in server_response.
84 
85  int sr_sz; ///<size of the server_response
86 
87  void *auxdata; ///<for passing other data to the handler. note that no memory management is done.
88 
89  int timeout; ///<true if last read was a timeout.
90 
91  time_t last_atime_out; ///<last access time for the output channel, used for clearing timeouts
92  time_t last_atime_in;///<last access time for the input channel, used for clearing timeouts
93 };
94 
95 ///Initializes the \ref __fifo_channel "fifo_channel" structure
96 /** All members are set to zero by this init.
97  * Should be called every time a \ref __fifo_channel "fifo_channel" is created.
98  * \param fc is a pointer the fifo_channel to initialize
99  * \retval 0 on success (always)
100  */
101 int init_fifo_channel(fifo_channel * fc);
102 
103 ///Allocate the server_response buffer.
104 /** Checks if buffer is non-zero and free's it if it is - so you must call \ref init_fifo_channel before setup.
105  * \param fc is a pointer the fifo_channel to initialize
106  * \param buffsz is the size of the server_response buffer to allocate
107  * \retval 0 on success
108  * \retval -1 on failure
109  */
110 int setup_fifo_channel(fifo_channel *fc, size_t buffsz);
111 
112 ///Set the details of the fifo_channel.
113 /** Allocates and assigns the file name strings, you must call \ref init_fifo_channel before using this function.
114  * Also installs the handler pointer.
115  * This function calls \ref create_fifos, thus creating them if they don't already exist.
116  * This function does not actually open the fifos.
117  * \param fc is a pointer the fifo_channel to initialize
118  * \param fin is the file name of the input fifo
119  * \param fout is the file name of the output fifo
120  * \param inp_hand is a pointer to the input handler function for this channel
121  * \param adata a pointer to auxiliary data.
122  * \retval 0 on success
123  * \retval -1 on failure
124  */
125 int set_fifo_channel(fifo_channel *fc, const char *fin, const char *fout, int (*inp_hand)(fifo_channel *), void *adata);
126 
127 ///Creates the fifos if they don't already exist
128 /** \param fc is a pointer the fifo_channel to initialize
129  * \retval 0 on success
130  * \retval -1 on failure (check errno)
131  */
132 int create_fifos(fifo_channel *fc);
133 
134 ///Opens the input fifo channel for async reading with an exculsive lock.
135 /** Clears the fifo, ignoring any pending input, so open before listening for SIGIO
136  * \param fc is a pointer the fifo_channel to initialize
137  * \retval 0 on success
138  * \retval -1 on failure
139  */
140 int open_fifo_channel_in(fifo_channel *fc);
141 
142 ///Opens the input fifo channel for async reading without an exculsive lock.
143 /** Clears the fifo, ignoring any pending input, so open before listening for SIGIO
144  * \param fc is a pointer the fifo_channel to initialize
145  * \retval 0 on success
146  * \retval -1 on failure
147  */
148 int open_fifo_channel_in_nolock(fifo_channel *fc);
149 
150 ///Opens the output fifo channel for non-blocking writing with an exclusive lock
151 /** \param fc is a pointer the fifo_channel to initialize
152  * \retval 0 on success
153  * \retval -1 on failure
154  */
155 int open_fifo_channel_out(fifo_channel *fc);
156 
157 ///Opens the output fifo channel for non-blocking writing without an exclusive lock
158 /** \param fc is a pointer the fifo_channel to initialize
159  * \retval 0 on success
160  * \retval -1 on failure
161  */
162 int open_fifo_channel_out_nolock(fifo_channel *fc);
163 
164 ///Write data to the output channel
165 /** \param fc is a pointer the fifo_channel to initialize
166  * \param com the buffer to write
167  * \param comlen length of the buffer
168  * \retval nbytes the number of bytes written, on success
169  * \retval -1 on failure
170  */
171 int write_fifo_channel(fifo_channel *fc, const char * com, int comlen);
172 
173 ///Write data to the output channel, including a sequence message.
174 /** \param fc is a pointer the fifo_channel to initialize
175  * \param com the buffer to write
176  * \param comlen length of the buffer
177  * \param seqmsg the 6 byte sequence message.
178  * \retval nbytes the number of bytes written, on success
179  * \retval -1 on failure
180  */
181 int write_fifo_channel_seqmsg(fifo_channel *fc, const char * com, int comlen, char * seqmsg);
182 
183 ///Read data from the input fifo channel
184 /** \param fc is a pointer the fifo_channel to initialize
185  * \retval 0 on success
186  * \retval 1 if read not complete before filling \ref __fifo_channel::server_response.
187  */
188 int read_fifo_channel(fifo_channel * fc);
189 
190 ///Checks if the output fifo of the channel is locked
191 /** Normally a process obtains an exclusive lock on the input of its fifo channels. That is
192  * it wants to be the only process which can receive commands on that channel. This function
193  * checks for the presence of such a lock on the output fifo of a channel, as a way to test if
194  * anybody is listening. This can be used to prevent writing to a fifo that isn't being read.
195  * See \ref VisApp_base::write_fifo_channel for an example.
196  * \param fc the relevant fifo_channel
197  * \retval 0 if there is not lock
198  * \retval 1 if there is a lock
199  */
200 int check_if_in_locked(fifo_channel *fc);
201 
202 
203 ///A structure to hold a list of \ref __fifo_channel "fifo_channels"
204 typedef struct
205 {
206  int nchan; ///<The number of channels.
207  fifo_channel * fifo_ch; ///<An array of \ref __fifo_channel "fifo_channels"
208 
209  fd_set fds; ///< the fd_set for the async SIGIO handler
210  int maxfile; ///< the maximum file descriptor for the SIGIO handler to worry about.
211 
212  //version 2
213  int * fd_to_fifo_ch_index; ///< Array mapping a file descriptor to an index in the fifo_ch array.
214 
215  int tot_pending_reads; ///< The total number of pending reads.
216  int * pending_reads; ///< An array, with same index as fifo_ch, which tracks number of pending reads on each channel
217  int * read_queue; ///< Circular buffer which contains the fifo_ch index to read next.
218  int rq_sz;///< Size of the read_queue
219 
220  int read_queue_pos; ///< The current position in the read_queue
221  int read_queue_nextpos;
222 
223  int RTSIGIO_overflow; ///< flag indicating that the signal queue has overflown.
224  //Todo:
225  /* X populate fd_to_fifo_ch_index at end of connect_fifo_list
226  * X initialize the pending reads and queue.
227  * X SIGIO to real time
228  * X Signal handler just updates tot_pending_reads, pending_reads, read_queue_pos, and read_queue[read_queue_pos] using sig_fd from the realtime signal
229  * X App main loop is responsible for checking for tot_pending_reads > 0.
230  * X Write fifo_list_do_pending_reads, which handles the pending reads undle tot_pending_reads == 0
231  */
232 } fifo_list;
233 
234 
235 ///Initialize the fifo_list.
236 /** All members set to 0.
237  * \param fl is a pointer to the fifo_list to initialize
238  * \retval 0 on success (always)*/
239 int init_fifo_list(fifo_list * fl);
240 
241 ///Setup a fifo_list.
242 /** Allocates the fifo_ch array, then initializes each fifo_channel
243  * \param fl is a pointer to the initialized fifo_list to setup
244  * \param nch is the number of channels in the list
245  * \retval 0 on success
246  * \retval -1 on failure*/
247 int setup_fifo_list(fifo_list * fl, int nch);
248 
249 ///Set the details of one channel in the list.
250 /** First calls \ref setup_fifo_channel
251  * Then calls \ref set_fifo_channel
252  * \param fl is a pointer to the initialized fifo_list to setup
253  * \param nch is the channel number to set
254  * \param buffsz is the size of the server_reponse buvver for this channel
255  * \param fin is the file name of the input fifo
256  * \param fout is the file name of the output fifo
257  * \param inp_hand is a pointer to the input handler function for this channel
258  * \param adata a pointer to auxiliary data.
259  * \retval 0 on success
260  * \retval -1 on failure*/
261 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);
262 
263 ///Open each fifo in the list, with exclusive lock on the input fifo.
264 /** The input channel is locked so that no other process will intercept communications
265  * intended for the calling process. Output fifos are not locked, as multiple processes
266  * could conceivable write to the same channel (e.g. a ping or watchdog).
267  * Both channels can't be locked, as then nobody could establish a connection.
268  * \param fl is a pointer to the initialized fifo_list to setup
269  * \retval 0 on success
270  * \retval -1 on failure*/
272 
273 ///Open each fifo in the list, without exclusive locks.
274 /** \param fl is a pointer to the initialized fifo_list to setup
275  * \retval 0 on success
276  * \retval -1 on failure*/
278 
279 ///Populates the fd_to_fifo_ch_index array
281 
282 ///The global fifo_list, for signal handling
283 extern fifo_list * global_fifo_list;
284 
285 ///A SIGIO handler, which uses \ref global_fifo_list to call the appropriate handler.
286 /** This means you must define global_fifo_list and point it at your \ref fifo_list
287  * or this will segfault.
288  */
289 void catch_fifo_response_list(int signum);
290 
291 
292 ///Change from SIGIO to real time signals
294 
295 ///A handler for a R/T SIGIO, which just updates the pending reads meta data but does no actual signal handling.
296 void catch_fifo_pending_reads(int signum, siginfo_t *siginf, void *ucont);
297 
298 ///A handler for normal SIGIO when we should have gotten the R/T SIGIO, implying signal queue overflow
299 void catch_fifo_standard_sigio(int signum);
300 
301 ///Runs through the pending reads, dispatching each handler in turn.
303 
304 
305 ///Open a file for non-blocking asynchronous reads.
306 /** The nolock parameter controls whether or not to attempt an exclusive lock.
307  * \param fname is the name of the file to open
308  * \param nolock if 0 attempt to get an exclusive lock (WRLCK) and close file if rejected. if 1 do not lock.
309  * \retval >0 (the file descriptor) on success
310  * \retval 0 on failure
311  * \retval -1 on failure to lock
312  */
313 int ropen_async(char * fname, int nolock);
314 
315 ///Open a file for non-blocking writes.
316 /** The nolock parameter controls whether or not to attempt an exclusive lock.
317  * \param fname is the name of the file to open
318  * \param nolock if 0 attempt to get an exclusive lock (WRLCK) and close file if rejected. if 1 do not lock.
319  * \retval >0 (the file descriptor) on success
320  * \retval 0 on failure
321  * \retval -1 on failure to lock
322  */
323 int wopen_nonblock(char * fname, int nolock);
324 
325 ///Returns time since the Unix epoch in double precision seconds
326 /** Uses clock_gettime, CLOCK_REALTIME, and the attendant timespec, so it has precision of nanoseconds.
327  */
328 double get_currt();
329 
330 #ifdef __cplusplus
331 } //extern "C"
332 #endif
333 
334 #endif //__FIFOUTILS_H__
335 
int timeout
true if last read was a timeout.
Definition: fifoutils.h:89
char * infname
input file name
Definition: fifoutils.h:79
int set_fifo_list_rtsig(fifo_list *fl)
Change from SIGIO to real time signals.
Definition: fifoutils.c:517
int nchan
The number of channels.
Definition: fifoutils.h:206
fd_set fds
the fd_set for the async SIGIO handler
Definition: fifoutils.h:209
char * server_response
buffer for the server response after output
Definition: fifoutils.h:82
The basic fifo_channel structure.
Definition: fifoutils.h:73
void * auxdata
for passing other data to the handler. note that no memory management is done.
Definition: fifoutils.h:87
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
int rq_sz
Size of the read_queue.
Definition: fifoutils.h:218
int open_fifo_channel_out_nolock(fifo_channel *fc)
Opens the output fifo channel for non-blocking writing without an exclusive lock. ...
Definition: fifoutils.c:180
int * read_queue
Circular buffer which contains the fifo_ch index to read next.
Definition: fifoutils.h:217
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
int init_fifo_list(fifo_list *fl)
Initialize the fifo_list.
Definition: fifoutils.c:341
int connect_fifo_list_nolock(fifo_list *fl)
Open each fifo in the list, without exclusive locks.
Definition: fifoutils.c:415
char * outfname
output file name
Definition: fifoutils.h:78
A structure to hold a list of fifo_channels.
Definition: fifoutils.h:204
int ropen_async(char *fname, int nolock)
Open a file for non-blocking asynchronous reads.
Definition: fifoutils.c:607
fifo_channel * fifo_ch
An array of fifo_channels.
Definition: fifoutils.h:207
time_t last_atime_out
last access time for the output channel, used for clearing timeouts
Definition: fifoutils.h:91
int init_fifo_list_pending_reads(fifo_list *fl)
Populates the fd_to_fifo_ch_index array.
Definition: fifoutils.c:454
int open_fifo_channel_in_nolock(fifo_channel *fc)
Opens the input fifo channel for async reading without an exculsive lock.
Definition: fifoutils.c:144
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.
Definition: fifoutils.c:63
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.
Definition: fifoutils.c:218
int open_fifo_channel_out(fifo_channel *fc)
Opens the output fifo channel for non-blocking writing with an exclusive lock.
Definition: fifoutils.c:166
void fifo_error_message(const char *, const char *, int)
The fifoutils error reporting function.
Definition: libvisaoc.c:18
int wopen_nonblock(char *fname, int nolock)
Open a file for non-blocking writes.
Definition: fifoutils.c:649
int * pending_reads
An array, with same index as fifo_ch, which tracks number of pending reads on each channel...
Definition: fifoutils.h:216
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.
Definition: fifoutils.h:210
int create_fifos(fifo_channel *fc)
Creates the fifos if they don't already exist.
Definition: fifoutils.c:92
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.
Definition: fifoutils.c:373
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(* input_handler)(fifo_channel *)
the handler for input
Definition: fifoutils.h:81
int RTSIGIO_overflow
flag indicating that the signal queue has overflown.
Definition: fifoutils.h:223
double get_currt()
Returns time since the Unix epoch in double precision seconds.
Definition: fifoutils.c:23
char * seqmsg
Pointer to a possible sequence message, normally just the \0 in server_response.
Definition: fifoutils.h:83
int write_fifo_channel(fifo_channel *fc, const char *com, int comlen)
Write data to the output channel.
Definition: fifoutils.c:194
int setup_fifo_list(fifo_list *fl, int nch)
Setup a fifo_list.
Definition: fifoutils.c:354
int init_fifo_channel(fifo_channel *fc)
Initializes the fifo_channel structure.
Definition: fifoutils.c:31
int fd_out
output file descriptor
Definition: fifoutils.h:75
int * fd_to_fifo_ch_index
Array mapping a file descriptor to an index in the fifo_ch array.
Definition: fifoutils.h:213
int fd_in
input file descriptor
Definition: fifoutils.h:76
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...
int sr_sz
size of the server_response
Definition: fifoutils.h:85
int check_if_in_locked(fifo_channel *fc)
Checks if the output fifo of the channel is locked.
Definition: fifoutils.c:316
int fifo_list_do_pending_read(fifo_list *fl)
Runs through the pending reads, dispatching each handler in turn.
Definition: fifoutils.c:576
int setup_fifo_channel(fifo_channel *fc, size_t buffsz)
Allocate the server_response buffer.
Definition: fifoutils.c:47
int read_queue_pos
The current position in the read_queue.
Definition: fifoutils.h:220
int open_fifo_channel_in(fifo_channel *fc)
Opens the input fifo channel for async reading with an exculsive lock.
Definition: fifoutils.c:119
int connect_fifo_list(fifo_list *fl)
Open each fifo in the list, with exclusive lock on the input fifo.
Definition: fifoutils.c:379
int tot_pending_reads
The total number of pending reads.
Definition: fifoutils.h:215
time_t last_atime_in
last access time for the input channel, used for clearing timeouts
Definition: fifoutils.h:92