Skip to content

Commit e442871

Browse files
committed
added Cache_background_download() to enable the download of the next block
1 parent 12c19e3 commit e442871

5 files changed

Lines changed: 115 additions & 33 deletions

File tree

Makefile

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
VERSION=1.1.0
22

3-
CFLAGS+= -g -O2 -Wall -Wextra -D_FILE_OFFSET_BITS=64 -DVERSION=\"$(VERSION)\" `pkg-config --cflags-only-I gumbo libcurl fuse`
4-
LDFLAGS+= -lgumbo -lcurl -lfuse -lcrypto `pkg-config --libs-only-L gumbo libcurl fuse`
3+
CFLAGS+= -g -O2 -Wall -Wextra -D_FILE_OFFSET_BITS=64 -DVERSION=\"$(VERSION)\" \
4+
`pkg-config --cflags-only-I gumbo libcurl fuse`
5+
LDFLAGS+= -pthread -lgumbo -lcurl -lfuse -lcrypto \
6+
`pkg-config --libs-only-L gumbo libcurl fuse`
57
COBJS = main.o network.o fuse_local.o link.o cache.o util.o
68

79
prefix ?= /usr/local

src/cache.c

Lines changed: 90 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ typedef enum {
4545

4646
int CACHE_SYSTEM_INIT = 0;
4747

48-
/**
49-
* \brief the receive buffer
50-
*/
51-
static uint8_t RECV_BUF[DATA_BLK_SZ];
52-
5348
/**
5449
* \brief The metadata directory
5550
*/
@@ -280,19 +275,13 @@ static long Data_size(const char *fn)
280275
* - negative values on error,
281276
* - otherwise, the number of bytes read.
282277
*/
283-
static long Data_read(const Cache *cf, uint8_t *buf, off_t len, off_t offset)
278+
static long Data_read(Cache *cf, uint8_t *buf, off_t len, off_t offset)
284279
{
285280
if (len == 0) {
286281
fprintf(stderr, "Data_read(): requested to read 0 byte!\n");
287282
return -EINVAL;
288283
}
289284

290-
size_t start = offset;
291-
size_t end = start + len;
292-
char range_str[64];
293-
snprintf(range_str, sizeof(range_str), "%lu-%lu", start, end);
294-
fprintf(stderr, "Data_read(%s, %s);\n", cf->path, range_str);
295-
296285
long byte_read = -EIO;
297286

298287
if (fseeko(cf->dfp, offset, SEEK_SET)) {
@@ -332,20 +321,14 @@ static long Data_read(const Cache *cf, uint8_t *buf, off_t len, off_t offset)
332321
* - otherwise, the number of bytes written.
333322
*/
334323

335-
static long Data_write(const Cache *cf, const uint8_t *buf, off_t len,
324+
static long Data_write(Cache *cf, const uint8_t *buf, off_t len,
336325
off_t offset)
337326
{
338327
if (len == 0) {
339328
fprintf(stderr, "Data_write(): requested to write 0 byte!\n");
340329
return -EINVAL;
341330
}
342331

343-
size_t start = offset;
344-
size_t end = start + len;
345-
char range_str[64];
346-
snprintf(range_str, sizeof(range_str), "%lu-%lu", start, end);
347-
fprintf(stderr, "Data_write(%s, %s);\n", cf->path, range_str);
348-
349332
long byte_written = -EIO;
350333

351334
if (fseeko(cf->dfp, offset, SEEK_SET)) {
@@ -404,8 +387,26 @@ static Cache *Cache_alloc()
404387
}
405388

406389
if (pthread_mutex_init(&cf->rw_lock, NULL)) {
407-
printf(
408-
"Cache_alloc(): rw_lock initialisation failed!\n");
390+
fprintf(stderr, "Cache_alloc(): rw_lock initialisation failed!\n");
391+
}
392+
393+
if (pthread_mutex_init(&cf->bgt_lock, NULL)) {
394+
fprintf(stderr, "Cache_alloc(): seg_lock initialisation failed!\n");
395+
}
396+
397+
398+
if (pthread_mutexattr_init(&cf->bgt_lock_attr)) {
399+
fprintf(stderr,
400+
"Cache_alloc(): bgt_lock_attr initialisation failed!\n");
401+
}
402+
403+
if (pthread_mutexattr_setpshared(&cf->bgt_lock_attr,
404+
PTHREAD_PROCESS_SHARED)) {
405+
fprintf(stderr, "Cache_alloc(): could not set bgt_lock_attr!\n");
406+
}
407+
408+
if (pthread_mutex_init(&cf->bgt_lock, NULL)) {
409+
fprintf(stderr, "Cache_alloc(): bgt_lock initialisation failed!\n");
409410
}
410411

411412
return cf;
@@ -420,12 +421,21 @@ static void Cache_free(Cache *cf)
420421
fprintf(stderr, "Cache_free(): could not destroy rw_lock!\n");
421422
}
422423

424+
if (pthread_mutex_destroy(&cf->bgt_lock)) {
425+
fprintf(stderr, "Cache_free(): could not destroy bgt_lock!\n");
426+
}
427+
428+
if (pthread_mutexattr_destroy(&cf->bgt_lock_attr)) {
429+
fprintf(stderr, "Cache_alloc(): could not destroy bgt_lock_attr!\n");
430+
}
431+
423432
if (cf->path) {
424433
free(cf->path);
425434
}
426435
if (cf->seg) {
427436
free(cf->seg);
428437
}
438+
429439
free(cf);
430440
}
431441

@@ -626,7 +636,6 @@ Cache *Cache_open(const char *fn)
626636
{
627637
/* Check if both metadata and data file exist */
628638
if (!Cache_exist(fn)) {
629-
// fprintf(stderr, "dataset does not exist!\n");
630639
return NULL;
631640
}
632641

@@ -689,6 +698,10 @@ cf->content_length: %ld, Data_size(fn): %ld.\n", fn, cf->content_length,
689698

690699
void Cache_close(Cache *cf)
691700
{
701+
/* Must wait for the background download thread to stop */
702+
pthread_mutex_lock(&cf->bgt_lock);
703+
pthread_mutex_unlock(&cf->bgt_lock);
704+
692705
if (Meta_write(cf)) {
693706
fprintf(stderr, "Cache_close(): Meta_write() error.");
694707
}
@@ -728,9 +741,41 @@ static void Seg_set(Cache *cf, off_t offset, int i)
728741
cf->seg[byte] = i;
729742
}
730743

744+
/**
745+
* \brief Background download function
746+
* \details If we are requesting the data from the second half of the current
747+
* segment, we can spawn a pthread using this function to download the next
748+
* segment.
749+
*/
750+
static void *Cache_background_download(void *arg)
751+
{
752+
fprintf(stderr, "Starting Cache_background_download in its own thread.\n");
753+
Cache *cf = (Cache *) arg;
754+
uint8_t recv_buf[DATA_BLK_SZ];
755+
756+
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
757+
cf->next_offset);
758+
if ( (recv == cf->blksz) ||
759+
(cf->next_offset == (cf->content_length / cf->blksz * cf->blksz)) )
760+
{
761+
Data_write(cf, recv_buf, cf->blksz, cf->next_offset);
762+
Seg_set(cf, cf->next_offset, 1);
763+
} else {
764+
fprintf(stderr,
765+
"Cache_background_download(): recv (%ld) < cf->blksz! \
766+
Possible network error?\n",
767+
recv);
768+
}
769+
770+
pthread_mutex_unlock(&cf->bgt_lock);
771+
fprintf(stderr, "Exiting Cache_background_download thread.\n");
772+
pthread_exit(NULL);
773+
}
774+
731775
long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
732776
{
733777
long send;
778+
uint8_t recv_buf[DATA_BLK_SZ];
734779
/*
735780
* Quick fix for SIGFPE,
736781
* this shouldn't happen in the first place!
@@ -741,18 +786,19 @@ long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
741786
cf->blksz);
742787
return path_download(cf->path, output_buf, len, offset);
743788
}
789+
744790
pthread_mutex_lock(&cf->rw_lock);
791+
/* Calculate the aligned offset */
792+
off_t dl_offset = offset / cf->blksz * cf->blksz;
745793
if (Seg_exist(cf, offset)) {
746794
/*
747795
* The metadata shows the segment already exists. This part is easy,
748796
* as you don't have to worry about alignment
749797
*/
750798
send = Data_read(cf, (uint8_t *) output_buf, len, offset);
751799
} else {
752-
/* Calculate the aligned offset */
753-
off_t dl_offset = offset / cf->blksz * cf->blksz;
754800
/* Download the segment */
755-
long recv = path_download(cf->path, (char *) RECV_BUF, cf->blksz,
801+
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
756802
dl_offset);
757803
/*
758804
* check if we have received enough data
@@ -762,19 +808,34 @@ long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
762808
* Condition 2: offset is the last segment
763809
*/
764810
if ( (recv == cf->blksz) ||
765-
(dl_offset == (cf->content_length / cf->blksz * cf->blksz)) ) {
766-
memmove(output_buf, RECV_BUF + (offset - dl_offset), len);
811+
(dl_offset == (cf->content_length / cf->blksz * cf->blksz)) )
812+
{
813+
memmove(output_buf, recv_buf + (offset - dl_offset), len);
767814
send = len;
768-
Data_write(cf, RECV_BUF, cf->blksz, dl_offset);
815+
Data_write(cf, recv_buf, cf->blksz, dl_offset);
769816
Seg_set(cf, dl_offset, 1);
770817
} else {
771-
memmove(output_buf, RECV_BUF + (offset - dl_offset), recv);
818+
memmove(output_buf, recv_buf + (offset - dl_offset), recv);
772819
send = recv;
773820
fprintf(stderr,
774821
"Cache_read(): recv (%ld) < cf->blksz! Possible network error?\n",
775822
recv);
776823
}
777824
}
778825
pthread_mutex_unlock(&cf->rw_lock);
826+
827+
/* Download the next segment in background */
828+
cf->next_offset = round_div(offset, cf->blksz) * cf->blksz;
829+
if ( (cf->next_offset > dl_offset) && !Seg_exist(cf, cf->next_offset) ) {
830+
/* Stop the spawning of multiple background pthreads */
831+
if(!pthread_mutex_trylock(&cf->bgt_lock)) {
832+
if (pthread_create(&cf->bgt, NULL, Cache_background_download, cf)) {
833+
fprintf(stderr,
834+
"Cache_read(): Error creating background download thread\n"
835+
);
836+
}
837+
}
838+
}
839+
779840
return send;
780841
}

src/cache.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,19 @@ typedef uint8_t Seg;
2424
*/
2525
typedef struct {
2626
char *path; /**< the path to the file on the web server */
27+
Link *link; /**< The Link associated with this cache data set */
2728
long time; /**<the modified time of the file */
2829
off_t content_length; /**<the size of the file */
29-
pthread_mutex_t rw_lock; /**< mutex for disk operation */
30+
31+
pthread_t bgt; /**< background pthread */
32+
pthread_mutex_t bgt_lock; /**< mutex for spawning a background thread */
33+
pthread_mutexattr_t bgt_lock_attr;
34+
off_t next_offset; /**<the offset of the next segment to be
35+
downloaded in background*/
36+
37+
pthread_mutex_t rw_lock; /**< mutex for read/write operation */
3038
FILE *dfp; /**< The FILE pointer for the data file*/
3139
FILE *mfp; /**< The FILE pointer for the metadata */
32-
Link *link; /**< The Link associated with this cache data set */
3340
int blksz; /**<the block size of the data file */
3441
long segbc; /**<segment array byte count */
3542
Seg *seg; /**< the detail of each segment */

src/util.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@ char *strndupcat(const char *a, const char *b, int n)
2828
c[nc-1] = '\0';
2929
return c;
3030
}
31+
32+
int64_t round_div(int64_t a, int64_t b)
33+
{
34+
return (a + (b / 2)) / b;
35+
}

src/util.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef UTIL_H
22
#define UTIL_H
33

4+
#include <stdint.h>
5+
46
/**
57
* \file util.h
68
* \brief utility functions
@@ -16,4 +18,9 @@
1618
*/
1719
char *strndupcat(const char *a, const char *b, int n);
1820

21+
/**
22+
* \brief division, but rounded to the nearest integer rather than truncating
23+
*/
24+
int64_t round_div(int64_t a, int64_t b);
25+
1926
#endif

0 commit comments

Comments
 (0)