* Andres Freund ([email protected]) wrote: > Seems more consistent with the rest of the code too. But anyway, I am > fine with fixing it either way.
Patch attached which mirrors what GetRunningTransactionData() (the other
function called from LogStandbySnapshot) does, more-or-less- uses a
static variable to keep track of memory allocated for the data being
returned to the caller.
Looks like this will need to be back-patched to 9.0. Barring objections
or better ideas, I'll do that in a few hours.
Thanks,
Stephen
colordiff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
new file mode 100644
index 8cd871f..1fb7884
*** a/src/backend/storage/lmgr/lock.c
--- b/src/backend/storage/lmgr/lock.c
*************** GetLockStatusData(void)
*** 3401,3415 ****
* Returns a list of currently held AccessExclusiveLocks, for use
* by GetRunningTransactionData().
*/
xl_standby_lock *
GetRunningTransactionLocks(int *nlocks)
{
PROCLOCK *proclock;
HASH_SEQ_STATUS seqstat;
int i;
int index;
! int els;
! xl_standby_lock *accessExclusiveLocks;
/*
* Acquire lock on the entire shared lock data structure.
--- 3401,3445 ----
* Returns a list of currently held AccessExclusiveLocks, for use
* by GetRunningTransactionData().
*/
+ #define INIT_STANDBY_LOCK_ARR_SIZE 32 /* Initial return workspace size */
xl_standby_lock *
GetRunningTransactionLocks(int *nlocks)
{
+ /* result workspace */
+ static xl_standby_locks *accessExclusiveLocks;
+
PROCLOCK *proclock;
HASH_SEQ_STATUS seqstat;
int i;
int index;
!
! /*
! * Allocating space for all locks is overkill. We only need space for
! * access exclusive locks, but we can't count the number of locks without
! * locking all of the lock partitions. We don't really want to do
! * allocations while holding all those locks, so instead do a bit of
! * allocation up front, to hopefully avoid having to do them later.
! */
! if (accessExclusiveLocks == NULL)
! {
! /*
! * First call
! *
! * Note: We are tracking the allocated space for locks in ->nlocks,
! * not the actual number of locks found, that's handled with index
! * below. Also, allocating the structure will start us off with space
! * for one, so discount that from the malloc request.
! */
! accessExclusiveLocks = (xl_standby_locks *)
! malloc(sizeof(xl_standby_locks) +
! ((INIT_STANDBY_LOCK_ARR_SIZE - 1) * sizeof(xl_standby_lock)));
! if (accessExclusiveLocks == NULL)
! ereport(ERROR,
! (errcode(ERRCODE_OUT_OF_MEMORY),
! errmsg("out of memory")));
!
! accessExclusiveLocks->nlocks = INIT_STANDBY_LOCK_ARR_SIZE;
! }
/*
* Acquire lock on the entire shared lock data structure.
*************** GetRunningTransactionLocks(int *nlocks)
*** 3419,3433 ****
for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
LWLockAcquire(FirstLockMgrLock + i, LW_SHARED);
- /* Now we can safely count the number of proclocks */
- els = hash_get_num_entries(LockMethodProcLockHash);
-
- /*
- * Allocating enough space for all locks in the lock table is overkill,
- * but it's more convenient and faster than having to enlarge the array.
- */
- accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
-
/* Now scan the tables to copy the data */
hash_seq_init(&seqstat, LockMethodProcLockHash);
--- 3449,3454 ----
*************** GetRunningTransactionLocks(int *nlocks)
*** 3459,3467 ****
if (!TransactionIdIsValid(xid))
continue;
! accessExclusiveLocks[index].xid = xid;
! accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
! accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
index++;
}
--- 3480,3508 ----
if (!TransactionIdIsValid(xid))
continue;
! /*
! * Check if we need to allocate more space in our workspace due to
! * the number of access exclusive locks actually found. If we do
! * run out, double the size of our return area to hopefully avoid
! * having to do this again any time soon.
! */
! if (index >= accessExclusiveLocks->nlocks)
! {
! accessExclusiveLocks->nlocks *= 2;
!
! accessExclusiveLocks = (xl_standby_locks *)
! realloc(accessExclusiveLocks,
! sizeof(xl_standby_locks) +
! ((accessExclusiveLocks->nlocks - 1) *
! sizeof(xl_standby_lock)));
! if (accessExclusiveLocks == NULL)
! ereport(ERROR,
! (errcode(ERRCODE_OUT_OF_MEMORY),
! errmsg("out of memory")));
! }
! accessExclusiveLocks->locks[index].xid = xid;
! accessExclusiveLocks->locks[index].dbOid = lock->tag.locktag_field1;
! accessExclusiveLocks->locks[index].relOid = lock->tag.locktag_field2;
index++;
}
*************** GetRunningTransactionLocks(int *nlocks)
*** 3477,3484 ****
for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
LWLockRelease(FirstLockMgrLock + i);
*nlocks = index;
! return accessExclusiveLocks;
}
/* Provide the textual name of any lock mode */
--- 3518,3526 ----
for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
LWLockRelease(FirstLockMgrLock + i);
+ /* Pass back out the number of locks actually found. */
*nlocks = index;
! return accessExclusiveLocks->locks;
}
/* Provide the textual name of any lock mode */
signature.asc
Description: Digital signature
