LCOV - code coverage report
Current view: top level - lib - lwan-tq.c (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 43 48 89.6 %
Date: 2023-04-18 16:19:03 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /*
       2             :  * lwan - web server
       3             :  * Copyright (c) 2019 L. A. F. Pereira <l@tia.mat.br>
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or
       6             :  * modify it under the terms of the GNU General Public License
       7             :  * as published by the Free Software Foundation; either version 2
       8             :  * of the License, or any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
      18             :  * USA.
      19             :  */
      20             : 
      21             : #include <unistd.h>
      22             : 
      23             : #include "lwan-private.h"
      24             : #include "lwan-tq.h"
      25             : 
      26         595 : static inline int timeout_queue_node_to_idx(struct timeout_queue *tq,
      27             :                                             struct lwan_connection *conn)
      28             : {
      29         595 :     return (conn == &tq->head) ? -1 : (int)(intptr_t)(conn - tq->conns);
      30             : }
      31             : 
      32             : static inline struct lwan_connection *
      33        1599 : timeout_queue_idx_to_node(struct timeout_queue *tq, int idx)
      34             : {
      35        1599 :     return (idx < 0) ? &tq->head : &tq->conns[idx];
      36             : }
      37             : 
      38         595 : inline void timeout_queue_insert(struct timeout_queue *tq,
      39             :                                  struct lwan_connection *new_node)
      40             : {
      41         595 :     new_node->next = -1;
      42         595 :     new_node->prev = tq->head.prev;
      43         595 :     struct lwan_connection *prev = timeout_queue_idx_to_node(tq, tq->head.prev);
      44         595 :     tq->head.prev = prev->next = timeout_queue_node_to_idx(tq, new_node);
      45         595 : }
      46             : 
      47         500 : static inline void timeout_queue_remove(struct timeout_queue *tq,
      48             :                                         struct lwan_connection *node)
      49             : {
      50         500 :     struct lwan_connection *prev = timeout_queue_idx_to_node(tq, node->prev);
      51         500 :     struct lwan_connection *next = timeout_queue_idx_to_node(tq, node->next);
      52             : 
      53         500 :     next->prev = node->prev;
      54         500 :     prev->next = node->next;
      55         500 : }
      56             : 
      57          13 : inline bool timeout_queue_empty(struct timeout_queue *tq)
      58             : {
      59          13 :     return tq->head.next < 0;
      60             : }
      61             : 
      62         263 : inline void timeout_queue_move_to_last(struct timeout_queue *tq,
      63             :                                        struct lwan_connection *conn)
      64             : {
      65             :     /* CONN_IS_KEEP_ALIVE isn't checked here because non-keep-alive connections
      66             :      * are closed in the request processing coroutine after they have been
      67             :      * served.  In practice, if this is called, it's a keep-alive connection. */
      68         263 :     conn->time_to_expire = tq->current_time + tq->move_to_last_bump;
      69             : 
      70         263 :     timeout_queue_remove(tq, conn);
      71         263 :     timeout_queue_insert(tq, conn);
      72         263 : }
      73             : 
      74         184 : void timeout_queue_init(struct timeout_queue *tq, const struct lwan *lwan)
      75             : {
      76         184 :     *tq = (struct timeout_queue){
      77             :         .lwan = lwan,
      78         184 :         .conns = lwan->conns,
      79             :         .current_time = 0,
      80         184 :         .move_to_last_bump = lwan->config.keep_alive_timeout,
      81             :         .head.next = -1,
      82             :         .head.prev = -1,
      83             :         .timeout = (struct timeout){},
      84             :     };
      85         184 : }
      86             : 
      87         237 : void timeout_queue_expire(struct timeout_queue *tq,
      88             :                           struct lwan_connection *conn)
      89             : {
      90         237 :     timeout_queue_remove(tq, conn);
      91             : 
      92         237 :     if (LIKELY(conn->coro)) {
      93         237 :         coro_free(conn->coro);
      94         237 :         conn->coro = NULL;
      95             :     }
      96             : 
      97         237 :     close(lwan_connection_get_fd(tq->lwan, conn));
      98         237 : }
      99             : 
     100           6 : void timeout_queue_expire_waiting(struct timeout_queue *tq)
     101             : {
     102           6 :     tq->current_time++;
     103             : 
     104           7 :     while (!timeout_queue_empty(tq)) {
     105             :         struct lwan_connection *conn =
     106           4 :             timeout_queue_idx_to_node(tq, tq->head.next);
     107             : 
     108           4 :         if (conn->time_to_expire > tq->current_time)
     109           3 :             return;
     110             : 
     111           1 :         timeout_queue_expire(tq, conn);
     112             :     }
     113             : 
     114             :     /* Timeout queue exhausted: reset epoch */
     115           3 :     tq->current_time = 0;
     116             : }
     117             : 
     118           0 : void timeout_queue_expire_all(struct timeout_queue *tq)
     119             : {
     120           0 :     while (!timeout_queue_empty(tq)) {
     121             :         struct lwan_connection *conn =
     122           0 :             timeout_queue_idx_to_node(tq, tq->head.next);
     123           0 :         timeout_queue_expire(tq, conn);
     124             :     }
     125           0 : }

Generated by: LCOV version 1.15-2-gb9d6727