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;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(attribute_provider_t, acquire_address, host_t*,
|
/**
|
||||||
private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
|
* Find an existing or not yet existing lease
|
||||||
host_t *requested)
|
*/
|
||||||
|
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;
|
enumerator_t *enumerator;
|
||||||
mem_pool_t *pool;
|
mem_pool_t *pool;
|
||||||
host_t *addr = NULL;
|
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
enumerator = pools->create_enumerator(pools);
|
enumerator = pools->create_enumerator(pools);
|
||||||
this->lock->read_lock(this->lock);
|
|
||||||
while (enumerator->enumerate(enumerator, &name))
|
while (enumerator->enumerate(enumerator, &name))
|
||||||
{
|
{
|
||||||
pool = find_pool(this, name);
|
pool = find_pool(this, name);
|
||||||
if (pool)
|
if (pool)
|
||||||
{
|
{
|
||||||
addr = pool->acquire_address(pool, id, requested);
|
addr = pool->acquire_address(pool, id, requested, operation);
|
||||||
if (addr)
|
if (addr)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->lock->unlock(this->lock);
|
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
return addr;
|
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,
|
METHOD(attribute_provider_t, release_address, bool,
|
||||||
private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
|
private_stroke_attribute_t *this, linked_list_t *pools, host_t *address,
|
||||||
identification_t *id)
|
identification_t *id)
|
||||||
|
|||||||
@@ -212,12 +212,123 @@ METHOD(mem_pool_t, get_offline, u_int,
|
|||||||
return count;
|
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;
|
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
|
/* if the pool is empty (e.g. in the %config case) we simply return the
|
||||||
* requested address */
|
* requested address */
|
||||||
@@ -233,76 +344,24 @@ METHOD(mem_pool_t, acquire_address, host_t*,
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->mutex->lock(this->mutex);
|
this->mutex->lock(this->mutex);
|
||||||
while (TRUE)
|
switch (operation)
|
||||||
{
|
{
|
||||||
entry = this->leases->get(this->leases, id);
|
case MEM_POOL_EXISTING:
|
||||||
if (entry)
|
offset = get_existing(this, id, requested);
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
break;
|
break;
|
||||||
}
|
case MEM_POOL_NEW:
|
||||||
|
offset = get_new(this, id);
|
||||||
/* no more addresses, replace the first found offline lease */
|
break;
|
||||||
enumerator = this->leases->create_enumerator(this->leases);
|
case MEM_POOL_REASSIGN:
|
||||||
while (enumerator->enumerate(enumerator, NULL, &old))
|
offset = get_reassigned(this, id);
|
||||||
{
|
if (!offset)
|
||||||
if (old->offline->remove_first(old->offline,
|
|
||||||
(void**)¤t) == SUCCESS)
|
|
||||||
{
|
{
|
||||||
offset = current;
|
DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
|
||||||
entry->online->insert_last(entry->online, (void*)offset);
|
this->name);
|
||||||
DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
|
|
||||||
" to '%Y'", old->id, id);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
enumerator->destroy(enumerator);
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this->mutex->unlock(this->mutex);
|
this->mutex->unlock(this->mutex);
|
||||||
|
|
||||||
@@ -310,11 +369,6 @@ METHOD(mem_pool_t, acquire_address, host_t*,
|
|||||||
{
|
{
|
||||||
return offset2host(this, offset);
|
return offset2host(this, offset);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
|
|
||||||
this->name);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,23 @@
|
|||||||
#define MEM_POOL_H
|
#define MEM_POOL_H
|
||||||
|
|
||||||
typedef struct mem_pool_t mem_pool_t;
|
typedef struct mem_pool_t mem_pool_t;
|
||||||
|
typedef enum mem_pool_op_t mem_pool_op_t;
|
||||||
|
|
||||||
#include <utils/host.h>
|
#include <utils/host.h>
|
||||||
#include <utils/identification.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.
|
* An in-memory IP address pool.
|
||||||
*/
|
*/
|
||||||
@@ -69,12 +82,18 @@ struct mem_pool_t {
|
|||||||
/**
|
/**
|
||||||
* Acquire an address for the given id from this pool.
|
* 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 id the id to acquire an address for
|
||||||
* @param requested acquire this address, if possible
|
* @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
|
* @return the acquired address
|
||||||
*/
|
*/
|
||||||
host_t* (*acquire_address)(mem_pool_t *this, identification_t *id,
|
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.
|
* Release a previously acquired address.
|
||||||
|
|||||||
Reference in New Issue
Block a user