Skip to content

Commit f67a68a

Browse files
author
virco
committed
fix psync_pagecache_get_free_page() not to try to flush cache itself when somebody else is flushing already, instead wait for a page
1 parent 30608c5 commit f67a68a

File tree

1 file changed

+39
-10
lines changed

1 file changed

+39
-10
lines changed

ppagecache.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ static int cache_pages_reset=1;
152152
static psync_list free_pages;
153153
static psync_list wait_page_hash[PAGE_WAITER_HASH];
154154
static char *pages_base;
155+
static uint32_t free_page_waiters=0;
156+
static int flush_page_running=0;
155157

156158
static psync_cachepage_to_update cachepages_to_update[DB_CACHE_UPDATE_HASH];
157159
static uint32_t cachepages_to_update_cnt=0;
@@ -161,6 +163,7 @@ static pthread_mutex_t clean_cache_mutex=PTHREAD_MUTEX_INITIALIZER;
161163
static pthread_cond_t clean_cache_cond=PTHREAD_COND_INITIALIZER;
162164
static pthread_mutex_t cache_mutex=PTHREAD_MUTEX_INITIALIZER;
163165
static pthread_mutex_t flush_cache_mutex=PTHREAD_MUTEX_INITIALIZER;
166+
static pthread_cond_t free_page_cond=PTHREAD_COND_INITIALIZER;
164167
static pthread_mutex_t url_cache_mutex=PTHREAD_MUTEX_INITIALIZER;
165168
static pthread_cond_t url_cache_cond=PTHREAD_COND_INITIALIZER;
166169
static pthread_mutex_t wait_page_mutex;
@@ -219,17 +222,29 @@ static psync_cache_page_t *psync_pagecache_get_free_page(int runflushcacheinside
219222
if (likely(!psync_list_isempty(&free_pages)))
220223
page=psync_list_remove_head_element(&free_pages, psync_cache_page_t, list);
221224
else{
222-
debug(D_NOTICE, "no free pages, flushing cache");
223-
pthread_mutex_unlock(&cache_mutex);
224-
flush_pages(1);
225-
pthread_mutex_lock(&cache_mutex);
226-
while (unlikely(psync_list_isempty(&free_pages))){
225+
if (flush_page_running){
226+
debug(D_NOTICE, "no free pages, but somebody is flushing cache, waiting for a page");
227+
do {
228+
free_page_waiters++;
229+
pthread_cond_wait(&free_page_cond, &cache_mutex);
230+
free_page_waiters--;
231+
} while (flush_page_running && psync_list_isempty(&free_pages));
232+
}
233+
if (psync_list_isempty(&free_pages)){
234+
debug(D_NOTICE, "no free pages, flushing cache");
227235
pthread_mutex_unlock(&cache_mutex);
228-
debug(D_NOTICE, "no free pages after flush, sleeping");
229-
psync_milisleep(200);
230236
flush_pages(1);
231237
pthread_mutex_lock(&cache_mutex);
238+
while (unlikely(psync_list_isempty(&free_pages))){
239+
pthread_mutex_unlock(&cache_mutex);
240+
debug(D_NOTICE, "no free pages after flush, sleeping");
241+
psync_milisleep(200);
242+
flush_pages(1);
243+
pthread_mutex_lock(&cache_mutex);
244+
}
232245
}
246+
else
247+
debug(D_NOTICE, "waited for a free page");
233248
page=psync_list_remove_head_element(&free_pages, psync_cache_page_t, list);
234249
}
235250
cache_pages_free--;
@@ -1122,6 +1137,9 @@ static int flush_pages(int nosleep){
11221137
time_t ctime;
11231138
uint32_t cpih;
11241139
int ret, diskfull;
1140+
pthread_mutex_lock(&cache_mutex);
1141+
flush_page_running++;
1142+
pthread_mutex_unlock(&cache_mutex);
11251143
flushedbetweentimers=1;
11261144
pthread_mutex_lock(&flush_cache_mutex);
11271145
diskfull=check_disk_full();
@@ -1158,6 +1176,8 @@ static int flush_pages(int nosleep){
11581176
}
11591177
debug(D_NOTICE, "discarded %u pages", (unsigned)i);
11601178
psync_list_init(&pages_to_flush);
1179+
if (free_page_waiters)
1180+
pthread_cond_broadcast(&free_page_cond);
11611181
}
11621182
if (cache_pages_in_hash){
11631183
debug(D_NOTICE, "flushing cache free_db_pages=%u", (unsigned)free_db_pages);
@@ -1256,7 +1276,7 @@ static int flush_pages(int nosleep){
12561276
pthread_mutex_unlock(&cache_mutex);
12571277
psync_sql_free_result(res);
12581278
psync_sql_commit_transaction();
1259-
if (!nosleep)
1279+
if (!nosleep && !free_page_waiters)
12601280
psync_milisleep(1);
12611281
psync_sql_start_transaction();
12621282
pthread_mutex_lock(&cache_mutex);
@@ -1292,10 +1312,13 @@ static int flush_pages(int nosleep){
12921312
psync_list_add_head(&free_pages, &page->list);
12931313
cache_pages_free++;
12941314
if (nosleep!=1 && updates%64==0){
1315+
if (free_page_waiters)
1316+
pthread_cond_broadcast(&free_page_cond);
12951317
pthread_mutex_unlock(&cache_mutex);
12961318
psync_sql_free_result(res);
12971319
psync_sql_commit_transaction();
1298-
psync_milisleep(1);
1320+
if (!free_page_waiters) // it is ok if we read a stale value, because we don't hold cache_mutex any more
1321+
psync_milisleep(1);
12991322
psync_sql_start_transaction();
13001323
pthread_mutex_lock(&cache_mutex);
13011324
res=psync_sql_prep_statement("UPDATE OR IGNORE pagecache SET hash=?, pageid=?, type="NTO_STR(PAGE_TYPE_READ)", lastuse=?, usecnt=?, size=?, crc=? WHERE id=?");
@@ -1320,7 +1343,8 @@ static int flush_pages(int nosleep){
13201343
pthread_mutex_unlock(&cache_mutex);
13211344
psync_sql_free_result(res);
13221345
psync_sql_commit_transaction();
1323-
psync_milisleep(1);
1346+
if (!free_page_waiters)
1347+
psync_milisleep(1);
13241348
psync_sql_start_transaction();
13251349
pthread_mutex_lock(&cache_mutex);
13261350
res=psync_sql_prep_statement("UPDATE pagecache SET lastuse=?, usecnt=usecnt+? WHERE id=?");
@@ -1332,6 +1356,11 @@ static int flush_pages(int nosleep){
13321356
lastflush=ctime;
13331357
}
13341358
flushcacherun=0;
1359+
flush_page_running--;
1360+
if (free_page_waiters){
1361+
debug(D_NOTICE, "finished flushing cache, but there are still free page waiters, broadcasting");
1362+
pthread_cond_broadcast(&free_page_cond);
1363+
}
13351364
if (updates){
13361365
pthread_mutex_unlock(&cache_mutex);
13371366
ret=psync_sql_commit_transaction();

0 commit comments

Comments
 (0)