X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=blobdiff_plain;f=bluesky%2Fcache.c;h=b20960c1a7c4b5d0ee741c0dfebb79eb94646226;hp=16e3d8162d21561974cd9e1f54a8ee153ba7d8ba;hb=b52abd849493636b81dda8c752a60834f1a6b91f;hpb=1b57824ed22fb6a40a0f85e5cbc3b0a9538b08ec diff --git a/bluesky/cache.c b/bluesky/cache.c index 16e3d81..b20960c 100644 --- a/bluesky/cache.c +++ b/bluesky/cache.c @@ -421,9 +421,50 @@ void bluesky_flushd_invoke(BlueSkyFS *fs) g_thread_create((GThreadFunc)flushd_task, fs, FALSE, NULL); } -void bluesky_flushd_invoke_conditional(BlueSkyFS *fs) +/* How urgent is flushing out data? Returns one of several values: + * 0 - memory state is fine + * 1 - should launch flushd if not already running + * 2 - should block writers until memory frees up + */ +static int compute_pressure(BlueSkyFS *fs) { + /* LEVEL 2 */ + /* Too much dirty data in memory? */ + if (g_atomic_int_get(&fs->cache_dirty) + + g_atomic_int_get(&fs->cache_log_dirty) + > bluesky_watermark_high_dirty) + return 2; + + /* Too much uncommitted data in the journal on disk, not yet flushed to the + * cloud? */ + printf("Dirty journals: %d to %d\n", + fs->log->journal_watermark, fs->log->seq_num); + int dirty_limit; + dirty_limit = bluesky_options.cache_size / (LOG_SEGMENT_SIZE / 1024) / 2; + int dirty_journals = fs->log->seq_num - fs->log->journal_watermark + 1; + if (dirty_journals > 1 && dirty_journals >= dirty_limit) { + printf("Too many dirty journals (%d >= %d)\n", + dirty_journals, dirty_limit); + return 2; + } + + /* LEVEL 1 */ if (g_atomic_int_get(&fs->cache_dirty) < bluesky_watermark_medium_dirty) + return 1; + + if (dirty_journals > 1 && dirty_journals > dirty_limit / 2) { + printf("Many dirty journals (%d), should start writeback\n", + dirty_journals); + return 1; + } + + return 0; +} + +void bluesky_flushd_invoke_conditional(BlueSkyFS *fs) +{ + int pressure = compute_pressure(fs); + if (pressure == 0) return; if (bluesky_verbose) { @@ -436,16 +477,17 @@ void bluesky_flushd_invoke_conditional(BlueSkyFS *fs) /* If the system is under heavy memory pressure, actually delay execution * so the flush daemon can catch up. */ - while (g_atomic_int_get(&fs->cache_dirty) - + g_atomic_int_get(&fs->cache_log_dirty) - > bluesky_watermark_high_dirty) { + while (pressure > 1) { g_log("bluesky/flushd", G_LOG_LEVEL_DEBUG, "Waiting due to memory pressure, dirty=%d + %d", g_atomic_int_get(&fs->cache_dirty), g_atomic_int_get(&fs->cache_log_dirty)); g_mutex_lock(fs->lock); - g_cond_wait(fs->flushd_cond, fs->lock); + pressure = compute_pressure(fs); + if (pressure > 1) + g_cond_wait(fs->flushd_cond, fs->lock); g_mutex_unlock(fs->lock); + pressure = compute_pressure(fs); } }