@@ -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! \
766776Possible 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
774785long 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 );
0 commit comments