Commit 5d071453 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Rework source.c to be in log(n).

The source table is now sorted, just like the route table.  Source insertion
is still linear, and source expiry quadratic, but this hopefully doesn't
matter much.
parent 76db959b
...@@ -32,7 +32,89 @@ THE SOFTWARE. ...@@ -32,7 +32,89 @@ THE SOFTWARE.
#include "interface.h" #include "interface.h"
#include "route.h" #include "route.h"
struct source *srcs = NULL; static struct source **sources = NULL;
static int source_slots = 0, max_source_slots = 0;
static int
source_compare(const unsigned char *id,
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
const struct source *src)
{
int rc;
rc = memcmp(id, src->id, 8);
if(rc != 0)
return rc;
if(plen < src->plen)
return -1;
if(plen > src->plen)
return 1;
rc = memcmp(prefix, src->prefix, 16);
if(rc != 0)
return rc;
rc = memcmp(src_prefix, src->src_prefix, 16);
if(rc != 0)
return rc;
return 0;
}
static int
find_source_slot(const unsigned char *id,
const unsigned char *prefix, unsigned char plen,
const unsigned char *src_prefix, unsigned char src_plen,
int *new_return)
{
int p, m, g, c;
if(source_slots < 1) {
if(new_return)
*new_return = 0;
return -1;
}
p = 0; g = source_slots - 1;
do {
m = (p + g) / 2;
c = source_compare(id, prefix, plen, src_prefix, src_plen, sources[m]);
if(c == 0)
return m;
else if(c < 0)
g = m - 1;
else
p = m + 1;
} while(p <= g);
if(new_return)
*new_return = p;
return -1;
}
static int
resize_source_table(int new_slots)
{
struct source **new_sources;
assert(new_slots >= source_slots);
if(new_slots == 0) {
new_sources = NULL;
free(sources);
} else {
new_sources = realloc(sources, new_slots * sizeof(struct source*));
if(new_sources == NULL)
return -1;
}
max_source_slots = new_slots;
sources = new_sources;
return 1;
}
struct source* struct source*
find_source(const unsigned char *id, find_source(const unsigned char *id,
...@@ -40,24 +122,12 @@ find_source(const unsigned char *id, ...@@ -40,24 +122,12 @@ find_source(const unsigned char *id,
const unsigned char *src_prefix, unsigned char src_plen, const unsigned char *src_prefix, unsigned char src_plen,
int create, unsigned short seqno) int create, unsigned short seqno)
{ {
int n = -1;
int i = find_source_slot(id, prefix, plen, src_prefix, src_plen, &n);
struct source *src; struct source *src;
for(src = srcs; src; src = src->next) { if(i >= 0)
/* This should really be a hash table. For now, check the return sources[i];
last byte first. */
if(src->id[7] != id[7])
continue;
if(memcmp(src->id, id, 8) != 0)
continue;
if(src->plen != plen)
continue;
if(src->src_plen != src_plen)
continue;
if(memcmp(src->prefix, prefix, 16) != 0)
continue;
if(memcmp(src->src_prefix, src_prefix, 16) == 0)
return src;
}
if(!create) if(!create)
return NULL; return NULL;
...@@ -77,8 +147,19 @@ find_source(const unsigned char *id, ...@@ -77,8 +147,19 @@ find_source(const unsigned char *id,
src->metric = INFINITY; src->metric = INFINITY;
src->time = now.tv_sec; src->time = now.tv_sec;
src->route_count = 0; src->route_count = 0;
src->next = srcs;
srcs = src; if(source_slots >= max_source_slots)
resize_source_table(max_source_slots < 1 ? 8 : 2 * max_source_slots);
if(source_slots >= max_source_slots) {
free(src);
return NULL;
}
if(n < source_slots)
memmove(sources + n + 1, sources + n,
(source_slots - n) * sizeof(struct source*));
source_slots++;
sources[n] = src;
return src; return src;
} }
...@@ -97,26 +178,6 @@ release_source(struct source *src) ...@@ -97,26 +178,6 @@ release_source(struct source *src)
src->route_count--; src->route_count--;
} }
int
flush_source(struct source *src)
{
if(src->route_count > 0)
/* The source is in use by a route. */
return 0;
if(srcs == src) {
srcs = src->next;
} else {
struct source *previous = srcs;
while(previous->next != src)
previous = previous->next;
previous->next = src->next;
}
free(src);
return 1;
}
void void
update_source(struct source *src, update_source(struct source *src,
unsigned short seqno, unsigned short metric) unsigned short seqno, unsigned short metric)
...@@ -140,29 +201,34 @@ update_source(struct source *src, ...@@ -140,29 +201,34 @@ update_source(struct source *src,
void void
expire_sources() expire_sources()
{ {
struct source *src; int i = 0;
while(i < source_slots) {
struct source *src = sources[i];
src = srcs;
while(src) {
if(src->time > now.tv_sec) if(src->time > now.tv_sec)
/* clock stepped */ /* clock stepped */
src->time = now.tv_sec; src->time = now.tv_sec;
if(src->time < now.tv_sec - SOURCE_GC_TIME) { if(src->time < now.tv_sec - SOURCE_GC_TIME) {
struct source *old = src; free(src);
src = src->next; memmove(sources + i, sources + i + 1,
flush_source(old); (source_slots - i - 1) * sizeof(struct source));
continue; sources[source_slots - 1] = NULL;
source_slots--;
} else {
i++;
} }
src = src->next;
} }
} }
void void
check_sources_released(void) check_sources_released(void)
{ {
struct source *src; int i;
for(i = 0; i < source_slots; i++) {
struct source *src = sources[i];
for(src = srcs; src; src = src->next) {
if(src->route_count != 0) if(src->route_count != 0)
fprintf(stderr, "Warning: source %s %s has refcount %d.\n", fprintf(stderr, "Warning: source %s %s has refcount %d.\n",
format_eui64(src->id), format_eui64(src->id),
......
...@@ -23,7 +23,6 @@ THE SOFTWARE. ...@@ -23,7 +23,6 @@ THE SOFTWARE.
#define SOURCE_GC_TIME 200 #define SOURCE_GC_TIME 200
struct source { struct source {
struct source *next;
unsigned char id[8]; unsigned char id[8];
unsigned char prefix[16]; unsigned char prefix[16];
unsigned char plen; unsigned char plen;
...@@ -43,7 +42,6 @@ struct source *find_source(const unsigned char *id, ...@@ -43,7 +42,6 @@ struct source *find_source(const unsigned char *id,
int create, unsigned short seqno); int create, unsigned short seqno);
struct source *retain_source(struct source *src); struct source *retain_source(struct source *src);
void release_source(struct source *src); void release_source(struct source *src);
int flush_source(struct source *src);
void update_source(struct source *src, void update_source(struct source *src,
unsigned short seqno, unsigned short metric); unsigned short seqno, unsigned short metric);
void expire_sources(void); void expire_sources(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment