greenplumn shmmc 源码

  • 2022-08-18
  • 浏览 (343)

greenplumn shmmc 代码

文件路径:/gpcontrib/orafce/shmmc.c

/*
 *
 * 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 "orafce.h"

#include "stdint.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;
	size_t 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)
{
	ptrdiff_t d;

	list_item *_a = (list_item*) a;
	list_item *_b = (list_item*) b;

	d = (uintptr_t)_a->first_byte_ptr - (uintptr_t)_b->first_byte_ptr;

	return d > 0 ? 1 : (d < 0 ? -1 : 0);
}

char *
ora_sstrcpy(char *str)
{
	size_t 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.", (int) 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.", (int) 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;
}

/*
  initialize 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 = ((char *) &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 authors.")));
}


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 authors.")));


	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;
}

相关信息

greenplumn 源码目录

相关文章

greenplumn aggregate 源码

greenplumn alert 源码

greenplumn assert 源码

greenplumn assert 源码

greenplumn builtins 源码

greenplumn charlen 源码

greenplumn charpad 源码

greenplumn convert 源码

greenplumn datefce 源码

greenplumn file 源码

0  赞