Commit bf6a341b4cf51c8eef9f23765a6f89a380d1d999

Authored by Georg Hopp
1 parent 3d0057d4

changed header hashing to use btree (GNU only). @TODO: make this conditional for…

… other systems. Removed the qsort calls on server->fds making O(2nlogn) to O(n)
  1 +2012-02-12 00:05:13 +0100 Georg Hopp
  2 +
  3 + * changed header hashing to use btree (GNU only). @TODO: make this conditional for other systems. Removed the qsort calls on server->fds making O(2nlogn) to O(n) (HEAD, master)
  4 +
  5 +2012-02-11 13:52:32 +0100 Georg Hopp
  6 +
  7 + * daemonize testserver now (origin/master, origin/HEAD)
  8 +
1 9 2012-02-11 12:47:01 +0100 Georg Hopp
2 10
3   - * fix seaks and hangs after adding response object (mostly not related with the response object but how i integated it into serverRun (HEAD, master)
  11 + * fix seaks and hangs after adding response object (mostly not related with the response object but how i integated it into serverRun
4 12
5 13 2012-02-10 19:57:57 +0100 Georg Hopp
6 14
7   - * started a response handler and changed serverRun to use it for its response (origin/master, origin/HEAD)
  15 + * started a response handler and changed serverRun to use it for its response
8 16
9 17 2012-02-10 12:42:04 +0100 Georg Hopp
10 18
... ...
... ... @@ -8,7 +8,9 @@
8 8
9 9 #include "interface.h"
10 10
  11 +#ifndef _ISOC99_SOURCE
11 12 #define _ISOC99_SOURCE
  13 +#endif
12 14
13 15 #define CLASS_MAGIC 0xFEFE
14 16
... ...
... ... @@ -9,13 +9,14 @@ CLASS(HttpRequest) {
9 9 char * uri;
10 10 char * version;
11 11
12   - HttpHeader header[128];
13   - int nheader;
  12 + HttpHeader header;
14 13
15 14 char * body;
16 15 int nbody;
17 16 };
18 17
  18 +void httpHeaderAdd(HttpHeader *, HttpHeader);
  19 +char * XhttpHeaderGet(HttpHeader *, const char *);
19 20 char * httpRequestHeaderGet(HttpRequest, const char *);
20 21 char httpRequestHasKeepAlive(HttpRequest);
21 22
... ...
1 1 #include <stdlib.h>
  2 +#include <search.h>
2 3
3 4 #include "http/header.h"
4 5
... ...
  1 +#ifndef _GNU_SOURCE
  2 +#define _GNU_SOURCE
  3 +#endif
  4 +
1 5 #include <stdlib.h>
2 6 #include <stdarg.h>
  7 +#include <search.h>
3 8
4 9 #include "class.h"
5 10 #include "interface/class.h"
6 11
7 12 #include "http/request.h"
8 13
  14 +
9 15 static
  16 +inline
10 17 void
11 18 _free(void ** data)
12 19 {
... ... @@ -16,6 +23,14 @@ _free(void ** data)
16 23 }
17 24
18 25 static
  26 +inline
  27 +void
  28 +tDelete(void * node)
  29 +{
  30 + delete(&node);
  31 +}
  32 +
  33 +static
19 34 void
20 35 ctor(void * _this, va_list * params) {}
21 36
... ... @@ -24,16 +39,17 @@ void
24 39 dtor(void * _this)
25 40 {
26 41 HttpRequest this = _this;
27   - int i;
28 42
29 43 _free((void **)&(this->version));
30 44 _free((void **)&(this->uri));
31 45 _free((void **)&(this->method));
32 46
33   - for (i=0; i<128; i++) {
34   - if (NULL == (this->header)[i]) break;
35   - delete(&(this->header)[i]);
36   - }
  47 + /**
  48 + * this is a GNU extension...anyway on most non
  49 + * GNUish systems i would not use tsearch anyway
  50 + * as the trees will be unbalanced.
  51 + */
  52 + tdestroy(this->header, tDelete);
37 53
38 54 _free((void **)&(this->body));
39 55 }
... ...
... ... @@ -11,7 +11,7 @@ httpRequestHasKeepAlive(HttpRequest request)
11 11 char * header;
12 12 char * header_ptr;
13 13
14   - header = httpHeaderGet(request->header, request->nheader, "connection");
  14 + header = XhttpHeaderGet(&(request->header), "connection");
15 15
16 16 if (NULL == header) {
17 17 return 0;
... ...
... ... @@ -3,44 +3,10 @@
3 3
4 4 #include "http/request.h"
5 5
6   -static
7   -inline
8   -unsigned long
9   -sdbm(const unsigned char * str)
10   -{
11   - unsigned long hash = 0;
12   - int c;
13   -
14   - while ((c = tolower(*str++)))
15   - hash = c + (hash << 6) + (hash << 16) - hash;
16   -
17   - return hash;
18   -}
19   -
20   -static
21   -inline
22   -int
23   -comp (const void * _a, const void * _b)
24   -{
25   - unsigned long a = *(unsigned long *)_a;
26   - const struct HttpRequestHeader * b = _b;
27   - return (a < b->hash)? -1 : (a > b->hash)? 1 : 0;
28   -}
29   -
30 6 char *
31 7 httpRequestHeaderGet(HttpRequest this, const char * name)
32 8 {
33   - unsigned long hash = sdbm((unsigned char *)name);
34   - struct HttpRequestHeader * header;
35   -
36   - header = bsearch(
37   - &hash,
38   - this->header,
39   - this->nheader,
40   - sizeof(struct HttpRequestHeader),
41   - comp);
42   -
43   - return (NULL != header)? header->value : NULL;
  9 + return XhttpHeaderGet(&(this->header), name);
44 10 }
45 11
46 12 // vim: set ts=4 sw=4:
... ...
  1 +#include <search.h>
  2 +#include <ctype.h>
  3 +#include <stdio.h>
  4 +
1 5 #include "class.h"
2 6 #include "interface/class.h"
3 7 #include "http/header.h"
4 8 #include "http/request.h"
5 9
  10 +static
  11 +inline
  12 +unsigned long
  13 +sdbm(const unsigned char * str)
  14 +{
  15 + unsigned long hash = 0;
  16 + int c;
  17 +
  18 + while ((c = tolower(*str++)))
  19 + hash = c + (hash << 6) + (hash << 16) - hash;
  20 +
  21 + return hash;
  22 +}
  23 +
  24 +static
  25 +inline
  26 +int
  27 +comp(const void * _a, const void * _b)
  28 +{
  29 + HttpHeader a = (HttpHeader)_a;
  30 + HttpHeader b = (HttpHeader)_b;
  31 + return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0;
  32 +}
  33 +
6 34 void
7 35 httpRequestParserGetHeader(HttpRequest request, char * line)
8 36 {
... ... @@ -12,7 +40,29 @@ httpRequestParserGetHeader(HttpRequest request, char * line)
12 40 *(value++) = 0;
13 41 for (; *value == ' ' && *value != 0; value++);
14 42
15   - (request->header)[request->nheader++] = new(HttpHeader, name, value);
  43 + httpHeaderAdd(&(request->header), new(HttpHeader, name, value));
  44 +}
  45 +
  46 +void
  47 +httpHeaderAdd(HttpHeader * root, HttpHeader header)
  48 +{
  49 + HttpHeader * found = tsearch(header, (void **)root, comp);
  50 +
  51 + if (*found != header) {
  52 + puts("uhh, duplicate header set. "
  53 + "This is not implemented right now. "
  54 + "Keep the first one found.");
  55 + delete(&header);
  56 + }
  57 +}
  58 +
  59 +char *
  60 +XhttpHeaderGet(HttpHeader * root, const char * name)
  61 +{
  62 + struct c_HttpHeader search = {sdbm((const unsigned char*)name), NULL, NULL};
  63 + HttpHeader * found = tfind(&search, (void **)root, comp);
  64 +
  65 + return (NULL != found)? (*found)->value : NULL;
16 66 }
17 67
18 68 // vim: set ts=4 sw=4:
... ...
... ... @@ -82,15 +82,12 @@ httpRequestParserParse(HttpRequestParser this)
82 82 break;
83 83
84 84 case HTTP_REQUEST_HEADERS_DONE:
85   - httpHeaderSort(this->cur_request->header, this->cur_request->nheader);
86   -
87 85 {
88 86 char * nbody;
89 87
90 88 if (0 == this->cur_request->nbody) {
91   - nbody = httpHeaderGet(
92   - this->cur_request->header,
93   - this->cur_request->nheader,
  89 + nbody = XhttpHeaderGet(
  90 + &(this->cur_request->header),
94 91 "Content-Length");
95 92
96 93 if (NULL == nbody) {
... ...
1 1 #include <poll.h> /* for select system call and related */
2 2 #include <string.h> /* for memset and stuff */
3 3 #include <stdlib.h> /* for getopt */
  4 +#include <unistd.h>
  5 +#include <fcntl.h>
4 6
5 7 #include "class.h"
6 8 #include "server.h"
... ... @@ -15,6 +17,7 @@ ctor(void * _this, va_list * params)
15 17 Server this = _this;
16 18 in_port_t port;
17 19 unsigned int backlog;
  20 + int flags;
18 21
19 22 this->logger = va_arg(* params, Logger);
20 23 this->reader = va_arg(* params, void*);
... ... @@ -22,6 +25,10 @@ ctor(void * _this, va_list * params)
22 25 backlog = va_arg(* params, unsigned int);
23 26
24 27 this->sock = new(Sock, this->logger, port);
  28 +
  29 + flags = fcntl(this->sock->handle, F_GETFL, 0);
  30 + fcntl(this->sock->handle, F_SETFL, flags | O_NONBLOCK);
  31 +
25 32 socketListen(this->sock, backlog);
26 33
27 34 (this->fds)[0].fd = this->sock->handle;
... ...
  1 +#include <stdlib.h>
1 2 #include <string.h>
2 3
3 4 #include "server.h"
... ... @@ -17,9 +18,7 @@ serverCloseConn(Server this, unsigned int i)
17 18 }
18 19 (this->conns)[fd].keep_alive = 0;
19 20
20   - (this->fds)[i].events = 0;
21   - (this->fds)[i].revents = 0;
22   - (this->fds)[i].fd = 0;
  21 + memset(&(this->fds[i]), 0, sizeof(struct pollfd));
23 22 }
24 23
25 24 // vim: set ts=4 sw=4:
... ...
1 1 static
2   -void
  2 +int
3 3 serverHandleAccept(Server this)
4 4 {
5 5 char remoteAddr[16] = "";
... ... @@ -21,7 +21,7 @@ serverHandleAccept(Server this)
21 21 delete(&acc);
22 22 }
23 23
24   -// (this->fds)[0].revents |= POLLIN;
  24 + return (acc)? acc->handle : -1;
25 25 }
26 26
27 27 // vim: set ts=4 sw=4:
... ...
1 1 #define POLLFD(ptr) ((struct pollfd *)(ptr))
  2 +#define SWAP(a, b) ((a)^=(b),(b)^=(a),(a)^=(b))
2 3
3 4 static
4 5 inline
... ... @@ -25,9 +26,27 @@ int
25 26 serverPoll(Server this) {
26 27 int events;
27 28
28   - qsort(this->fds, this->nfds, sizeof(struct pollfd), sortEvents);
29   - while((this->fds)[this->nfds].fd == 0 && this->nfds > 0) this->nfds--;
30   - this->nfds++;
  29 + /**
  30 + * put all closed fds to end of array in O(this->nfds)
  31 + */
  32 + struct pollfd * fda = &(this->fds[1]);
  33 + struct pollfd * fdb = &(this->fds[this->nfds-1]);
  34 +
  35 + while (fda <= fdb) {
  36 + while (0 == fdb->fd && fda <= fdb) {
  37 + fdb--;
  38 + this->nfds--;
  39 + }
  40 +
  41 + while (0 != fda->fd && fda <= fdb) fda++;
  42 +
  43 + if (fda < fdb) {
  44 + memcpy(fda, fdb, sizeof(struct pollfd));
  45 + memset(fdb, 0, sizeof(struct pollfd));
  46 + fdb--;
  47 + this->nfds--;
  48 + }
  49 + }
31 50
32 51 /*
33 52 * wait for handles to become ready
... ... @@ -45,14 +64,9 @@ serverPoll(Server this) {
45 64 loggerLog(this->logger, LOGGER_CRIT,
46 65 "poll systemcall failed: [%s] - service terminated",
47 66 strerror(errno));
48   - //exit(EXIT_FAILURE); /* @TODO do real shutdown here */
49 67 }
50 68 }
51 69
52   - if (-1 != events) {
53   - qsort(this->fds, this->nfds, sizeof(struct pollfd), sortRevents);
54   - }
55   -
56 70 return events;
57 71 }
58 72
... ...
... ... @@ -5,6 +5,7 @@
5 5 #include <unistd.h>
6 6 #include <ctype.h>
7 7 #include <time.h>
  8 +#include <errno.h>
8 9
9 10 #include "server.h"
10 11 #include "socket.h"
... ... @@ -51,22 +52,43 @@ serverRun(Server this)
51 52 events = serverPoll(this);
52 53 if (doShutdown) break;
53 54
54   - for (i=0; i < events; i++) {
  55 + for (i=0; i < this->nfds; i++) {
55 56 int fd = (this->fds)[i].fd;
56   - //int nreads = 0, nwrites = 0;
  57 + int naccs = 10, nreads = 10, nwrites = 10;
  58 +
  59 + if (0 >= events) break;
  60 +
  61 + if (0 != ((this->fds)[i].revents & POLLIN) && 0 < nreads) {
  62 + events--;
57 63
58   - if (0 != ((this->fds)[i].revents & POLLIN)) {
59 64 /**
60 65 * handle accept
61 66 */
62 67 if (this->sock->handle == (this->fds)[i].fd) {
63   - serverHandleAccept(this);
  68 + while(-1 != serverHandleAccept(this) && 0 < naccs) {
  69 + naccs--;
  70 +
  71 + switch(errno) {
  72 + case EAGAIN:
  73 + loggerLog(this->logger,
  74 + LOGGER_DEBUG,
  75 + "server accept blocks");
  76 + break;
  77 +
  78 + default:
  79 + loggerLog(this->logger,
  80 + LOGGER_DEBUG,
  81 + "server accept error");
  82 + break;
  83 + }
  84 + }
64 85 }
65 86
66 87 /**
67 88 * handle reads
68 89 */
69 90 else {
  91 + nreads--;
70 92 /**
71 93 * do some other processing
72 94 * @TODO: actually this will hard assume that our stream reader
... ... @@ -126,9 +148,12 @@ serverRun(Server this)
126 148 /**
127 149 * handle writes
128 150 */
129   - if (0 != ((this->fds)[i].revents & POLLOUT)) {
  151 + if (0 != ((this->fds)[i].revents & POLLOUT) && 0 < nwrites) {
130 152 int size;
131 153
  154 + events--;
  155 + nwrites--;
  156 +
132 157 size = write(
133 158 (this->fds)[i].fd,
134 159 (this->conns)[fd].wbuf,
... ...
... ... @@ -42,7 +42,7 @@ dtor(void * _this)
42 42 {
43 43 Sock this = _this;
44 44
45   - if (0 != this->handle) {
  45 + if (STDERR_FILENO < this->handle) {
46 46 shutdown(this->handle, SHUT_RDWR);
47 47 close(this->handle);
48 48 }
... ...
... ... @@ -26,7 +26,7 @@ main()
26 26 setrlimit(RLIMIT_CPU, &limit);
27 27
28 28 init_signals();
29   - daemonize();
  29 + //daemonize();
30 30 serverRun(server);
31 31
32 32 delete(&server);
... ...
Please register or login to post a comment