Skip to content

Commit 072bc87

Browse files
committed
Attempt at cleaning up getting the next bucket
The code for getting the next bucket was unnecessarily complex and hard to read.
1 parent 479f326 commit 072bc87

3 files changed

Lines changed: 30 additions & 49 deletions

File tree

src/hash_query.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ pgsm_startup(void)
137137
static void
138138
InitializeSharedState(pgsmSharedState *pgsm)
139139
{
140-
pg_atomic_init_u64(&pgsm->current_wbucket, 0);
141-
pg_atomic_init_u64(&pgsm->prev_bucket_sec, 0);
140+
pg_atomic_init_u64(&pgsm->current_bucket, 0);
141+
pg_atomic_init_u64(&pgsm->current_bucket_sec, 0);
142142
}
143143

144144
/*

src/hash_query.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,8 @@ typedef struct pgsmEntry
231231
typedef struct pgsmSharedState
232232
{
233233
LWLock *lock; /* protects hashtable search/modification */
234-
pg_atomic_uint64 current_wbucket;
235-
pg_atomic_uint64 prev_bucket_sec;
234+
pg_atomic_uint64 current_bucket;
235+
pg_atomic_uint64 current_bucket_sec;
236236
void *raw_dsa_area; /* DSA area pointer to store query texts */
237237
HTAB *hash_handle;
238238

src/pg_stat_monitor.c

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1712,7 +1712,7 @@ pgsm_store(pgsmEntry *entry)
17121712

17131713
pgsm = pgsm_get_ss();
17141714

1715-
prev_bucket_id = pg_atomic_read_u64(&pgsm->current_wbucket);
1715+
prev_bucket_id = pg_atomic_read_u64(&pgsm->current_bucket);
17161716
bucketid = get_next_wbucket(pgsm);
17171717

17181718
if (bucketid != prev_bucket_id)
@@ -2405,7 +2405,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
24052405
values[i++] = BoolGetDatum(toplevel);
24062406

24072407
/* bucket_done at column number 72 */
2408-
values[i++] = BoolGetDatum(pg_atomic_read_u64(&pgsm->current_wbucket) != bucketid);
2408+
values[i++] = BoolGetDatum(pg_atomic_read_u64(&pgsm->current_bucket) != bucketid);
24092409

24102410
/* clean up and return the tuplestore */
24112411
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
@@ -2423,64 +2423,45 @@ static uint64
24232423
get_next_wbucket(pgsmSharedState *pgsm)
24242424
{
24252425
struct timeval tv;
2426-
uint64 current_bucket_sec;
2427-
bool update_bucket = false;
2426+
uint64 new_bucket_start;
2427+
uint64 new_bucket_id;
24282428

24292429
gettimeofday(&tv, NULL);
2430-
current_bucket_sec = pg_atomic_read_u64(&pgsm->prev_bucket_sec);
2430+
2431+
new_bucket_start = (tv.tv_sec / pgsm_bucket_time) * (uint64) pgsm_bucket_time;
24312432

24322433
/*
2433-
* If current bucket expired we loop attempting to update prev_bucket_sec.
2434-
*
2435-
* pg_atomic_compare_exchange_u64 may fail in two possible ways: 1.
2436-
* Another thread/process updated the variable before us. 2. A spurious
2437-
* failure / hardware event.
2434+
* If current bucket expired we loop attempting to update current_bucket_sec.
24382435
*
2439-
* In both failure cases we read prev_bucket_sec from memory again, if it
2440-
* was a spurious failure then the value of prev_bucket_sec must be the
2441-
* same as before, which will cause the while loop to execute again.
2436+
* If another thread updated current_bucket_sec, then use the new bucket
2437+
* created by that thread.
24422438
*
2443-
* If another thread updated prev_bucket_sec, then its current value will
2444-
* definitely make the while condition to fail, we can stop the loop as
2445-
* another thread has already updated prev_bucket_sec.
2439+
* XXX: This code looks potentially racy, especially if we skip buckets.
24462440
*/
2447-
while ((tv.tv_sec - (uint) current_bucket_sec) >= ((uint) pgsm_bucket_time))
2448-
{
2449-
if (pg_atomic_compare_exchange_u64(&pgsm->prev_bucket_sec, &current_bucket_sec, (uint64) tv.tv_sec))
2450-
{
2451-
update_bucket = true;
2452-
break;
2453-
}
2454-
2455-
current_bucket_sec = pg_atomic_read_u64(&pgsm->prev_bucket_sec);
2456-
}
2457-
2458-
if (update_bucket)
2441+
while (1)
24592442
{
2460-
uint64 new_bucket_id;
2443+
uint64 current_bucket_sec = pg_atomic_read_u64(&pgsm->current_bucket_sec);
24612444

2462-
new_bucket_id = (tv.tv_sec / pgsm_bucket_time) % pgsm_max_buckets;
2445+
if (current_bucket_sec + (uint64) pgsm_bucket_time > (uint64) tv.tv_sec)
2446+
return pg_atomic_read_u64(&pgsm->current_bucket);
24632447

2464-
/* Update bucket id and retrieve the previous one. */
2465-
pg_atomic_exchange_u64(&pgsm->current_wbucket, new_bucket_id);
2466-
2467-
pgsm_lock_aquire(pgsm, LW_EXCLUSIVE);
2468-
hash_entry_dealloc(new_bucket_id);
2448+
if (pg_atomic_compare_exchange_u64(&pgsm->current_bucket_sec, &current_bucket_sec, new_bucket_start))
2449+
break;
2450+
}
24692451

2470-
pgsm_lock_release(pgsm);
2452+
new_bucket_id = (new_bucket_start / pgsm_bucket_time) % pgsm_max_buckets;
24712453

2472-
/* Align the value in prev_bucket_sec to the bucket start time */
2473-
tv.tv_sec = (tv.tv_sec) - (tv.tv_sec % pgsm_bucket_time);
2454+
/* Update bucket id and retrieve the previous one. */
2455+
pg_atomic_exchange_u64(&pgsm->current_bucket, new_bucket_id);
24742456

2475-
pg_atomic_exchange_u64(&pgsm->prev_bucket_sec, (uint64) tv.tv_sec);
2457+
pgsm_lock_aquire(pgsm, LW_EXCLUSIVE);
2458+
hash_entry_dealloc(new_bucket_id);
2459+
pgsm_lock_release(pgsm);
24762460

2477-
pgsm->bucket_start_time[new_bucket_id] = (TimestampTz) tv.tv_sec -
2478-
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
2479-
pgsm->bucket_start_time[new_bucket_id] = pgsm->bucket_start_time[new_bucket_id] * USECS_PER_SEC;
2480-
return new_bucket_id;
2481-
}
2461+
pgsm->bucket_start_time[new_bucket_id] = (TimestampTz) (new_bucket_start -
2462+
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY)) * USECS_PER_SEC;
24822463

2483-
return pg_atomic_read_u64(&pgsm->current_wbucket);
2464+
return new_bucket_id;
24842465
}
24852466

24862467
/*

0 commit comments

Comments
 (0)