diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-07-09 06:22:35 +0000 |
commit | d31084e9d1118b25fd16580d9d8c2924b5740dff (patch) | |
tree | 3179e66307d54df9c7b966543550e601eb55e668 /src/backend/libpq/be-fsstubs.c | |
download | postgresql-PG95-1_01.tar.gz postgresql-PG95-1_01.zip |
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/backend/libpq/be-fsstubs.c')
-rw-r--r-- | src/backend/libpq/be-fsstubs.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c new file mode 100644 index 00000000000..e32cd3b474b --- /dev/null +++ b/src/backend/libpq/be-fsstubs.c @@ -0,0 +1,351 @@ +/*------------------------------------------------------------------------- + * + * be-fsstubs.c-- + * support for filesystem operations on large objects + * + * Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.1.1.1 1996/07/09 06:21:30 scrappy Exp $ + * + * NOTES + * This should be moved to a more appropriate place. It is here + * for lack of a better place. + * + * Builtin functions for open/close/read/write operations on large objects. + * + * These functions operate in the current portal variable context, which + * means the large object descriptors hang around between transactions and + * are not deallocated until explicitly closed, or until the portal is + * closed. + *------------------------------------------------------------------------- + */ +#include "postgres.h" +#include "lib/dllist.h" +#include "libpq/libpq.h" +#include "libpq/libpq-fs.h" +#include "utils/mcxt.h" +#include "utils/palloc.h" + +#include "storage/fd.h" /* for O_ */ +#include "storage/large_object.h" + +#include "utils/elog.h" +#include "libpq/be-fsstubs.h" + +/*#define FSDB 1*/ +#define MAX_LOBJ_FDS 256 + +static LargeObjectDesc *cookies[MAX_LOBJ_FDS]; + +static GlobalMemory fscxt = NULL; + + +static int newLOfd(LargeObjectDesc *lobjCookie); +static void deleteLOfd(int fd); + + +/***************************************************************************** + * File Interfaces for Large Objects + *****************************************************************************/ + +int +lo_open(Oid lobjId, int mode) +{ + LargeObjectDesc *lobjDesc; + int fd; + MemoryContext currentContext; + +#if FSDB + elog(NOTICE,"LOopen(%d,%d)",lobjId,mode); +#endif + + if (fscxt == NULL) { + fscxt = CreateGlobalMemory("Filesystem"); + } + currentContext = MemoryContextSwitchTo((MemoryContext)fscxt); + + lobjDesc = inv_open(lobjId, mode); + + if (lobjDesc == NULL) { /* lookup failed */ + MemoryContextSwitchTo(currentContext); +#if FSDB + elog(NOTICE,"cannot open large object %d", lobjId); +#endif + return -1; + } + + fd = newLOfd(lobjDesc); + + /* switch context back to orig. */ + MemoryContextSwitchTo(currentContext); + + return fd; +} + +int +lo_close(int fd) +{ + MemoryContext currentContext; + + if (fd >= MAX_LOBJ_FDS) { + elog(WARN,"lo_close: large obj descriptor (%d) out of range", fd); + return -2; + } + if (cookies[fd] == NULL) { + elog(WARN,"lo_close: invalid large obj descriptor (%d)", fd); + return -3; + } +#if FSDB + elog(NOTICE,"LOclose(%d)",fd); +#endif + + Assert(fscxt != NULL); + currentContext = MemoryContextSwitchTo((MemoryContext)fscxt); + + inv_close(cookies[fd]); + + MemoryContextSwitchTo(currentContext); + + deleteLOfd(fd); + return 0; +} + +/* + * We assume the large object supports byte oriented reads and seeks so + * that our work is easier. + */ +int +lo_read(int fd, char *buf, int len) +{ + Assert(cookies[fd]!=NULL); + return inv_read(cookies[fd], buf, len); +} + +int +lo_write(int fd, char *buf, int len) +{ + Assert(cookies[fd]!=NULL); + return inv_write(cookies[fd], buf, len); +} + + +int +lo_lseek(int fd, int offset, int whence) +{ + if (fd >= MAX_LOBJ_FDS) { + elog(WARN,"lo_seek: large obj descriptor (%d) out of range", fd); + return -2; + } + return inv_seek(cookies[fd], offset, whence); +} + +Oid +lo_creat(int mode) +{ + LargeObjectDesc *lobjDesc; + MemoryContext currentContext; + Oid lobjId; + + if (fscxt == NULL) { + fscxt = CreateGlobalMemory("Filesystem"); + } + + currentContext = MemoryContextSwitchTo((MemoryContext)fscxt); + + lobjDesc = inv_create(mode); + + if (lobjDesc == NULL) { + MemoryContextSwitchTo(currentContext); + return InvalidOid; + } + + lobjId = lobjDesc->heap_r->rd_id; + + inv_close(lobjDesc); + + /* switch context back to original memory context */ + MemoryContextSwitchTo(currentContext); + + return lobjId; +} + +int +lo_tell(int fd) +{ + if (fd >= MAX_LOBJ_FDS) { + elog(WARN,"lo_tell: large object descriptor (%d) out of range",fd); + return -2; + } + if (cookies[fd] == NULL) { + elog(WARN,"lo_tell: invalid large object descriptor (%d)",fd); + return -3; + } + return inv_tell(cookies[fd]); +} + +int +lo_unlink(Oid lobjId) +{ + return (inv_destroy(lobjId)); +} + +/***************************************************************************** + * Read/Write using varlena + *****************************************************************************/ + +struct varlena * +LOread(int fd, int len) +{ + struct varlena *retval; + int totalread = 0; + + retval = (struct varlena *)palloc(sizeof(int32) + len); + totalread = lo_read(fd, VARDATA(retval), len); + VARSIZE(retval) = totalread + sizeof(int32); + + return retval; +} + +int LOwrite(int fd, struct varlena *wbuf) +{ + int totalwritten; + int bytestowrite; + + bytestowrite = VARSIZE(wbuf) - sizeof(int32); + totalwritten = lo_write(fd, VARDATA(wbuf), bytestowrite); + return totalwritten; +} + +/***************************************************************************** + * Import/Export of Large Object + *****************************************************************************/ + +/* + * lo_import - + * imports a file as an (inversion) large object. + */ +Oid +lo_import(text *filename) +{ + int fd; + int nbytes, tmp; +#define BUFSIZE 1024 + char buf[BUFSIZE]; + LargeObjectDesc *lobj; + Oid lobjOid; + + /* + * open the file to be read in + */ + fd = open(VARDATA(filename), O_RDONLY, 0666); + if (fd < 0) { /* error */ + elog(WARN, "lo_import: can't open unix file\"%s\"\n", filename); + } + + /* + * create an inversion "object" + */ + lobj = inv_create(INV_READ|INV_WRITE); + if (lobj == NULL) { + elog(WARN, "lo_import: can't create inv object for \"%s\"", + VARDATA(filename)); + } + + /* + * the oid for the large object is just the oid of the relation + * XInv??? which contains the data. + */ + lobjOid = lobj->heap_r->rd_id; + + /* + * read in from the Unix file and write to the inversion file + */ + while ((nbytes = read(fd, buf, BUFSIZE)) > 0) { + tmp = inv_write(lobj, buf, nbytes); + if (tmp < nbytes) { + elog(WARN, "lo_import: error while reading \"%s\"", + VARDATA(filename)); + } + } + + (void) close(fd); + (void) inv_close(lobj); + + return lobjOid; +} + +/* + * lo_export - + * exports an (inversion) large object. + */ +int4 +lo_export(Oid lobjId, text *filename) +{ + int fd; + int nbytes, tmp; +#define BUFSIZE 1024 + char buf[BUFSIZE]; + LargeObjectDesc *lobj; + + /* + * create an inversion "object" + */ + lobj = inv_open(lobjId, INV_READ); + if (lobj == NULL) { + elog(WARN, "lo_export: can't open inv object %d", + lobjId); + } + + /* + * open the file to be written to + */ + fd = open(VARDATA(filename), O_CREAT|O_WRONLY, 0666); + if (fd < 0) { /* error */ + elog(WARN, "lo_export: can't open unix file\"%s\"", + VARDATA(filename)); + } + + /* + * read in from the Unix file and write to the inversion file + */ + while ((nbytes = inv_read(lobj, buf, BUFSIZE)) > 0) { + tmp = write(fd, buf, nbytes); + if (tmp < nbytes) { + elog(WARN, "lo_export: error while writing \"%s\"", + VARDATA(filename)); + } + } + + (void) inv_close(lobj); + (void) close(fd); + + return 1; +} + + +/***************************************************************************** + * Support routines for this file + *****************************************************************************/ + +static int +newLOfd(LargeObjectDesc *lobjCookie) +{ + int i; + + for (i = 0; i < MAX_LOBJ_FDS; i++) { + + if (cookies[i] == NULL) { + cookies[i] = lobjCookie; + return i; + } + } + return -1; +} + +static void +deleteLOfd(int fd) +{ + cookies[fd] = NULL; +} |