Skip to content

Commit df025b1

Browse files
committed
improved the correctness of Cache_bgdl()
1 parent f5aceba commit df025b1

3 files changed

Lines changed: 71 additions & 48 deletions

File tree

src/cache.c

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -387,14 +387,19 @@ static Cache *Cache_alloc()
387387
exit(EXIT_FAILURE);
388388
}
389389

390-
if (pthread_mutex_init(&cf->rw_lock, NULL)) {
391-
fprintf(stderr, "Cache_alloc(): rw_lock initialisation failed!\n");
390+
if (pthread_mutexattr_init(&cf->rw_lock_attr)) {
391+
fprintf(stderr,
392+
"Cache_alloc(): rw_lock_attr initialisation failed!\n");
392393
}
393394

394-
if (pthread_mutex_init(&cf->bgt_lock, NULL)) {
395-
fprintf(stderr, "Cache_alloc(): seg_lock initialisation failed!\n");
395+
if (pthread_mutexattr_setpshared(&cf->rw_lock_attr,
396+
PTHREAD_PROCESS_SHARED)) {
397+
fprintf(stderr, "Cache_alloc(): could not set rw_lock_attr!\n");
396398
}
397399

400+
if (pthread_mutex_init(&cf->rw_lock, &cf->rw_lock_attr)) {
401+
fprintf(stderr, "Cache_alloc(): rw_lock initialisation failed!\n");
402+
}
398403

399404
if (pthread_mutexattr_init(&cf->bgt_lock_attr)) {
400405
fprintf(stderr,
@@ -422,6 +427,10 @@ static void Cache_free(Cache *cf)
422427
fprintf(stderr, "Cache_free(): could not destroy rw_lock!\n");
423428
}
424429

430+
if (pthread_mutexattr_destroy(&cf->rw_lock_attr)) {
431+
fprintf(stderr, "Cache_alloc(): could not destroy rw_lock_attr!\n");
432+
}
433+
425434
if (pthread_mutex_destroy(&cf->bgt_lock)) {
426435
fprintf(stderr, "Cache_free(): could not destroy bgt_lock!\n");
427436
}
@@ -748,11 +757,12 @@ static void Seg_set(Cache *cf, off_t offset, int i)
748757
* segment, we can spawn a pthread using this function to download the next
749758
* segment.
750759
*/
751-
static void *Cache_bg_download(void *arg)
760+
static void *Cache_bgdl(void *arg)
752761
{
753762
Cache *cf = (Cache *) arg;
763+
pthread_mutex_lock(&cf->rw_lock);
754764
uint8_t *recv_buf = calloc(DATA_BLK_SZ, sizeof(uint8_t));
755-
fprintf(stderr, "Cache_bg_download(): ");
765+
fprintf(stderr, "Cache_bgdl(): ");
756766
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
757767
cf->next_offset);
758768
if ( (recv == cf->blksz) ||
@@ -762,75 +772,87 @@ static void *Cache_bg_download(void *arg)
762772
Seg_set(cf, cf->next_offset, 1);
763773
} else {
764774
fprintf(stderr,
765-
"Cache_bg_download(): recv (%ld) < cf->blksz! \
775+
"Cache_bgdl(): recv (%ld) < cf->blksz! \
766776
Possible network error?\n",
767777
recv);
768778
}
769779
free(recv_buf);
770780
pthread_mutex_unlock(&cf->bgt_lock);
781+
pthread_mutex_unlock(&cf->rw_lock);
771782
pthread_exit(NULL);
772783
}
773784

774785
long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
775786
{
776-
/*
777-
* Quick fix for SIGFPE,
778-
* this shouldn't happen in the first place!
779-
*/
787+
// size_t start = offset;
788+
// size_t end = start + len;
789+
// char range_str[64];
790+
// snprintf(range_str, sizeof(range_str), "%lu-%lu", start, end);
791+
// fprintf(stderr, "Cache_read(%s, %s);\n", cf->path, range_str);
792+
793+
/* SIGFPE prevention, although this shouldn't happen in the first place! */
780794
if (!cf->blksz) {
781795
fprintf(stderr,
782796
"Cache_read(): Warning: cf->blksz: %d, directly downloading",
783797
cf->blksz);
784798
return path_download(cf->path, output_buf, len, offset);
785799
}
786800

787-
pthread_mutex_lock(&cf->rw_lock);
788801
long send;
789-
/* Calculate the aligned offset */
790802
off_t dl_offset = offset / cf->blksz * cf->blksz;
803+
804+
/* ------------------ Check if the segment already exists ---------------*/
791805
if (Seg_exist(cf, offset)) {
792-
/*
793-
* The metadata shows the segment already exists. This part is easy,
794-
* as you don't have to worry about alignment
795-
*/
796806
send = Data_read(cf, (uint8_t *) output_buf, len, offset);
807+
goto bgdl;
797808
} else {
798-
/* Download the segment */
799-
fprintf(stderr, "Cache_read(): ");
800-
uint8_t *recv_buf = calloc(DATA_BLK_SZ, sizeof(uint8_t));
801-
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
802-
dl_offset);
803-
/*
804-
* check if we have received enough data
805-
* send it off, then write it to the disk
806-
*
807-
* Condition 1: received the exact amount as the segment size.
808-
* Condition 2: offset is the last segment
809-
*/
810-
if ( (recv == cf->blksz) ||
811-
(dl_offset == (cf->content_length / cf->blksz * cf->blksz)) )
812-
{
813-
memmove(output_buf, recv_buf + (offset - dl_offset), len);
814-
send = len;
815-
Data_write(cf, recv_buf, cf->blksz, dl_offset);
816-
Seg_set(cf, dl_offset, 1);
817-
} else {
818-
memmove(output_buf, recv_buf + (offset - dl_offset), recv);
819-
send = recv;
820-
fprintf(stderr,
821-
"Cache_read(): recv (%ld) < cf->blksz! Possible network error?\n",
822-
recv);
809+
/* Wait until the background thread finishes, then lock the I/O */
810+
pthread_mutex_lock(&cf->rw_lock);
811+
if (Seg_exist(cf, offset)) {
812+
/* The segment already exists, send it off the unlock the I/O */
813+
send = Data_read(cf, (uint8_t *) output_buf, len, offset);
814+
pthread_mutex_unlock(&cf->rw_lock);
815+
goto bgdl;
823816
}
824-
free(recv_buf);
825817
}
818+
819+
/* ------------------------Download the segment -------------------------*/
820+
821+
uint8_t *recv_buf = calloc(DATA_BLK_SZ, sizeof(uint8_t));
822+
fprintf(stderr, "Cache_read(): ");
823+
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
824+
dl_offset);
825+
/*
826+
* check if we have received enough data
827+
* send it off, then write it to the disk
828+
*
829+
* Condition 1: received the exact amount as the segment size.
830+
* Condition 2: offset is the last segment
831+
*/
832+
if ( (recv == cf->blksz) ||
833+
(dl_offset == (cf->content_length / cf->blksz * cf->blksz)) )
834+
{
835+
memmove(output_buf, recv_buf + (offset - dl_offset), len);
836+
send = len;
837+
Data_write(cf, recv_buf, cf->blksz, dl_offset);
838+
Seg_set(cf, dl_offset, 1);
839+
} else {
840+
memmove(output_buf, recv_buf + (offset - dl_offset), recv);
841+
send = recv;
842+
fprintf(stderr,
843+
"Cache_read(): recv (%ld) < cf->blksz! Possible network error?\n",
844+
recv);
845+
}
846+
free(recv_buf);
826847
pthread_mutex_unlock(&cf->rw_lock);
827848

828-
/* Download the next segment in background */
849+
/* -----------Download the next segment in background -------------------*/
850+
bgdl:
829851
cf->next_offset = round_div(offset, cf->blksz) * cf->blksz;
830852
if ( (cf->next_offset > dl_offset) && !Seg_exist(cf, cf->next_offset) ) {
831853
/* Stop the spawning of multiple background pthreads */
832854
if(!pthread_mutex_trylock(&cf->bgt_lock)) {
833-
if (pthread_create(&cf->bgt, NULL, Cache_bg_download, cf)) {
855+
if (pthread_create(&cf->bgt, NULL, Cache_bgdl, cf)) {
834856
fprintf(stderr,
835857
"Cache_read(): Error creating background download thread\n"
836858
);

src/cache.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ typedef struct {
3030

3131
pthread_t bgt; /**< background pthread */
3232
pthread_mutex_t bgt_lock; /**< mutex for spawning a background thread */
33-
pthread_mutexattr_t bgt_lock_attr;
33+
pthread_mutexattr_t bgt_lock_attr; /**< attributes for bgt_lock */
3434
off_t next_offset; /**<the offset of the next segment to be
3535
downloaded in background*/
3636

3737
pthread_mutex_t rw_lock; /**< mutex for read/write operation */
38+
pthread_mutexattr_t rw_lock_attr; /**< attributes for rw_lock */
39+
3840
FILE *dfp; /**< The FILE pointer for the data file*/
3941
FILE *mfp; /**< The FILE pointer for the metadata */
4042
int blksz; /**<the block size of the data file */

src/link.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,13 +411,12 @@ long path_download(const char *path, char *output_buf, size_t size,
411411
size_t end = start + size;
412412
char range_str[64];
413413
snprintf(range_str, sizeof(range_str), "%lu-%lu", start, end);
414+
fprintf(stderr, "path_download(%s, %s);\n", path, range_str);
414415

415416
MemoryStruct buf;
416417
buf.size = 0;
417418
buf.memory = NULL;
418419

419-
fprintf(stderr, "path_download(%s, %s);\n", path, range_str);
420-
421420
CURL *curl = Link_to_curl(link);
422421
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buf);
423422
curl_easy_setopt(curl, CURLOPT_RANGE, range_str);

0 commit comments

Comments
 (0)