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.c122
1 files changed, 86 insertions, 36 deletions
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 5f75e06e189..470dcf11aa9 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -9,36 +9,92 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.102 2003/11/29 19:51:56 pgsql Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.103 2004/07/28 14:23:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-#include <errno.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-
#include "access/genam.h"
#include "access/heapam.h"
-#include "access/htup.h"
#include "access/tuptoaster.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
-#include "catalog/heap.h"
-#include "catalog/index.h"
#include "catalog/indexing.h"
-#include "catalog/pg_opclass.h"
#include "catalog/pg_largeobject.h"
-#include "catalog/pg_type.h"
#include "commands/comment.h"
#include "libpq/libpq-fs.h"
-#include "miscadmin.h"
#include "storage/large_object.h"
-#include "storage/smgr.h"
-#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/resowner.h"
+
+
+/*
+ * All accesses to pg_largeobject and its index make use of a single Relation
+ * reference, so that we only need to open pg_relation once per transaction.
+ * To avoid problems when the first such reference occurs inside a
+ * subtransaction, we execute a slightly klugy maneuver to assign ownership of
+ * the Relation reference to TopTransactionResourceOwner.
+ */
+static Relation lo_heap_r = NULL;
+static Relation lo_index_r = NULL;
+
+
+/*
+ * Open pg_largeobject and its index, if not already done in current xact
+ */
+static void
+open_lo_relation(void)
+{
+ ResourceOwner currentOwner;
+
+ if (lo_heap_r && lo_index_r)
+ return; /* already open in current xact */
+
+ /* Arrange for the top xact to own these relation references */
+ currentOwner = CurrentResourceOwner;
+ CurrentResourceOwner = TopTransactionResourceOwner;
+
+ /* Use RowExclusiveLock since we might either read or write */
+ if (lo_heap_r == NULL)
+ lo_heap_r = heap_openr(LargeObjectRelationName, RowExclusiveLock);
+ if (lo_index_r == NULL)
+ lo_index_r = index_openr(LargeObjectLOidPNIndex);
+
+ CurrentResourceOwner = currentOwner;
+}
+
+/*
+ * Clean up at main transaction end
+ */
+void
+close_lo_relation(bool isCommit)
+{
+ if (lo_heap_r || lo_index_r)
+ {
+ /*
+ * Only bother to close if committing; else abort cleanup will
+ * handle it
+ */
+ if (isCommit)
+ {
+ ResourceOwner currentOwner;
+
+ currentOwner = CurrentResourceOwner;
+ CurrentResourceOwner = TopTransactionResourceOwner;
+
+ if (lo_index_r)
+ index_close(lo_index_r);
+ if (lo_heap_r)
+ heap_close(lo_heap_r, NoLock);
+
+ CurrentResourceOwner = currentOwner;
+ }
+ lo_heap_r = NULL;
+ lo_index_r = NULL;
+ }
+}
static int32
@@ -50,6 +106,7 @@ getbytealen(bytea *data)
return (VARSIZE(data) - VARHDRSZ);
}
+
/*
* inv_create -- create a new large object.
*
@@ -92,23 +149,20 @@ inv_create(int flags)
retval = (LargeObjectDesc *) palloc(sizeof(LargeObjectDesc));
retval->id = file_oid;
+ retval->xid = GetCurrentTransactionId();
retval->offset = 0;
if (flags & INV_WRITE)
{
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
- retval->heap_r = heap_openr(LargeObjectRelationName, RowExclusiveLock);
}
else if (flags & INV_READ)
{
retval->flags = IFS_RDLOCK;
- retval->heap_r = heap_openr(LargeObjectRelationName, AccessShareLock);
}
else
elog(ERROR, "invalid flags: %d", flags);
- retval->index_r = index_openr(LargeObjectLOidPNIndex);
-
return retval;
}
@@ -131,23 +185,20 @@ inv_open(Oid lobjId, int flags)
retval = (LargeObjectDesc *) palloc(sizeof(LargeObjectDesc));
retval->id = lobjId;
+ retval->xid = GetCurrentTransactionId();
retval->offset = 0;
if (flags & INV_WRITE)
{
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
- retval->heap_r = heap_openr(LargeObjectRelationName, RowExclusiveLock);
}
else if (flags & INV_READ)
{
retval->flags = IFS_RDLOCK;
- retval->heap_r = heap_openr(LargeObjectRelationName, AccessShareLock);
}
else
elog(ERROR, "invalid flags: %d", flags);
- retval->index_r = index_openr(LargeObjectLOidPNIndex);
-
return retval;
}
@@ -158,13 +209,6 @@ void
inv_close(LargeObjectDesc *obj_desc)
{
Assert(PointerIsValid(obj_desc));
-
- if (obj_desc->flags & IFS_WRLOCK)
- heap_close(obj_desc->heap_r, RowExclusiveLock);
- else if (obj_desc->flags & IFS_RDLOCK)
- heap_close(obj_desc->heap_r, AccessShareLock);
- index_close(obj_desc->index_r);
-
pfree(obj_desc);
}
@@ -212,12 +256,14 @@ inv_getsize(LargeObjectDesc *obj_desc)
Assert(PointerIsValid(obj_desc));
+ open_lo_relation();
+
ScanKeyInit(&skey[0],
Anum_pg_largeobject_loid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(obj_desc->id));
- sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
+ sd = index_beginscan(lo_heap_r, lo_index_r,
SnapshotNow, 1, skey);
/*
@@ -316,6 +362,8 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
if (nbytes <= 0)
return 0;
+ open_lo_relation();
+
ScanKeyInit(&skey[0],
Anum_pg_largeobject_loid,
BTEqualStrategyNumber, F_OIDEQ,
@@ -326,7 +374,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
BTGreaterEqualStrategyNumber, F_INT4GE,
Int32GetDatum(pageno));
- sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
+ sd = index_beginscan(lo_heap_r, lo_index_r,
SnapshotNow, 2, skey);
while ((tuple = index_getnext(sd, ForwardScanDirection)) != NULL)
@@ -421,7 +469,9 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
if (nbytes <= 0)
return 0;
- indstate = CatalogOpenIndexes(obj_desc->heap_r);
+ open_lo_relation();
+
+ indstate = CatalogOpenIndexes(lo_heap_r);
ScanKeyInit(&skey[0],
Anum_pg_largeobject_loid,
@@ -433,7 +483,7 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
BTGreaterEqualStrategyNumber, F_INT4GE,
Int32GetDatum(pageno));
- sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r,
+ sd = index_beginscan(lo_heap_r, lo_index_r,
SnapshotNow, 2, skey);
oldtuple = NULL;
@@ -510,9 +560,9 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
memset(replace, ' ', sizeof(replace));
values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
replace[Anum_pg_largeobject_data - 1] = 'r';
- newtup = heap_modifytuple(oldtuple, obj_desc->heap_r,
+ newtup = heap_modifytuple(oldtuple, lo_heap_r,
values, nulls, replace);
- simple_heap_update(obj_desc->heap_r, &newtup->t_self, newtup);
+ simple_heap_update(lo_heap_r, &newtup->t_self, newtup);
CatalogIndexInsert(indstate, newtup);
heap_freetuple(newtup);
@@ -554,8 +604,8 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes)
values[Anum_pg_largeobject_loid - 1] = ObjectIdGetDatum(obj_desc->id);
values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno);
values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf);
- newtup = heap_formtuple(obj_desc->heap_r->rd_att, values, nulls);
- simple_heap_insert(obj_desc->heap_r, newtup);
+ newtup = heap_formtuple(lo_heap_r->rd_att, values, nulls);
+ simple_heap_insert(lo_heap_r, newtup);
CatalogIndexInsert(indstate, newtup);
heap_freetuple(newtup);
}