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)
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)
+{
+ enumerator_t *enumerator;
+ 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)
{
- uintptr_t offset = 0, current;
enumerator_t *enumerator;
- entry_t *entry, *old;
+ 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 */
}
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);
{
return offset2host(this, offset);
}
- else
- {
- DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
- this->name);
- }
return NULL;
}