#ifndef _LIGHTTPD_BACKENDS_H_ #define _LIGHTTPD_BACKENDS_H_ #include enum liBackendResult { LI_BACKEND_SUCCESS, /* got a connection */ LI_BACKEND_WAIT, /* establishing new connection, or waiting for a free slot */ LI_BACKEND_TIMEOUT /* wait timed out, no free slots available */ }; typedef enum liBackendResult liBackendResult; typedef struct liBackendCallbacks liBackendCallbacks; typedef struct liBackendWait liBackendWait; typedef struct liBackendConnection liBackendConnection; typedef struct liBackendPool liBackendPool; typedef struct liBackendConfig liBackendConfig; typedef void (*liBackendConnectionThreadCB)(liBackendPool *bpool, liWorker *wrk, liBackendConnection *bcon); typedef void (*liBackendCB)(liBackendPool *bpool); struct liBackendConnection { liEventIO watcher; gpointer data; }; /* states: [start] ->(new)-> [INACTIVE] ->(detach)-> [detached] ->(attach)-> [INACTIVE] ->get-> [active] ->put-> [INACTIVE] ->(close)-> [done] */ /* the backend pool might be locked while the callbacks are running, but don't rely on it */ struct liBackendCallbacks { /* for moving connection between threads */ liBackendConnectionThreadCB detach_thread_cb; liBackendConnectionThreadCB attach_thread_cb; /* for initializing/shutdown */ liBackendConnectionThreadCB new_cb; liBackendConnectionThreadCB close_cb; /* free pool config */ liBackendCB free_cb; }; struct liBackendPool { /* READ ONLY CONFIGURATION DATA */ const liBackendConfig *config; }; struct liBackendConfig { const liBackendCallbacks *callbacks; liSocketAddress sock_addr; /* >0: real limit for current connections + pendings connects * <0: unlimited connections, absolute value limits the number of pending connects per worker * =0: no limit * * if there is no limit (i.e. <= 0), backend connections won't be moved between threads */ int max_connections; /* how long we wait on keep-alive connections. 0: no keep-alive; * also used for new connection we didn't use */ guint idle_timeout; /* how long we wait for connect to succeed, must be > 0; when connect fails the pool gets "disabled". */ guint connect_timeout; /* how long a vrequest is allowed to wait for a connect before we return an error. if pool gets disabled all requests fail. * if a pending connect is assigned to a vrequest wait_timeout is not active. */ guint wait_timeout; /* how long the pool stays disabled. even if this is 0, all vrequests will receive an error on disable */ guint disable_time; /* max requests per connection. -1: unlimited */ int max_requests; /* if enabled, the backend.watcher will be set to internal callback and LI_EV_READ while the connection * is not used by a vrequest; * if it sees input data it will log an error and close it, and if it sees eof it will * close it too * if you disable this you should have to handle this yourself */ gboolean watch_for_close; }; LI_API liBackendPool* li_backend_pool_new(const liBackendConfig *config); LI_API void li_backend_pool_free(liBackendPool *bpool); LI_API liBackendResult li_backend_get(liVRequest *vr, liBackendPool *bpool, liBackendConnection **pbcon, liBackendWait **pbwait); LI_API void li_backend_wait_stop(liVRequest *vr, liBackendPool *bpool, liBackendWait **pbwait); /* set bcon->fd = -1 if you closed the connection after an error */ LI_API void li_backend_put(liWorker *wrk, liBackendPool *bpool, liBackendConnection *bcon, gboolean closecon); /* if closecon == TRUE or bcon->watcher.fd == -1 the connection gets removed */ /* if an idle connections gets closed; bcon must be INACTIVE (i.e. not detached and not active). * call in worker that bcon is attached to. */ LI_API void li_backend_connection_closed(liBackendPool *bpool, liBackendConnection *bcon); #endif