You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.9 KiB
103 lines
3.9 KiB
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "admissions_info.h"
|
|
#include "http.h"
|
|
#include "listener_thread.h"
|
|
#include "panic.h"
|
|
#include "scheduler_options.h"
|
|
#include "tenant.h"
|
|
#include "tenant_config.h"
|
|
|
|
int tenant_database_add(struct tenant *tenant);
|
|
struct tenant *tenant_database_find_by_name(char *name);
|
|
struct tenant *tenant_database_find_by_socket_descriptor(int socket_descriptor);
|
|
struct tenant *tenant_database_find_by_port(uint16_t port);
|
|
|
|
static inline struct tenant *
|
|
tenant_alloc(struct tenant_config *config)
|
|
{
|
|
/* Validate config */
|
|
if (strlen(config->name) == 0) panic("name field is required\n");
|
|
if (config->port == 0) panic("port field is required\n");
|
|
if (config->routes_len == 0) panic("one or more routesa are required\n");
|
|
|
|
struct tenant *existing_tenant = tenant_database_find_by_name(config->name);
|
|
if (existing_tenant != NULL) panic("Tenant %s is already initialized\n", existing_tenant->name);
|
|
|
|
existing_tenant = tenant_database_find_by_port(config->port);
|
|
if (existing_tenant != NULL)
|
|
panic("Tenant %s is already configured with port %u\n", existing_tenant->name, config->port);
|
|
|
|
for (int i = 0; i < config->routes_len; i++) {
|
|
struct route_config *route_config = &config->routes[i];
|
|
if (route_config->path == 0) panic("path field is required\n");
|
|
if (route_config->route == 0) panic("route field is required\n");
|
|
|
|
|
|
if (route_config->http_req_size > RUNTIME_HTTP_REQUEST_SIZE_MAX)
|
|
panic("request_size must be between 0 and %u, was %u\n",
|
|
(uint32_t)RUNTIME_HTTP_REQUEST_SIZE_MAX, route_config->http_req_size);
|
|
|
|
if (route_config->http_resp_size > RUNTIME_HTTP_RESPONSE_SIZE_MAX)
|
|
panic("response-size must be between 0 and %u, was %u\n",
|
|
(uint32_t)RUNTIME_HTTP_RESPONSE_SIZE_MAX, route_config->http_resp_size);
|
|
|
|
if (route_config->relative_deadline_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX)
|
|
panic("Relative-deadline-us must be between 0 and %u, was %u\n",
|
|
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, route_config->relative_deadline_us);
|
|
|
|
#ifdef ADMISSIONS_CONTROL
|
|
/* expected-execution-us and relative-deadline-us are required in case of admissions control */
|
|
if (route_config->expected_execution_us == 0) panic("expected-execution-us is required\n");
|
|
if (route_config->relative_deadline_us == 0) panic("relative_deadline_us is required\n");
|
|
|
|
if (route_config->admissions_percentile > 99 || route_config->admissions_percentile < 50)
|
|
panic("admissions-percentile must be > 50 and <= 99 but was %u\n",
|
|
route_config->admissions_percentile);
|
|
|
|
/* If the ratio is too big, admissions control is too coarse */
|
|
uint32_t ratio = route_config->relative_deadline_us / route_config->expected_execution_us;
|
|
if (ratio > ADMISSIONS_CONTROL_GRANULARITY)
|
|
panic("Ratio of Deadline to Execution time cannot exceed admissions control "
|
|
"granularity of "
|
|
"%d\n",
|
|
ADMISSIONS_CONTROL_GRANULARITY);
|
|
#else
|
|
/* relative-deadline-us is required if scheduler is EDF */
|
|
if (scheduler == SCHEDULER_EDF && route_config->relative_deadline_us == 0)
|
|
panic("relative_deadline_us is required\n");
|
|
#endif
|
|
}
|
|
|
|
|
|
struct tenant *tenant = (struct tenant *)calloc(1, sizeof(struct tenant));
|
|
|
|
/* Move name */
|
|
tenant->name = config->name;
|
|
config->name = NULL;
|
|
|
|
tcp_server_init(&tenant->tcp_server, config->port);
|
|
http_router_init(&tenant->router);
|
|
module_database_init(&tenant->module_db);
|
|
|
|
for (int i = 0; i < config->routes_len; i++) {
|
|
/* Resolve module */
|
|
struct module *module = module_database_find_by_path(&tenant->module_db, config->routes[i].path);
|
|
assert(module != NULL);
|
|
http_router_add_route(&tenant->router, &config->routes[i], module);
|
|
}
|
|
|
|
return tenant;
|
|
}
|
|
|
|
/**
|
|
* Start the tenant as a server listening at tenant->port
|
|
* @param tenant
|
|
* @returns 0 on success, -1 on error
|
|
*/
|
|
int tenant_listen(struct tenant *tenant);
|
|
int listener_thread_register_tenant(struct tenant *tenant);
|