/* Copyright (C) 2005 Red Hat, Inc. */

/* Object: dbase_llist_t (Linked List)
 * Partially Implements: dbase_t (Database)
 */

struct dbase_llist;
typedef struct dbase_llist dbase_t;
#define DBASE_DEFINED

#include <stdlib.h>
#include "debug.h"
#include "handle.h"
#include "database_llist.h"

int dbase_llist_needs_resync(semanage_handle_t * handle, dbase_llist_t * dbase)
{

	int cache_serial;

	if (dbase->cache_serial < 0)
		return 1;

	cache_serial = handle->funcs->get_serial(handle);
	if (cache_serial < 0)
		return 1;

	if (cache_serial != dbase->cache_serial) {
		dbase_llist_drop_cache(dbase);
		dbase->cache_serial = -1;
		return 1;
	}
	return 0;
}

/* Helper for adding records to the cache */
int dbase_llist_cache_prepend(semanage_handle_t * handle,
			      dbase_llist_t * dbase, const record_t * data)
{

	/* Initialize */
	cache_entry_t *entry = (cache_entry_t *) malloc(sizeof(cache_entry_t));
	if (entry == NULL)
		goto omem;

	if (dbase->rtable->clone(handle, data, &entry->data) < 0)
		goto err;

	entry->prev = NULL;
	entry->next = dbase->cache;

	/* Link */
	if (dbase->cache != NULL)
		dbase->cache->prev = entry;
	if (dbase->cache_tail == NULL)
		dbase->cache_tail = entry;
	dbase->cache = entry;
	dbase->cache_sz++;
	return STATUS_SUCCESS;

      omem:
	ERR(handle, "out of memory");

      err:
	ERR(handle, "could not cache record");
	free(entry);
	return STATUS_ERR;
}

void dbase_llist_drop_cache(dbase_llist_t * dbase)
{

	if (dbase->cache_serial < 0)
		return;

	cache_entry_t *prev, *ptr = dbase->cache;
	while (ptr != NULL) {
		prev = ptr;
		ptr = ptr->next;
		dbase->rtable->free(prev->data);
		free(prev);
	}

	dbase->cache_serial = -1;
	dbase->modified = 0;
}

int dbase_llist_set_serial(semanage_handle_t * handle, dbase_llist_t * dbase)
{

	int cache_serial = handle->funcs->get_serial(handle);
	if (cache_serial < 0) {
		ERR(handle, "could not update cache serial");
		return STATUS_ERR;
	}

	dbase->cache_serial = cache_serial;
	return STATUS_SUCCESS;
}

/* Helper for finding records in the cache */
static int dbase_llist_cache_locate(semanage_handle_t * handle,
				    dbase_llist_t * dbase,
				    const record_key_t * key,
				    cache_entry_t ** entry)
{

	cache_entry_t *ptr;

	/* Implemented in parent */
	if (dbase->dtable->cache(handle, dbase) < 0)
		goto err;

	for (ptr = dbase->cache; ptr != NULL; ptr = ptr->next) {
		if (!dbase->rtable->compare(ptr->data, key)) {
			*entry = ptr;
			return STATUS_SUCCESS;
		}
	}

	return STATUS_NODATA;

      err:
	ERR(handle, "could not complete cache lookup");
	return STATUS_ERR;
}

int dbase_llist_exists(semanage_handle_t * handle,
		       dbase_llist_t * dbase,
		       const record_key_t * key, int *response)
{

	cache_entry_t *entry;
	int status;

	status = dbase_llist_cache_locate(handle, dbase, key, &entry);
	if (status < 0)
		goto err;

	*response = (status != STATUS_NODATA);
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not check if record exists");
	return STATUS_ERR;
}

int dbase_llist_add(semanage_handle_t * handle,
		    dbase_llist_t * dbase,
		    const record_key_t * key __attribute__ ((unused)),
			 const record_t * data)
{

	if (dbase_llist_cache_prepend(handle, dbase, data) < 0)
		goto err;

	dbase->modified = 1;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not add record to the database");
	return STATUS_ERR;
}

int dbase_llist_set(semanage_handle_t * handle,
		    dbase_llist_t * dbase,
		    const record_key_t * key, const record_t * data)
{

	cache_entry_t *entry;
	int status;

	status = dbase_llist_cache_locate(handle, dbase, key, &entry);
	if (status < 0)
		goto err;
	if (status == STATUS_NODATA) {
		ERR(handle, "record not found in the database");
		goto err;
	} else {
		dbase->rtable->free(entry->data);
		if (dbase->rtable->clone(handle, data, &entry->data) < 0)
			goto err;
	}

	dbase->modified = 1;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not set record value");
	return STATUS_ERR;
}

int dbase_llist_modify(semanage_handle_t * handle,
		       dbase_llist_t * dbase,
		       const record_key_t * key, const record_t * data)
{

	cache_entry_t *entry;
	int status;

	status = dbase_llist_cache_locate(handle, dbase, key, &entry);
	if (status < 0)
		goto err;
	if (status == STATUS_NODATA) {
		if (dbase_llist_cache_prepend(handle, dbase, data) < 0)
			goto err;
	} else {
		dbase->rtable->free(entry->data);
		if (dbase->rtable->clone(handle, data, &entry->data) < 0)
			goto err;
	}

	dbase->modified = 1;
	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not modify record value");
	return STATUS_ERR;
}

hidden int dbase_llist_count(semanage_handle_t * handle __attribute__ ((unused)),
			     dbase_llist_t * dbase, unsigned int *response)
{

	*response = dbase->cache_sz;
	return STATUS_SUCCESS;
}

int dbase_llist_query(semanage_handle_t * handle,
		      dbase_llist_t * dbase,
		      const record_key_t * key, record_t ** response)
{

	cache_entry_t *entry;
	int status;

	status = dbase_llist_cache_locate(handle, dbase, key, &entry);
	if (status < 0 || status == STATUS_NODATA)
		goto err;

	if (dbase->rtable->clone(handle, entry->data, response) < 0)
		goto err;

	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not query record value");
	return STATUS_ERR;
}

int dbase_llist_iterate(semanage_handle_t * handle,
			dbase_llist_t * dbase,
			int (*fn) (const record_t * record,
				   void *fn_arg), void *arg)
{

	int rc;
	cache_entry_t *ptr;

	for (ptr = dbase->cache_tail; ptr != NULL; ptr = ptr->prev) {

		rc = fn(ptr->data, arg);
		if (rc < 0)
			goto err;

		else if (rc > 1)
			break;
	}

	return STATUS_SUCCESS;

      err:
	ERR(handle, "could not iterate over records");
	return STATUS_ERR;
}

int dbase_llist_del(semanage_handle_t * handle __attribute__ ((unused)),
		    dbase_llist_t * dbase, const record_key_t * key)
{

	cache_entry_t *ptr, *prev = NULL;

	for (ptr = dbase->cache; ptr != NULL; ptr = ptr->next) {
		if (!dbase->rtable->compare(ptr->data, key)) {
			if (prev != NULL)
				prev->next = ptr->next;
			else
				dbase->cache = ptr->next;

			if (ptr->next != NULL)
				ptr->next->prev = ptr->prev;
			else
				dbase->cache_tail = ptr->prev;

			dbase->rtable->free(ptr->data);
			dbase->cache_sz--;
			free(ptr);
			dbase->modified = 1;
			return STATUS_SUCCESS;
		} else
			prev = ptr;
	}

	return STATUS_SUCCESS;
}

int dbase_llist_clear(semanage_handle_t * handle, dbase_llist_t * dbase)
{

	int old_serial = dbase->cache_serial;

	if (dbase_llist_set_serial(handle, dbase) < 0) {
		ERR(handle, "could not set serial of cleared dbase");
		return STATUS_ERR;
	}

	if (old_serial >= 0) {
		cache_entry_t *prev, *ptr = dbase->cache;
		while (ptr != NULL) {
			prev = ptr;
			ptr = ptr->next;
			dbase->rtable->free(prev->data);
			free(prev);
		}
	}

	dbase->cache = NULL;
	dbase->cache_tail = NULL;
	dbase->cache_sz = 0;
	dbase->modified = 1;
	return STATUS_SUCCESS;
}

int dbase_llist_list(semanage_handle_t * handle,
		     dbase_llist_t * dbase,
		     record_t *** records, unsigned int *count)
{

	cache_entry_t *ptr;
	record_t **tmp_records = NULL;
	unsigned int tmp_count;
	int i = 0;

	tmp_count = dbase->cache_sz;
	if (tmp_count > 0) {
		tmp_records = (record_t **)
		    calloc(tmp_count, sizeof(record_t *));

		if (tmp_records == NULL)
			goto omem;

		for (ptr = dbase->cache_tail; ptr != NULL; ptr = ptr->prev) {
			if (dbase->rtable->clone(handle,
						 ptr->data,
						 &tmp_records[i]) < 0)
				goto err;
			i++;
		}
	}

	*records = tmp_records;
	*count = tmp_count;
	return STATUS_SUCCESS;

      omem:
	ERR(handle, "out of memory");

      err:
	if (tmp_records) {
		for (; i >= 0; i--)
			dbase->rtable->free(tmp_records[i]);
		free(tmp_records);
	}
	ERR(handle, "could not allocate record array");
	return STATUS_ERR;
}
