1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

use simple lookup table for extpoll

Hash stuff is overkill since Edwin found a max connection limit of 30000 on his
box anyway.  Just use a simple preallocated lookup table and fds array.

AG Modified for style and removed debugging bits

Signed-off-by: Edwin van der Oetelaar <oetelaar.automatisering@gmail.com>
Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
Edwin van der Oetelaar 2013-01-17 11:16:15 +08:00 committed by Andy Green
parent b2de95d2d4
commit 6c720c4440

View file

@ -33,50 +33,12 @@ static int close_testing;
#ifdef EXTERNAL_POLL
#define LWS_NO_FORK
#ifndef MAX_CLIENTS
#define MAX_POLL_ELEMENTS 100
#else
#define MAX_POLL_ELEMENTS (MAX_CLIENTS)
#endif
struct poll_hash_map {
int fd;
int index;
};
#define POLL_HASH_BITS 8
#define POLL_HASH_BUCKETS (1 << POLL_HASH_BITS)
#define POLL_ENTRIES_PER_BUCKET (MAX_POLL_ELEMENTS / (1 << (POLL_HASH_BITS - 2)))
#define POLL_HASH(num) (num & (POLL_HASH_BUCKETS - 1))
#define MAX_POLL_ELEMENTS 32000
struct pollfd pollfds[MAX_POLL_ELEMENTS];
struct poll_hash_map pollfd_maps[POLL_HASH_BUCKETS][POLL_ENTRIES_PER_BUCKET];
int pollfd_count[POLL_HASH_BUCKETS];
int count_pollfds = 0;
static int find_poll_map_index(int hash, int fd)
{
int n;
for (n = 0; n < pollfd_count[hash]; n++)
if (pollfd_maps[hash][n].fd == fd)
return n;
return -1;
}
static int find_pollfd_index(int fd)
{
int n;
int hash = POLL_HASH(fd);
n = find_poll_map_index(hash, fd);
if (n < 0)
return n;
return pollfd_maps[hash][n].index;
}
int fd_lookup[MAX_POLL_ELEMENTS];
int count_pollfds;
#endif /* EXTERNAL_POLL */
@ -126,11 +88,6 @@ static const struct serveable whitelist[] = {
{ "/test.html", "text/html" },
};
/* some versions of gcc see a false positive here, workaround */
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
/* this protocol server (always the first one) just knows how to do HTTP */
static int callback_http(struct libwebsocket_context *context,
@ -143,8 +100,7 @@ static int callback_http(struct libwebsocket_context *context,
char buf[256];
int n;
#ifdef EXTERNAL_POLL
int m, m1;
int hash, hash1;
int m;
int fd = (int)(long)user;
#endif
@ -199,95 +155,36 @@ static int callback_http(struct libwebsocket_context *context,
*/
case LWS_CALLBACK_ADD_POLL_FD:
if (count_pollfds == MAX_POLL_ELEMENTS) {
if (count_pollfds >= MAX_POLL_ELEMENTS) {
fprintf(stderr, "LWS_CALLBACK_ADD_POLL_FD: too many sockets to track\n");
return 1;
}
hash = POLL_HASH(fd);
if (pollfd_count[hash] == POLL_ENTRIES_PER_BUCKET) {
fprintf(stderr, "LWS_CALLBACK_ADD_POLL_FD: hash table overflow\n");
return 1;
}
// fprintf(stderr, "Adding fd %d at pollfd_maps[%d][%d], pollfds[%d]\n", fd, hash, pollfd_count[hash], count_pollfds);
pollfd_maps[hash][pollfd_count[hash]].fd = fd;
pollfd_maps[hash][pollfd_count[hash]++].index = count_pollfds;
pollfds[count_pollfds].fd = (int)(long)user;
pollfds[count_pollfds].events = (int)len;
fd_lookup[fd] = count_pollfds;
pollfds[count_pollfds].fd = fd;
pollfds[count_pollfds].events = (int)(long)len;
pollfds[count_pollfds++].revents = 0;
break;
case LWS_CALLBACK_DEL_POLL_FD:
hash = POLL_HASH(fd);
n = find_poll_map_index(hash, fd);
if (n < 0) {
fprintf(stderr, "unable to find fd %d in poll_maps\n", fd);
return 1;
}
m = pollfd_maps[hash][n].index;
assert(pollfds[m].fd == fd);
assert(count_pollfds);
assert(pollfd_count[hash]);
// fprintf(stderr, "Removing fd %d at pollfd_maps[%d][%d], pollfds[%d]\n", fd, hash, n, m);
/*
* swap the end guy into our vacant slot...
* works ok if n is the end guy
*/
count_pollfds--;
if (count_pollfds) {
/* end guy... */
hash1 = POLL_HASH(pollfds[count_pollfds].fd);
m1 = find_poll_map_index(hash1, pollfds[count_pollfds].fd);
/* your index has changed... */
pollfd_maps[hash1][m1].index = m;
pollfds[m] = pollfds[count_pollfds];
pollfds[count_pollfds].fd = -1;
}
/*
* similar trick with hashtable
* old end guy goes into vacant slot in hash table
*/
pollfd_count[hash]--;
if (pollfd_count[hash]) {
pollfd_maps[hash][n].index = pollfd_maps[hash][pollfd_count[hash]].index;
pollfd_maps[hash][n].fd = pollfd_maps[hash][pollfd_count[hash]].fd;
}
if (!--count_pollfds)
break;
m = fd_lookup[fd];
/* have the last guy take up the vacant slot */
pollfds[m] = pollfds[count_pollfds];
fd_lookup[pollfds[count_pollfds].fd] = m;
break;
case LWS_CALLBACK_SET_MODE_POLL_FD:
n = find_pollfd_index(fd);
if (n < 0) {
fprintf(stderr, "unable to find fd %d\n", fd);
return 1;
}
if(pollfds[n].fd != fd) {
fprintf(stderr, "Setting fd %d, found at pollfd_index %d, actually fd %d\n", fd, n, pollfds[n].fd);
assert(0);
}
pollfds[n].events |= (int)(long)len;
pollfds[fd_lookup[fd]].events |= (int)(long)len;
break;
case LWS_CALLBACK_CLEAR_MODE_POLL_FD:
n = find_pollfd_index(fd);
if (n < 0) {
fprintf(stderr, "unable to find fd %d\n", fd);
return 1;
}
assert(pollfds[n].fd == fd);
pollfds[n].events &= ~(int)(long)len;
pollfds[fd_lookup[fd]].events &= ~(int)(long)len;
break;
#endif
default:
break;
}
@ -295,10 +192,6 @@ static int callback_http(struct libwebsocket_context *context,
return 0;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
/*
* this is just an example of parsing handshake headers, you don't need this
* in your code unless you will filter allowing connections by the header