Commit 622c0cd4 authored by Dag Erling Smørgrav's avatar Dag Erling Smørgrav

Store stevedores in a circular list. The head pointer keeps moving from

one stevedore to the next.  The LRU code is invoked as soon as any of the
stevedores fills up.

This algorithm is far from ideal, and will not work well with differently
sized stevedores, but it has the advantage of being simple and lock-free.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@1734 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 920657dd
......@@ -36,48 +36,42 @@
#include "heritage.h"
#include "stevedore.h"
/*
* Stevedores are kept in a circular list with the head pointer
* continuously moving from one element to the next.
*/
extern struct stevedore sma_stevedore;
extern struct stevedore smf_stevedore;
static TAILQ_HEAD(stevedore_head, stevedore) stevedores;
static struct stevedore * volatile stevedores;
struct storage *
STV_alloc(size_t size)
{
struct storage *st;
struct stevedore *stv, *stv_first;
struct stevedore *stv;
/* Simple round robin selecting of a stevedore. */
stv_first = TAILQ_FIRST(&stevedores);
stv = stv_first;
do {
AN(stv->alloc);
st = stv->alloc(stv, size);
TAILQ_REMOVE(&stevedores, stv, stevedore_list);
TAILQ_INSERT_TAIL(&stevedores, stv, stevedore_list);
if (st != NULL)
return (st);
} while ((stv = TAILQ_FIRST(&stevedores)) != stv_first);
for (;;) {
/* pick a stevedore and bump the head along */
stv = stevedores = stevedores->next;
/* No stevedore with enough space is found. Make room in the first
* one in the list, and move it to the end. Ensuring the round-robin.
*/
stv = TAILQ_FIRST(&stevedores);
TAILQ_REMOVE(&stevedores, stv, stevedore_list);
TAILQ_INSERT_TAIL(&stevedores, stv, stevedore_list);
do {
if ((st = stv->alloc(stv, size)) == NULL)
AN(LRU_DiscardOne());
} while (st == NULL);
/* try to allocate from it */
if ((st = stv->alloc(stv, size)) != NULL) {
CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
return (st);
}
return (st);
/* no luck; free some space and keep trying */
AN(LRU_DiscardOne());
}
}
void
STV_trim(struct storage *st, size_t size)
{
CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
AN(st->stevedore);
if (st->stevedore->trim)
st->stevedore->trim(st, size);
......@@ -87,6 +81,7 @@ void
STV_free(struct storage *st)
{
CHECK_OBJ_NOTNULL(st, STORAGE_MAGIC);
AN(st->stevedore);
AN(st->stevedore->free);
st->stevedore->free(st);
......@@ -106,7 +101,7 @@ void
STV_add(const char *spec)
{
const char *p, *q;
struct stevedore *stp;
struct stevedore *stv;
p = strchr(spec, ',');
if (p == NULL)
......@@ -116,29 +111,42 @@ STV_add(const char *spec)
xxxassert(p != NULL);
xxxassert(q != NULL);
stp = malloc(sizeof *stp);
stv = malloc(sizeof *stv);
if (!cmp_storage(&sma_stevedore, spec, p)) {
*stp = sma_stevedore;
*stv = sma_stevedore;
} else if (!cmp_storage(&smf_stevedore, spec, p)) {
*stp = smf_stevedore;
*stv = smf_stevedore;
} else {
fprintf(stderr, "Unknown storage method \"%.*s\"\n",
(int)(p - spec), spec);
exit (2);
}
TAILQ_INSERT_HEAD(&stevedores, stp, stevedore_list);
if (stp->init != NULL)
stp->init(stp, q);
if (stv->init != NULL)
stv->init(stv, q);
if (!stevedores) {
fprintf(stderr, "first stevedore\n");
stevedores = stv->next = stv->prev = stv;
} else {
fprintf(stderr, "additional stevedore\n");
stv->next = stevedores;
stv->prev = stevedores->prev;
stv->next->prev = stv;
stv->prev->next = stv;
stevedores = stv;
}
}
void
STV_open(void)
{
struct stevedore *st;
struct stevedore *stv;
TAILQ_FOREACH(st, &stevedores, stevedore_list) {
if (st->open != NULL)
st->open(st);
}
stv = stevedores;
do {
if (stv->open != NULL)
stv->open(stv);
stv = stv->next;
} while (stv != stevedores);
}
......@@ -28,7 +28,6 @@
*
* $Id$
*/
#include "queue.h"
......@@ -52,7 +51,8 @@ struct stevedore {
/* private fields */
void *priv;
TAILQ_ENTRY(stevedore) stevedore_list;
struct stevedore *next, *prev;
};
struct storage *STV_alloc(size_t size);
......
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