Check for an existing lease in all stroke pools before creating a new one

This commit is contained in:
Martin Willi
2012-09-11 16:18:28 +02:00
parent 28a3d5bfbd
commit 1e04488f32
3 changed files with 180 additions and 83 deletions
@@ -89,35 +89,59 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
return found;
}
METHOD(attribute_provider_t, acquire_address, host_t*,
private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
/**
* Find an existing or not yet existing lease
*/
static host_t *find_addr(private_stroke_attribute_t *this, linked_list_t *pools,
identification_t *id, host_t *requested,
mem_pool_op_t operation)
{
host_t *addr = NULL;
enumerator_t *enumerator;
mem_pool_t *pool;
host_t *addr = NULL;
char *name;
enumerator = pools->create_enumerator(pools);
this->lock->read_lock(this->lock);
while (enumerator->enumerate(enumerator, &name))
{
pool = find_pool(this, name);
if (pool)
{
addr = pool->acquire_address(pool, id, requested);
addr = pool->acquire_address(pool, id, requested, operation);
if (addr)
{
break;
}
}
}
this->lock->unlock(this->lock);
enumerator->destroy(enumerator);
return addr;
}
METHOD(attribute_provider_t, acquire_address, host_t*,
private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
{
host_t *addr;
this->lock->read_lock(this->lock);
addr = find_addr(this, pools, id, requested, MEM_POOL_EXISTING);
if (!addr)
{
addr = find_addr(this, pools, id, requested, MEM_POOL_NEW);
if (!addr)
{
addr = find_addr(this, pools, id, requested, MEM_POOL_REASSIGN);
}
}
this->lock->unlock(this->lock);
return addr;
}
METHOD(attribute_provider_t, release_address, bool,
private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
identification_t *id)
+129 -75
View File
@@ -212,12 +212,123 @@ METHOD(mem_pool_t, get_offline, u_int,
return count;
}
METHOD(mem_pool_t, acquire_address, host_t*,
private_mem_pool_t *this, identification_t *id, host_t *requested)
/**
* Get an existing lease for id
*/
static int get_existing(private_mem_pool_t *this, identification_t *id,
host_t *requested)
{
uintptr_t offset = 0, current;
enumerator_t *enumerator;
entry_t *entry, *old;
uintptr_t current;
entry_t *entry;
int offset = 0;
entry = this->leases->get(this->leases, id);
if (!entry)
{
return 0;
}
/* check for a valid offline lease, refresh */
enumerator = entry->offline->create_enumerator(entry->offline);
if (enumerator->enumerate(enumerator, &current))
{
entry->offline->remove_at(entry->offline, enumerator);
entry->online->insert_last(entry->online, (void*)current);
offset = current;
}
enumerator->destroy(enumerator);
if (offset)
{
DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
return offset;
}
/* check for a valid online lease to reassign */
enumerator = entry->online->create_enumerator(entry->online);
while (enumerator->enumerate(enumerator, &current))
{
if (current == host2offset(this, requested))
{
offset = current;
break;
}
}
enumerator->destroy(enumerator);
if (offset)
{
DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
}
return offset;
}
/**
* Get a new lease for id
*/
static int get_new(private_mem_pool_t *this, identification_t *id)
{
entry_t *entry;
int offset = 0;
if (this->unused < this->size)
{
INIT(entry,
.id = id->clone(id),
.online = linked_list_create(),
.offline = linked_list_create(),
);
this->leases->put(this->leases, entry->id, entry);
/* assigning offset, starting by 1 */
offset = ++this->unused;
entry->online->insert_last(entry->online, (void*)offset);
DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
}
return offset;
}
/**
* Get a reassigned lease for id in case the pool is full
*/
static int get_reassigned(private_mem_pool_t *this, identification_t *id)
{
enumerator_t *enumerator;
entry_t *entry;
uintptr_t current;
int offset = 0;
enumerator = this->leases->create_enumerator(this->leases);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
if (entry->offline->remove_first(entry->offline,
(void**)&current) == SUCCESS)
{
offset = current;
DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
" to '%Y'", entry->id, id);
break;
}
}
enumerator->destroy(enumerator);
if (offset)
{
INIT(entry,
.id = id->clone(id),
.online = linked_list_create(),
.offline = linked_list_create(),
);
entry->online->insert_last(entry->online, (void*)offset);
this->leases->put(this->leases, entry->id, entry);
}
return offset;
}
METHOD(mem_pool_t, acquire_address, host_t*,
private_mem_pool_t *this, identification_t *id, host_t *requested,
mem_pool_op_t operation)
{
int offset = 0;
/* if the pool is empty (e.g. in the %config case) we simply return the
* requested address */
@@ -233,76 +344,24 @@ METHOD(mem_pool_t, acquire_address, host_t*,
}
this->mutex->lock(this->mutex);
while (TRUE)
switch (operation)
{
entry = this->leases->get(this->leases, id);
if (entry)
{
/* check for a valid offline lease, refresh */
enumerator = entry->offline->create_enumerator(entry->offline);
if (enumerator->enumerate(enumerator, &current))
{
entry->offline->remove_at(entry->offline, enumerator);
entry->online->insert_last(entry->online, (void*)current);
offset = current;
}
enumerator->destroy(enumerator);
if (offset)
{
DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
break;
}
/* check for a valid online lease to reassign */
enumerator = entry->online->create_enumerator(entry->online);
while (enumerator->enumerate(enumerator, &current))
{
if (current == host2offset(this, requested))
{
offset = current;
break;
}
}
enumerator->destroy(enumerator);
if (offset)
{
DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
break;
}
}
else
{
INIT(entry,
.id = id->clone(id),
.online = linked_list_create(),
.offline = linked_list_create(),
);
this->leases->put(this->leases, entry->id, entry);
}
if (this->unused < this->size)
{
/* assigning offset, starting by 1 */
offset = ++this->unused;
entry->online->insert_last(entry->online, (void*)offset);
DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
case MEM_POOL_EXISTING:
offset = get_existing(this, id, requested);
break;
}
/* no more addresses, replace the first found offline lease */
enumerator = this->leases->create_enumerator(this->leases);
while (enumerator->enumerate(enumerator, NULL, &old))
{
if (old->offline->remove_first(old->offline,
(void**)&current) == SUCCESS)
case MEM_POOL_NEW:
offset = get_new(this, id);
break;
case MEM_POOL_REASSIGN:
offset = get_reassigned(this, id);
if (!offset)
{
offset = current;
entry->online->insert_last(entry->online, (void*)offset);
DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
" to '%Y'", old->id, id);
break;
DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
this->name);
}
}
enumerator->destroy(enumerator);
break;
break;
default:
break;
}
this->mutex->unlock(this->mutex);
@@ -310,11 +369,6 @@ METHOD(mem_pool_t, acquire_address, host_t*,
{
return offset2host(this, offset);
}
else
{
DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
this->name);
}
return NULL;
}
+20 -1
View File
@@ -22,10 +22,23 @@
#define MEM_POOL_H
typedef struct mem_pool_t mem_pool_t;
typedef enum mem_pool_op_t mem_pool_op_t;
#include <utils/host.h>
#include <utils/identification.h>
/**
* In-memory IP pool acquire operation.
*/
enum mem_pool_op_t {
/** Check for an exsiting lease */
MEM_POOL_EXISTING,
/** Get a new lease */
MEM_POOL_NEW,
/** Replace an existing offline lease of another ID */
MEM_POOL_REASSIGN,
};
/**
* An in-memory IP address pool.
*/
@@ -69,12 +82,18 @@ struct mem_pool_t {
/**
* Acquire an address for the given id from this pool.
*
* This call is usually invoked several times: The first time to find an
* existing lease (MEM_POOL_EXISTING), if none found a second time to
* acquire a new lease (MEM_POOL_NEW), and if the pool is full once again
* to assign an existing offline lease (MEM_POOL_REASSIGN).
*
* @param id the id to acquire an address for
* @param requested acquire this address, if possible
* @param existing TRUE to look for an existing lease, FALSE for a new one
* @return the acquired address
*/
host_t* (*acquire_address)(mem_pool_t *this, identification_t *id,
host_t *requested);
host_t *requested, mem_pool_op_t operation);
/**
* Release a previously acquired address.