Re: C set return function differences on 8.0?]] - Mailing list pgsql-interfaces
From | Tim Jackson |
---|---|
Subject | Re: C set return function differences on 8.0?]] |
Date | |
Msg-id | 42D2E683.5080302@ints.com Whole thread Raw |
Responses |
Re: C set return function differences on 8.0?]]
|
List | pgsql-interfaces |
Michael Fuhr wrote: >Where did you look for a core dump? If one was made then it'll >probably be somewhere under $PGDATA (e.g., $PGDATA/base/XXX/core) >unless your system is configured to put core dumps elsewhere. > > > I was able to get the core dump by adding 'ulimit -c unlimited' to the start script (thanks Tom) It is huge (14 megs) One interesting thing happened once the core dump is created. Now if I re connect to the data base and rerun the select on the view after it has crashed once it will select the view. >If there isn't a core dump then you could add some debugging ereport() >calls to your code so you can find out where the crash is happening. >Another possibility might be to attach a debugger to the backend. > > > If you can tell me how to do that. I tried attaching gdb to the running servers pid and it seems to lock up the server. >So your C function calls these library functions, which query some >other data source and return strings back to you, right? How are >these strings returned -- as char * values? Can you at least post >your code? > > > The full so code is 4000 lines and caused the news group to reject the mail , but here is the basic format with the piece that builds the record replaced by hardcoded values. /*******************************/ // // Program: call_good.c // // Listing Date: 07/08/2005 // /*******************************/ #include "server/postgres.h" #include "server/fmgr.h" #include "server/funcapi.h" #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <string.h> #include <ctype.h> #include <time.h> #define TRUE 1 #define FALSE 0 #define OK 0 #define ERROR1 (-1) #define YES 1 #define NO 0 #define DATA1 2 #define MAYBE 2 char record[1024 * 1024]; char buffer[256]; unsigned char * bufptr = (unsigned char *)buffer; char buffer1[256]; unsigned char * bufptr1 = (unsignedchar *)buffer1; char buffer2[256]; unsigned char * bufptr2 = (unsigned char *)buffer2; char buffer3[256]; unsignedchar * bufptr3 = (unsigned char *)buffer3; int count, count1; long CurrentSize; char request[8192]; char response[512]; char typedefin[1024]; int max_fields; int field_lengths[256]; char field_types[256][16]; char *record_add; char parsed[256]; char *select_add; char *from_add; char *where_add; char *end_add; char select1[8192]; char from[512]; char where[512]; FILE *stream; FILE *stream1; char filein[128]; char fileout[128]; char filename_out[128]; int num_targets_work; intnum_targets_index; int chunk_amount = 5; int chunk_counter; int fileOpen; FuncCallContext *funcctx; int call_cntr; int max_calls; TupleDesc tupdesc; TupleTableSlot *slot; AttInMetadata *attinmeta; /***********************************/ // select_more_data /***********************************/ int tselect_more_data (void) { int recordFound; memset (record, 0, sizeof(record)); sprintf (buffer1, "%s|%s|%s|%s|", "6","6666.01","6-6 Wide","Y"); strcat (record, buffer1); sprintf (buffer1,"%s|%s|%s|%s|", "7","7777.01","7-6 Wide","Y"); strcat (record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|","8","888888.0001","8-6 Wide","Y"); strcat (record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|", "9","9999.01","9-6Wide","Y"); strcat (record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|", "10","1010.01","10-6Wide","Y"); strcat (record, buffer1); count = 5; if (count) recordFound = DATA1; return (recordFound); } /***********************************/ // select_data /***********************************/ int tselect_data (void) { int recordFound; memset (record, 0, sizeof(record)); sprintf (buffer1, "%s|%s|%s|%s|", "1","1111.01","1-6 Wide","Y"); strcat(record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|", "2","2222.01","2-6 Wide","Y"); strcat (record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|", "3","3333.01","3-6 Wide","Y"); strcat (record, buffer1); sprintf(buffer1, "%s|%s|%s|%s|", "4"," 4444.01","4-6 Wide","Y"); strcat (record, buffer1); sprintf (buffer1, "%s|%s|%s|%s|","5","5555.01","5-8 Wide","Y"); strcat (record, buffer1); count = 5; if (count) recordFound = DATA1; return (recordFound); } /***********************************/ // select_field_lengths /***********************************/ int tselect_field_lengths (void) { int recordFound; int len; CurrentSize = 10; len = 3; field_lengths[0] = len * 2 + 1; strcpy (field_types[0], "numeric"); len = 4; field_lengths[1] = len * 2 + 1; strcpy (field_types[1], "numeric"); len = 30; field_lengths[2] = len; strcpy (field_types[2], "string"); len = 1; field_lengths[3] = len; strcpy (field_types[3], "string"); max_fields = 4; recordFound = DATA1; return (recordFound); } /***********************************/ // parse_record /***********************************/ void tparse_record (void) { char *ptr; char *ptr1; ptr = record_add; ptr1 = strchr (ptr, '|'); if (ptr1) { *ptr1 = 0; strcpy (parsed,ptr); } record_add= ++ptr1; } /***********************************/ // parse_sql /***********************************/ int tparse_sql (char * request) { int func; select_add = from_add = where_add = end_add = 0L; memset ( select1, 0, sizeof(select1)); memset ( from, 0, sizeof(from)); memset ( where, 0, sizeof(where)); select_add = strstr(request, "SELECT "); if (select_add == 0) select_add = strstr(request, "select "); if (select_add != 0) { from_add = strstr(request, "FROM "); if (from_add == 0) from_add = strstr(request, "from "); } where_add = strstr(request, "WHERE "); if (where_add == 0) where_add = strstr(request, "where "); if (select_add != 0) { end_add = select_add+strlen(request); func = 40; } else { func= 999; return func; } if (select_add != 0) { memcpy ( select1, select_add, from_add-select_add); if (where_add == 0) { memcpy ( from, from_add, end_add-from_add); } else if (where_add) { memcpy ( from, from_add,where_add-from_add); memcpy ( where, where_add, end_add-where_add); } } return func; } /************************************/ PG_FUNCTION_INFO_V1 (call_good); Datum call_good (PG_FUNCTION_ARGS) { int i, func, retval; // stuff done only on the first call of the function if (SRF_IS_FIRSTCALL()) { MemoryContext oldcontext; text *t = PG_GETARG_TEXT_P(0); text *t1 = PG_GETARG_TEXT_P(1); memset (request, 0, sizeof(request)); strncpy (request, t->vl_dat, t->vl_len- VARHDRSZ); memset (typedefin, 0, sizeof(typedefin)); strncpy (typedefin, t1->vl_dat, t1->vl_len- VARHDRSZ); // create a function context for cross-call persistence funcctx = SRF_FIRSTCALL_INIT(); // switch to memory context appropriate for multiple function calls oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); // Build a tuple description for a incoming type tuple tupdesc = RelationNameGetTupleDesc(typedefin); // allocate a slot for a tulpe with this tupdesc slot = TupleDescGetSlot(tupdesc); // assign slot to function context funcctx->slot = slot; // Generate attribute metadata needed later to produce // tupples from raw C strings attinmeta = TupleDescGetAttInMetadata(tupdesc); funcctx->attinmeta = attinmeta; MemoryContextSwitchTo(oldcontext); strcpy (fileout, "pfxG"); sprintf (filename_out, "/tmp/%s.rsp", fileout); // rf if ((stream1 = fopen (filename_out, "wb")) == NULL) { return 1; } if ((stream =fopen ("/tmp/call_good.log", "a+")) == NULL) { return 1; } fprintf (stream1,"Call_Good\n"); fprintf (stream1,"request>%s<\n",request); fprintf (stream1,"file: %s\n",typedefin); func = tparse_sql (request); record_add = 0; tselect_field_lengths(); fprintf (stream,"NumRecs = %ld NumFields = %d\n", CurrentSize, max_fields); for (i=0; i < max_fields; i++) { fprintf (stream1,"Field: %3d Type: %-8s Length: %d\n", i,field_types[i],field_lengths[i]); } switch (func) { case 40: if (select_add) { fprintf (stream1,"select: %s\n",select1); fprintf (stream1, "from: %s\n",from); if (where_add) { fprintf (stream1, "where: %s\n",where); } } funcctx->max_calls = CurrentSize; // Go get first chunk of records from file retval = tselect_data(); if (retval != DATA1) { strcpy (record, "Not Found\n"); fwrite(record, strlen(record), 1, stream1); } break; case 999: strcpy(record, "Invalid Statement"); fwrite (record, strlen(record), 1, stream1); break; default: strcpy (record, "Invalid"); fwrite (record, strlen(record), 1, stream1); retval = NO; break; } fprintf (stream,"Count = %ld Data = %.50s\n",CurrentSize,record); fprintf (stream,"File: %s Type: %s\n",filein,typedefin); record_add = record; chunk_counter = chunk_amount; fflush (stream); } // stuff done on every call of the function funcctx= SRF_PERCALL_SETUP(); call_cntr = funcctx->call_cntr; max_calls = funcctx->max_calls; slot = funcctx->slot; attinmeta = funcctx->attinmeta; if (call_cntr < max_calls) { char **values; HeapTuple tuple; Datum result; if (call_cntr == chunk_counter) { // Go get next chunk of records from file retval = tselect_more_data(); record_add = record; chunk_counter += chunk_amount; } // Prepare a values array for storage in our slot. // This should be an array of C strings which will // be processed later by the appropriate "in" functions. values = (char **) palloc(max_fields * sizeof(char *)); for (i=0; i < max_fields; i++) { values[i] = (char *) palloc(field_lengths[i] * sizeof(char)); } for (i=0; i < max_fields; i++) { tparse_record(); if (strlen(parsed) == 0 && strcmp(field_types[i],"date") == 0) { strcpy (values[i], "01/01/1980"); } else { strcpy (values[i], parsed); } } // build a tuple tuple = BuildTupleFromCStrings(attinmeta, values); // make the tuple into a datum result = TupleGetDatum(slot,tuple); // result = HeapTupleGetDatum(tuple); // Clean up (this is not actually necessary) for (i=0; i < max_fields; i++) { pfree(values[i]); } pfree(values); fflush (stream); SRF_RETURN_NEXT(funcctx, result); } else // do when there is no more left { if (fileOpen) { fprintf (stream, "EOD Set5\n"); fileOpen = 0; } fprintf (stream1,"DONE:call_cntr= %d max_calls= %d\n", call_cntr,max_calls); fclose (stream1); fclose(stream); SRF_RETURN_DONE(funcctx); } }
pgsql-interfaces by date: