check for an existing lease over all assigned pools first

This commit is contained in:
Andreas Steffen
2009-07-17 11:48:35 +02:00
parent 07be083b7f
commit 7f522b5fd8
+55 -24
View File
@@ -92,25 +92,18 @@ static u_int get_pool(private_sql_attribute_t *this, char *name, u_int *timeout)
} }
/** /**
* Lookup a lease * Look up an existing lease
*/ */
static host_t *get_address(private_sql_attribute_t *this, char *name, static host_t* check_lease(private_sql_attribute_t *this, char *name,
u_int pool, u_int timeout, u_int identity) u_int pool, u_int identity)
{ {
enumerator_t *e;
u_int id;
chunk_t address;
host_t *host;
time_t now = time(NULL);
/* We check for leases for that identity first and for other expired
* leases afterwards. We select an address as a candidate, but double
* check if it is still valid in the update. This allows us to work
* without locking. */
/* check for an existing lease for that identity */
while (TRUE) while (TRUE)
{ {
u_int id;
chunk_t address;
enumerator_t *e;
time_t now = time(NULL);
e = this->db->query(this->db, e = this->db->query(this->db,
"SELECT id, address FROM addresses " "SELECT id, address FROM addresses "
"WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1", "WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1",
@@ -122,11 +115,14 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
} }
address = chunk_clonea(address); address = chunk_clonea(address);
e->destroy(e); e->destroy(e);
if (this->db->execute(this->db, NULL, if (this->db->execute(this->db, NULL,
"UPDATE addresses SET acquired = ?, released = 0 " "UPDATE addresses SET acquired = ?, released = 0 "
"WHERE id = ? AND identity = ? AND released != 0", "WHERE id = ? AND identity = ? AND released != 0",
DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0) DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
{ {
host_t *host;
host = host_create_from_chunk(AF_UNSPEC, address, 0); host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host) if (host)
{ {
@@ -136,10 +132,23 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
} }
} }
} }
return NULL;
/* check for an available address */ }
/**
* We check for unallocated addresses or expired leases. First we select an
* address as a candidate, but double check later on if it is still available
* during the update operation. This allows us to work without locking.
*/
static host_t* get_lease(private_sql_attribute_t *this, char *name,
u_int pool, u_int timeout, u_int identity)
{
while (TRUE) while (TRUE)
{ {
u_int id;
chunk_t address;
enumerator_t *e;
time_t now = time(NULL);
int hits; int hits;
if (timeout) if (timeout)
@@ -187,6 +196,8 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
} }
if (hits > 0) if (hits > 0)
{ {
host_t *host;
host = host_create_from_chunk(AF_UNSPEC, address, 0); host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host) if (host)
{ {
@@ -197,30 +208,50 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
} }
} }
DBG1(DBG_CFG, "no available address found in pool '%s'", name); DBG1(DBG_CFG, "no available address found in pool '%s'", name);
return 0; return NULL;
} }
/** /**
* Implementation of attribute_provider_t.acquire_address * Implementation of attribute_provider_t.acquire_address
*/ */
static host_t* acquire_address(private_sql_attribute_t *this, static host_t* acquire_address(private_sql_attribute_t *this,
char *name, identification_t *id, char *names, identification_t *id,
host_t *requested) host_t *requested)
{ {
enumerator_t *enumerator;
u_int pool, timeout, identity;
host_t *address = NULL; host_t *address = NULL;
u_int identity, pool, timeout;
identity = get_identity(this, id); identity = get_identity(this, id);
if (identity) if (identity)
{ {
enumerator = enumerator_create_token(name, ",", " "); char *name;
enumerator_t *enumerator;
/* in a first step check for an existing lease over all pools */
enumerator = enumerator_create_token(names, ",", " ");
while (enumerator->enumerate(enumerator, &name)) while (enumerator->enumerate(enumerator, &name))
{ {
pool = get_pool(this, name, &timeout); pool = get_pool(this, name, &timeout);
if (pool) if (pool)
{ {
address = get_address(this, name, pool, timeout, identity); address = check_lease(this, name, pool, identity);
if (address)
{
enumerator->destroy(enumerator);
return address;
}
}
}
enumerator->destroy(enumerator);
/* in a second step get an unallocated address or expired lease */
enumerator = enumerator_create_token(names, ",", " ");
while (enumerator->enumerate(enumerator, &name))
{
pool = get_pool(this, name, &timeout);
if (pool)
{
address = get_lease(this, name, pool, timeout, identity);
if (address) if (address)
{ {
break; break;