1*743Smax.romanov@nginx.com 2*743Smax.romanov@nginx.com /* 3*743Smax.romanov@nginx.com * Copyright (C) NGINX, Inc. 4*743Smax.romanov@nginx.com */ 5*743Smax.romanov@nginx.com 6*743Smax.romanov@nginx.com #ifndef _NXT_UNIT_H_INCLUDED_ 7*743Smax.romanov@nginx.com #define _NXT_UNIT_H_INCLUDED_ 8*743Smax.romanov@nginx.com 9*743Smax.romanov@nginx.com 10*743Smax.romanov@nginx.com #include <inttypes.h> 11*743Smax.romanov@nginx.com #include <sys/types.h> 12*743Smax.romanov@nginx.com #include <string.h> 13*743Smax.romanov@nginx.com 14*743Smax.romanov@nginx.com #include "nxt_unit_typedefs.h" 15*743Smax.romanov@nginx.com 16*743Smax.romanov@nginx.com enum { 17*743Smax.romanov@nginx.com NXT_UNIT_OK = 0, 18*743Smax.romanov@nginx.com NXT_UNIT_ERROR = 1, 19*743Smax.romanov@nginx.com }; 20*743Smax.romanov@nginx.com 21*743Smax.romanov@nginx.com enum { 22*743Smax.romanov@nginx.com NXT_UNIT_LOG_ALERT = 0, 23*743Smax.romanov@nginx.com NXT_UNIT_LOG_ERR = 1, 24*743Smax.romanov@nginx.com NXT_UNIT_LOG_WARN = 2, 25*743Smax.romanov@nginx.com NXT_UNIT_LOG_NOTICE = 3, 26*743Smax.romanov@nginx.com NXT_UNIT_LOG_INFO = 4, 27*743Smax.romanov@nginx.com NXT_UNIT_LOG_DEBUG = 5, 28*743Smax.romanov@nginx.com }; 29*743Smax.romanov@nginx.com 30*743Smax.romanov@nginx.com #define NXT_UNIT_INIT_ENV "NXT_UNIT_INIT" 31*743Smax.romanov@nginx.com 32*743Smax.romanov@nginx.com /* 33*743Smax.romanov@nginx.com * Mostly opaque structure with library state. 34*743Smax.romanov@nginx.com * 35*743Smax.romanov@nginx.com * Only user defined 'data' pointer exposed here. The rest is unit 36*743Smax.romanov@nginx.com * implementation specific and hidden. 37*743Smax.romanov@nginx.com */ 38*743Smax.romanov@nginx.com struct nxt_unit_s { 39*743Smax.romanov@nginx.com void *data; /* User defined data. */ 40*743Smax.romanov@nginx.com }; 41*743Smax.romanov@nginx.com 42*743Smax.romanov@nginx.com /* 43*743Smax.romanov@nginx.com * Thread context. 44*743Smax.romanov@nginx.com * 45*743Smax.romanov@nginx.com * First (main) context is provided 'for free'. To receive and process 46*743Smax.romanov@nginx.com * requests in other thread, one need to allocate context and use it 47*743Smax.romanov@nginx.com * further in this thread. 48*743Smax.romanov@nginx.com */ 49*743Smax.romanov@nginx.com struct nxt_unit_ctx_s { 50*743Smax.romanov@nginx.com void *data; /* User context-specific data. */ 51*743Smax.romanov@nginx.com nxt_unit_t *unit; 52*743Smax.romanov@nginx.com }; 53*743Smax.romanov@nginx.com 54*743Smax.romanov@nginx.com /* 55*743Smax.romanov@nginx.com * Unit port identification structure. 56*743Smax.romanov@nginx.com * 57*743Smax.romanov@nginx.com * Each port can be uniquely identified by listen process id (pid) and port id. 58*743Smax.romanov@nginx.com * This identification is required to refer the port from different process. 59*743Smax.romanov@nginx.com */ 60*743Smax.romanov@nginx.com struct nxt_unit_port_id_s { 61*743Smax.romanov@nginx.com pid_t pid; 62*743Smax.romanov@nginx.com uint32_t hash; 63*743Smax.romanov@nginx.com uint16_t id; 64*743Smax.romanov@nginx.com }; 65*743Smax.romanov@nginx.com 66*743Smax.romanov@nginx.com /* 67*743Smax.romanov@nginx.com * unit provides port storage which is able to store and find the following 68*743Smax.romanov@nginx.com * data structures. 69*743Smax.romanov@nginx.com */ 70*743Smax.romanov@nginx.com struct nxt_unit_port_s { 71*743Smax.romanov@nginx.com nxt_unit_port_id_t id; 72*743Smax.romanov@nginx.com 73*743Smax.romanov@nginx.com int in_fd; 74*743Smax.romanov@nginx.com int out_fd; 75*743Smax.romanov@nginx.com 76*743Smax.romanov@nginx.com void *data; 77*743Smax.romanov@nginx.com }; 78*743Smax.romanov@nginx.com 79*743Smax.romanov@nginx.com 80*743Smax.romanov@nginx.com struct nxt_unit_buf_s { 81*743Smax.romanov@nginx.com char *start; 82*743Smax.romanov@nginx.com char *free; 83*743Smax.romanov@nginx.com char *end; 84*743Smax.romanov@nginx.com }; 85*743Smax.romanov@nginx.com 86*743Smax.romanov@nginx.com 87*743Smax.romanov@nginx.com struct nxt_unit_request_info_s { 88*743Smax.romanov@nginx.com nxt_unit_t *unit; 89*743Smax.romanov@nginx.com nxt_unit_ctx_t *ctx; 90*743Smax.romanov@nginx.com 91*743Smax.romanov@nginx.com nxt_unit_port_id_t request_port; 92*743Smax.romanov@nginx.com nxt_unit_port_id_t response_port; 93*743Smax.romanov@nginx.com 94*743Smax.romanov@nginx.com nxt_unit_request_t *request; 95*743Smax.romanov@nginx.com nxt_unit_buf_t *request_buf; 96*743Smax.romanov@nginx.com 97*743Smax.romanov@nginx.com nxt_unit_response_t *response; 98*743Smax.romanov@nginx.com nxt_unit_buf_t *response_buf; 99*743Smax.romanov@nginx.com uint32_t response_max_fields; 100*743Smax.romanov@nginx.com 101*743Smax.romanov@nginx.com nxt_unit_buf_t *content_buf; 102*743Smax.romanov@nginx.com uint64_t content_length; 103*743Smax.romanov@nginx.com 104*743Smax.romanov@nginx.com void *data; 105*743Smax.romanov@nginx.com }; 106*743Smax.romanov@nginx.com 107*743Smax.romanov@nginx.com /* 108*743Smax.romanov@nginx.com * Set of application-specific callbacks. Application may leave all optional 109*743Smax.romanov@nginx.com * callbacks as NULL. 110*743Smax.romanov@nginx.com */ 111*743Smax.romanov@nginx.com struct nxt_unit_callbacks_s { 112*743Smax.romanov@nginx.com /* 113*743Smax.romanov@nginx.com * Process request data. Unlike all other callback, this callback 114*743Smax.romanov@nginx.com * need to be defined by application. 115*743Smax.romanov@nginx.com */ 116*743Smax.romanov@nginx.com void (*request_handler)(nxt_unit_request_info_t *req); 117*743Smax.romanov@nginx.com 118*743Smax.romanov@nginx.com /* Add new Unit port to communicate with process pid. Optional. */ 119*743Smax.romanov@nginx.com int (*add_port)(nxt_unit_ctx_t *, nxt_unit_port_t *port); 120*743Smax.romanov@nginx.com 121*743Smax.romanov@nginx.com /* Remove previously added port. Optional. */ 122*743Smax.romanov@nginx.com void (*remove_port)(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id); 123*743Smax.romanov@nginx.com 124*743Smax.romanov@nginx.com /* Remove all data associated with process pid including ports. Optional. */ 125*743Smax.romanov@nginx.com void (*remove_pid)(nxt_unit_ctx_t *, pid_t pid); 126*743Smax.romanov@nginx.com 127*743Smax.romanov@nginx.com /* Gracefully quit the application. Optional. */ 128*743Smax.romanov@nginx.com void (*quit)(nxt_unit_ctx_t *); 129*743Smax.romanov@nginx.com 130*743Smax.romanov@nginx.com /* Send data and control to process pid using port id. Optional. */ 131*743Smax.romanov@nginx.com ssize_t (*port_send)(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id, 132*743Smax.romanov@nginx.com const void *buf, size_t buf_size, 133*743Smax.romanov@nginx.com const void *oob, size_t oob_size); 134*743Smax.romanov@nginx.com 135*743Smax.romanov@nginx.com /* Receive data on port id. Optional. */ 136*743Smax.romanov@nginx.com ssize_t (*port_recv)(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id, 137*743Smax.romanov@nginx.com void *buf, size_t buf_size, void *oob, size_t oob_size); 138*743Smax.romanov@nginx.com 139*743Smax.romanov@nginx.com }; 140*743Smax.romanov@nginx.com 141*743Smax.romanov@nginx.com 142*743Smax.romanov@nginx.com struct nxt_unit_init_s { 143*743Smax.romanov@nginx.com void *data; /* Opaque pointer to user-defined data. */ 144*743Smax.romanov@nginx.com void *ctx_data; /* Opaque pointer to user-defined data. */ 145*743Smax.romanov@nginx.com int max_pending_requests; 146*743Smax.romanov@nginx.com 147*743Smax.romanov@nginx.com uint32_t request_data_size; 148*743Smax.romanov@nginx.com 149*743Smax.romanov@nginx.com nxt_unit_callbacks_t callbacks; 150*743Smax.romanov@nginx.com 151*743Smax.romanov@nginx.com nxt_unit_port_t ready_port; 152*743Smax.romanov@nginx.com uint32_t ready_stream; 153*743Smax.romanov@nginx.com nxt_unit_port_t read_port; 154*743Smax.romanov@nginx.com int log_fd; 155*743Smax.romanov@nginx.com }; 156*743Smax.romanov@nginx.com 157*743Smax.romanov@nginx.com 158*743Smax.romanov@nginx.com typedef ssize_t (*nxt_unit_read_func_t)(nxt_unit_read_info_t *read_info, 159*743Smax.romanov@nginx.com void *dst, size_t size); 160*743Smax.romanov@nginx.com 161*743Smax.romanov@nginx.com 162*743Smax.romanov@nginx.com struct nxt_unit_read_info_s { 163*743Smax.romanov@nginx.com nxt_unit_read_func_t read; 164*743Smax.romanov@nginx.com int eof; 165*743Smax.romanov@nginx.com uint32_t buf_size; 166*743Smax.romanov@nginx.com void *data; 167*743Smax.romanov@nginx.com }; 168*743Smax.romanov@nginx.com 169*743Smax.romanov@nginx.com 170*743Smax.romanov@nginx.com /* 171*743Smax.romanov@nginx.com * Initialize Unit application library with necessary callbacks and 172*743Smax.romanov@nginx.com * ready/reply port parameters, send 'READY' response to master. 173*743Smax.romanov@nginx.com */ 174*743Smax.romanov@nginx.com nxt_unit_ctx_t *nxt_unit_init(nxt_unit_init_t *); 175*743Smax.romanov@nginx.com 176*743Smax.romanov@nginx.com /* 177*743Smax.romanov@nginx.com * Process received message, invoke configured callbacks. 178*743Smax.romanov@nginx.com * 179*743Smax.romanov@nginx.com * If application implements it's own event loop, each datagram received 180*743Smax.romanov@nginx.com * from port socket should be initially processed by unit. This function 181*743Smax.romanov@nginx.com * may invoke other application-defined callback for message processing. 182*743Smax.romanov@nginx.com */ 183*743Smax.romanov@nginx.com int nxt_unit_process_msg(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id, 184*743Smax.romanov@nginx.com void *buf, size_t buf_size, void *oob, size_t oob_size); 185*743Smax.romanov@nginx.com 186*743Smax.romanov@nginx.com /* 187*743Smax.romanov@nginx.com * Main function useful in case when application does not have it's own 188*743Smax.romanov@nginx.com * event loop. nxt_unit_run() starts infinite message wait and process loop. 189*743Smax.romanov@nginx.com * 190*743Smax.romanov@nginx.com * for (;;) { 191*743Smax.romanov@nginx.com * app_lib->port_recv(...); 192*743Smax.romanov@nginx.com * nxt_unit_process_msg(...); 193*743Smax.romanov@nginx.com * } 194*743Smax.romanov@nginx.com * 195*743Smax.romanov@nginx.com * The normally function returns when QUIT message received from Unit. 196*743Smax.romanov@nginx.com */ 197*743Smax.romanov@nginx.com int nxt_unit_run(nxt_unit_ctx_t *); 198*743Smax.romanov@nginx.com 199*743Smax.romanov@nginx.com /* Destroy application library object. */ 200*743Smax.romanov@nginx.com void nxt_unit_done(nxt_unit_ctx_t *); 201*743Smax.romanov@nginx.com 202*743Smax.romanov@nginx.com /* 203*743Smax.romanov@nginx.com * Allocate and initialize new execution context with new listen port to 204*743Smax.romanov@nginx.com * process requests in other thread. 205*743Smax.romanov@nginx.com */ 206*743Smax.romanov@nginx.com nxt_unit_ctx_t *nxt_unit_ctx_alloc(nxt_unit_ctx_t *, void *); 207*743Smax.romanov@nginx.com 208*743Smax.romanov@nginx.com /* Free unused context. It is not required to free main context. */ 209*743Smax.romanov@nginx.com void nxt_unit_ctx_free(nxt_unit_ctx_t *); 210*743Smax.romanov@nginx.com 211*743Smax.romanov@nginx.com /* Initialize port_id, calculate hash. */ 212*743Smax.romanov@nginx.com void nxt_unit_port_id_init(nxt_unit_port_id_t *port_id, pid_t pid, uint16_t id); 213*743Smax.romanov@nginx.com 214*743Smax.romanov@nginx.com /* 215*743Smax.romanov@nginx.com * Create extra incoming port, perform all required actions to propogate 216*743Smax.romanov@nginx.com * the port to Unit server. Fills structure referenced by port_id with 217*743Smax.romanov@nginx.com * current pid and new port id. 218*743Smax.romanov@nginx.com */ 219*743Smax.romanov@nginx.com int nxt_unit_create_send_port(nxt_unit_ctx_t *, nxt_unit_port_id_t *dst, 220*743Smax.romanov@nginx.com nxt_unit_port_id_t *port_id); 221*743Smax.romanov@nginx.com 222*743Smax.romanov@nginx.com /* Default 'add_port' implementation. */ 223*743Smax.romanov@nginx.com int nxt_unit_add_port(nxt_unit_ctx_t *, nxt_unit_port_t *port); 224*743Smax.romanov@nginx.com 225*743Smax.romanov@nginx.com /* Find previously added port. */ 226*743Smax.romanov@nginx.com nxt_unit_port_t *nxt_unit_find_port(nxt_unit_ctx_t *, 227*743Smax.romanov@nginx.com nxt_unit_port_id_t *port_id); 228*743Smax.romanov@nginx.com 229*743Smax.romanov@nginx.com /* Find, fill output 'port' and remove port from storage. */ 230*743Smax.romanov@nginx.com void nxt_unit_find_remove_port(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id, 231*743Smax.romanov@nginx.com nxt_unit_port_t *port); 232*743Smax.romanov@nginx.com 233*743Smax.romanov@nginx.com /* Default 'remove_port' implementation. */ 234*743Smax.romanov@nginx.com void nxt_unit_remove_port(nxt_unit_ctx_t *, nxt_unit_port_id_t *port_id); 235*743Smax.romanov@nginx.com 236*743Smax.romanov@nginx.com /* Default 'remove_pid' implementation. */ 237*743Smax.romanov@nginx.com void nxt_unit_remove_pid(nxt_unit_ctx_t *, pid_t pid); 238*743Smax.romanov@nginx.com 239*743Smax.romanov@nginx.com /* Default 'quit' implementation. */ 240*743Smax.romanov@nginx.com void nxt_unit_quit(nxt_unit_ctx_t *); 241*743Smax.romanov@nginx.com 242*743Smax.romanov@nginx.com /* Default 'port_send' implementation. */ 243*743Smax.romanov@nginx.com ssize_t nxt_unit_port_send(nxt_unit_ctx_t *, int fd, 244*743Smax.romanov@nginx.com const void *buf, size_t buf_size, 245*743Smax.romanov@nginx.com const void *oob, size_t oob_size); 246*743Smax.romanov@nginx.com 247*743Smax.romanov@nginx.com /* Default 'port_recv' implementation. */ 248*743Smax.romanov@nginx.com ssize_t nxt_unit_port_recv(nxt_unit_ctx_t *, int fd, void *buf, size_t buf_size, 249*743Smax.romanov@nginx.com void *oob, size_t oob_size); 250*743Smax.romanov@nginx.com 251*743Smax.romanov@nginx.com /* Calculates hash for given field name. */ 252*743Smax.romanov@nginx.com uint16_t nxt_unit_field_hash(const char* name, size_t name_length); 253*743Smax.romanov@nginx.com 254*743Smax.romanov@nginx.com /* Split host for server name and port. */ 255*743Smax.romanov@nginx.com void nxt_unit_split_host(char *host_start, uint32_t host_length, 256*743Smax.romanov@nginx.com char **name, uint32_t *name_length, char **port, uint32_t *port_length); 257*743Smax.romanov@nginx.com 258*743Smax.romanov@nginx.com /* Group duplicate fields for easy enumeration. */ 259*743Smax.romanov@nginx.com void nxt_unit_request_group_dup_fields(nxt_unit_request_info_t *req); 260*743Smax.romanov@nginx.com 261*743Smax.romanov@nginx.com /* 262*743Smax.romanov@nginx.com * Allocate response structure capable to store limited numer of fields. 263*743Smax.romanov@nginx.com * The structure may be accessed directly via req->response pointer or 264*743Smax.romanov@nginx.com * filled step-by-step using functions add_field and add_content. 265*743Smax.romanov@nginx.com */ 266*743Smax.romanov@nginx.com int nxt_unit_response_init(nxt_unit_request_info_t *req, 267*743Smax.romanov@nginx.com uint16_t status, uint32_t max_fields_count, uint32_t max_fields_size); 268*743Smax.romanov@nginx.com 269*743Smax.romanov@nginx.com int nxt_unit_response_realloc(nxt_unit_request_info_t *req, 270*743Smax.romanov@nginx.com uint32_t max_fields_count, uint32_t max_fields_size); 271*743Smax.romanov@nginx.com 272*743Smax.romanov@nginx.com int nxt_unit_response_is_init(nxt_unit_request_info_t *req); 273*743Smax.romanov@nginx.com 274*743Smax.romanov@nginx.com int nxt_unit_response_add_field(nxt_unit_request_info_t *req, 275*743Smax.romanov@nginx.com const char* name, uint8_t name_length, 276*743Smax.romanov@nginx.com const char* value, uint32_t value_length); 277*743Smax.romanov@nginx.com 278*743Smax.romanov@nginx.com int nxt_unit_response_add_content(nxt_unit_request_info_t *req, 279*743Smax.romanov@nginx.com const void* src, uint32_t size); 280*743Smax.romanov@nginx.com 281*743Smax.romanov@nginx.com /* 282*743Smax.romanov@nginx.com * Send prepared response to Unit server. Response structure destroyed during 283*743Smax.romanov@nginx.com * this call. 284*743Smax.romanov@nginx.com */ 285*743Smax.romanov@nginx.com int nxt_unit_response_send(nxt_unit_request_info_t *req); 286*743Smax.romanov@nginx.com 287*743Smax.romanov@nginx.com int nxt_unit_response_is_sent(nxt_unit_request_info_t *req); 288*743Smax.romanov@nginx.com 289*743Smax.romanov@nginx.com nxt_unit_buf_t *nxt_unit_response_buf_alloc(nxt_unit_request_info_t *req, 290*743Smax.romanov@nginx.com uint32_t size); 291*743Smax.romanov@nginx.com 292*743Smax.romanov@nginx.com int nxt_unit_buf_send(nxt_unit_buf_t *buf); 293*743Smax.romanov@nginx.com 294*743Smax.romanov@nginx.com void nxt_unit_buf_free(nxt_unit_buf_t *buf); 295*743Smax.romanov@nginx.com 296*743Smax.romanov@nginx.com nxt_unit_buf_t *nxt_unit_buf_next(nxt_unit_buf_t *buf); 297*743Smax.romanov@nginx.com 298*743Smax.romanov@nginx.com uint32_t nxt_unit_buf_max(void); 299*743Smax.romanov@nginx.com 300*743Smax.romanov@nginx.com uint32_t nxt_unit_buf_min(void); 301*743Smax.romanov@nginx.com 302*743Smax.romanov@nginx.com int nxt_unit_response_write(nxt_unit_request_info_t *req, const void *start, 303*743Smax.romanov@nginx.com size_t size); 304*743Smax.romanov@nginx.com 305*743Smax.romanov@nginx.com int nxt_unit_response_write_cb(nxt_unit_request_info_t *req, 306*743Smax.romanov@nginx.com nxt_unit_read_info_t *read_info); 307*743Smax.romanov@nginx.com 308*743Smax.romanov@nginx.com ssize_t nxt_unit_request_read(nxt_unit_request_info_t *req, void *dst, 309*743Smax.romanov@nginx.com size_t size); 310*743Smax.romanov@nginx.com 311*743Smax.romanov@nginx.com void nxt_unit_request_done(nxt_unit_request_info_t *req, int rc); 312*743Smax.romanov@nginx.com 313*743Smax.romanov@nginx.com 314*743Smax.romanov@nginx.com void nxt_unit_log(nxt_unit_ctx_t *ctx, int level, const char* fmt, ...); 315*743Smax.romanov@nginx.com 316*743Smax.romanov@nginx.com void nxt_unit_req_log(nxt_unit_request_info_t *req, int level, 317*743Smax.romanov@nginx.com const char* fmt, ...); 318*743Smax.romanov@nginx.com 319*743Smax.romanov@nginx.com #if (NXT_DEBUG) 320*743Smax.romanov@nginx.com 321*743Smax.romanov@nginx.com #define nxt_unit_debug(ctx, fmt, ARGS...) \ 322*743Smax.romanov@nginx.com nxt_unit_log(ctx, NXT_UNIT_LOG_DEBUG, fmt, ##ARGS) 323*743Smax.romanov@nginx.com 324*743Smax.romanov@nginx.com #define nxt_unit_req_debug(req, fmt, ARGS...) \ 325*743Smax.romanov@nginx.com nxt_unit_req_log(req, NXT_UNIT_LOG_DEBUG, fmt, ##ARGS) 326*743Smax.romanov@nginx.com 327*743Smax.romanov@nginx.com #else 328*743Smax.romanov@nginx.com 329*743Smax.romanov@nginx.com #define nxt_unit_debug(ctx, fmt, ARGS...) 330*743Smax.romanov@nginx.com 331*743Smax.romanov@nginx.com #define nxt_unit_req_debug(req, fmt, ARGS...) 332*743Smax.romanov@nginx.com 333*743Smax.romanov@nginx.com #endif 334*743Smax.romanov@nginx.com 335*743Smax.romanov@nginx.com 336*743Smax.romanov@nginx.com #define nxt_unit_warn(ctx, fmt, ARGS...) \ 337*743Smax.romanov@nginx.com nxt_unit_log(ctx, NXT_UNIT_LOG_WARN, fmt, ##ARGS) 338*743Smax.romanov@nginx.com 339*743Smax.romanov@nginx.com #define nxt_unit_req_warn(req, fmt, ARGS...) \ 340*743Smax.romanov@nginx.com nxt_unit_req_log(req, NXT_UNIT_LOG_WARN, fmt, ##ARGS) 341*743Smax.romanov@nginx.com 342*743Smax.romanov@nginx.com #define nxt_unit_error(ctx, fmt, ARGS...) \ 343*743Smax.romanov@nginx.com nxt_unit_log(ctx, NXT_UNIT_LOG_ERR, fmt, ##ARGS) 344*743Smax.romanov@nginx.com 345*743Smax.romanov@nginx.com #define nxt_unit_req_error(req, fmt, ARGS...) \ 346*743Smax.romanov@nginx.com nxt_unit_req_log(req, NXT_UNIT_LOG_ERR, fmt, ##ARGS) 347*743Smax.romanov@nginx.com 348*743Smax.romanov@nginx.com #define nxt_unit_alert(ctx, fmt, ARGS...) \ 349*743Smax.romanov@nginx.com nxt_unit_log(ctx, NXT_UNIT_LOG_ALERT, fmt, ##ARGS) 350*743Smax.romanov@nginx.com 351*743Smax.romanov@nginx.com #define nxt_unit_req_alert(req, fmt, ARGS...) \ 352*743Smax.romanov@nginx.com nxt_unit_req_log(req, NXT_UNIT_LOG_ALERT, fmt, ##ARGS) 353*743Smax.romanov@nginx.com 354*743Smax.romanov@nginx.com 355*743Smax.romanov@nginx.com #endif /* _NXT_UNIT_H_INCLUDED_ */ 356