xref: /unit/src/nxt_buf_filter.h (revision 0)
2*0Sigor@sysoev.ru /*
3*0Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
4*0Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
5*0Sigor@sysoev.ru  */
7*0Sigor@sysoev.ru #ifndef _NXT_BUF_FILTER_H_INCLUDED_
8*0Sigor@sysoev.ru #define _NXT_BUF_FILTER_H_INCLUDED_
11*0Sigor@sysoev.ru /*
12*0Sigor@sysoev.ru  * nxt_buf_filter is a framework intended to simplify processing file
13*0Sigor@sysoev.ru  * buffers content by a filter.  The filter should set callbacks and
14*0Sigor@sysoev.ru  * call nxt_buf_filter_add() to start processing.
15*0Sigor@sysoev.ru  *
16*0Sigor@sysoev.ru  * At first buf_filter calls filter_ready() and the filter ensures
17*0Sigor@sysoev.ru  * it may allocate or reuse its internal buffer.  No real allocation
18*0Sigor@sysoev.ru  * is performed at this step.
19*0Sigor@sysoev.ru  *
20*0Sigor@sysoev.ru  * TODO prevent unneeded allocaiton if no input data.
21*0Sigor@sysoev.ru  *
22*0Sigor@sysoev.ru  *
23*0Sigor@sysoev.ru  * TODO:  The filter can flush data buffered
24*0Sigor@sysoev.ru  * previously, if all internal buffers are full.
25*0Sigor@sysoev.ru  *
26*0Sigor@sysoev.ru  * Then buf_filter looks buffer chains.  There are two buffer chains:
27*0Sigor@sysoev.ru  * the input chain is a chain of original incoming memory, file, and sync
28*0Sigor@sysoev.ru  * buffers; and the current chain is a chain of memory/file buffers read
29*0Sigor@sysoev.ru  * from a file-only buffer.  The current chain is processed first.  Since
30*0Sigor@sysoev.ru  * buffers in this chain always contains a memory part, they can be passed
31*0Sigor@sysoev.ru  * one by one to the filter using filter_process().  If there is an output
32*0Sigor@sysoev.ru  * buffer after the buffer processing, it is added to output chain.  The
33*0Sigor@sysoev.ru  * output buffers are not filter internal buffers.  They just point to these
34*0Sigor@sysoev.ru  * internal buffers and one internal buffer can correspond to several output
35*0Sigor@sysoev.ru  * buffers which point to adjoining parts of the internal buffer.  Further
36*0Sigor@sysoev.ru  * processing depends on filter_process() result code: if it returns NXT_OK,
37*0Sigor@sysoev.ru  * then the filter internal buffer is not full and buf_filter looks the next
38*0Sigor@sysoev.ru  * current or input buffer.  If result code is NXT_AGAIN, then the filter
39*0Sigor@sysoev.ru  * internal buffer is full and buf_filter calls filter_flush() and then
40*0Sigor@sysoev.ru  * schedules to run nxt_buf_filter_repeat().  nxt_buf_filter_repeat() will
41*0Sigor@sysoev.ru  * run after all ready output buffer completion handlers and will call
42*0Sigor@sysoev.ru  * buf_filter again if no one completion handler will do it already using
43*0Sigor@sysoev.ru  * nxt_buf_filter_enqueue().  So in any case buf_filter will run again only
44*0Sigor@sysoev.ru  * once.
45*0Sigor@sysoev.ru  *
46*0Sigor@sysoev.ru  * TODO:
47*0Sigor@sysoev.ru  * in ideal just one the filter internal buffer.
48*0Sigor@sysoev.ru  * This allows to minimize number of the filter internal buffers if they
49*0Sigor@sysoev.ru  * flush fast.
50*0Sigor@sysoev.ru  *
51*0Sigor@sysoev.ru  * If the current chain is empty, the buf_filter processes the input chain.
52*0Sigor@sysoev.ru  * Memory buffers are passed to the filter using filter_process().  If an
53*0Sigor@sysoev.ru  * input buffer is a file buffer, then buf_filter calls filter_flush()
54*0Sigor@sysoev.ru  * and starts a file job to read the buffer in memory.  The file job reads
55*0Sigor@sysoev.ru  * file parts into memory/file buffers and adds them to the current chain.
56*0Sigor@sysoev.ru  *
57*0Sigor@sysoev.ru  * Sync buffers are passed to the filter using filter_sync().  Its
58*0Sigor@sysoev.ru  * post-processing is similar to the filter_process() post-processing,
59*0Sigor@sysoev.ru  * except sync buffers are always added unmodified to the output chain.
60*0Sigor@sysoev.ru  */
62*0Sigor@sysoev.ru typedef struct {
63*0Sigor@sysoev.ru     nxt_job_file_t               job_file;
64*0Sigor@sysoev.ru     nxt_buf_pool_t               buffers;
65*0Sigor@sysoev.ru } nxt_buf_filter_file_t;
68*0Sigor@sysoev.ru typedef struct nxt_buf_filter_s  nxt_buf_filter_t;
70*0Sigor@sysoev.ru typedef struct {
71*0Sigor@sysoev.ru     nxt_int_t                    (*filter_ready)(nxt_buf_filter_t *f);
72*0Sigor@sysoev.ru     nxt_int_t                    (*filter_process)(nxt_buf_filter_t *f);
73*0Sigor@sysoev.ru     nxt_int_t                    (*filter_flush)(nxt_buf_filter_t *f);
75*0Sigor@sysoev.ru     nxt_int_t                    (*filter_sync_nobuf)(nxt_buf_filter_t *f);
76*0Sigor@sysoev.ru     nxt_int_t                    (*filter_sync_flush)(nxt_buf_filter_t *f);
77*0Sigor@sysoev.ru     nxt_int_t                    (*filter_sync_last)(nxt_buf_filter_t *f);
79*0Sigor@sysoev.ru     void                         (*filter_next)(nxt_buf_filter_t *f);
80*0Sigor@sysoev.ru     void                         (*filter_error)(nxt_thread_t *thr, void *obj,
81*0Sigor@sysoev.ru                                      void *data);
83*0Sigor@sysoev.ru     nxt_buf_filter_file_t        *(*job_file_create)(nxt_buf_filter_t *f);
84*0Sigor@sysoev.ru     void                         (*job_file_retain)(nxt_buf_filter_t *f);
85*0Sigor@sysoev.ru     void                         (*job_file_release)(nxt_buf_filter_t *f);
86*0Sigor@sysoev.ru } nxt_buf_filter_ops_t;
89*0Sigor@sysoev.ru struct nxt_buf_filter_s {
90*0Sigor@sysoev.ru     nxt_buf_t                    *current;
91*0Sigor@sysoev.ru     nxt_buf_t                    *input;
92*0Sigor@sysoev.ru     nxt_buf_t                    *output;
93*0Sigor@sysoev.ru     nxt_buf_t                    *last;
95*0Sigor@sysoev.ru     nxt_work_queue_t             *work_queue;
96*0Sigor@sysoev.ru     nxt_buf_filter_file_t        *filter_file;
97*0Sigor@sysoev.ru     void                         *data;
98*0Sigor@sysoev.ru     nxt_mem_pool_t               *mem_pool;
100*0Sigor@sysoev.ru     const nxt_buf_filter_ops_t   *run;
102*0Sigor@sysoev.ru     uint8_t                      mmap;       /* 1 bit */
103*0Sigor@sysoev.ru     uint8_t                      done;       /* 1 bit */
104*0Sigor@sysoev.ru     uint8_t                      queued;     /* 1 bit */
105*0Sigor@sysoev.ru     uint8_t                      reading;    /* 1 bit */
106*0Sigor@sysoev.ru     uint8_t                      buffering;  /* 1 bit */
107*0Sigor@sysoev.ru };
110*0Sigor@sysoev.ru NXT_EXPORT void nxt_buf_filter_add(nxt_thread_t *thr, nxt_buf_filter_t *f,
111*0Sigor@sysoev.ru     nxt_buf_t *b);
112*0Sigor@sysoev.ru NXT_EXPORT void nxt_buf_filter(nxt_thread_t *thr, void *obj, void *data);
113*0Sigor@sysoev.ru NXT_EXPORT void nxt_buf_filter_enqueue(nxt_thread_t *thr, nxt_buf_filter_t *f);
116*0Sigor@sysoev.ru #endif /* _NXT_BUF_FILTER_H_INCLUDED_ */