@@ -345,6 +345,7 @@ static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode);
345
345
static void FinishStrongLockAcquire (void );
346
346
static void WaitOnLock (LOCALLOCK * locallock , ResourceOwner owner );
347
347
static void ReleaseLockIfHeld (LOCALLOCK * locallock , bool sessionLock );
348
+ static void LockReassignOwner (LOCALLOCK * locallock , ResourceOwner parent );
348
349
static bool UnGrantLock (LOCK * lock , LOCKMODE lockmode ,
349
350
PROCLOCK * proclock , LockMethod lockMethodTable );
350
351
static void CleanUpLock (LOCK * lock , PROCLOCK * proclock ,
@@ -1098,8 +1099,16 @@ SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
1098
1099
static void
1099
1100
RemoveLocalLock (LOCALLOCK * locallock )
1100
1101
{
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
+ }
1101
1109
pfree (locallock -> lockOwners );
1102
1110
locallock -> lockOwners = NULL ;
1111
+
1103
1112
if (locallock -> holdsStrongLockCount )
1104
1113
{
1105
1114
uint32 fasthashcode ;
@@ -1112,6 +1121,7 @@ RemoveLocalLock(LOCALLOCK *locallock)
1112
1121
locallock -> holdsStrongLockCount = FALSE;
1113
1122
SpinLockRelease (& FastPathStrongRelationLocks -> mutex );
1114
1123
}
1124
+
1115
1125
if (!hash_search (LockMethodLocalHash ,
1116
1126
(void * ) & (locallock -> tag ),
1117
1127
HASH_REMOVE , NULL ))
@@ -1355,6 +1365,8 @@ GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
1355
1365
lockOwners [i ].owner = owner ;
1356
1366
lockOwners [i ].nLocks = 1 ;
1357
1367
locallock -> numLockOwners ++ ;
1368
+ if (owner != NULL )
1369
+ ResourceOwnerRememberLock (owner , locallock );
1358
1370
}
1359
1371
1360
1372
/*
@@ -1670,6 +1682,8 @@ LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
1670
1682
Assert (lockOwners [i ].nLocks > 0 );
1671
1683
if (-- lockOwners [i ].nLocks == 0 )
1672
1684
{
1685
+ if (owner != NULL )
1686
+ ResourceOwnerForgetLock (owner , locallock );
1673
1687
/* compact out unused slot */
1674
1688
locallock -> numLockOwners -- ;
1675
1689
if (i < locallock -> numLockOwners )
@@ -1862,14 +1876,13 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
1862
1876
{
1863
1877
LOCALLOCKOWNER * lockOwners = locallock -> lockOwners ;
1864
1878
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 ++ )
1867
1881
{
1868
1882
if (lockOwners [i ].owner == NULL )
1869
- {
1870
1883
lockOwners [0 ] = lockOwners [i ];
1871
- break ;
1872
- }
1884
+ else
1885
+ ResourceOwnerForgetLock ( lockOwners [ i ]. owner , locallock );
1873
1886
}
1874
1887
1875
1888
if (locallock -> numLockOwners > 0 &&
@@ -1882,6 +1895,8 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
1882
1895
/* We aren't deleting this locallock, so done */
1883
1896
continue ;
1884
1897
}
1898
+ else
1899
+ locallock -> numLockOwners = 0 ;
1885
1900
}
1886
1901
1887
1902
/*
@@ -2067,18 +2082,31 @@ LockReleaseSession(LOCKMETHODID lockmethodid)
2067
2082
/*
2068
2083
* LockReleaseCurrentOwner
2069
2084
* 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.
2070
2090
*/
2071
2091
void
2072
- LockReleaseCurrentOwner (void )
2092
+ LockReleaseCurrentOwner (LOCALLOCK * * locallocks , int nlocks )
2073
2093
{
2074
- HASH_SEQ_STATUS status ;
2075
- LOCALLOCK * locallock ;
2094
+ if (locallocks == NULL )
2095
+ {
2096
+ HASH_SEQ_STATUS status ;
2097
+ LOCALLOCK * locallock ;
2076
2098
2077
- hash_seq_init (& status , LockMethodLocalHash );
2099
+ hash_seq_init (& status , LockMethodLocalHash );
2078
2100
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
2080
2105
{
2081
- ReleaseLockIfHeld (locallock , false);
2106
+ int i ;
2107
+
2108
+ for (i = nlocks - 1 ; i >= 0 ; i -- )
2109
+ ReleaseLockIfHeld (locallocks [i ], false);
2082
2110
}
2083
2111
}
2084
2112
@@ -2124,6 +2152,8 @@ ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
2124
2152
locallock -> nLocks -= lockOwners [i ].nLocks ;
2125
2153
/* compact out unused slot */
2126
2154
locallock -> numLockOwners -- ;
2155
+ if (owner != NULL )
2156
+ ResourceOwnerForgetLock (owner , locallock );
2127
2157
if (i < locallock -> numLockOwners )
2128
2158
lockOwners [i ] = lockOwners [locallock -> numLockOwners ];
2129
2159
}
@@ -2146,57 +2176,83 @@ ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
2146
2176
/*
2147
2177
* LockReassignCurrentOwner
2148
2178
* 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.
2150
2185
*/
2151
2186
void
2152
- LockReassignCurrentOwner (void )
2187
+ LockReassignCurrentOwner (LOCALLOCK * * locallocks , int nlocks )
2153
2188
{
2154
2189
ResourceOwner parent = ResourceOwnerGetParent (CurrentResourceOwner );
2155
- HASH_SEQ_STATUS status ;
2156
- LOCALLOCK * locallock ;
2157
- LOCALLOCKOWNER * lockOwners ;
2158
2190
2159
2191
Assert (parent != NULL );
2160
2192
2161
- hash_seq_init (& status , LockMethodLocalHash );
2193
+ if (locallocks == NULL )
2194
+ {
2195
+ HASH_SEQ_STATUS status ;
2196
+ LOCALLOCK * locallock ;
2162
2197
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
2164
2204
{
2165
- int i ;
2166
- int ic = -1 ;
2167
- int ip = -1 ;
2205
+ int i ;
2168
2206
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
+ }
2181
2211
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 ;
2184
2223
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 ];
2199
2254
}
2255
+ ResourceOwnerForgetLock (CurrentResourceOwner , locallock );
2200
2256
}
2201
2257
2202
2258
/*
0 commit comments