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