Check for an existing lease in all stroke pools before creating a new one
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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, ¤t))
|
||||
{
|
||||
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, ¤t))
|
||||
{
|
||||
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**)¤t) == 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, ¤t))
|
||||
{
|
||||
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, ¤t))
|
||||
{
|
||||
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**)¤t) == 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user