<commit_before>/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*  Monkey HTTP Daemon
 *  ------------------
 *  Copyright (C) 2001-2012, <NAME>. <<EMAIL>>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>

#include "monkey.h"
#include "mk_socket.h"
#include "mk_clock.h"
#include "mk_request.h"
#include "mk_config.h"
#include "mk_scheduler.h"
#include "mk_epoll.h"
#include "mk_utils.h"
#include "mk_macros.h"

pthread_key_t mk_epoll_state_k;

/*
 * Initialize the epoll state index per worker thread, every index struct contains
 * a fixed array of epoll_state entries and two mk_list to represent an available and
 * busy queue for each entry
 */
int mk_epoll_state_init()
{
    int i;
    struct epoll_state *es;
    struct epoll_state_index *index;

    index = mk_mem_malloc_z(sizeof(struct epoll_state_index));
    index->size  = MK_EPOLL_STATE_INDEX_CHUNK;
    mk_list_init(&index->busy_queue);
    mk_list_init(&index->av_queue);

    for (i = 0; i < index->size; i++) {
        es = mk_mem_malloc_z(sizeof(struct epoll_state));
        mk_list_add(&es->_head, &index->av_queue);
    }

    return pthread_setspecific(mk_epoll_state_k, (void *) index);
}

inline struct epoll_state *mk_epoll_state_set(int efd, int fd, uint8_t mode,
                                              uint8_t  behavior,
                                              uint32_t events)
{
    int i;
    struct epoll_state_index *index;
    struct epoll_state *es_entry = NULL, *es_tmp;
    struct mk_list *head;

    index = (struct epoll_state_index *) pthread_getspecific(mk_epoll_state_k);

    /*
     * Lets check if we are in the thread context, if dont, this can be the
     * situation when the file descriptor is new and comes from the parent
     * server loop and is just being assigned to the worker thread
     */
    if (mk_unlikely(!index)) {
        return NULL;
    }

    mk_list_foreach(head, &index->busy_queue) {
        es_entry = mk_list_entry(head, struct epoll_state, _head);
        if (es_entry->instance == efd && es_entry->fd == fd) {
            break;
        }
        es_entry = NULL;
    }

    /* Add new entry to the list */
    if (!es_entry) {

        /* check if we have available slots */
        if (mk_list_is_empty(&index->av_queue) == 0) {

            /* We need to grow the epoll_states list */
            for (i = 0; i < MK_EPOLL_STATE_INDEX_CHUNK; i++) {
                es_tmp = mk_mem_malloc(sizeof(struct epoll_state));
                mk_list_add(&es_tmp->_head, &index->av_queue);
            }
            MK_TRACE("state index size=%i, grow from %i to %i",
                     index->size, index->size + MK_EPOLL_STATE_INDEX_CHUNK);
            index->size += MK_EPOLL_STATE_INDEX_CHUNK;

        }

        /* New entry */
        es_entry = mk_list_entry_first(&index->av_queue, struct epoll_state, _head);
        es_entry->instance = efd;
        es_entry->fd       = fd;
        es_entry->mode     = mode;
        es_entry->behavior = behavior;
        es_entry->events   = events;

        /* Unlink from available queue and link to busy queue */
        mk_list_del(&es_entry->_head);
        mk_list_add(&es_entry->_head, &index->busy_queue);
<commit_msg>Epoll: epoll states array size now its equal to worker capacity<commit_after>/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*  Monkey HTTP Daemon
 *  ------------------
 *  Copyright (C) 2001-2012, <NAME>. <<EMAIL>>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>

#include "monkey.h"
#include "mk_socket.h"
#include "mk_clock.h"
#include "mk_request.h"
#include "mk_config.h"
#include "mk_scheduler.h"
#include "mk_epoll.h"
#include "mk_utils.h"
#include "mk_macros.h"

pthread_key_t mk_epoll_state_k;

/*
 * Initialize the epoll state index per worker thread, every index struct contains
 * a fixed array of epoll_state entries and two mk_list to represent an available and
 * busy queue for each entry
 */
int mk_epoll_state_init()
{
    int i;
    struct epoll_state *es;
    struct epoll_state_index *index;

    index = mk_mem_malloc_z(sizeof(struct epoll_state_index));
    index->size  = config->worker_capacity;
    mk_list_init(&index->busy_queue);
    mk_list_init(&index->av_queue);

    for (i = 0; i < index->size; i++) {
        es = mk_mem_malloc_z(sizeof(struct epoll_state));
        mk_list_add(&es->_head, &index->av_queue);
    }

    return pthread_setspecific(mk_epoll_state_k, (void *) index);
}

inline struct epoll_state *mk_epoll_state_set(int efd, int fd, uint8_t mode,
                                              uint8_t  behavior,
                                              uint32_t events)
{
    int i;
    struct epoll_state_index *index;
    struct epoll_state *es_entry = NULL, *es_tmp;
    struct mk_list *head;

    index = (struct epoll_state_index *) pthread_getspecific(mk_epoll_state_k);

    /*
     * Lets check if we are in the thread context, if dont, this can be the
     * situation when the file descriptor is new and comes from the parent
     * server loop and is just being assigned to the worker thread
     */
    if (mk_unlikely(!index)) {
        return NULL;
    }

    mk_list_foreach(head, &index->busy_queue) {
        es_entry = mk_list_entry(head, struct epoll_state, _head);
        if (es_entry->instance == efd && es_entry->fd == fd) {
            break;
        }
        es_entry = NULL;
    }

    /* Add new entry to the list */
    if (!es_entry) {

        /* check if we have available slots */
        if (mk_list_is_empty(&index->av_queue) == 0) {

            /* We need to grow the epoll_states list */
            es_tmp = mk_mem_malloc(sizeof(struct epoll_state) * MK_EPOLL_STATE_INDEX_CHUNK);
            for (i = 0; i < MK_EPOLL_STATE_INDEX_CHUNK; i++) {
                mk_list_add(&es_tmp[i]._head, &index->av_queue);
            }
            MK_TRACE("state index grow from %i to %i\n",
                     index->size, index->size + MK_EPOLL_STATE_INDEX_CHUNK);
            index->size += MK_EPOLL_STATE_INDEX_CHUNK;

        }

        /* New entry */
        es_entry = mk_list_entry_first(&index->av_queue, struct epoll_state, _head);
        es_entry->instance = efd;
        es_entry->fd       = fd;
        es_entry->mode     = mode;
        es_entry->behavior = behavior;
        es_entry->events   = events;

        /* Unlink from available queue and link to busy queue */
        mk_list_del(&es_entry->_head);
        mk_list_add(&es_entry->_head, &index->busy_queue);

{'fraction_non_alphanumeric': 0.107981220657277, 'fraction_numerical': 0.006982063320091489, 'mean_word_length': 2.650263620386643, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5166543', 'n_tokens_mistral': 2723, 'n_tokens_neox': 2643, 'n_words': 802}