view seobeo/os/s_linux_edge.c @ 71:75de5903355c

Giagantic changes that update Dowa library to be more align with stb style array and hashmap. Updated Seobeo to be caching on server side instead of file level caching. Deleted bunch of things I don't really use.
author June Park <parkjune1995@gmail.com>
date Sun, 28 Dec 2025 20:34:22 -0800
parents a0f0ad5e42eb
children 48f260576059
line wrap: on
line source

#include <sys/epoll.h>
#include "seobeo/seobeo.h"


void *Seobeo_Web_Edge_Worker(void *vargs)
{
  WorkerArgs *args = vargs;
  const int max_events = 64;
  struct epoll_event events[max_events];

  // Each thread creates its own epoll to avoid race conditions
  int epfd = epoll_create1(0);
  if (epfd < 0) {
    perror("epoll_create1");
    return NULL;
  }

  // Add server socket to this thread's epoll
  struct epoll_event ev = {
    .events = EPOLLIN | EPOLLET,
    .data.ptr = args->srv
  };
  if (epoll_ctl(epfd, EPOLL_CTL_ADD, args->srv->socket, &ev) < 0) {
    perror("epoll_ctl ADD server");
    close(epfd);
    return NULL;
  }

  while (1) {
    int n = epoll_wait(epfd, events, max_events, -1);
    if (n < 0) {
      if (errno == EINTR) continue;
      perror("epoll_wait");
      continue;
    }

    for (int i = 0; i < n; i++) {
      Seobeo_Handle *phandle = events[i].data.ptr;

      if (phandle == args->srv) {
        // Accept all pending connections (edge-triggered mode)
        while (1) {
          Seobeo_Handle *p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv);
          if (!p_cli_handle) break;

          struct epoll_event client_ev = {
            .events = EPOLLIN | EPOLLET,
            .data.ptr = p_cli_handle
          };
          if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0)
          {
            perror("epoll_ctl ADD client");
            Seobeo_Handle_Destroy(p_cli_handle);
          }
        }
      } else {
        // Remove from epoll first
        epoll_ctl(epfd, EPOLL_CTL_DEL, phandle->socket, NULL);

        // Handle request (this function destroys the handle internally)
        Seobeo_Web_HandleClientRequest(phandle, args->cache);
      }
    }
  }

  close(epfd);
  return NULL;
}

void Seobeo_Web_Edge(
    Seobeo_Handle *p_server_handle,
    int thread_count,
    Seobeo_Cache_Entry *p_html_cache)
{
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB

  pthread_t threads[thread_count];
  for (int i = 0; i < thread_count; i++) {
    WorkerArgs *args = malloc(sizeof(WorkerArgs));
    *args = (WorkerArgs){ p_server_handle, p_html_cache };

    pthread_create(&threads[i], &attr, Seobeo_Web_Edge_Worker, args);
  }

  // Join threads instead of detaching for proper cleanup
  for (int i = 0; i < thread_count; i++) {
    pthread_join(threads[i], NULL);
  }

  pthread_attr_destroy(&attr);
}