From 01ae8736e96acc7ea120b0653bef21ae84e449ec Mon Sep 17 00:00:00 2001 From: Georg Hopp Date: Tue, 21 Feb 2012 09:45:01 +0100 Subject: [PATCH] now a child is spawned and writes random values in a shared memory segment. These values will be shown in the me action --- .doxygen | 6 +- include/http/response.h | 2 +- include/http/worker.h | 1 + src/http/response/me.c | 8 +-- src/http/worker.c | 5 +- src/http/worker/process.c | 2 +- src/server/run.c | 8 +++ src/testserver.c | 130 ++++++++++++++++++++++++++++++++++---- 8 files changed, 141 insertions(+), 21 deletions(-) diff --git a/.doxygen b/.doxygen index 464be58..7d07de8 100644 --- a/.doxygen +++ b/.doxygen @@ -4,9 +4,9 @@ # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = server +PROJECT_NAME = Server PROJECT_NUMBER = 0.0.1 -PROJECT_BRIEF = basic server infrastructure +PROJECT_BRIEF = "HTTP/REST server implementation" PROJECT_LOGO = OUTPUT_DIRECTORY = docs CREATE_SUBDIRS = NO @@ -27,7 +27,7 @@ INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO diff --git a/include/http/response.h b/include/http/response.h index 2b263d9..bb31c34 100644 --- a/include/http/response.h +++ b/include/http/response.h @@ -40,7 +40,7 @@ CLASS(HttpResponse) { HttpResponse httpResponse304(int, const char *); HttpResponse httpResponse404(); -HttpResponse httpResponseMe(); +HttpResponse httpResponseMe(int); HttpResponse httpResponseImage(int); #endif // __HTTP_RESPONSE_H__ diff --git a/include/http/worker.h b/include/http/worker.h index 7892339..08bf8dc 100644 --- a/include/http/worker.h +++ b/include/http/worker.h @@ -44,6 +44,7 @@ CLASS(HttpWorker) { char * id; + int * val; Cbuf pbuf; Cbuf wbuf; diff --git a/src/http/response/me.c b/src/http/response/me.c index 7c0263b..e91df81 100644 --- a/src/http/response/me.c +++ b/src/http/response/me.c @@ -37,12 +37,12 @@ " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" \ "\n" \ "200 - OK" \ - "

200 - OK

" \ + "

200 - OK


%02d" \ "" HttpResponse -httpResponseMe() +httpResponseMe(int value) { char buffer[200]; HttpResponse response; @@ -58,8 +58,8 @@ httpResponseMe() message->type = HTTP_MESSAGE_BUFFERED; message->nbody = sizeof(RESP_DATA) - 1; - message->body = calloc(1, sizeof(RESP_DATA)); - strcpy(message->body, RESP_DATA); + message->body = calloc(1, sizeof(RESP_DATA)-2); + sprintf(message->body, RESP_DATA, value); sprintf(buffer, "%d", message->nbody); httpHeaderAdd(&(message->header), diff --git a/src/http/worker.c b/src/http/worker.c index 04bb426..7e3d849 100644 --- a/src/http/worker.c +++ b/src/http/worker.c @@ -20,10 +20,12 @@ ctor(void * _this, va_list * params) { HttpWorker this = _this; char * id = va_arg(*params, char *); + int * val = va_arg(*params, int *); char cbuf_id[100]; - this->id = malloc(strlen(id) + 1); + this->id = malloc(strlen(id) + 1); strcpy(this->id, id); + this->val = val; sprintf(cbuf_id, "%s_%s", "parser", id); this->pbuf = new(Cbuf, cbuf_id, REQUEST_PARSER_BUFFER_MAX); @@ -58,6 +60,7 @@ _clone(void * _this, void * _base) HttpWorker base = _base; this->id = NULL; + this->val = base->val; this->pbuf = NULL; this->wbuf = NULL; diff --git a/src/http/worker/process.c b/src/http/worker/process.c index bfaae83..6ba8a3a 100644 --- a/src/http/worker/process.c +++ b/src/http/worker/process.c @@ -56,7 +56,7 @@ httpWorkerProcess(HttpWorker this, int fd) if (0 == strcmp("GET", request->method) && 0 == strcmp("/me/", request->uri)) { - response = (HttpMessage)httpResponseMe(); + response = (HttpMessage)httpResponseMe(*(this->val)); } else if (0 == strcmp("GET", request->method) && 0 == strcmp("/image/", request->uri)) { diff --git a/src/server/run.c b/src/server/run.c index 992b3be..97aff94 100644 --- a/src/server/run.c +++ b/src/server/run.c @@ -48,6 +48,14 @@ serverRun(Server this) * this single process. * What we can first do to get some processing between read/write * cicles is to use the poll timeout. + * A first candidate for a separate process would be the + * generation of the responses piped responses then still need + * to open the filehandle in this process and reading and + * writing would be done here. So the benefit might not be + * very big. Otherwise we could share the read and write + * ringbuffer as well as the message queues. Then the child + * process can do the file readings, but this would involve + * some more IPC. */ while (!doShutdown) //! until error or signal { diff --git a/src/testserver.c b/src/testserver.c index ce3aec2..5ef4355 100644 --- a/src/testserver.c +++ b/src/testserver.c @@ -20,12 +20,19 @@ * along with this program. If not, see . */ -#include -#include -#include +#include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include #include "server.h" #include "logger.h" @@ -35,25 +42,126 @@ #include "utils/signalHandling.h" +//#define DEFAULT_SECS 0 +//#define DEFAULT_USECS (1000000 / HZ) +#define DEFAULT_SECS 1 +#define DEFAULT_USECS 0 + +void nullhandler() {} + void daemonize(void); int main() { - Logger logger = new(LoggerSyslog, LOGGER_ERR); - HttpWorker worker = new(HttpWorker, "my"); - Server server = new(Server, logger, worker, 11212, SOMAXCONN); + pid_t pid; + long psize = sysconf(_SC_PAGESIZE); + int status; + int shm; + int * value; struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY}; setrlimit(RLIMIT_CPU, &limit); init_signals(); - //daemonize(); - serverRun(server); - delete(&server); - delete(&worker); - delete(&logger); + shm = shm_open("/fooshm", O_RDWR|O_CREAT, S_IRWXU); + ftruncate(shm, psize); + + switch((pid = fork())) { + case -1: + break; + + case 0: + { + sigset_t block_these, pause_mask; + struct sigaction s; + struct itimerval interval; + + value = mmap (0, sizeof(int), PROT_READ|PROT_WRITE, + MAP_SHARED, shm, 0); + *value = 0; + + close(shm); + + /* Block SIGALRM */ + sigemptyset(&block_these); + sigaddset(&block_these, SIGALRM); + sigprocmask(SIG_BLOCK, &block_these, &pause_mask); + + /* Set up handler for SIGALRM */ + sigemptyset(&s.sa_mask); + sigaddset(&s.sa_mask, SIGINT); + s.sa_flags = 0; + s.sa_handler = nullhandler; + if (sigaction(SIGALRM, &s, NULL) < 0) { + perror("sigaction SIGALRM"); + exit (1); + } + + interval.it_value.tv_sec = DEFAULT_SECS; + interval.it_value.tv_usec = DEFAULT_USECS; + interval.it_interval.tv_sec = DEFAULT_SECS; + interval.it_interval.tv_usec = DEFAULT_USECS; + + setitimer(ITIMER_REAL, &interval, NULL); + + // child + while(!doShutdown) { + *value = rand() % 10; + sigsuspend(&pause_mask); + } + + _exit(EXIT_SUCCESS); + } + + default: + { + Logger logger; + HttpWorker worker; + Server server; + + value = mmap (0, sizeof(int), PROT_READ|PROT_WRITE, + MAP_SHARED, shm, 0); + + shm_unlink("/fooshm"); + close(shm); + + logger = new(LoggerSyslog, LOGGER_ERR); + worker = new(HttpWorker, "my", value); + server = new(Server, logger, worker, 11212, SOMAXCONN); + + //daemonize(); + serverRun(server); + + do { + pid_t w; + + w = waitpid(pid, &status, WUNTRACED | WCONTINUED); + + if (w == -1) { + perror("waitpid"); + exit(EXIT_FAILURE); + } + + if (WIFEXITED(status)) { + printf("exited, status=%d\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + printf("killed by signal %d\n", WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + printf("stopped by signal %d\n", WSTOPSIG(status)); + } else if (WIFCONTINUED(status)) { + printf("continued\n"); + } + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + + delete(&server); + delete(&worker); + delete(&logger); + } + + break; + } return 0; }