/**
 * @file db_manage.c
 * Management of a DB file
 *
 * @remark Copyright 2002 OProfile authors
 * @remark Read the file COPYING
 *
 * @author Philippe Elie
 */

#define _GNU_SOURCE

#include <stdlib.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

#include "odb.h"
#include "op_string.h"
#include "op_libiberty.h"

 
static __inline odb_descr_t * odb_to_descr(odb_data_t * data)
{
	return (odb_descr_t *)(((char*)data->base_memory) + data->sizeof_header);
}

 
static __inline odb_node_t * odb_to_node_base(odb_data_t * data)
{
	return (odb_node_t *)(((char *)data->base_memory) + data->offset_node);
}

 
static __inline odb_index_t * odb_to_hash_base(odb_data_t * data)
{
	return (odb_index_t *)(((char *)data->base_memory) + 
				data->offset_node +
				(data->descr->size * sizeof(odb_node_t)));
}

 
/**
 * return the number of bytes used by hash table, node table and header.
 */
static unsigned int tables_size(odb_data_t const * data, odb_node_nr_t node_nr)
{
	size_t size;

	size = node_nr * (sizeof(odb_index_t) * BUCKET_FACTOR);
	size += node_nr * sizeof(odb_node_t);
	size += data->offset_node;

	return size;
}


int odb_grow_hashtable(odb_data_t * data)
{
	unsigned int old_file_size;
	unsigned int new_file_size;
	unsigned int pos;
	void * new_map;

	old_file_size = tables_size(data, data->descr->size);
	new_file_size = tables_size(data, data->descr->size * 2);

	if (ftruncate(data->fd, new_file_size))
		return 1;

	new_map = mremap(data->base_memory,
			 old_file_size, new_file_size, MREMAP_MAYMOVE);

	if (new_map == MAP_FAILED)
		return 1;

	data->base_memory = new_map;
	data->descr = odb_to_descr(data);
	data->descr->size *= 2;
	data->node_base = odb_to_node_base(data);
	data->hash_base = odb_to_hash_base(data);
	data->hash_mask = (data->descr->size * BUCKET_FACTOR) - 1;

	/* rebuild the hash table, node zero is never used. This works
	 * because layout of file is node table then hash table,
	 * sizeof(node) > sizeof(bucket) and when we grow table we
	 * double size ==> old hash table and new hash table can't
	 * overlap so on the new hash table is entirely in the new
	 * memory area (the grown part) and we know the new hash
	 * hash table is zeroed. That's why we don't need to zero init
	 * the new table */
	/* OK: the above is not exact
	 * if BUCKET_FACTOR < sizeof(bd_node_t) / sizeof(bd_node_nr_t)
	 * all things are fine and we don't need to init the hash
	 * table because in this case the new hash table is completely
	 * inside the new growed part. Avoiding to touch this memory is
	 * useful.
	 */
#if 0
	for (pos = 0 ; pos < data->descr->size*BUCKET_FACTOR ; ++pos)
		data->hash_base[pos] = 0;
#endif

	for (pos = 1; pos < data->descr->current_size; ++pos) {
		odb_node_t * node = &data->node_base[pos];
		size_t index = odb_do_hash(data, node->key);
		node->next = data->hash_base[index];
		data->hash_base[index] = pos;
	}

	return 0;
}


void odb_init(odb_t * odb)
{
	odb->data = NULL;
}


/* the default number of page, calculated to fit in 4096 bytes */
#define DEFAULT_NODE_NR(offset_node)	128
#define FILES_HASH_SIZE                 512

static struct list_head files_hash[FILES_HASH_SIZE];


static void init_hash()
{
	size_t i;
	for (i = 0; i < FILES_HASH_SIZE; ++i)
		list_init(&files_hash[i]);
}


static odb_data_t *
find_samples_data(size_t hash, char const * filename)
{
	struct list_head * pos;

	/* FIXME: maybe an initial init routine ? */
	if (files_hash[0].next == NULL) {
		init_hash();
		return NULL;
	}

	list_for_each(pos, &files_hash[hash]) {
		odb_data_t * entry = list_entry(pos, odb_data_t, list);
		if (strcmp(entry->filename, filename) == 0)
			return entry;
	}

	return NULL;
}


int odb_open(odb_t * odb, char const * filename, enum odb_rw rw,
	     size_t sizeof_header)
{
	struct stat stat_buf;
	odb_node_nr_t nr_node;
	odb_data_t * data;
	size_t hash;
	int err = 0;

	int flags = (rw == ODB_RDWR) ? (O_CREAT | O_RDWR) : O_RDONLY;
	int mmflags = (rw == ODB_RDWR) ? (PROT_READ | PROT_WRITE) : PROT_READ;

	hash = op_hash_string(filename) % FILES_HASH_SIZE;
	data = find_samples_data(hash, filename);
	if (data) {
		odb->data = data;
		data->ref_count++;
		return 0;
	}

	data = xmalloc(sizeof(odb_data_t));
	memset(data, '\0', sizeof(odb_data_t));
	list_init(&data->list);
	data->offset_node = sizeof_header + sizeof(odb_descr_t);
	data->sizeof_header = sizeof_header;
	data->ref_count = 1;
	data->filename = xstrdup(filename);

	data->fd = open(filename, flags, 0644);
	if (data->fd < 0) {
		err = errno;
		goto out;
	}

	if (fstat(data->fd, &stat_buf)) {
		err = errno;
		goto fail;
	}

	if (stat_buf.st_size == 0) {
		size_t file_size;

		if (rw == ODB_RDONLY) {
			err = EIO;
			goto fail;
		}

		nr_node = DEFAULT_NODE_NR(data->offset_node);

		file_size = tables_size(data, nr_node);
		if (ftruncate(data->fd, file_size)) {
			err = errno;
			goto fail;
		}
	} else {
		/* Calculate nr node allowing a sanity check later */
		nr_node = (stat_buf.st_size - data->offset_node) /
			((sizeof(odb_index_t) * BUCKET_FACTOR) + sizeof(odb_node_t));
	}

	data->base_memory = mmap(0, tables_size(data, nr_node), mmflags,
				MAP_SHARED, data->fd, 0);

	if (data->base_memory == MAP_FAILED) {
		err = errno;
		goto fail;
	}

	data->descr = odb_to_descr(data);

	if (stat_buf.st_size == 0) {
		data->descr->size = nr_node;
		/* page zero is not used */
		data->descr->current_size = 1;
	} else {
		/* file already exist, sanity check nr node */
		if (nr_node != data->descr->size) {
			err = EINVAL;
			goto fail_unmap;
		}
	}

	data->hash_base = odb_to_hash_base(data);
	data->node_base = odb_to_node_base(data);
	data->hash_mask = (data->descr->size * BUCKET_FACTOR) - 1;

	list_add(&data->list, &files_hash[hash]);
	odb->data = data;
out:
	return err;
fail_unmap:
	munmap(data->base_memory, tables_size(data, nr_node));
fail:
	close(data->fd);
	free(data->filename);
	free(data);
	odb->data = NULL;
	goto out;
}


void odb_close(odb_t * odb)
{
	odb_data_t * data = odb->data;

	if (data) {
		data->ref_count--;
		if (data->ref_count == 0) {
			size_t size = tables_size(data, data->descr->size);
			list_del(&data->list);
			munmap(data->base_memory, size);
			if (data->fd >= 0)
				close(data->fd);
			free(data->filename);
			free(data);
			odb->data = NULL;
		}
	}
}


int odb_open_count(odb_t const * odb)
{
	if (!odb->data)
		return 0;
	return odb->data->ref_count;
}


void * odb_get_data(odb_t * odb)
{
	return odb->data->base_memory;
}


void odb_sync(odb_t const * odb)
{
	odb_data_t * data = odb->data;
	size_t size;

	if (!data)
		return;

	size = tables_size(data, data->descr->size);
	msync(data->base_memory, size, MS_ASYNC);
}
