diff -Nru pgsql/src/backend/access/transam/xact.c pgsql-mod/src/backend/access/transam/xact.c --- pgsql/src/backend/access/transam/xact.c Sat Jun 20 09:00:27 1998 +++ pgsql-mod/src/backend/access/transam/xact.c Fri Jul 17 11:22:29 1998 @@ -137,6 +137,11 @@ *------------------------------------------------------------------------- */ +/* + * Large object clean up added in CommitTransaction() to prevent buffer leaks. + * [PA, 7/17/98] + * [PA] is Pascal André + */ #include #include @@ -151,6 +156,9 @@ #include #include +/* included for _lo_commit [PA, 7/17/98] */ +#include + static void AbortTransaction(void); static void AtAbort_Cache(void); static void AtAbort_Locks(void); @@ -889,6 +897,10 @@ * do commit processing * ---------------- */ + + /* handle commit for large objects [ PA, 7/17/98 ] */ + _lo_commit(); + CloseSequences(); DestroyTempRels(); AtEOXact_portals(); diff -Nru pgsql/src/backend/libpq/be-fsstubs.c pgsql-mod/src/backend/libpq/be-fsstubs.c --- pgsql/src/backend/libpq/be-fsstubs.c Sat Jun 20 09:00:32 1998 +++ pgsql-mod/src/backend/libpq/be-fsstubs.c Fri Jul 17 11:11:14 1998 @@ -41,6 +41,8 @@ #include #include +/* [PA] is Pascal André */ + /*#define FSDB 1*/ #define MAX_LOBJ_FDS 256 @@ -52,7 +54,6 @@ static int newLOfd(LargeObjectDesc *lobjCookie); static void deleteLOfd(int fd); - /***************************************************************************** * File Interfaces for Large Objects *****************************************************************************/ @@ -365,6 +366,26 @@ close(fd); 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); + } diff -Nru pgsql/src/backend/storage/large_object/inv_api.c pgsql-mod/src/backend/storage/large_object/inv_api.c --- pgsql/src/backend/storage/large_object/inv_api.c Sat Jun 20 09:00:43 1998 +++ pgsql-mod/src/backend/storage/large_object/inv_api.c Fri Jul 17 11:30:27 1998 @@ -60,6 +60,19 @@ * 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é + */ + #define IFREESPC(p) (PageGetFreeSpace(p) - sizeof(HeapTupleData) - sizeof(struct varlena) - sizeof(int32)) #define IMAXBLK 8092 #define IMINBLK 512 @@ -261,8 +274,11 @@ { 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); @@ -547,6 +563,28 @@ } /* + * 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 @@ -591,8 +629,13 @@ { 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, @@ -622,7 +665,7 @@ /* remember this tid -- we may need it for later reads/writes */ ItemPointerCopy(&(res->heap_iptr), &(obj_desc->htid)); - + pfree(res); } else { @@ -1179,6 +1222,7 @@ if (res == (RetrieveIndexResult) NULL) { index_endscan(iscan); + pfree(iscan); return (0); } @@ -1192,11 +1236,13 @@ 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); diff -Nru pgsql/src/include/libpq/be-fsstubs.h pgsql-mod/src/include/libpq/be-fsstubs.h --- pgsql/src/include/libpq/be-fsstubs.h Mon Sep 8 23:52:33 1997 +++ pgsql-mod/src/include/libpq/be-fsstubs.h Fri Jul 17 11:11:43 1998 @@ -37,4 +37,9 @@ extern struct varlena *loread(int fd, int len); extern int lowrite(int fd, struct varlena * wbuf); +/* + * Added for buffer leak prevention [ Pascal André ] + */ +extern void _lo_commit(void); + #endif /* BE_FSSTUBS_H */ diff -Nru pgsql/src/include/storage/large_object.h pgsql-mod/src/include/storage/large_object.h --- pgsql/src/include/storage/large_object.h Mon Sep 8 23:54:29 1997 +++ pgsql-mod/src/include/storage/large_object.h Fri Jul 17 11:13:21 1998 @@ -54,4 +54,7 @@ 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 */