Skip to content

Commit c0a4c36

Browse files
Artem FadeevDaniil Anisimov
authored andcommitted
Fix race condition in cleanup_aqo_database
1 parent d1a37e0 commit c0a4c36

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

storage.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ static void data_load(const char *filename, deform_record_t callback, void *ctx)
9797
static size_t _compute_data_dsa(const DataEntry *entry);
9898

9999
static bool _aqo_stat_remove(uint64 queryid);
100-
static bool _aqo_queries_remove(uint64 queryid);
100+
static bool _aqo_queries_remove(uint64 queryid, bool lock);
101101
static bool _aqo_qtexts_remove(uint64 queryid);
102102
static bool _aqo_data_remove(data_key *key);
103103
static bool nearest_neighbor(double **matrix, int old_rows, double *neighbor, int cols);
@@ -1186,7 +1186,7 @@ aqo_qtext_store(uint64 queryid, const char *query_string, bool *dsa_valid)
11861186
* that caller recognize it and don't try to call us more.
11871187
*/
11881188
(void) hash_search(qtexts_htab, &queryid, HASH_REMOVE, NULL);
1189-
_aqo_queries_remove(queryid);
1189+
_aqo_queries_remove(queryid, true);
11901190
LWLockRelease(&aqo_state->qtexts_lock);
11911191
if (dsa_valid)
11921192
*dsa_valid = false;
@@ -1284,12 +1284,19 @@ _aqo_stat_remove(uint64 queryid)
12841284
}
12851285

12861286
static bool
1287-
_aqo_queries_remove(uint64 queryid)
1287+
_aqo_queries_remove(uint64 queryid, bool lock)
12881288
{
12891289
bool found;
12901290

1291-
Assert(!LWLockHeldByMe(&aqo_state->queries_lock));
1292-
LWLockAcquire(&aqo_state->queries_lock, LW_EXCLUSIVE);
1291+
if (lock)
1292+
{
1293+
LWLockAcquire(&aqo_state->queries_lock, LW_EXCLUSIVE);
1294+
}
1295+
else
1296+
{
1297+
Assert(LWLockHeldByMeInMode(&aqo_state->queries_lock, LW_EXCLUSIVE));
1298+
}
1299+
12931300
(void) hash_search(queries_htab, &queryid, HASH_FIND, &found);
12941301

12951302
if (found)
@@ -1298,7 +1305,8 @@ _aqo_queries_remove(uint64 queryid)
12981305
aqo_state->queries_changed = true;
12991306
}
13001307

1301-
LWLockRelease(&aqo_state->queries_lock);
1308+
if (lock)
1309+
LWLockRelease(&aqo_state->queries_lock);
13021310
return found;
13031311
}
13041312

@@ -2324,10 +2332,7 @@ cleanup_aqo_database(bool gentle, int *fs_num, int *fss_num)
23242332
*fs_num = 0;
23252333
*fss_num = 0;
23262334

2327-
/*
2328-
* It's a long haul. So, make seq scan without any lock. It is possible
2329-
* because only this operation can delete data from hash table.
2330-
*/
2335+
LWLockAcquire(&aqo_state->queries_lock, LW_EXCLUSIVE);
23312336
hash_seq_init(&hash_seq, queries_htab);
23322337
while ((entry = hash_seq_search(&hash_seq)) != NULL)
23332338
{
@@ -2338,6 +2343,7 @@ cleanup_aqo_database(bool gentle, int *fs_num, int *fss_num)
23382343
ListCell *lc;
23392344

23402345
/* Scan aqo_data for any junk records related to this FS */
2346+
LWLockAcquire(&aqo_state->data_lock, LW_SHARED);
23412347
hash_seq_init(&hash_seq2, data_htab);
23422348
while ((dentry = hash_seq_search(&hash_seq2)) != NULL)
23432349
{
@@ -2347,8 +2353,6 @@ cleanup_aqo_database(bool gentle, int *fs_num, int *fss_num)
23472353
/* Another FS */
23482354
continue;
23492355

2350-
LWLockAcquire(&aqo_state->data_lock, LW_SHARED);
2351-
23522356
Assert(DsaPointerIsValid(dentry->data_dp));
23532357
ptr = dsa_get_address(data_dsa, dentry->data_dp);
23542358

@@ -2388,10 +2392,10 @@ cleanup_aqo_database(bool gentle, int *fs_num, int *fss_num)
23882392
UINT64_FORMAT" fss=%d",
23892393
dentry->key.fs, (int32) dentry->key.fss)));
23902394
}
2391-
2392-
LWLockRelease(&aqo_state->data_lock);
23932395
}
23942396

2397+
LWLockRelease(&aqo_state->data_lock);
2398+
23952399
/*
23962400
* In forced mode remove all child FSSes even some of them are still
23972401
* link to existed tables.
@@ -2419,10 +2423,12 @@ cleanup_aqo_database(bool gentle, int *fs_num, int *fss_num)
24192423
_aqo_qtexts_remove(entry->queryid);
24202424

24212425
/* Query class preferences */
2422-
(*fs_num) += (int) _aqo_queries_remove(entry->queryid);
2426+
(*fs_num) += (int) _aqo_queries_remove(entry->queryid, false);
24232427
}
24242428
}
24252429

2430+
LWLockRelease(&aqo_state->queries_lock);
2431+
24262432
/*
24272433
* The best place to flush updated AQO storage: calling the routine, user
24282434
* realizes how heavy it is.
@@ -2504,7 +2510,7 @@ aqo_drop_class(PG_FUNCTION_ARGS)
25042510
"id = "INT64_FORMAT", fs = "UINT64_FORMAT".", (int64) queryid, fs);
25052511

25062512
/* Now, remove all data related to the class */
2507-
_aqo_queries_remove(queryid);
2513+
_aqo_queries_remove(queryid, true);
25082514
_aqo_stat_remove(queryid);
25092515
_aqo_qtexts_remove(queryid);
25102516
cnt = _aqo_data_clean(fs);

0 commit comments

Comments
 (0)