*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.20 1998/06/15 19:28:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.21 1998/07/21 04:17:21 momjian Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
*-------------------------------------------------------------------------
*/
+/*
+ * Large object clean up added in CommitTransaction() to prevent buffer leaks.
+ * [PA, 7/17/98]
+ * [PA] is Pascal André <andre@via.ecp.fr>
+ */
#include <postgres.h>
#include <access/xact.h>
#include <commands/async.h>
#include <commands/sequence.h>
+/* included for _lo_commit [PA, 7/17/98] */
+#include <libpq/be-fsstubs.h>
+
static void AbortTransaction(void);
static void AtAbort_Cache(void);
static void AtAbort_Locks(void);
* do commit processing
* ----------------
*/
+
+ /* handle commit for large objects [ PA, 7/17/98 ] */
+ _lo_commit();
+
CloseSequences();
DestroyTempRels();
AtEOXact_portals();
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.21 1998/06/15 19:28:25 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.22 1998/07/21 04:17:23 momjian Exp $
*
* NOTES
* This should be moved to a more appropriate place. It is here
#include <storage/large_object.h>
#include <libpq/be-fsstubs.h>
+/* [PA] is Pascal André <andre@via.ecp.fr> */
+
/*#define FSDB 1*/
#define MAX_LOBJ_FDS 256
static int newLOfd(LargeObjectDesc *lobjCookie);
static void deleteLOfd(int fd);
-
/*****************************************************************************
* File Interfaces for Large Objects
*****************************************************************************/
return 1;
}
+/*
+ * lo_commit -
+ * prepares large objects for transaction commit [PA, 7/17/98]
+ */
+void
+_lo_commit(void)
+{
+ int i;
+ MemoryContext currentContext;
+
+ currentContext = MemoryContextSwitchTo((MemoryContext) fscxt);
+
+ for (i = 0; i < MAX_LOBJ_FDS; i++) {
+ if (cookies[i] != NULL) inv_cleanindex(cookies[i]);
+ }
+
+ MemoryContextSwitchTo(currentContext);
+
+}
+
/*****************************************************************************
* Support routines for this file
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.30 1998/06/15 19:29:16 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.31 1998/07/21 04:17:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
* for data.
*/
+/*
+ * In order to prevent buffer leak on transaction commit, large object
+ * scan index handling has been modified. Indexes are persistant inside
+ * a transaction but may be closed between two calls to this API (when
+ * transaction is committed while object is opened, or when no
+ * transaction is active). Scan indexes are thus now reinitialized using
+ * the object current offset. [PA]
+ *
+ * Some cleanup has been also done for non freed memory.
+ *
+ * For subsequent notes, [PA] is Pascal André <andre@via.ecp.fr>
+ */
+
#define IFREESPC(p) (PageGetFreeSpace(p) - sizeof(HeapTupleData) - sizeof(struct varlena) - sizeof(int32))
#define IMAXBLK 8092
#define IMINBLK 512
{
Assert(PointerIsValid(obj_desc));
- if (obj_desc->iscan != (IndexScanDesc) NULL)
+ if (obj_desc->iscan != (IndexScanDesc) NULL) {
index_endscan(obj_desc->iscan);
+ pfree(obj_desc->iscan);
+ obj_desc->iscan = NULL;
+ }
heap_close(obj_desc->heap_r);
index_close(obj_desc->index_r);
}
/*
+ * inv_cleanindex --
+ * Clean opened indexes for large objects, and clears current result.
+ * This is necessary on transaction commit in order to prevent buffer
+ * leak.
+ * This function must be called for each opened large object.
+ * [ PA, 7/17/98 ]
+ */
+void
+inv_cleanindex(LargeObjectDesc *obj_desc)
+{
+ Assert(PointerIsValid(obj_desc));
+
+ if (obj_desc->iscan == (IndexScanDesc) NULL) return;
+
+ index_endscan(obj_desc->iscan);
+ pfree(obj_desc->iscan);
+ obj_desc->iscan = (IndexScanDesc) NULL;
+
+ ItemPointerSetInvalid(&(obj_desc->htid));
+}
+
+/*
* inv_fetchtup -- Fetch an inversion file system block.
*
* This routine finds the file system block containing the offset
{
ScanKeyData skey;
+ /*
+ * As scan index may be prematurely closed (on commit),
+ * we must use object current offset (was 0) to
+ * reinitialize the entry [ PA ].
+ */
ScanKeyEntryInitialize(&skey, 0x0, 1, F_INT4GE,
- Int32GetDatum(0));
+ Int32GetDatum(obj_desc->offset));
obj_desc->iscan =
index_beginscan(obj_desc->index_r,
(bool) 0, (uint16) 1,
/* remember this tid -- we may need it for later reads/writes */
ItemPointerCopy(&(res->heap_iptr), &(obj_desc->htid));
-
+ pfree(res);
}
else
{
if (res == (RetrieveIndexResult) NULL)
{
index_endscan(iscan);
+ pfree(iscan);
return (0);
}
ReleaseBuffer(buf);
htup = heap_fetch(hreln, false, &(res->heap_iptr), &buf);
+ pfree(res);
} while (!HeapTupleIsValid(htup));
/* don't need the index scan anymore */
index_endscan(iscan);
+ pfree(iscan);
/* get olastbyte attribute */
d = heap_getattr(htup, 1, hdesc, &isNull);
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: be-fsstubs.h,v 1.5 1997/09/08 21:52:33 momjian Exp $
+ * $Id: be-fsstubs.h,v 1.6 1998/07/21 04:17:26 momjian Exp $
*
*-------------------------------------------------------------------------
*/
extern struct varlena *loread(int fd, int len);
extern int lowrite(int fd, struct varlena * wbuf);
+/*
+ * Added for buffer leak prevention [ Pascal André <andre@via.ecp.fr> ]
+ */
+extern void _lo_commit(void);
+
#endif /* BE_FSSTUBS_H */
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: large_object.h,v 1.7 1997/09/08 21:54:29 momjian Exp $
+ * $Id: large_object.h,v 1.8 1998/07/21 04:17:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
extern int inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes);
extern int inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes);
+/* added for buffer leak prevention [ PA ] */
+extern void inv_cleanindex(LargeObjectDesc *obj_desc);
+
#endif /* LARGE_OBJECT_H */