xref: /unit/src/nxt_buf_filter.h (revision 65:10688b89aa16)
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
70Sigor@sysoev.ru #ifndef _NXT_BUF_FILTER_H_INCLUDED_
80Sigor@sysoev.ru #define _NXT_BUF_FILTER_H_INCLUDED_
110Sigor@sysoev.ru /*
120Sigor@sysoev.ru  * nxt_buf_filter is a framework intended to simplify processing file
130Sigor@sysoev.ru  * buffers content by a filter.  The filter should set callbacks and
140Sigor@sysoev.ru  * call nxt_buf_filter_add() to start processing.
150Sigor@sysoev.ru  *
160Sigor@sysoev.ru  * At first buf_filter calls filter_ready() and the filter ensures
170Sigor@sysoev.ru  * it may allocate or reuse its internal buffer.  No real allocation
180Sigor@sysoev.ru  * is performed at this step.
190Sigor@sysoev.ru  *
200Sigor@sysoev.ru  * TODO prevent unneeded allocaiton if no input data.
210Sigor@sysoev.ru  *
220Sigor@sysoev.ru  *
230Sigor@sysoev.ru  * TODO:  The filter can flush data buffered
240Sigor@sysoev.ru  * previously, if all internal buffers are full.
250Sigor@sysoev.ru  *
260Sigor@sysoev.ru  * Then buf_filter looks buffer chains.  There are two buffer chains:
270Sigor@sysoev.ru  * the input chain is a chain of original incoming memory, file, and sync
280Sigor@sysoev.ru  * buffers; and the current chain is a chain of memory/file buffers read
290Sigor@sysoev.ru  * from a file-only buffer.  The current chain is processed first.  Since
300Sigor@sysoev.ru  * buffers in this chain always contains a memory part, they can be passed
310Sigor@sysoev.ru  * one by one to the filter using filter_process().  If there is an output
320Sigor@sysoev.ru  * buffer after the buffer processing, it is added to output chain.  The
330Sigor@sysoev.ru  * output buffers are not filter internal buffers.  They just point to these
340Sigor@sysoev.ru  * internal buffers and one internal buffer can correspond to several output
350Sigor@sysoev.ru  * buffers which point to adjoining parts of the internal buffer.  Further
360Sigor@sysoev.ru  * processing depends on filter_process() result code: if it returns NXT_OK,
370Sigor@sysoev.ru  * then the filter internal buffer is not full and buf_filter looks the next
380Sigor@sysoev.ru  * current or input buffer.  If result code is NXT_AGAIN, then the filter
390Sigor@sysoev.ru  * internal buffer is full and buf_filter calls filter_flush() and then
400Sigor@sysoev.ru  * schedules to run nxt_buf_filter_repeat().  nxt_buf_filter_repeat() will
410Sigor@sysoev.ru  * run after all ready output buffer completion handlers and will call
420Sigor@sysoev.ru  * buf_filter again if no one completion handler will do it already using
430Sigor@sysoev.ru  * nxt_buf_filter_enqueue().  So in any case buf_filter will run again only
440Sigor@sysoev.ru  * once.
450Sigor@sysoev.ru  *
460Sigor@sysoev.ru  * TODO:
470Sigor@sysoev.ru  * in ideal just one the filter internal buffer.
480Sigor@sysoev.ru  * This allows to minimize number of the filter internal buffers if they
490Sigor@sysoev.ru  * flush fast.
500Sigor@sysoev.ru  *
510Sigor@sysoev.ru  * If the current chain is empty, the buf_filter processes the input chain.
520Sigor@sysoev.ru  * Memory buffers are passed to the filter using filter_process().  If an
530Sigor@sysoev.ru  * input buffer is a file buffer, then buf_filter calls filter_flush()
540Sigor@sysoev.ru  * and starts a file job to read the buffer in memory.  The file job reads
550Sigor@sysoev.ru  * file parts into memory/file buffers and adds them to the current chain.
560Sigor@sysoev.ru  *
570Sigor@sysoev.ru  * Sync buffers are passed to the filter using filter_sync().  Its
580Sigor@sysoev.ru  * post-processing is similar to the filter_process() post-processing,
590Sigor@sysoev.ru  * except sync buffers are always added unmodified to the output chain.
600Sigor@sysoev.ru  */
620Sigor@sysoev.ru typedef struct {
630Sigor@sysoev.ru     nxt_job_file_t               job_file;
640Sigor@sysoev.ru     nxt_buf_pool_t               buffers;
650Sigor@sysoev.ru } nxt_buf_filter_file_t;
680Sigor@sysoev.ru typedef struct nxt_buf_filter_s  nxt_buf_filter_t;
700Sigor@sysoev.ru typedef struct {
710Sigor@sysoev.ru     nxt_int_t                    (*filter_ready)(nxt_buf_filter_t *f);
720Sigor@sysoev.ru     nxt_int_t                    (*filter_process)(nxt_buf_filter_t *f);
730Sigor@sysoev.ru     nxt_int_t                    (*filter_flush)(nxt_buf_filter_t *f);
750Sigor@sysoev.ru     nxt_int_t                    (*filter_sync_nobuf)(nxt_buf_filter_t *f);
760Sigor@sysoev.ru     nxt_int_t                    (*filter_sync_flush)(nxt_buf_filter_t *f);
770Sigor@sysoev.ru     nxt_int_t                    (*filter_sync_last)(nxt_buf_filter_t *f);
790Sigor@sysoev.ru     void                         (*filter_next)(nxt_buf_filter_t *f);
801Sigor@sysoev.ru     nxt_work_handler_t           filter_error;
820Sigor@sysoev.ru     nxt_buf_filter_file_t        *(*job_file_create)(nxt_buf_filter_t *f);
830Sigor@sysoev.ru     void                         (*job_file_retain)(nxt_buf_filter_t *f);
840Sigor@sysoev.ru     void                         (*job_file_release)(nxt_buf_filter_t *f);
850Sigor@sysoev.ru } nxt_buf_filter_ops_t;
880Sigor@sysoev.ru struct nxt_buf_filter_s {
890Sigor@sysoev.ru     nxt_buf_t                    *current;
900Sigor@sysoev.ru     nxt_buf_t                    *input;
910Sigor@sysoev.ru     nxt_buf_t                    *output;
920Sigor@sysoev.ru     nxt_buf_t                    *last;
940Sigor@sysoev.ru     nxt_work_queue_t             *work_queue;
950Sigor@sysoev.ru     nxt_buf_filter_file_t        *filter_file;
960Sigor@sysoev.ru     void                         *data;
97*65Sigor@sysoev.ru     nxt_mp_t                     *mem_pool;
990Sigor@sysoev.ru     const nxt_buf_filter_ops_t   *run;
1010Sigor@sysoev.ru     uint8_t                      mmap;       /* 1 bit */
1020Sigor@sysoev.ru     uint8_t                      done;       /* 1 bit */
1030Sigor@sysoev.ru     uint8_t                      queued;     /* 1 bit */
1040Sigor@sysoev.ru     uint8_t                      reading;    /* 1 bit */
1050Sigor@sysoev.ru     uint8_t                      buffering;  /* 1 bit */
1060Sigor@sysoev.ru };
1091Sigor@sysoev.ru NXT_EXPORT void nxt_buf_filter_add(nxt_task_t *task, nxt_buf_filter_t *f,
1100Sigor@sysoev.ru     nxt_buf_t *b);
1111Sigor@sysoev.ru NXT_EXPORT void nxt_buf_filter(nxt_task_t *task, void *obj, void *data);
1121Sigor@sysoev.ru NXT_EXPORT void nxt_buf_filter_enqueue(nxt_task_t *task, nxt_buf_filter_t *f);
1150Sigor@sysoev.ru #endif /* _NXT_BUF_FILTER_H_INCLUDED_ */