Fixed buffer over-read at the boundary.
- Say we are using a lock size of 1024k, we send a request for 128k at 1008k. It won't trigger the download, because we already download 1024k at 0. So it would read off from the empty disk space! - This problem only occurs during the first time you download a file. During subsequent accesses, when you are only reading from the cache, this problem does not occur.
This commit is contained in:
parent
9e3e4747ae
commit
6c8a15d8cc
28
src/cache.c
28
src/cache.c
|
@ -948,14 +948,16 @@ static void *Cache_bgdl(void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
const off_t offset)
|
const off_t offset_start)
|
||||||
{
|
{
|
||||||
long send;
|
long send;
|
||||||
off_t dl_offset = offset / cf->blksz * cf->blksz;
|
|
||||||
|
/* The offset of the segment to be downloaded */
|
||||||
|
off_t dl_offset = (offset_start + len) / cf->blksz * cf->blksz;
|
||||||
|
|
||||||
/* ------------------ Check if the segment already exists ---------------*/
|
/* ------------------ Check if the segment already exists ---------------*/
|
||||||
if (Seg_exist(cf, offset)) {
|
if (Seg_exist(cf, dl_offset)) {
|
||||||
send = Data_read(cf, (uint8_t *) output_buf, len, offset);
|
send = Data_read(cf, (uint8_t *) output_buf, len, offset_start);
|
||||||
goto bgdl;
|
goto bgdl;
|
||||||
} else {
|
} else {
|
||||||
/* Wait for any other download thread to finish*/
|
/* Wait for any other download thread to finish*/
|
||||||
|
@ -964,10 +966,10 @@ long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
pthread_self());
|
pthread_self());
|
||||||
#endif
|
#endif
|
||||||
PTHREAD_MUTEX_LOCK(&cf->w_lock);
|
PTHREAD_MUTEX_LOCK(&cf->w_lock);
|
||||||
if (Seg_exist(cf, offset)) {
|
if (Seg_exist(cf, dl_offset)) {
|
||||||
/* The segment now exists - it was downloaded by another
|
/* The segment now exists - it was downloaded by another
|
||||||
* download thread. Send it off and unlock the I/O */
|
* download thread. Send it off and unlock the I/O */
|
||||||
send = Data_read(cf, (uint8_t *) output_buf, len, offset);
|
send = Data_read(cf, (uint8_t *) output_buf, len, offset_start);
|
||||||
#ifdef CACHE_LOCK_DEBUG
|
#ifdef CACHE_LOCK_DEBUG
|
||||||
fprintf(stderr, "Cache_read(): thread %lu: unlocking w_lock;\n",
|
fprintf(stderr, "Cache_read(): thread %lu: unlocking w_lock;\n",
|
||||||
pthread_self());
|
pthread_self());
|
||||||
|
@ -983,13 +985,6 @@ long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
fprintf(stderr, "Cache_read(): thread %lu: ", pthread_self());
|
fprintf(stderr, "Cache_read(): thread %lu: ", pthread_self());
|
||||||
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
|
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
|
||||||
dl_offset);
|
dl_offset);
|
||||||
if (recv < len) {
|
|
||||||
send = recv;
|
|
||||||
} else {
|
|
||||||
send = len;
|
|
||||||
}
|
|
||||||
memmove(output_buf, recv_buf + (offset - dl_offset), send);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* check if we have received enough data, write it to the disk
|
* check if we have received enough data, write it to the disk
|
||||||
*
|
*
|
||||||
|
@ -1006,6 +1001,7 @@ long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
"Cache_read(): received %ld, possible network error.\n", recv);
|
"Cache_read(): received %ld, possible network error.\n", recv);
|
||||||
}
|
}
|
||||||
free(recv_buf);
|
free(recv_buf);
|
||||||
|
send = Data_read(cf, (uint8_t *) output_buf, len, offset_start);
|
||||||
|
|
||||||
#ifdef CACHE_LOCK_DEBUG
|
#ifdef CACHE_LOCK_DEBUG
|
||||||
fprintf(stderr, "Cache_read(): thread %lu: unlocking w_lock;\n",
|
fprintf(stderr, "Cache_read(): thread %lu: unlocking w_lock;\n",
|
||||||
|
@ -1015,7 +1011,9 @@ long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
|
|
||||||
/* -----------Download the next segment in background -------------------*/
|
/* -----------Download the next segment in background -------------------*/
|
||||||
bgdl:
|
bgdl:
|
||||||
if ( (cf->next_offset > dl_offset) &&
|
;
|
||||||
|
off_t next_offset = round_div(offset_start, cf->blksz) * cf->blksz;
|
||||||
|
if ( (next_offset > dl_offset) &&
|
||||||
!Seg_exist(cf, cf->next_offset) &&
|
!Seg_exist(cf, cf->next_offset) &&
|
||||||
cf->next_offset < cf->content_length ){
|
cf->next_offset < cf->content_length ){
|
||||||
/* Stop the spawning of multiple background pthreads */
|
/* Stop the spawning of multiple background pthreads */
|
||||||
|
@ -1024,7 +1022,7 @@ long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
fprintf(stderr, "Cache_read(): thread %lu: trylocked bgt_lock;\n",
|
fprintf(stderr, "Cache_read(): thread %lu: trylocked bgt_lock;\n",
|
||||||
pthread_self());
|
pthread_self());
|
||||||
#endif
|
#endif
|
||||||
cf->next_offset = round_div(offset, cf->blksz) * cf->blksz;
|
cf->next_offset = next_offset;
|
||||||
if (pthread_create(&cf->bgt, NULL, Cache_bgdl, cf)) {
|
if (pthread_create(&cf->bgt, NULL, Cache_bgdl, cf)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Cache_read(): Error creating background download thread\n"
|
"Cache_read(): Error creating background download thread\n"
|
||||||
|
|
|
@ -136,10 +136,10 @@ void Cache_delete(const char *fn);
|
||||||
* \param[in] cf the cache in-memory data structure
|
* \param[in] cf the cache in-memory data structure
|
||||||
* \param[out] output_buf the output buffer
|
* \param[out] output_buf the output buffer
|
||||||
* \param[in] len the requested segment size
|
* \param[in] len the requested segment size
|
||||||
* \param[in] offset the start of the segment
|
* \param[in] offset_start the start of the segment
|
||||||
* \return the length of the segment the cache system managed to obtain.
|
* \return the length of the segment the cache system managed to obtain.
|
||||||
* \note Called by fs_read(), verified to be working
|
* \note Called by fs_read(), verified to be working
|
||||||
*/
|
*/
|
||||||
long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
||||||
const off_t offset);
|
const off_t offset_start);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue