From 884240a356e7e3ba1fd7c86b216ae27a1f189d96 Mon Sep 17 00:00:00 2001 From: =?utf8?q?C=C3=A9dric=20Villemain?= Date: Mon, 10 Aug 2009 01:43:15 +0200 Subject: [PATCH] SRF set of record ok with 8.4 --- pgfincore.c | 83 ++++++++++++++++++++++++++++++--------------- pgfincore_84.sql.in | 9 ++--- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/pgfincore.c b/pgfincore.c index b256cf8..5f0a61c 100644 --- a/pgfincore.c +++ b/pgfincore.c @@ -38,6 +38,7 @@ #include "utils/builtins.h" /* textToQualifiedNameList */ #include "utils/rel.h" /* Relation */ #include "funcapi.h" /* SRF */ +#include "catalog/pg_type.h" /* TEXTOID for tuple_desc */ #ifdef PG_VERSION_NUM @@ -52,13 +53,13 @@ PG_MODULE_MAGIC; /* } */ -Datum pgfincore(PG_FUNCTION_ARGS); /* Prototype */ +Datum pgfincore(PG_FUNCTION_ARGS); static int64 pgfincore_file(char *filename); typedef struct { Relation rel; /* the relation */ - int64 segcount; /* the segment current number */ + unsigned int segcount; /* the segment current number */ char *relationpath; /* the relation path */ } pgfincore_fctx; @@ -68,20 +69,18 @@ PG_FUNCTION_INFO_V1(pgfincore); Datum pgfincore(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; - MemoryContext oldcontext; pgfincore_fctx *fctx; - - Oid relOid = PG_GETARG_OID(0); - text *forkName = PG_GETARG_TEXT_P(1); - Relation rel; - char *relationpath; - char pathname[MAXPGPATH]; - int64 segcount; - int64 result = 0; + int64 result; + char pathname[MAXPGPATH]; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { + TupleDesc tupdesc; + MemoryContext oldcontext; + Oid relOid = PG_GETARG_OID(0); + text *forkName = PG_GETARG_TEXT_P(1); + /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); @@ -100,38 +99,56 @@ Datum pgfincore(PG_FUNCTION_ARGS) * every other call. */ fctx->rel = relation_open(relOid, AccessShareLock); - fctx->relationpath = relpath(fctx->rel->rd_node, forkname_to_number(text_to_cstring(forkName))); + fctx->relationpath = relpath(fctx->rel->rd_node, + forkname_to_number(text_to_cstring(forkName))); fctx->segcount = 0; -// elog(DEBUG2, "1st call : %s",fctx->relationpath); funcctx->user_fctx = fctx; + + tupdesc = CreateTemplateTupleDesc(2, false); + TupleDescInitEntry(tupdesc, (AttrNumber) 1, "relpath", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 2, "block_mem", + INT8OID, -1, 0); + + funcctx->tuple_desc = BlessTupleDesc(tupdesc); + + elog(DEBUG3, "1st call : %s",fctx->relationpath); MemoryContextSwitchTo(oldcontext); } - /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); - segcount = fctx->segcount; - relationpath = fctx->relationpath; - rel = fctx->rel; - // result - if (segcount == 0) - snprintf(pathname, MAXPGPATH, "%s", relationpath); + if (fctx->segcount == 0) + snprintf(pathname, MAXPGPATH, "%s", fctx->relationpath); else - snprintf(pathname, MAXPGPATH, "%s.%u", relationpath, segcount); + snprintf(pathname, MAXPGPATH, "%s.%u", fctx->relationpath, fctx->segcount); + + elog(DEBUG2, "pathname is %s", pathname); result = pgfincore_file(pathname); - elog(DEBUG2, "pgfincore : %lu",(unsigned long)result); + + elog(DEBUG2, "got result = %lu", (unsigned long)result); // TODO fix the %lu /* do when there is no more left */ if (result == -1) { - relation_close(rel, AccessShareLock); + relation_close(fctx->rel, AccessShareLock); + elog(DEBUG3, "last call : %s", fctx->relationpath); SRF_RETURN_DONE(funcctx); } /* or send the result */ else { + HeapTuple tuple; + Datum values[2]; + bool nulls[2]; + fctx->segcount++; - SRF_RETURN_NEXT(funcctx, Int64GetDatum(result)); + values[0] = CStringGetTextDatum(pathname); + values[1] = Int64GetDatum(result); + memset(nulls, 0, sizeof(nulls)); + tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); + elog(DEBUG1, "file %s contain %i block in linux cache memory", pathname, result); + SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); } } @@ -169,11 +186,17 @@ static int64 pgfincore_file(char *filename) { } if (st.st_size == 0) { return 0; - } + } + + /* We need to split mmap size to be sure (?) to be able to mmap */ pa = mmap(NULL, st.st_size, PROT_NONE, MAP_SHARED, fd, 0); if (pa == MAP_FAILED) { close(fd); - elog(ERROR, "Can not mmap object file : %s", filename); + elog(ERROR, + "Can not mmap object file : %s, errno = %i,%s", + filename, + errno, + strerror(errno)); } vec = calloc(1, (st.st_size+pageSize-1)/pageSize); @@ -209,7 +232,13 @@ static int64 pgfincore_file(char *filename) { // free things free(vec); - munmap(pa, (st.st_size+pageSize-1)/pageSize); + if (munmap(pa, st.st_size) == -1) { + elog(ERROR, + "Can not munmap object file : %s, errno = %i,%s", + filename, + errno, + strerror(errno)); + } close(fd); elog(DEBUG1, "pgfincore %s: %lu of %lu block in linux cache, %lu groups",filename, (unsigned long)n, (unsigned long)(st.st_size/pageSize), (unsigned long)cut); diff --git a/pgfincore_84.sql.in b/pgfincore_84.sql.in index 3b6359a..f2e9afe 100644 --- a/pgfincore_84.sql.in +++ b/pgfincore_84.sql.in @@ -1,11 +1,12 @@ SET search_path = public; -CREATE OR REPLACE FUNCTION pgfincore(regclass, text) -RETURNS setof bigint +CREATE OR REPLACE FUNCTION +pgfincore(IN regclass, IN text, OUT relpath text, OUT block_mem bigint) +RETURNS setof record AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION pgfincore(regclass) -RETURNS setof bigint +CREATE OR REPLACE FUNCTION pgfincore(IN regclass, OUT relpath text, OUT block_mem bigint) +RETURNS setof record AS 'SELECT pgfincore($1, ''main'')' LANGUAGE SQL; -- 2.39.5