/*
 *
 * Shared memory control - based on alocating chunks aligned on
 * asize array (fibonachi), and dividing free bigger block.
 *
 */

#include "postgres.h"
#include "shmmc.h"
#include "stdlib.h"
#include "string.h"
#include "orafunc.h"


#define LIST_ITEMS  512

int context;

typedef struct {
	size_t size;
	void* first_byte_ptr;
	bool dispossible;
/*	int16 context; */
} list_item;

typedef struct {
	int list_c;
	int max_size;
	vardata data[1];	 /* flexible array member */
} mem_desc;

#define MAX_SIZE 82688

static size_t asize[] = {
	32,
	64,       96,   160,  256,
	416,     672,  1088,  1760,
	2848,   4608,  7456, 12064,
	19520, 31584, 51104, 82688};


int *list_c = NULL;
list_item *list = NULL;
size_t max_size;

int cycle = 0;


/* align requested size */

static int
ptr_comp(const void* a, const void* b)
{
	list_item *_a = (list_item*) a;
	list_item *_b = (list_item*) b;

	return (long)_a->first_byte_ptr - (long)_b->first_byte_ptr;
}

char *
ora_sstrcpy(char *str)
{
	int len;
	char *result;

	len = strlen(str);
	if (NULL != (result = ora_salloc(len+1)))
		memcpy(result, str, len + 1);
	else
		ereport(ERROR,
			(errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory"),
			errdetail("Failed while allocation block %d bytes in shared memory.", len+1),
			errhint("Increase SHMEMMSGSZ and recompile package.")));

	return result;
}

char *
ora_scstring(text *str)
{
	int len;
	char *result;

	len = VARSIZE_ANY_EXHDR(str);

	if (NULL != (result = ora_salloc(len+1)))
	{
		memcpy(result, VARDATA_ANY(str), len);
		result[len] = '\0';
	}
	else
		ereport(ERROR,
			(errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory"),
			errdetail("Failed while allocation block %d bytes in shared memory.", len+1),
			errhint("Increase SHMEMMSGSZ and recompile package.")));

	return result;
}

/*
 * Compact the list of slots, by merging adjacent unused slots into larger
 * slots.
 */
static void
defragmentation()
{
	int src, target;

	/* Sort the array to pointer order */
	qsort(list, *list_c, sizeof(list_item), ptr_comp);

	/* Merge adjacent dispossible slots, and move up other slots */
	target = 0;
	for (src = 0; src < *list_c; src++)
	{
		if (target > 0 &&
			list[src].dispossible &&
			list[target - 1].dispossible)
		{
			list[target - 1].size += list[src].size;
		}
		else
		{
			if (src != target)
				memcpy(&list[target], &list[src], sizeof(list_item));
			target++;
		}
	}
	*list_c = target;
}

static size_t
align_size(size_t size)
{
	int i;

	/* default, we can allocate max MAX_SIZE memory block */

	for (i = 0; i < 17; i++)
		if (asize[i] >= size)
			return asize[i];

	ereport(ERROR,
		   (errcode(ERRCODE_OUT_OF_MEMORY),
		    errmsg("too much large memory block request"),
		    errdetail("Failed while allocation block %lu bytes in shared memory.", (unsigned long) size),
		    errhint("Increase MAX_SIZE constant, fill table a_size and recompile package.")));

	return 0;
}

/*
  inicialize shared memory. It works in two modes, create and no create.
  No create is used for mounting shared memory buffer. Top of memory is
  used for list_item array.
*/

void
ora_sinit(void *ptr, size_t size, bool create)
{
	if (list == NULL)
	{
		mem_desc *m = (mem_desc*)ptr;
		list = (list_item*)m->data;
		list_c = &m->list_c;
		max_size = m->max_size = size;

		if (create)
		{
			list[0].size = size - sizeof(list_item)*LIST_ITEMS - sizeof(mem_desc);
			list[0].first_byte_ptr = &m->data + sizeof(list_item)*LIST_ITEMS;
			list[0].dispossible = true;
			*list_c = 1;
		}
	}
}


void*
ora_salloc(size_t size)
{
	size_t aligned_size;
	int repeat_c;
	void *ptr = NULL;

	aligned_size = align_size(size);

	for (repeat_c = 0; repeat_c < 2; repeat_c++)
	{
		size_t	max_min = max_size;
		int		select = -1;
		int		i;

		/* find first good free block */
		for (i = 0; i < *list_c; i++)
		{
			if (list[i].dispossible)
			{
				/* If this block is just the right size, return it */
				if (list[i].size == aligned_size)
				{
					list[i].dispossible = false;
					ptr = list[i].first_byte_ptr;
					/* list[i].context = context; */

					return ptr;
				}

				if (list[i].size > aligned_size && list[i].size < max_min)
				{
					max_min = list[i].size;
					select = i;
				}
			}
		}

		/* If no suitable free slot found, defragment and try again. */
		if (select == -1 || *list_c == LIST_ITEMS)
		{
			defragmentation();
			continue;
		}

		/*
		 * A slot larger than required was found. Divide it to avoid wasting
		 * space, and return the slot of the right size.
		 */
		list[*list_c].size = list[select].size - aligned_size;
		list[*list_c].first_byte_ptr = (char*)list[select].first_byte_ptr + aligned_size;
		list[*list_c].dispossible = true;
		list[select].size = aligned_size;
		list[select].dispossible = false;
		/* list[select].context = context; */
		ptr = list[select].first_byte_ptr;
		*list_c += 1;
 		break;
	}

	return ptr;
}

void
ora_sfree(void* ptr)
{
	int i;

/*
	if (cycle++ % 100 == 0)
	{
		size_t suma = 0;
		for (i = 0; i < *list_c; i++)
			if (list[i].dispossible)
				suma += list[i].size;
		elog(NOTICE, "=============== FREE MEM REPORT === %10d ================", suma);
	}
*/

	for (i = 0; i < *list_c; i++)
		if (list[i].first_byte_ptr == ptr)
		{
			list[i].dispossible = true;
			/* list[i].context = -1; */
			memset(list[i].first_byte_ptr, '#', list[i].size);
			return;
		}

	ereport(ERROR,
			(errcode(ERRCODE_INTERNAL_ERROR),
			 errmsg("corrupted pointer"),
			 errdetail("Failed while reallocating memory block in shared memory."),
			 errhint("Report this bug to autors.")));
}


void*
ora_srealloc(void *ptr, size_t size)
{
	void *result;
	size_t aux_s = 0;
	int i;

	for (i = 0; i < *list_c; i++)
		if (list[i].first_byte_ptr == ptr)
		{
			if (align_size(size) <= list[i].size)
				return ptr;
			aux_s = list[i].size;
		}

	if (aux_s == 0)
		ereport(ERROR,
			(errcode(ERRCODE_INTERNAL_ERROR),
			errmsg("corrupted pointer"),
			errdetail("Failed while reallocating memory block in shared memory."),
			errhint("Report this bug to autors.")));


	if (NULL != (result = ora_salloc(size)))
	{
		memcpy(result, ptr, aux_s);
		ora_sfree(ptr);
	}

	return result;
}

/*
 *  alloc shared memory, raise exception if not
 */

void*
salloc(size_t size)
{
	void* result;

	if (NULL == (result = ora_salloc(size)))
		ereport(ERROR,
			(errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory"),
			errdetail("Failed while allocation block %lu bytes in shared memory.", (unsigned long) size),
			errhint("Increase SHMEMMSGSZ and recompile package.")));

	return result;
}

void*
srealloc(void *ptr, size_t size)
{
	void* result;

	if (NULL == (result = ora_srealloc(ptr, size)))
		ereport(ERROR,
			(errcode(ERRCODE_OUT_OF_MEMORY),
			errmsg("out of memory"),
			errdetail("Failed while reallocation block %lu bytes in shared memory.", (unsigned long) size),
			errhint("Increase SHMEMMSGSZ and recompile package.")));

	return result;
}
