diff --git a/samples/knot.full.conf b/samples/knot.full.conf index bb3213e44109771515256d88d99a1b80983c401a..1b67376e7ee310e545133c98817b07f581defc66 100644 --- a/samples/knot.full.conf +++ b/samples/knot.full.conf @@ -23,6 +23,11 @@ system { # Working directory of the server # Used to store compiled zones and PID file storage "/tmp/knot-sample"; + + # Number of workers per interface + # This option is used to force number of threads used per interface + # Default: unset (auto-estimates optimal value from the number of online CPUs) + workers 1; } # Section 'keys' contains list of TSIG keys diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l index f5d38d13d9639e44918e12c4b85c2e93641d596b..97ac8f811126367756fbd55df9f20f537acc2692 100644 --- a/src/knot/conf/cf-lex.l +++ b/src/knot/conf/cf-lex.l @@ -72,6 +72,7 @@ xfr-in { lval.t = yytext; return XFR_IN; } xfr-out { lval.t = yytext; return XFR_OUT; } notify-in { lval.t = yytext; return NOTIFY_IN; } notify-out { lval.t = yytext; return NOTIFY_OUT; } +workers { lval.t = yytext; return WORKERS; } interfaces { lval.t = yytext; return INTERFACES; } address { lval.t = yytext; return ADDRESS; } diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y index 672acb9205c6bc4e88a477098b1b7b29da106a8a..d793865c841d252a3b39408380c7bd8111648ac6 100644 --- a/src/knot/conf/cf-parse.y +++ b/src/knot/conf/cf-parse.y @@ -155,6 +155,7 @@ static int conf_key_add(void *scanner, knot_key_t **key, char *item) %token <tok> SYSTEM IDENTITY VERSION STORAGE KEY KEYS %token <tok> TSIG_ALGO_NAME +%token <tok> WORKERS %token <tok> REMOTES @@ -240,9 +241,9 @@ interface: this_iface->address = $3.t; this_iface->family = AF_INET6; if (this_iface->port != CONFIG_DEFAULT_PORT) { - cf_error(scanner, "only one port definition is allowed in interface section\n"); + cf_error(scanner, "only one port definition is allowed in interface section\n"); } else { - this_iface->port = $5.i; + this_iface->port = $5.i; } } } @@ -269,6 +270,13 @@ system: "and has no effect.\n"); free($4.t); } + | system WORKERS NUM ';' { + if ($3.i <= 0) { + cf_error(scanner, "worker count must be greater than 0\n"); + } else { + new_config->workers = $3.i; + } + } ; keys: diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index ad61350e57b7289b05ce787c6caf27eb06ee4357..687dcc2d7583d8157b18fae94fbbf274856aa467 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -139,6 +139,7 @@ typedef struct conf_t { char *version; /*!< Version for CH TXT version.{bind|server} */ char *storage; /*!< Persistent storage path for databases and such. */ char *pidfile; /*!< PID file path. */ + int workers; /*!< Number of workers per interface. */ /* * Log diff --git a/src/knot/server/server.c b/src/knot/server/server.c index 39aef26f1d4668402aca5304dc7fded8bcebca9f..8a27319b3e184fbc8cf18a72ba95962aaccf06b8 100644 --- a/src/knot/server/server.c +++ b/src/knot/server/server.c @@ -305,16 +305,25 @@ static int server_bind_handlers(server_t *server) if (!server || !server->ifaces) { return KNOTD_EINVAL; } + + /* Lock config. */ + conf_read_lock(); /* Estimate number of threads/manager. */ - int thr_count = dt_optimal_size(); - int tcp_unit_size = (thr_count >> 1); - if (tcp_unit_size < 3) { - tcp_unit_size = 3; + int thr_count = 0; + int tcp_unit_size = 0; + if (conf()->workers < 1) { + thr_count = dt_optimal_size(); + tcp_unit_size = (thr_count * 2) + 1; /* Will be always odd. */ + } else { + thr_count = conf()->workers; + tcp_unit_size = thr_count + 1; /* Force configured value. */ } - - /* Lock config. */ - conf_read_lock(); + + dbg_server("server: configured %d worker%s per UDP iface\n", + thr_count, thr_count > 1 ? "s" : ""); + dbg_server("server: configured %d worker%s per TCP iface\n", + tcp_unit_size - 1, (tcp_unit_size - 1) > 1 ? "s" : ""); /* Create socket handlers. */ node *n = 0; @@ -333,7 +342,7 @@ static int server_bind_handlers(server_t *server) /* Save pointer. */ rcu_set_pointer(&iface->handler[UDP_ID], h); - dbg_server("Creating UDP socket handlers for '%s:%d'\n", + dbg_server("server: creating UDP socket handlers for '%s:%d'\n", iface->addr, iface->port); } @@ -348,7 +357,7 @@ static int server_bind_handlers(server_t *server) /* Save pointer. */ rcu_set_pointer(&iface->handler[TCP_ID], h); - dbg_server("Creating TCP socket handlers for '%s:%d'\n", + dbg_server("server: creating TCP socket handlers for '%s:%d'\n", iface->addr, iface->port); } @@ -375,21 +384,21 @@ server_t *server_create() init_list(server->ifaces); // Create event scheduler - dbg_server("Creating event scheduler...\n"); + dbg_server("server: creating event scheduler\n"); server->sched = evsched_new(); dt_unit_t *unit = dt_create_coherent(1, evsched_run, 0); iohandler_t *h = server_create_handler(server, -1, unit); h->data = server->sched; // Create name server - dbg_server("Creating Name Server structure...\n"); + dbg_server("server: creating Name Server structure\n"); server->nameserver = knot_ns_create(); if (server->nameserver == NULL) { free(server); return NULL; } knot_ns_set_data(server->nameserver, server); - dbg_server("Initializing OpenSSL...\n"); + dbg_server("server: initializing OpenSSL\n"); OpenSSL_add_all_digests(); // Create XFR handler @@ -400,7 +409,7 @@ server_t *server_create() return NULL; } - dbg_server("Done.\n"); + dbg_server("server: created server instance\n"); return server; } @@ -509,7 +518,7 @@ int server_start(server_t *server) return KNOTD_EINVAL; } - dbg_server("Starting handlers...\n"); + dbg_server("server: starting server instance\n"); /* Start XFR handler. */ xfr_start(server->xfr_h); @@ -538,7 +547,7 @@ int server_start(server_t *server) /* Unlock configuration. */ conf_read_unlock(); - dbg_server("Done.\n"); + dbg_server("server: server started\n"); return ret; } @@ -578,6 +587,8 @@ int server_wait(server_t *server) void server_stop(server_t *server) { + dbg_server("server: stopping server\n"); + /* Wait for XFR master. */ xfr_stop(server->xfr_h); @@ -620,6 +631,8 @@ void server_destroy(server_t **server) return; } + dbg_server("server: destroying server instance\n"); + // Free XFR master xfr_free((*server)->xfr_h); diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c index ab93bdf4a18d44bd9c6ce5bb1e23ee1e8a2e0c53..b96d32ea06ccbc160e0d49c1fbbf7c50ba46170f 100644 --- a/src/knot/server/zones.c +++ b/src/knot/server/zones.c @@ -672,7 +672,7 @@ static int zones_load_zone(knot_zonedb_t *zonedb, const char *zone_name, // Check path if (filename) { - dbg_server("Parsing zone database '%s'\n", filename); + dbg_zones("zones: parsing zone database '%s'\n", filename); zloader_t *zl = 0; int ret = knot_zload_open(&zl, filename); switch(ret) {