#ifndef _LIGHTTPD_WORKER_H_ #define _LIGHTTPD_WORKER_H_ #ifndef _LIGHTTPD_BASE_H_ #error Please include instead of this file #endif #include #include struct lua_State; typedef struct liStatistics liStatistics; struct liStatistics { guint64 bytes_out; /** bytes transfered, outgoing */ guint64 bytes_in; /** bytes transfered, incoming */ guint64 requests; /** processed requests */ guint64 active_cons_cum; /** cummulative value of active connections, updated once a second */ guint64 actions_executed; /** actions executed */ /* 5 seconds frame avg */ guint64 requests_5s; guint64 requests_5s_diff; guint64 bytes_out_5s; guint64 bytes_out_5s_diff; guint64 bytes_in_5s; guint64 bytes_in_5s_diff; guint active_cons_5s; li_tstamp last_avg; /* peak values from 5s avg */ struct { guint64 requests; guint64 bytes_out; guint64 bytes_in; guint active_cons; } peak; /* updated in timer */ guint64 last_requests; double requests_per_sec; li_tstamp last_update; }; typedef struct liWorkerTS liWorkerTS; struct liWorkerTS { time_t last_generated; GString *str; }; struct liWorker { liServer *srv; GThread *thread; /* managed by server.c */ guint ndx; /* worker index */ liLuaState LL; liEventLoop loop; liEventPrepare loop_prepare; liEventAsync worker_stop_watcher, worker_stopping_watcher, worker_suspend_watcher, worker_exit_watcher; liLogWorkerData logs; guint connections_active; /** 0..con_act-1: active connections, con_act..used-1: free connections * use with atomic, read direct from local worker context */ guint connections_active_max_5min; /** max() of active connections during the last 5 minutes */ GArray *connections; /** array of (connection*), use only from local worker context */ li_tstamp connections_gc_ts; GString *tmp_str; /**< can be used everywhere for local temporary needed strings */ /* keep alive timeout queue */ liEventTimer keep_alive_timer; GQueue keep_alive_queue; liWaitQueue io_timeout_queue; liWaitQueue throttle_queue; guint connection_load; /** incremented by server_accept_cb, decremented by worker_con_put. use atomic access */ GArray *timestamps_gmt; /** array of (worker_ts), use only from local worker context and through li_worker_current_timestamp(wrk, LI_GMTIME, ndx) */ GArray *timestamps_local; /* incoming queues */ /* - new connections (after accept) */ liEventAsync new_con_watcher; GAsyncQueue *new_con_queue; liServerStateWait wait_for_stop_connections; liEventTimer stats_watcher; liStatistics stats; /* collect framework */ liEventAsync collect_watcher; GAsyncQueue *collect_queue; liTaskletPool *tasklets; liStatCache *stat_cache; liBuffer *network_read_buf; /** available buffer - steal it if you need it, can be NULL. refcount must be 1, no other references. */ }; LI_API liWorker* li_worker_new(liServer *srv, struct ev_loop *loop); LI_API struct ev_loop* li_worker_free(liWorker *wrk); LI_API void li_worker_run(liWorker *wrk); /* stopped now, all connections down. exit loop soon */ LI_API void li_worker_stop(liWorker *context, liWorker *wrk); /* start stopping. don't stop loop yet, connection handling on other workers might need all workers (mod_status) */ LI_API void li_worker_stopping(liWorker *context, liWorker *wrk); LI_API void li_worker_suspend(liWorker *context, liWorker *wrk); LI_API void li_worker_exit(liWorker *context, liWorker *wrk); LI_API void li_worker_new_con(liWorker *ctx, liWorker *wrk, liSocketAddress remote_addr, int s, liServerSocket *srv_sock); LI_API void li_worker_check_keepalive(liWorker *wrk); LI_API GString* li_worker_current_timestamp(liWorker *wrk, liTimeFunc, guint format_ndx); /* shutdown write and wait for eof before shutdown read and close */ LI_API void li_worker_add_closing_socket(liWorker *wrk, int fd); /* internal function to recycle connection */ LI_API void li_worker_con_put(liConnection *con); INLINE li_tstamp li_cur_ts(liWorker *wrk); INLINE liWorker* li_worker_from_iostream(liIOStream *stream); INLINE liWorker* li_worker_from_stream(liStream *stream); /* inline implementations */ INLINE li_tstamp li_cur_ts(liWorker *wrk) { return li_event_now(&wrk->loop); } INLINE liWorker* li_worker_from_stream(liStream *stream) { if (NULL == stream->loop) return NULL; return LI_CONTAINER_OF(stream->loop, liWorker, loop); } INLINE liWorker* li_worker_from_iostream(liIOStream *stream) { liWorker* wrk; wrk = li_worker_from_stream(&stream->stream_in); if (NULL != wrk) return wrk; wrk = li_worker_from_stream(&stream->stream_out); if (NULL != wrk) return wrk; { liEventLoop *loop = li_event_get_loop(&stream->io_watcher); if (NULL == loop) return NULL; return LI_CONTAINER_OF(loop, liWorker, loop); } } #endif