Subject: Again: LOread hangs up

From: Wolf Guddat <[email-masked]>
Date: Mon, 21 Jun 93 12:54:14 MESZ

Hi !
The following is a question which i sent to you (developers) on June, 2nd.
You answered me and said: "it seems to be a bug,if you don't 
hear from us this week ask again."

Okay, two weeks have passed -here i go again

Hi everybody!

I have some problems using the Inversion File LO-Interface (the 
problems seem to be the same with the Unix File LO-Interface)
in user defined functions.
What i want to do is quite simple.
I want to store some data (which can be very large) in an Inversion 
File. So i wrote the in/out-ADT function xpr_str_in and xpr_str_out.
Writing (xpr_str_in) seems to be OK, because i found a new file named
LOxxxxxx in the .../data/base/STR directory, which has exactly the 
expected size and is protected with 0600-rights (xxxxxx stands for an integer).
But reading it causes problems. Opening this  Inversion File
seems to work, but reading doesn't (backend doesn't return);

   I tried the following too: I found the example icopy.c in the directory-tree
   of postgres. So i copied a standard unix-file into a inversion file using
   icopy. It seemed to work. But when i tried to read it the LOread-call returned
   0 Bytes read. (This is surprising, because copying the Inversion-File back
   to a unix-File using icopy works.)
   Analyzing the icopy.c Code surprised me again, because in the section
   where it wants to create the new Inversion-File it creates a UNIX-File.
   Is it possible that icopy.c is some old code from former days where
   the Inversion-System didn't work and where it was simulated with the UNIX-system?

After one week of puzzling i've got no more ideas what i'm doing wrong. So
i would be very very glad if someone could give me a hint. (I have not very
much time because the countdown for my work began)

My resources are: Ultrix 4.3 on DECstation, Postgres 4.1

Thanks Wolf

Here is my code: (1. C-Code, 2. Monitor Commands, 3. Checking)

************************************************
************************************************
************************************************
************* 1. the C-Code for the functions

#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "postgres.h"
#include "palloc.h"
#include "builtins.h"
#include "libpq-fe.h"
#include "libpq-fs.h"
#include "pg_lobj.h"

/* This is a nonpostgres unix-file for some fprintf-checks */
#define EF_NAME "/user/sonst/wfguddat/XPR2PG/str_loinv.err"

/* This is the Inversion-File i want to read and write */
#define INV_FNAME "/inv_lo1"

/* Prototypes  */
struct varlena *xpr_str_in ();
char *xpr_str_out ();

struct varlena *xpr_str_in (str)
  char *str;
{
  long len;
  struct varlena *buffer;
  FILE *ef;
  int inv_fd;
  int n_bytes;
  int retval;
  struct varlena *result;
  struct varlena dummy[1];
  struct varlena *vl;
  int MODE;

ef = fopen (EF_NAME, "w");
fprintf (ef, "xpr_str_in:\n");
fprintf (ef, "str=[%s]\n", str);
fprintf (ef, "strlen(str)=%d\n", strlen(str));
fclose (ef);
  dummy->vl_len = sizeof(long)+1;
  dummy->vl_dat[0] = '\0';
  buffer = (struct varlena *) palloc (len =(sizeof(long) + strlen(str) +1)); 
  if (!buffer) { goto NOMEM; }
  VARSIZE(buffer) = len;
  strcpy (VARDATA(buffer), str);
ef = fopen (EF_NAME, "a");
fprintf (ef, "VARSIZE(buffer)=%d\n", VARSIZE(buffer));
fclose (ef);

  MODE=(INV_READ|INV_WRITE);
  inv_fd = LOcreat (INV_FNAME, MODE , Inversion);

ef = fopen (EF_NAME, "a");
fprintf (ef, "created [%s], inv_fd=%d\n", INV_FNAME, inv_fd);
fclose (ef);
  if (inv_fd<0) { goto TROUBLE; }
  n_bytes = LOwrite (inv_fd, buffer);
ef = fopen (EF_NAME, "a");
fprintf (ef, "written bytes=%d\n", n_bytes);
fclose (ef);
  retval = LOclose (inv_fd);
ef = fopen (EF_NAME, "a");
fprintf (ef, "closing Inversion-File %d returns=%d\n", inv_fd, retval);
fclose (ef);

  if (retval<0) { goto TROUBLE; }
  if (n_bytes < 0) { goto NOWRT; }

  result = (struct varlena *) palloc (len=(sizeof(long) + strlen(INV_FNAME)+1));
  if (!result) { goto NOMEM; }
  VARSIZE(result) = len;
  strcpy (VARDATA(result), INV_FNAME);
ef = fopen (EF_NAME, "a");
fprintf (ef, "VARSIZE(result)=[%d]\n", VARSIZE(result));
fprintf (ef, "VARDATA(result)=[%s]\n", VARDATA(result));
fclose (ef);

  return (result);

NOMEM:
  ef = fopen (EF_NAME, "a");
  fprintf (ef, "no memory allocated\n");
  fclose (ef);
  return (dummy);
NOWRT:
  ef = fopen (EF_NAME, "a");
  fprintf (ef, "write failed\n");
  fclose (ef);
  return (dummy);
TROUBLE:
  ef = fopen (EF_NAME, "a");
  fprintf (ef, "other trouble\n");
  fclose (ef);
  return (dummy);

} /* xpr_string_in */

char *xpr_str_out (arg)
  struct varlena *arg; /* postgresinterne Darstellung eines Strings */
{
  struct varlena *vl;
  int    inv_fd;
  int n_read;
  int retval;
  char *result;
  int len;
  FILE *ef;
  char dummy[1];
  int MODE;

  dummy[0]='\0';

ef = fopen (EF_NAME, "a");
fprintf (ef, "***********************************\n");
fprintf (ef, "xpr_str_out:\n");
fprintf (ef, "VARSIZE(arg)=[%d]\n", VARSIZE(arg));
fprintf (ef, "VARDATA(arg)=[%s]\n", VARDATA(arg));
fclose (ef);

  MODE =INV_READ; 
  inv_fd = LOopen (INV_FNAME, MODE );
ef = fopen (EF_NAME, "a");
fprintf (ef, "opening: name=[%s], inv_fd=%d\n", INV_FNAME, inv_fd);
fclose (ef);
  if (inv_fd < 0) {goto TROUBLE; }

  len=10;
ef = fopen (EF_NAME, "a");
fprintf (ef, "trying to read %d bytes...\n", len);
fclose (ef);
  vl = LOread (inv_fd, len); 
ef = fopen (EF_NAME, "a");
fprintf (ef, "have read %d bytes\n", vl->vl_len-sizeof(long));
fprintf (ef, "VARSIZE(vl)=[%d]\n", VARSIZE(vl));
fprintf (ef, "VARDATA(vl)=[%s]\n", VARDATA(vl));
fclose (ef);

  retval = LOclose (inv_fd);
ef = fopen (EF_NAME, "a");
fprintf (ef, "closing Inversion-File %d returns=%d\n", inv_fd, retval);
fclose (ef);
  if (retval<0) { goto TROUBLE; }
  if (VARSIZE(vl)-sizeof(long)==0) { goto NOREAD; }

  strcpy (result, VARDATA (vl)); 
ef = fopen (EF_NAME, "a");
fprintf (ef, "result=[%s]\n", result);
fclose (ef);
  return (result);

NOREAD:
  ef = fopen (EF_NAME, "a");
  fprintf (ef, "read failed\n");
  fclose (ef);
  return (dummy);

TROUBLE:
  ef = fopen (EF_NAME, "a");
  fprintf (ef, "other trouble\n");
  fclose (ef);
  return (dummy);

} /* xpr_string_out */

************************************************
************************************************
************************************************
************* 2. the monitor commands

createdb STR
monitor STR

define function xpr_str_in (language = "c",
                            returntype = XPR_STR,
                            trusted = t
                           )
                           arg is (char16)
                           as "/user/sonst/wfguddat/XPR2PG/str_loinv.o"

define function xpr_str_out (language ="c",
                             returntype = char16,
                             trusted = t
                            )
                            arg is (XPR_STR)
                            as "/user/sonst/wfguddat/XPR2PG/str_loinv.o"

define type XPR_STR (internallength = variable,
                     externallength = variable,
                     input=xpr_str_in,
                     output = xpr_str_out
                    )

create S (s=XPR_STR)

append S (s="12345678901234567890")

retrieve (S.all)

************************************************
************************************************
************************************************
************* 3. some printf checks during my actions 

xpr_str_in:
str=[12345678901234567890]
strlen(str)=20
VARSIZE(buffer)=25
created [/inv_lo1], inv_fd=0
written bytes=21
closing Inversion-File 0 returns=0
VARSIZE(result)=[13]
VARDATA(result)=[/inv_lo1]
***********************************
xpr_str_out:
VARSIZE(arg)=[13]
VARDATA(arg)=[/inv_lo1]
opening: name=[/inv_lo1], inv_fd=0
trying to read 10 bytes...