From 3f17b101eebe8f266c63781f32d0a454dcb1e7d0 Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Mon, 24 Apr 2017 13:28:37 +0300 Subject: cache: fix unnecessary seek blocking from f4d62dc4a0 Commit 374600cec0 ("cache: propagate seek failures") changed stream-level seeks to be done in the calling thread so possible errors could be reported. This commit included some rationale why doing the stream-level seeks synchronously was not a big issue. However, the following fixup commit f4d62dc4a0 changed the seek code to always synchronize with the cache thread and do seek handling there. This is a problem because it affects even seeks within already cached data (which require no stream-level seek). With a network server that sends data in bursts, the cache thread can be blocked in a read call for a long time; the added synchronization means that seeking within already downloaded data can have unnecessary long delays. Change cache_seek() to check whether the seek is expected to result in a stream-level seek, and skip synchronization if it is not. This means that seeks within the cached portion of the file now again happen immediately without possibly waiting for network. Signed-off-by: wm4 --- stream/cache.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'stream') diff --git a/stream/cache.c b/stream/cache.c index 52bf86ba01..a74c58df77 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -602,16 +602,25 @@ static int cache_seek(stream_t *cache, int64_t pos) r = 0; } else { cache->pos = s->read_filepos = s->read_min = pos; - s->eof = false; // so that cache_read() will actually wait for new data - s->control = CACHE_CTRL_SEEK; - s->control_res = 0; - double retry = 0; - while (s->control != CACHE_CTRL_NONE) { - if (!cache_wakeup_and_wait(s, &retry)) - break; + // Is this seek likely to cause a stream-level seek? + // If it is, wait until that is complete and return its result. + // This check is not quite exact - if the reader thread is blocked in + // a read, the read might advance file position enough that a seek + // forward is no longer needed. + if (pos < s->min_filepos || pos > s->max_filepos + s->seek_limit) { + s->eof = false; + s->control = CACHE_CTRL_SEEK; + s->control_res = 0; + double retry = 0; + while (s->control != CACHE_CTRL_NONE) { + if (!cache_wakeup_and_wait(s, &retry)) + break; + } + r = s->control_res; + } else { + pthread_cond_signal(&s->wakeup); + r = 1; } - r = s->control_res; - pthread_cond_signal(&s->wakeup); } pthread_mutex_unlock(&s->mutex); -- cgit v1.2.3