diff --git a/benchmark.sh b/benchmark.sh new file mode 100755 index 0000000000000000000000000000000000000000..4da55304e55e440227efeb80e608b3af3f733676 --- /dev/null +++ b/benchmark.sh @@ -0,0 +1,10 @@ +#! /bin/bash +for ((x=0; x < $1; x++)) +do +time ( + for ((y=0; y < $2; y++)) + do + dig -t TXT ecklapos.sch.bme.hu @::1 -p 10053 + done > /dev/null +)& +done diff --git a/include/dns_server.h b/include/dns_server.h index 98cf62b4a1475119c0ceedbde1c4113423e53a37..5abb7fd295310240ebf559d430ed93ccad272bb1 100644 --- a/include/dns_server.h +++ b/include/dns_server.h @@ -12,19 +12,21 @@ #include "general_sockaddr_wp.h" #include "udp_socket_wp.h" -class dns_server { +class dns_server +{ private: dns_db db; udp_socket_wp socket; -#ifndef DEBUG + volatile bool running; // Más jelentést kéne neki adni és akkor egyértelműbb lenne, hogy mikor kell beállítani igazra/hamisra + pthread_t *threads; + int thread_num; + dns_server(const dns_db& __db) { throw "Not implementable"; } protected: -#else -public: -#endif + static void *thread_func(void *server_obj); void serve_one_request(); + void delete_threads(); public: - dns_server() {} - dns_server(const dns_db& __db): db(__db) {} + dns_server(); dns_server(const general_sockaddr_wp& addr); dns_server(const general_sockaddr_wp& addr, const char *db_path); dns_server(const general_sockaddr_wp& addr, const dns_db& __db); @@ -33,6 +35,11 @@ public: void init(const general_sockaddr_wp& addr); + void serve_forever(); + void serve_in_threads(int n); + + void stop(); + void shutdown(); virtual ~dns_server() { this->shutdown(); } }; diff --git a/include/exceptions/db_exception.h b/include/exceptions/db_exception.h index fb75cb8c0c2ac3a47ff692bd05716f5bcee7230f..93de0e2e559e27d12a9eda917eda99b391338237 100644 --- a/include/exceptions/db_exception.h +++ b/include/exceptions/db_exception.h @@ -8,13 +8,14 @@ #ifndef DB_EXCEPTION_H #define DB_EXCEPTION_H +#include <string> #include <exception> class db_exception: public std::exception { std::string msg; public: - db_exception(const std::string& msg): msg(msg) {} + explicit db_exception(const std::string& msg): msg(msg) {} virtual const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT { return msg.c_str(); } }; diff --git a/include/exceptions/dns_exception.h b/include/exceptions/dns_exception.h index d7cf7e9c4a9b1910148196ead71deb8a37d4821b..0f8df4172f12bf6824eb5b1fa39100d4a35425ed 100644 --- a/include/exceptions/dns_exception.h +++ b/include/exceptions/dns_exception.h @@ -8,13 +8,14 @@ #ifndef DNS_EXCEPTION_H #define DNS_EXCEPTION_H +#include <string> #include <exception> class dns_exception: public std::exception { std::string msg; public: - dns_exception(const std::string& msg): msg(msg) {} + explicit dns_exception(const std::string& msg): msg(msg) {} virtual const char *what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT { return msg.c_str(); } }; diff --git a/include/exceptions/server_error.h b/include/exceptions/server_error.h new file mode 100644 index 0000000000000000000000000000000000000000..9de8960b93db0d2811bac4a52e6d7fd9df13a5eb --- /dev/null +++ b/include/exceptions/server_error.h @@ -0,0 +1,20 @@ +/* + * File: server_error.h + * Author: Eckl Máté <ecklm94@gmail.com> + * + * Created on 2016. május 22., 22:23 + */ + +#ifndef SERVER_ERROR_H +#define SERVER_ERROR_H + +#include <string> +#include <stdexcept> + +class server_error: public std::runtime_error +{ +public: + explicit server_error(const std::string& msg): std::runtime_error(msg) {} +}; + +#endif /* SERVER_ERROR_H */ diff --git a/main.cpp b/main.cpp index a6a95d849ded81a64db840de304b8eadf7767fb5..3b6681a8bab71647f2c0764d469d87f02b227edd 100644 --- a/main.cpp +++ b/main.cpp @@ -72,11 +72,7 @@ int main(int argc, char *argv[]) { openlog("ecklm-dns", LOG_PID, LOG_DAEMON); log_on_demand = syslog_on_demand; -#ifdef DEBUG // ezt az egész mókát parancssori paraméterektől kell majd függővé tenni - if(daemon(0,1) < 0) -#else if(daemon(0,0) < 0) -#endif { PERROR_ON_DEMAND("daemon"); exit(EXIT_FAILURE); @@ -164,14 +160,17 @@ int main(int argc, char *argv[]) // ----------------- INIT END -------------------------- // ------------------ SERVE ---------------------------- - while(true) + int thread_num = 8; + server.serve_in_threads(thread_num); + bool stop = false; + while(!stop) { - server.serve_one_request(); if(comm_link.recv_data() == "kill") { comm_link.send_data("go to hell!"); - log_on_demand(LOG_DEBUG, "Raising SIGTERM"); - raise(SIGTERM); + stop = true; + log_on_demand(LOG_DEBUG, "Raising SIGPIPE"); + raise(SIGPIPE); } else comm_link.send_data("nothing has happened"); @@ -181,6 +180,7 @@ int main(int argc, char *argv[]) // ------------------- SHUTDOWN ------------------------- server.shutdown(); // ----------------- SHUTDOWN END ----------------------- + log_on_demand(LOG_INFO, "Server just exited."); exit(EXIT_SUCCESS); } diff --git a/measurement.md b/measurement.md new file mode 100644 index 0000000000000000000000000000000000000000..998c89bbc4563dea5f52bc8372ce4a5ba31c5fb8 --- /dev/null +++ b/measurement.md @@ -0,0 +1,216 @@ +# Körülmények + +A mérést végző szkript bash, ami a legkevésbé sem hatékony, úgyhogy az időkbe bele kell venni az interpretálást és egyéb bash lassúságát okozó tényezőket is. + +# 1 thread vs. 8*500 kérés, Debug: + + real 0m30.662s + user 0m6.947s + sys 0m2.273s + + real 0m30.817s + user 0m7.043s + sys 0m2.223s + + real 0m30.856s + user 0m6.967s + sys 0m2.287s + + real 0m30.911s + user 0m7.013s + sys 0m2.233s + + real 0m30.918s + user 0m7.117s + sys 0m2.177s + + real 0m31.146s + user 0m7.107s + sys 0m2.157s + + real 0m31.249s + user 0m7.183s + sys 0m2.083s + + real 0m31.239s + user 0m7.163s + sys 0m2.157s + +# 1 thread vs. 8*500 kérés, Release: + + real 0m21.074s + user 0m6.803s + sys 0m2.020s + + real 0m21.156s + user 0m6.737s + sys 0m2.117s + + real 0m21.178s + user 0m6.900s + sys 0m1.900s + + real 0m21.311s + user 0m6.807s + sys 0m2.000s + + real 0m21.342s + user 0m6.820s + sys 0m2.043s + + real 0m21.344s + user 0m6.793s + sys 0m2.060s + + real 0m21.350s + user 0m6.750s + sys 0m2.047s + + real 0m21.371s + user 0m6.777s + sys 0m2.010s + +# 4 thread vs. 8*500 kérés, Debug: + + real 0m28.167s + user 0m7.060s + sys 0m2.083s + + real 0m28.582s + user 0m6.973s + sys 0m2.177s + + real 0m28.598s + user 0m7.070s + sys 0m2.130s + + real 0m28.608s + user 0m7.027s + sys 0m2.123s + + real 0m30.697s + user 0m7.090s + sys 0m2.080s + + real 0m30.829s + user 0m7.023s + sys 0m2.100s + + real 0m32.545s + user 0m6.950s + sys 0m2.247s + + real 0m35.482s + user 0m6.967s + sys 0m2.140s + +# 4 thread vs. 8*500 kérés, Release: + + real 0m16.877s + user 0m6.647s + sys 0m2.253s + + real 0m22.030s + user 0m6.647s + sys 0m2.187s + + real 0m22.047s + user 0m6.790s + sys 0m2.050s + + real 0m22.144s + user 0m6.783s + sys 0m2.037s + + real 0m31.346s + user 0m6.707s + sys 0m2.457s + + real 0m31.670s + user 0m6.623s + sys 0m2.393s + + real 0m32.054s + user 0m6.687s + sys 0m2.250s + + real 0m36.725s + user 0m6.783s + sys 0m2.230s + +# 8 thread vs. 8*500 kérés, Debug: + + real 0m22.967s + user 0m6.930s + sys 0m2.090s + + real 0m23.015s + user 0m7.070s + sys 0m1.960s + + real 0m23.362s + user 0m7.010s + sys 0m2.077s + + real 0m26.676s + user 0m6.780s + sys 0m2.170s + + real 0m26.979s + user 0m6.807s + sys 0m2.220s + + real 0m29.270s + user 0m6.957s + sys 0m2.097s + + real 0m30.313s + user 0m6.740s + sys 0m2.250s + + real 0m36.571s + user 0m6.827s + sys 0m2.140s + +# 8 thread vs. 8*500 kérés, Release: + +Itt mer előjöttek szálkezeléssel kapcsolatos problémák. +Mivel a static lokális változók a heap-en allokálódnak, így több szál is írhatta egyszerre a dns_db::ger_record()-ban a query tömböt. Emiatt romlottak el a végső lekérdezések. + +> SQL error: near "select": syntax error + +> SQL error: near "select": syntax error + +> SQL error: unrecognized token: "s" + + real 0m16.450s + user 0m6.677s + sys 0m2.140s + + real 0m21.445s + user 0m6.643s + sys 0m2.230s + + real 0m25.883s + user 0m6.757s + sys 0m2.163s + + real 0m26.116s + user 0m6.810s + sys 0m2.073s + + real 0m26.525s + user 0m6.673s + sys 0m2.193s + + real 0m26.573s + user 0m6.660s + sys 0m2.127s + + real 0m31.140s + user 0m6.757s + sys 0m2.437s + + real 0m31.485s + user 0m6.867s + sys 0m2.037s diff --git a/nbproject/Makefile-Debug.mk b/nbproject/Makefile-Debug.mk index 910c1d64ffc941e4f6221ce138e3ec39e23029ba..39773f9bf6669903d679d5f5af758563a4b403fc 100644 --- a/nbproject/Makefile-Debug.mk +++ b/nbproject/Makefile-Debug.mk @@ -53,8 +53,8 @@ OBJECTFILES= \ CFLAGS= # CC Compiler Flags -CCFLAGS=-lsqlite3 -CXXFLAGS=-lsqlite3 +CCFLAGS=-lsqlite3 -pthread +CXXFLAGS=-lsqlite3 -pthread # Fortran Compiler Flags FFLAGS= diff --git a/nbproject/Makefile-Release.mk b/nbproject/Makefile-Release.mk index 73b1f9bdfdd6be88c938bbbafd70540fe11f1910..566495d8e2ca93382331c79800352147d26efc30 100644 --- a/nbproject/Makefile-Release.mk +++ b/nbproject/Makefile-Release.mk @@ -53,8 +53,8 @@ OBJECTFILES= \ CFLAGS= # CC Compiler Flags -CCFLAGS=-lsqlite3 -CXXFLAGS=-lsqlite3 +CCFLAGS=-lsqlite3 -pthread +CXXFLAGS=-lsqlite3 -pthread # Fortran Compiler Flags FFLAGS= diff --git a/src/dns_db.cpp b/src/dns_db.cpp index 9610d4d0693c1386b5eb477f8498867f004f0630..82c55253987f7d5c4a5facbffca151c9ce7466f0 100644 --- a/src/dns_db.cpp +++ b/src/dns_db.cpp @@ -13,6 +13,7 @@ #include <string.h> #include <string> +#include <pthread.h> extern logger log_on_demand; extern bool verbose; @@ -92,6 +93,7 @@ static int callback(void *param, int argc, char **argv, char **azColName) { ret->ttl = atoi(argv[3]); if(verbose) { + log_on_demand(LOG_DEBUG, "Called in thread %lu\n", pthread_self()); log_on_demand(LOG_DEBUG, "Database hit:"); for(int i=0;i<argc;i++) log_on_demand(LOG_DEBUG, "%s = %s", azColName[i], argv[i]); @@ -106,7 +108,7 @@ record dns_db::get_record(dns_question question) { } static const char *query_format_string = "select name, type, content, ttl from records where name='%s' and type='%s' limit 1"; - static char query[500]; + char query[500]; record query_result; char readable_name[500]; diff --git a/src/dns_server.cpp b/src/dns_server.cpp index 52bfdc0983ab16862bcca7f1a1b66d2103c96283..fbcc13b4ffc98fedd7f2787828209b2295375c94 100644 --- a/src/dns_server.cpp +++ b/src/dns_server.cpp @@ -5,37 +5,70 @@ * Created on 2016. május 21., 18:47 */ +#include <pthread.h> + #include "../include/dns_server.h" #include "../include/dns_types.h" #include "../include/exceptions/db_exception.h" #include "../include/exceptions/dns_exception.h" #include "../include/logger.h" +#include "../include/exceptions/server_error.h" +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + extern logger log_on_demand; extern bool verbose; -dns_server::dns_server(const general_sockaddr_wp& addr) { +dns_server::dns_server(): running(false), threads(NULL), thread_num(0) { } + +dns_server::dns_server(const general_sockaddr_wp& addr): running(false), threads(NULL), thread_num(0) { init(addr); } -dns_server::dns_server(const general_sockaddr_wp& addr, const char *db_path) { +dns_server::dns_server(const general_sockaddr_wp& addr, const char *db_path): running(false), threads(NULL), thread_num(0) { init(addr); connect_db(db_path); } -dns_server::dns_server(const general_sockaddr_wp& addr, const dns_db& __db): db(__db) { +dns_server::dns_server(const general_sockaddr_wp& addr, const dns_db& __db): db(__db), running(false), threads(NULL), thread_num(0) { init(addr); } void dns_server::init(const general_sockaddr_wp& addr) { + pthread_mutex_lock(&mutex); this->socket.close_socket(); // in case it's being changed this->socket.set_domain(addr.get_sockaddr()->sa_family); this->socket.bind_wp(addr); + running = true; + pthread_mutex_unlock(&mutex); +} + +void dns_server::delete_threads() { + pthread_mutex_lock(&mutex); + if(threads != NULL) + { + delete[] threads; + threads = NULL; + } + thread_num = 0; + pthread_mutex_unlock(&mutex); +} + +void dns_server::stop() { + pthread_mutex_lock(&mutex); + running = false; + pthread_mutex_unlock(&mutex); + for(int i=0; i<thread_num; i++) + pthread_join(threads[i], NULL); + delete_threads(); } void dns_server::shutdown() { + stop(); + pthread_mutex_lock(&mutex); this->socket.close_socket(); db.close(); + pthread_mutex_unlock(&mutex); } void dns_server::serve_one_request() { @@ -50,7 +83,7 @@ void dns_server::serve_one_request() { query.set_response(); query.set_error(ex.what()); this->socket.sendto_wp(query, 0 , (sockaddr*)&sender, slen); - exit(EXIT_SUCCESS); + return; } if(verbose) @@ -84,3 +117,51 @@ void dns_server::serve_one_request() { this->socket.sendto_wp(resp, 0, (sockaddr*) &sender, slen); } + +void dns_server::serve_forever() { + while (running) + { + serve_one_request(); + } +} + +void* dns_server::thread_func(void* server_obj) { + dns_server *server = (dns_server*) server_obj; + server->serve_forever(); + return NULL; +} + +void dns_server::serve_in_threads(int n) { + pthread_mutex_lock(&mutex); + try { + if(threads != NULL) + { + throw server_error("Threads are already running"); + } + thread_num = n; + threads = new pthread_t[thread_num]; + } + catch(...) { + pthread_mutex_unlock(&mutex); + throw; + } + pthread_mutex_unlock(&mutex); + + try { + pthread_mutex_lock(&mutex); + for(int i=0; i<thread_num; i++) + { + if (pthread_create(&threads[i], NULL, thread_func, this)) { + fprintf(stderr, "Hiba a szál Létrehozásakor.\n"); + // May throw some exception... + exit(EXIT_FAILURE); + } + } + pthread_mutex_unlock(&mutex); + } + catch (...) { + pthread_mutex_unlock(&mutex); + stop(); + throw; + } +}