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