@@ -345,6 +345,7 @@ static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode);
345345static void FinishStrongLockAcquire (void );
346346static void WaitOnLock (LOCALLOCK * locallock , ResourceOwner owner );
347347static void ReleaseLockIfHeld (LOCALLOCK * locallock , bool sessionLock );
348+ static void LockReassignOwner (LOCALLOCK * locallock , ResourceOwner parent );
348349static bool UnGrantLock (LOCK * lock , LOCKMODE lockmode ,
349350 PROCLOCK * proclock , LockMethod lockMethodTable );
350351static void CleanUpLock (LOCK * lock , PROCLOCK * proclock ,
@@ -1098,8 +1099,16 @@ SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
10981099static void
10991100RemoveLocalLock (LOCALLOCK * locallock )
11001101{
1102+ int i ;
1103+
1104+ for (i = locallock -> numLockOwners - 1 ; i >= 0 ; i -- )
1105+ {
1106+ if (locallock -> lockOwners [i ].owner != NULL )
1107+ ResourceOwnerForgetLock (locallock -> lockOwners [i ].owner , locallock );
1108+ }
11011109 pfree (locallock -> lockOwners );
11021110 locallock -> lockOwners = NULL ;
1111+
11031112 if (locallock -> holdsStrongLockCount )
11041113 {
11051114 uint32 fasthashcode ;
@@ -1112,6 +1121,7 @@ RemoveLocalLock(LOCALLOCK *locallock)
11121121 locallock -> holdsStrongLockCount = FALSE;
11131122 SpinLockRelease (& FastPathStrongRelationLocks -> mutex );
11141123 }
1124+
11151125 if (!hash_search (LockMethodLocalHash ,
11161126 (void * ) & (locallock -> tag ),
11171127 HASH_REMOVE , NULL ))
@@ -1355,6 +1365,8 @@ GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
13551365 lockOwners [i ].owner = owner ;
13561366 lockOwners [i ].nLocks = 1 ;
13571367 locallock -> numLockOwners ++ ;
1368+ if (owner != NULL )
1369+ ResourceOwnerRememberLock (owner , locallock );
13581370}
13591371
13601372/*
@@ -1670,6 +1682,8 @@ LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
16701682 Assert (lockOwners [i ].nLocks > 0 );
16711683 if (-- lockOwners [i ].nLocks == 0 )
16721684 {
1685+ if (owner != NULL )
1686+ ResourceOwnerForgetLock (owner , locallock );
16731687 /* compact out unused slot */
16741688 locallock -> numLockOwners -- ;
16751689 if (i < locallock -> numLockOwners )
@@ -1862,14 +1876,13 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
18621876 {
18631877 LOCALLOCKOWNER * lockOwners = locallock -> lockOwners ;
18641878
1865- /* If it's above array position 0, move it down to 0 */
1866- for (i = locallock -> numLockOwners - 1 ; i > 0 ; i -- )
1879+ /* If session lock is above array position 0, move it down to 0 */
1880+ for (i = 0 ; i < locallock -> numLockOwners ; i ++ )
18671881 {
18681882 if (lockOwners [i ].owner == NULL )
1869- {
18701883 lockOwners [0 ] = lockOwners [i ];
1871- break ;
1872- }
1884+ else
1885+ ResourceOwnerForgetLock ( lockOwners [ i ]. owner , locallock );
18731886 }
18741887
18751888 if (locallock -> numLockOwners > 0 &&
@@ -1882,6 +1895,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
18821895 /* We aren't deleting this locallock, so done */
18831896 continue ;
18841897 }
1898+ else
1899+ locallock -> numLockOwners = 0 ;
18851900 }
18861901
18871902 /*
@@ -2067,18 +2082,31 @@ LockReleaseSession(LOCKMETHODID lockmethodid)
20672082/*
20682083 * LockReleaseCurrentOwner
20692084 * Release all locks belonging to CurrentResourceOwner
2085+ *
2086+ * If the caller knows what those locks are, it can pass them as an array.
2087+ * That speeds up the call significantly, when a lot of locks are held.
2088+ * Otherwise, pass NULL for locallocks, and we'll traverse through our hash
2089+ * table to find them.
20702090 */
20712091void
2072- LockReleaseCurrentOwner (void )
2092+ LockReleaseCurrentOwner (LOCALLOCK * * locallocks , int nlocks )
20732093{
2074- HASH_SEQ_STATUS status ;
2075- LOCALLOCK * locallock ;
2094+ if (locallocks == NULL )
2095+ {
2096+ HASH_SEQ_STATUS status ;
2097+ LOCALLOCK * locallock ;
20762098
2077- hash_seq_init (& status , LockMethodLocalHash );
2099+ hash_seq_init (& status , LockMethodLocalHash );
20782100
2079- while ((locallock = (LOCALLOCK * ) hash_seq_search (& status )) != NULL )
2101+ while ((locallock = (LOCALLOCK * ) hash_seq_search (& status )) != NULL )
2102+ ReleaseLockIfHeld (locallock , false);
2103+ }
2104+ else
20802105 {
2081- ReleaseLockIfHeld (locallock , false);
2106+ int i ;
2107+
2108+ for (i = nlocks - 1 ; i >= 0 ; i -- )
2109+ ReleaseLockIfHeld (locallocks [i ], false);
20822110 }
20832111}
20842112
@@ -2124,6 +2152,8 @@ ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
21242152 locallock -> nLocks -= lockOwners [i ].nLocks ;
21252153 /* compact out unused slot */
21262154 locallock -> numLockOwners -- ;
2155+ if (owner != NULL )
2156+ ResourceOwnerForgetLock (owner , locallock );
21272157 if (i < locallock -> numLockOwners )
21282158 lockOwners [i ] = lockOwners [locallock -> numLockOwners ];
21292159 }
@@ -2146,57 +2176,83 @@ ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
21462176/*
21472177 * LockReassignCurrentOwner
21482178 * Reassign all locks belonging to CurrentResourceOwner to belong
2149- * to its parent resource owner
2179+ * to its parent resource owner.
2180+ *
2181+ * If the caller knows what those locks are, it can pass them as an array.
2182+ * That speeds up the call significantly, when a lot of locks are held
2183+ * (e.g pg_dump with a large schema). Otherwise, pass NULL for locallocks,
2184+ * and we'll traverse through our hash table to find them.
21502185 */
21512186void
2152- LockReassignCurrentOwner (void )
2187+ LockReassignCurrentOwner (LOCALLOCK * * locallocks , int nlocks )
21532188{
21542189 ResourceOwner parent = ResourceOwnerGetParent (CurrentResourceOwner );
2155- HASH_SEQ_STATUS status ;
2156- LOCALLOCK * locallock ;
2157- LOCALLOCKOWNER * lockOwners ;
21582190
21592191 Assert (parent != NULL );
21602192
2161- hash_seq_init (& status , LockMethodLocalHash );
2193+ if (locallocks == NULL )
2194+ {
2195+ HASH_SEQ_STATUS status ;
2196+ LOCALLOCK * locallock ;
21622197
2163- while ((locallock = (LOCALLOCK * ) hash_seq_search (& status )) != NULL )
2198+ hash_seq_init (& status , LockMethodLocalHash );
2199+
2200+ while ((locallock = (LOCALLOCK * ) hash_seq_search (& status )) != NULL )
2201+ LockReassignOwner (locallock , parent );
2202+ }
2203+ else
21642204 {
2165- int i ;
2166- int ic = -1 ;
2167- int ip = -1 ;
2205+ int i ;
21682206
2169- /*
2170- * Scan to see if there are any locks belonging to current owner or
2171- * its parent
2172- */
2173- lockOwners = locallock -> lockOwners ;
2174- for (i = locallock -> numLockOwners - 1 ; i >= 0 ; i -- )
2175- {
2176- if (lockOwners [i ].owner == CurrentResourceOwner )
2177- ic = i ;
2178- else if (lockOwners [i ].owner == parent )
2179- ip = i ;
2180- }
2207+ for (i = nlocks - 1 ; i >= 0 ; i -- )
2208+ LockReassignOwner (locallocks [i ], parent );
2209+ }
2210+ }
21812211
2182- if (ic < 0 )
2183- continue ; /* no current locks */
2212+ /*
2213+ * Subroutine of LockReassignCurrentOwner. Reassigns a given lock belonging to
2214+ * CurrentResourceOwner to its parent.
2215+ */
2216+ static void
2217+ LockReassignOwner (LOCALLOCK * locallock , ResourceOwner parent )
2218+ {
2219+ LOCALLOCKOWNER * lockOwners ;
2220+ int i ;
2221+ int ic = -1 ;
2222+ int ip = -1 ;
21842223
2185- if (ip < 0 )
2186- {
2187- /* Parent has no slot, so just give it child's slot */
2188- lockOwners [ic ].owner = parent ;
2189- }
2190- else
2191- {
2192- /* Merge child's count with parent's */
2193- lockOwners [ip ].nLocks += lockOwners [ic ].nLocks ;
2194- /* compact out unused slot */
2195- locallock -> numLockOwners -- ;
2196- if (ic < locallock -> numLockOwners )
2197- lockOwners [ic ] = lockOwners [locallock -> numLockOwners ];
2198- }
2224+ /*
2225+ * Scan to see if there are any locks belonging to current owner or
2226+ * its parent
2227+ */
2228+ lockOwners = locallock -> lockOwners ;
2229+ for (i = locallock -> numLockOwners - 1 ; i >= 0 ; i -- )
2230+ {
2231+ if (lockOwners [i ].owner == CurrentResourceOwner )
2232+ ic = i ;
2233+ else if (lockOwners [i ].owner == parent )
2234+ ip = i ;
2235+ }
2236+
2237+ if (ic < 0 )
2238+ return ; /* no current locks */
2239+
2240+ if (ip < 0 )
2241+ {
2242+ /* Parent has no slot, so just give it the child's slot */
2243+ lockOwners [ic ].owner = parent ;
2244+ ResourceOwnerRememberLock (parent , locallock );
2245+ }
2246+ else
2247+ {
2248+ /* Merge child's count with parent's */
2249+ lockOwners [ip ].nLocks += lockOwners [ic ].nLocks ;
2250+ /* compact out unused slot */
2251+ locallock -> numLockOwners -- ;
2252+ if (ic < locallock -> numLockOwners )
2253+ lockOwners [ic ] = lockOwners [locallock -> numLockOwners ];
21992254 }
2255+ ResourceOwnerForgetLock (CurrentResourceOwner , locallock );
22002256}
22012257
22022258/*
0 commit comments