2009/7/4 Greg Stark <[email protected]>: > On Sat, Jul 4, 2009 at 10:31 PM, Greg Stark<[email protected]> wrote: >> It's pretty hard to guess where your bug is sitting here with no code >> and no idea even what you've done to trigger it. >>
see attachment - sorry, comments are czech >> At a guess there someplace you haven't detoasted a datum that had to >> be detoasted. But like I said that's just a guess. >> I have a problem with "in" function. So I have not a control over process. I return a varlena value, that's all. > > Actually on further thought I think this smells like a memory > management bug. Maybe you've either you've prematurely freed this data > structure or realloc'd it without tracking the new pointer and have > returned a pointer to the freed object. > I'll look on it. It looks strange. I don't use pfree. 2x or 3x use repalloc. regards Pavel Stehule > > -- > greg > http://mit.edu/~gsstark/resume.pdf >
#include "postgres.h"
#include <float.h>
#include <math.h>
#include "kokes.h"
#include "access/gist.h"
#include "access/skey.h"
#include "lib/stringinfo.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "libpq/pqformat.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(kokes_in);
PG_FUNCTION_INFO_V1(kokes_out);
PG_FUNCTION_INFO_V1(kokes_send);
PG_FUNCTION_INFO_V1(kokes_recv);
Datum kokes_in(PG_FUNCTION_ARGS);
Datum kokes_out(PG_FUNCTION_ARGS);
Datum kokes_send(PG_FUNCTION_ARGS);
Datum kokes_recv(PG_FUNCTION_ARGS);
extern int kokes_yyparse();
extern void kokes_scanner_init(const char *str);
extern void kokes_scanner_finish(void);
static void print_double_list(StringInfo str, double *data, unsigned long
cntpnt);
static void print_short_list(StringInfo str, short int *data, unsigned long
cntpnt);
static char *print_info(StringInfo str, char *buf);
static char *print_infos(StringInfo str, char *buf);
static char *print_atrs(StringInfo str, char *buf);
KokesData *kokes;
#define PORTABLE_SERIALIZATION
Datum
kokes_in(PG_FUNCTION_ARGS)
{
char *str;
str = PG_GETARG_CSTRING(0);
kokes_scanner_init(str);
if (kokes_yyparse() != 0)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("bogus input")));
elog(NOTICE, "KOKES SIZE %d, pointer: %d, LEN: %d", VARSIZE( kokes), kokes,
kokes->vl_len_);
kokes_scanner_finish();
PG_RETURN_KokesData(kokes);
}
Datum
kokes_out(PG_FUNCTION_ARGS)
{
Kokes kokes;
StringInfoData buf;
char *readbuf;
initStringInfo(&buf);
kokes = PG_GETARG_KokesData(0);
elog(NOTICE, "1");
appendStringInfo(&buf, "((%u ", kokes->status);
elog(NOTICE, "2");
appendStringInfo(&buf, "(%ld %ld %ld %ld) ", kokes->OOO[0], kokes->OOO[1],
kokes->OOO[2], kokes->OOO[3]);
appendStringInfo(&buf, "%lu %lu %d %d)", kokes->key, kokes->cntpnt,
kokes->layer, kokes->alias);
elog(NOTICE, ">>> %s", buf.data);
print_double_list(&buf, KOKES_X_ARRAY(kokes), kokes->cntpnt);
print_double_list(&buf, KOKES_Y_ARRAY(kokes), kokes->cntpnt);
print_short_list(&buf, KOKES_SP_ARRAY(kokes), kokes->cntpnt);
readbuf = print_infos(&buf, KOKES_INF_ARRAY(kokes));
print_atrs(&buf, readbuf);
elog(NOTICE, "3");
appendStringInfoChar(&buf, ')');
PG_FREE_IF_COPY(kokes, 0);
PG_RETURN_CSTRING(buf.data);
}
static void
print_double_list(StringInfo str, double *data, unsigned long cntpnt)
{
int i;
appendStringInfo(str, " (");
for (i = 0; i < cntpnt; i++)
if (i > 0)
appendStringInfo(str, " %g", data[i]);
else
appendStringInfo(str, "%g", data[i]);
appendStringInfoChar(str, ')');
}
static void
print_short_list(StringInfo str, short int *data, unsigned long cntpnt)
{
int i;
appendStringInfo(str, " (");
for (i = 0; i < cntpnt; i++)
if (i > 0)
appendStringInfo(str, " %d", data[i]);
else
appendStringInfo(str, "%d", data[i]);
appendStringInfoChar(str, ')');
}
static char *
print_info(StringInfo str, char *buf)
{
GINFLEN ginflen = *((GINFLEN *) buf);
int processed_chars = 0;
buf += sizeof(GINFLEN);
appendStringInfoChar(str, '(');
/* pokud ma bod informace zobraz je */
if (*buf != '\0')
{
while (processed_chars < ginflen)
{
if (processed_chars != 0)
appendStringInfoChar(str, ' ');
appendStringInfo(str, "%c='", *buf++);
processed_chars += 1;
while (*buf != '\t' && *buf != '\0')
{
appendStringInfoChar(str, *buf++);
processed_chars += 1;
}
appendStringInfoChar(str, '\'');
if (*buf++ == '\0')
break;
processed_chars += 1;
}
}
appendStringInfoChar(str, ')');
return buf;
}
static char *
print_infos(StringInfo str, char *buf)
{
GATRLEN gatrlen = *((GATRLEN *) buf);
char *endbuf;
buf += sizeof(GATRLEN);
endbuf = buf + gatrlen;
appendStringInfo(str, " (");
while (buf < endbuf)
{
buf = print_info(str, buf);
}
appendStringInfoChar(str, ')');
return buf;
}
static char *
print_atrs(StringInfo str, char *buf)
{
GATRLEN gatrlen = *((GATRLEN *) buf);
int processed_chars = 0;
buf += sizeof(GATRLEN);
appendStringInfo(str, " (");
while (processed_chars++ < gatrlen)
{
char c = *buf++;
switch (c)
{
case '\0':
appendStringInfoChar(str, '\'');
break;
case '=':
appendStringInfo(str, "='");
break;
case '\n':
appendStringInfo(str, "' ");
break;
default:
appendStringInfoChar(str, c);
}
}
appendStringInfoChar(str, ')');
return buf;
}
/*
* Serializace je jednoducha - prenese se pole bytu.
* Tato serializace je funkci pouze pri shode uladani poradi bajtu!
* tj. je nezbytne aby server bezel na stejne platforme (z pohledu
* poradi ukladni bajtu) jako klient - pokud by tato podminka neplatila
* musel by se polozky struktury serializovat samostatne!!
* coz by nebyl az takovy problem a patrne by to nebylo nijak zvlast
* poznat na vykonu a bylo by to prenositelne, tj. do dalsi verze
* pridat variantu
*/
#define FILLINT(kokes, buf, field) kokes->field = pq_getmsgint(buf,
sizeof(kokes->field))
#define PUTINT(kokes, buf, field) pq_sendint(&buf, kokes->field,
sizeof(kokes->field))
Datum
kokes_recv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
Kokes kokes;
#ifdef PORTABLE_SERIALIZATION
unsigned long cntpnt;
int i;
size_t size;
double *aux_dp;
short int *aux_sp;
#endif
#ifndef PORTABLE_SERIALIZATION
kokes = palloc(buf->len + VARHDRSZ);
pq_copymsgbytes(buf, VARDATA(kokes), buf->len);
SET_VARSIZE(kokes, buf->len + VARHDRSZ);
#else
cntpnt = pq_getmsgint(buf, sizeof(unsigned long));
size = offsetof(KokesData, data[0]) + (2 * sizeof(double)*cntpnt)
+ sizeof(short int)*cntpnt;
kokes = (Kokes) palloc(size);
kokes->cntpnt = cntpnt;
FILLINT(kokes, buf, status);
FILLINT(kokes, buf, key);
FILLINT(kokes, buf, layer);
FILLINT(kokes, buf, alias);
FILLINT(kokes, buf, reserva);
FILLINT(kokes, buf, OOO[0]);
FILLINT(kokes, buf, OOO[1]);
FILLINT(kokes, buf, OOO[2]);
FILLINT(kokes, buf, OOO[3]);
aux_dp = KOKES_X_ARRAY(kokes);
for (i = 0; i < kokes->cntpnt; i++)
*aux_dp++ = pq_getmsgfloat8(buf);
aux_dp = KOKES_Y_ARRAY(kokes);
for (i = 0; i < kokes->cntpnt; i++)
*aux_dp++ = pq_getmsgfloat8(buf);
aux_sp = KOKES_SP_ARRAY(kokes);
for (i = 0; i < kokes->cntpnt; i++)
*aux_sp++ = pq_getmsgint(buf, sizeof(short int));
#endif
PG_RETURN_KokesData(kokes);
}
Datum
kokes_send(PG_FUNCTION_ARGS)
{
Kokes kokes = PG_GETARG_KokesData(0);
StringInfoData buf;
#ifdef PORTABLE_SERIALIZATION
int i;
double *aux_dp;
short int *aux_sp;
#endif
pq_begintypsend(&buf);
#ifndef PORTABLE_SERIALIZATION
pq_sendbytes(&buf, VARDATA(kokes),
VARSIZE(kokes) - VARHDRSZ);
#else
PUTINT(kokes, buf, cntpnt);
PUTINT(kokes, buf, status);
PUTINT(kokes, buf, key);
PUTINT(kokes, buf, layer);
PUTINT(kokes, buf, alias);
PUTINT(kokes, buf, reserva);
PUTINT(kokes, buf, OOO[0]);
PUTINT(kokes, buf, OOO[1]);
PUTINT(kokes, buf, OOO[2]);
PUTINT(kokes, buf, OOO[3]);
aux_dp = KOKES_X_ARRAY(kokes);
for (i = 0; i < kokes->cntpnt; i++)
pq_sendfloat8(&buf, *aux_dp++);
aux_dp = KOKES_Y_ARRAY(kokes);
for (i = 0; i < kokes->cntpnt; i++)
pq_sendfloat8(&buf, *aux_dp++);
aux_sp = KOKES_SP_ARRAY(kokes);
for (i = 0; i < kokes->cntpnt; i++)
pq_sendint(&buf, *aux_sp++, sizeof(short int));
#endif
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
/*
* Pro gepro Pavel Stěhule, srpen-listopad 2008
*/
typedef struct KokesData
{
int32 vl_len_; /* varlena header */
unsigned short status;
long OOO[4];
unsigned long key;
unsigned long cntpnt;
unsigned short layer;
unsigned short alias;
unsigned long reserva;
char data[1];
} KokesData;
typedef struct KokesData *Kokes;
typedef unsigned short GINFLEN; /* typ délka informace na jednom bodu */
typedef unsigned GATRLEN; /* typ délka atributu k objektu a všech
informací v objektu */
#define KOKES_X_ARRAY(kokes) ((double *) kokes->data)
#define KOKES_Y_ARRAY(kokes) ((double *) (KOKES_X_ARRAY(kokes) +
kokes->cntpnt))
#define KOKES_SP_ARRAY(kokes) ((short int *) (KOKES_Y_ARRAY(kokes) +
kokes->cntpnt))
#define KOKES_INF_ARRAY(kokes) ((char*) (KOKES_SP_ARRAY(kokes) +
kokes->cntpnt))
#define DatumGetKokesData(x) ((KokesData*)DatumGetPointer(x))
#define PG_GETARG_KokesData(x) DatumGetKokesData(
PG_DETOAST_DATUM(PG_GETARG_DATUM(x)) )
#define PG_RETURN_KokesData(x) PG_RETURN_POINTER(x)
/*
* Informace jsou serializovany do nasledujiciho formatu:
* INFPNT := GINFLEN _inf \t _inf \t _inf [ .. ] \0 - informace k
jednomu bodu
* INFALL := GATRLEN INFPNT INFPNT INFPNT [ .. ]
*
*/
typedef struct _inf
{
char name; /* a..zA..Z_, pokud bod nema informace
obsahuje 0 */
char *value; /* muze byt "" nebo NULL */
struct _inf *next; /* odkaz na dalsi informaci */
} _inf;
/*
* Atributy jsou serializovany do nasledujiciho formatu:
* ATR := char[] '=' char[]
* ATRALL := GATRLEN ATR \n ATR \n ATR \0
*
*/
typedef struct _atr
{
char *name; /* (a..zA..Z0..9}{1,256}, název
atributu */
char *value; /* muže být "" nebo NULL */
struct _atr *next; /* odkaz na další atribut */
} _atr;
unsigned alloclen_info_atr(struct _inf **inf, struct _atr *atr, unsigned
cntpnt);
void copy_and_add_info(struct _inf **inf, struct _atr *atr, Kokes kokes);
parse.y
Description: Binary data
-- Sent via pgsql-hackers mailing list ([email protected]) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers
