Stability improvement

Metadata corruption still occasionally happens when it gets read in.
I suspect it is due to some sort of race condition.
This commit is contained in:
Fufu Fang 2019-04-23 19:37:01 +01:00
parent fb8a132c14
commit 3a0c431bba
4 changed files with 51 additions and 31 deletions

View File

@ -124,10 +124,10 @@ static int Meta_read(Cache *cf)
return EFREAD;
}
fread(&(cf->time), sizeof(long), 1, fp);
fread(&(cf->content_length), sizeof(off_t), 1, fp);
fread(&(cf->blksz), sizeof(int), 1, fp);
fread(&(cf->segbc), sizeof(long), 1, fp);
fread(&cf->time, sizeof(long), 1, fp);
fread(&cf->content_length, sizeof(off_t), 1, fp);
fread(&cf->blksz, sizeof(int), 1, fp);
fread(&cf->segbc, sizeof(long), 1, fp);
/* Error checking for fread */
if (ferror(fp)) {
@ -194,7 +194,7 @@ blksz: %d, segbc: %ld\n", cf->content_length, cf->blksz, cf->segbc);
* - -1 on error,
* - 0 on success
*/
static int Meta_write(const Cache *cf)
static int Meta_write(Cache *cf)
{
FILE *fp;
char *metafn = strndupcat(META_DIR, cf->path, MAX_PATH_LEN);
@ -215,10 +215,10 @@ static int Meta_write(const Cache *cf)
%ld\n", cf->content_length, cf->blksz, cf->segbc);
}
fwrite(&(cf->time), sizeof(long), 1, fp);
fwrite(&(cf->content_length), sizeof(off_t), 1, fp);
fwrite(&(cf->blksz), sizeof(int), 1, fp);
fwrite(&(cf->segbc), sizeof(long), 1, fp);
fwrite(&cf->time, sizeof(long), 1, fp);
fwrite(&cf->content_length, sizeof(off_t), 1, fp);
fwrite(&cf->blksz, sizeof(int), 1, fp);
fwrite(&cf->segbc, sizeof(long), 1, fp);
fwrite(cf->seg, sizeof(Seg), cf->segbc, fp);
/* Error checking for fwrite */
@ -434,6 +434,17 @@ static Cache *Cache_alloc()
fprintf(stderr, "Cache_new(): calloc failure!\n");
exit(EXIT_FAILURE);
}
if (pthread_mutex_init(&cf->rw_lock, NULL)) {
printf(
"Cache_alloc(): rw_lock initialisation failed!\n");
}
if (pthread_mutex_init(&cf->meta_lock, NULL)) {
printf(
"Cache_alloc(): cf->meta_lock initialisation failed!\n");
}
return cf;
}
@ -442,6 +453,14 @@ static Cache *Cache_alloc()
*/
static void Cache_free(Cache *cf)
{
if (pthread_mutex_destroy(&cf->rw_lock)) {
fprintf(stderr, "Cache_free(): could not destroy rw_lock!\n");
}
if (pthread_mutex_destroy(&cf->meta_lock)) {
fprintf(stderr, "Cache_free(): could not destroy meta_lock!\n");
}
if (cf->path) {
free(cf->path);
}
@ -504,6 +523,7 @@ static int Cache_exist(const char *fn)
*/
void Cache_delete(const char *fn)
{
fprintf(stderr, "Cache_delete(): deleting %s\n", fn);
char *metafn = strndupcat(META_DIR, fn, MAX_PATH_LEN);
char *datafn = strndupcat(DATA_DIR, fn, MAX_PATH_LEN);
if (!access(metafn, F_OK)) {
@ -569,9 +589,12 @@ int Cache_create(Link *this_link)
fprintf(stderr, "Cache_create(): Data_create() failed!\n");
}
pthread_mutex_lock(&cf->meta_lock);
if (Meta_create(cf)) {
fprintf(stderr, "Cache_create(): Meta_create() failed!\n");
}
pthread_mutex_unlock(&cf->meta_lock);
Cache_free(cf);
@ -590,7 +613,7 @@ Cache *Cache_open(const char *fn)
/* Check if both metadata and data file exist */
if (!Cache_exist(fn)) {
fprintf(stderr, "Failure!\n");
fprintf(stderr, "dataset does not exist!\n");
return NULL;
}
@ -605,13 +628,17 @@ Cache *Cache_open(const char *fn)
return NULL;
}
pthread_mutex_lock(&cf->meta_lock);
int rtn = Meta_read(cf);
pthread_mutex_unlock(&cf->meta_lock);
/*
* Internally inconsistent or corrupt metadata
*/
int rtn = Meta_read(cf);
if ((rtn == EINCONSIST) || (rtn == EZERO) || (rtn == EMEM)) {
Cache_free(cf);
fprintf(stderr, "Failure!\nMetadata inconsistent or corrupt!\n");
fprintf(stderr, "metadata error!\n");
return NULL;
}
@ -622,8 +649,8 @@ Cache *Cache_open(const char *fn)
*/
if (cf->content_length > Data_size(fn)) {
fprintf(stderr,
"Failure!\nMetadata inconsistency: \
cf->content_length: %ld, Data_size(fn): %ld\n",
"metadata inconsistency: cf->content_length: %ld, \
Data_size(fn): %ld\n",
cf->content_length, Data_size(fn));
Cache_free(cf);
return NULL;
@ -631,7 +658,7 @@ cf->content_length: %ld, Data_size(fn): %ld\n",
if (Data_open(cf)) {
Cache_free(cf);
fprintf(stderr, "Failure!\n");
fprintf(stderr, "Data_open() failed!\n");
return NULL;
}
@ -643,13 +670,16 @@ void Cache_close(Cache *cf)
{
fprintf(stderr, "Cache_close(): Closing cache file %s.\n", cf->path);
pthread_mutex_lock(&cf->meta_lock);
if (Meta_write(cf)) {
fprintf(stderr, "Cache_close(): Meta_write() error.");
}
pthread_mutex_unlock(&cf->meta_lock);
if (fclose(cf->dfp)) {
fprintf(stderr, "Data_write(): fclose(): %s\n", strerror(errno));
}
return Cache_free(cf);
}
@ -687,7 +717,7 @@ long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
cf->blksz);
return path_download(cf->path, output_buf, len, offset);
}
pthread_mutex_lock(&(cf->rw_lock));
pthread_mutex_lock(&cf->rw_lock);
if (Seg_exist(cf, offset)) {
/*
* The metadata shows the segment already exists. This part is easy,
@ -717,6 +747,6 @@ long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
recv);
}
}
pthread_mutex_unlock(&(cf->rw_lock));
pthread_mutex_unlock(&cf->rw_lock);
return sent;
}

View File

@ -29,6 +29,7 @@ typedef struct {
long time; /**<the modified time of the file */
off_t content_length; /**<the size of the file */
pthread_mutex_t rw_lock; /**< mutex for disk operation */
pthread_mutex_t meta_lock; /**< mutex for metadata operation */
FILE *dfp; /**< The FILE pointer for the cache data file*/
Link *link; /**< The Link associated with this cache data set */
int blksz; /**<the block size of the data file */

View File

@ -8,9 +8,6 @@
#include <string.h>
#include <unistd.h>
static pthread_mutex_t open_lock;
static pthread_mutex_t close_lock;
static void *fs_init(struct fuse_conn_info *conn)
{
(void) conn;
@ -22,9 +19,7 @@ static int fs_release(const char *path, struct fuse_file_info *fi)
{
(void) path;
if (CACHE_SYSTEM_INIT) {
pthread_mutex_lock(&close_lock);
Cache_close((Cache *)fi->fh);
pthread_mutex_unlock(&close_lock);
}
return 0;
}
@ -89,13 +84,10 @@ static int fs_open(const char *path, struct fuse_file_info *fi)
if (!link) {
return -ENOENT;
}
if ((fi->flags & 3) != O_RDONLY) {
return -EACCES;
}
if (CACHE_SYSTEM_INIT) {
pthread_mutex_lock(&open_lock);
fi->fh = (uint64_t) Cache_open(path);
if (!fi->fh) {
/*
@ -112,10 +104,7 @@ static int fs_open(const char *path, struct fuse_file_info *fi)
return -ENOENT;
}
}
pthread_mutex_unlock(&open_lock);
}
return 0;
}

View File

@ -241,9 +241,9 @@ LinkTable *network_init(const char *url)
curl_multi_setopt(curl_multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
/* ------------ Initialise locks ---------*/
if (pthread_mutex_init(&transfer_lock, NULL) != 0) {
printf(
"network_init(): transfer_lock initialisation failed!\n");
if (pthread_mutex_init(&transfer_lock, NULL)) {
fprintf(stderr,
"network_init(): transfer_lock initialisation failed!\n");
exit(EXIT_FAILURE);
}