aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/large_object/inv_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/large_object/inv_api.c')
-rw-r--r--src/backend/storage/large_object/inv_api.c54
1 files changed, 50 insertions, 4 deletions
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index c3d63ac36b2..e92c75f0a34 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
@@ -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é <andre@via.ecp.fr>
+ */
+
#define IFREESPC(p) (PageGetFreeSpace(p) - sizeof(HeapTupleData) - sizeof(struct varlena) - sizeof(int32))
#define IMAXBLK 8092
#define IMINBLK 512
@@ -261,8 +274,11 @@ inv_close(LargeObjectDesc *obj_desc)
{
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_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
}
/*
+ * 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 @@ inv_fetchtup(LargeObjectDesc *obj_desc, Buffer *bufP)
{
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 @@ inv_fetchtup(LargeObjectDesc *obj_desc, Buffer *bufP)
/* 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 @@ _inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln)
if (res == (RetrieveIndexResult) NULL)
{
index_endscan(iscan);
+ pfree(iscan);
return (0);
}
@@ -1192,11 +1236,13 @@ _inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln)
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);