reentrant save cert_cache

This commit is contained in:
Martin Willi
2008-03-28 08:38:51 +00:00
parent ac1fefc2de
commit d55fa9aff7
+65 -12
View File
@@ -20,7 +20,7 @@
#include <daemon.h>
#include <utils/linked_list.h>
#define CACHE_LIMIT 30
#define CACHE_SIZE 30
typedef struct private_cert_cache_t private_cert_cache_t;
typedef struct relation_t relation_t;
@@ -39,6 +39,16 @@ struct private_cert_cache_t {
* list of trusted subject-issuer relations, as relation_t
*/
linked_list_t *relations;
/**
* do we have an active enumerator
*/
bool enumerating;
/**
* have we increased the cache without a check_cache?
*/
bool check_required;
};
/**
@@ -63,13 +73,45 @@ static void relation_destroy(relation_t *this)
free(this);
}
/**
* check the cache for oversize
*/
static void check_cache(private_cert_cache_t *this)
{
if (this->enumerating)
{
this->check_required = TRUE;
}
else
{
while (this->relations->get_count(this->relations) > CACHE_SIZE)
{
relation_t *oldest = NULL, *current;
enumerator_t *enumerator;
enumerator = this->relations->create_enumerator(this->relations);
while (enumerator->enumerate(enumerator, &current))
{
if (oldest == NULL || oldest->last_use <= current->last_use)
{
oldest = current;
}
}
enumerator->destroy(enumerator);
this->relations->remove(this->relations, oldest, NULL);
relation_destroy(oldest);
}
this->check_required = FALSE;
}
}
/**
* Implementation of cert_cache_t.issued_by.
*/
static bool issued_by(private_cert_cache_t *this,
certificate_t *subject, certificate_t *issuer)
{
relation_t *found = NULL, *current, *oldest = NULL;
relation_t *found = NULL, *current;
enumerator_t *enumerator;
/* lookup cache */
@@ -82,10 +124,6 @@ static bool issued_by(private_cert_cache_t *this,
found = current;
break;
}
if (oldest == NULL || oldest->last_use <= current->last_use)
{
oldest = current;
}
}
enumerator->destroy(enumerator);
if (found)
@@ -102,12 +140,8 @@ static bool issued_by(private_cert_cache_t *this,
found->subject = subject->get_ref(subject);
found->issuer = issuer->get_ref(issuer);
found->last_use = time(NULL);
if (this->relations->get_count(this->relations) > CACHE_LIMIT && oldest)
{
this->relations->remove(this->relations, oldest, NULL);
relation_destroy(oldest);
}
this->relations->insert_last(this->relations, found);
check_cache(this);
return TRUE;
}
@@ -121,6 +155,8 @@ typedef struct {
key_type_t key;
/** ID to get a cert from */
identification_t *id;
/** reverse pointer to cache */
private_cert_cache_t *this;
} cert_data_t;
/**
@@ -166,6 +202,19 @@ static bool certs_filter(cert_data_t *data, relation_t **in, certificate_t **out
return FALSE;
}
/**
* clean up enumeration data
*/
static void certs_destroy(cert_data_t *data)
{
data->this->enumerating--;
if (data->this->check_required)
{
check_cache(data->this);
}
free(data);
}
/**
* implementation of credential_set_t.create_cert_enumerator
*/
@@ -183,10 +232,12 @@ static enumerator_t *create_enumerator(private_cert_cache_t *this,
data->cert = cert;
data->key = key;
data->id = id;
data->this = this;
this->enumerating++;
return enumerator_create_filter(
this->relations->create_enumerator(this->relations),
(void*)certs_filter, data, (void*)free);
(void*)certs_filter, data, (void*)certs_destroy);
}
/**
@@ -235,6 +286,8 @@ cert_cache_t *cert_cache_create()
this->public.destroy = (void(*)(cert_cache_t*))destroy;
this->relations = linked_list_create();
this->enumerating = FALSE;
this->check_required = FALSE;
return &this->public;
}