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:
parent
fb8a132c14
commit
3a0c431bba
64
src/cache.c
64
src/cache.c
|
@ -124,10 +124,10 @@ static int Meta_read(Cache *cf)
|
||||||
return EFREAD;
|
return EFREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
fread(&(cf->time), sizeof(long), 1, fp);
|
fread(&cf->time, sizeof(long), 1, fp);
|
||||||
fread(&(cf->content_length), sizeof(off_t), 1, fp);
|
fread(&cf->content_length, sizeof(off_t), 1, fp);
|
||||||
fread(&(cf->blksz), sizeof(int), 1, fp);
|
fread(&cf->blksz, sizeof(int), 1, fp);
|
||||||
fread(&(cf->segbc), sizeof(long), 1, fp);
|
fread(&cf->segbc, sizeof(long), 1, fp);
|
||||||
|
|
||||||
/* Error checking for fread */
|
/* Error checking for fread */
|
||||||
if (ferror(fp)) {
|
if (ferror(fp)) {
|
||||||
|
@ -194,7 +194,7 @@ blksz: %d, segbc: %ld\n", cf->content_length, cf->blksz, cf->segbc);
|
||||||
* - -1 on error,
|
* - -1 on error,
|
||||||
* - 0 on success
|
* - 0 on success
|
||||||
*/
|
*/
|
||||||
static int Meta_write(const Cache *cf)
|
static int Meta_write(Cache *cf)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *metafn = strndupcat(META_DIR, cf->path, MAX_PATH_LEN);
|
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);
|
%ld\n", cf->content_length, cf->blksz, cf->segbc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fwrite(&(cf->time), sizeof(long), 1, fp);
|
fwrite(&cf->time, sizeof(long), 1, fp);
|
||||||
fwrite(&(cf->content_length), sizeof(off_t), 1, fp);
|
fwrite(&cf->content_length, sizeof(off_t), 1, fp);
|
||||||
fwrite(&(cf->blksz), sizeof(int), 1, fp);
|
fwrite(&cf->blksz, sizeof(int), 1, fp);
|
||||||
fwrite(&(cf->segbc), sizeof(long), 1, fp);
|
fwrite(&cf->segbc, sizeof(long), 1, fp);
|
||||||
fwrite(cf->seg, sizeof(Seg), cf->segbc, fp);
|
fwrite(cf->seg, sizeof(Seg), cf->segbc, fp);
|
||||||
|
|
||||||
/* Error checking for fwrite */
|
/* Error checking for fwrite */
|
||||||
|
@ -434,6 +434,17 @@ static Cache *Cache_alloc()
|
||||||
fprintf(stderr, "Cache_new(): calloc failure!\n");
|
fprintf(stderr, "Cache_new(): calloc failure!\n");
|
||||||
exit(EXIT_FAILURE);
|
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;
|
return cf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,6 +453,14 @@ static Cache *Cache_alloc()
|
||||||
*/
|
*/
|
||||||
static void Cache_free(Cache *cf)
|
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) {
|
if (cf->path) {
|
||||||
free(cf->path);
|
free(cf->path);
|
||||||
}
|
}
|
||||||
|
@ -504,6 +523,7 @@ static int Cache_exist(const char *fn)
|
||||||
*/
|
*/
|
||||||
void Cache_delete(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 *metafn = strndupcat(META_DIR, fn, MAX_PATH_LEN);
|
||||||
char *datafn = strndupcat(DATA_DIR, fn, MAX_PATH_LEN);
|
char *datafn = strndupcat(DATA_DIR, fn, MAX_PATH_LEN);
|
||||||
if (!access(metafn, F_OK)) {
|
if (!access(metafn, F_OK)) {
|
||||||
|
@ -569,9 +589,12 @@ int Cache_create(Link *this_link)
|
||||||
fprintf(stderr, "Cache_create(): Data_create() failed!\n");
|
fprintf(stderr, "Cache_create(): Data_create() failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&cf->meta_lock);
|
||||||
if (Meta_create(cf)) {
|
if (Meta_create(cf)) {
|
||||||
fprintf(stderr, "Cache_create(): Meta_create() failed!\n");
|
fprintf(stderr, "Cache_create(): Meta_create() failed!\n");
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&cf->meta_lock);
|
||||||
|
|
||||||
|
|
||||||
Cache_free(cf);
|
Cache_free(cf);
|
||||||
|
|
||||||
|
@ -590,7 +613,7 @@ Cache *Cache_open(const char *fn)
|
||||||
|
|
||||||
/* Check if both metadata and data file exist */
|
/* Check if both metadata and data file exist */
|
||||||
if (!Cache_exist(fn)) {
|
if (!Cache_exist(fn)) {
|
||||||
fprintf(stderr, "Failure!\n");
|
fprintf(stderr, "dataset does not exist!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,13 +628,17 @@ Cache *Cache_open(const char *fn)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pthread_mutex_lock(&cf->meta_lock);
|
||||||
|
int rtn = Meta_read(cf);
|
||||||
|
pthread_mutex_unlock(&cf->meta_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internally inconsistent or corrupt metadata
|
* Internally inconsistent or corrupt metadata
|
||||||
*/
|
*/
|
||||||
int rtn = Meta_read(cf);
|
|
||||||
if ((rtn == EINCONSIST) || (rtn == EZERO) || (rtn == EMEM)) {
|
if ((rtn == EINCONSIST) || (rtn == EZERO) || (rtn == EMEM)) {
|
||||||
Cache_free(cf);
|
Cache_free(cf);
|
||||||
fprintf(stderr, "Failure!\nMetadata inconsistent or corrupt!\n");
|
fprintf(stderr, "metadata error!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,8 +649,8 @@ Cache *Cache_open(const char *fn)
|
||||||
*/
|
*/
|
||||||
if (cf->content_length > Data_size(fn)) {
|
if (cf->content_length > Data_size(fn)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Failure!\nMetadata inconsistency: \
|
"metadata inconsistency: cf->content_length: %ld, \
|
||||||
cf->content_length: %ld, Data_size(fn): %ld\n",
|
Data_size(fn): %ld\n",
|
||||||
cf->content_length, Data_size(fn));
|
cf->content_length, Data_size(fn));
|
||||||
Cache_free(cf);
|
Cache_free(cf);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -631,7 +658,7 @@ cf->content_length: %ld, Data_size(fn): %ld\n",
|
||||||
|
|
||||||
if (Data_open(cf)) {
|
if (Data_open(cf)) {
|
||||||
Cache_free(cf);
|
Cache_free(cf);
|
||||||
fprintf(stderr, "Failure!\n");
|
fprintf(stderr, "Data_open() failed!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,13 +670,16 @@ void Cache_close(Cache *cf)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Cache_close(): Closing cache file %s.\n", cf->path);
|
fprintf(stderr, "Cache_close(): Closing cache file %s.\n", cf->path);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&cf->meta_lock);
|
||||||
if (Meta_write(cf)) {
|
if (Meta_write(cf)) {
|
||||||
fprintf(stderr, "Cache_close(): Meta_write() error.");
|
fprintf(stderr, "Cache_close(): Meta_write() error.");
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&cf->meta_lock);
|
||||||
|
|
||||||
if (fclose(cf->dfp)) {
|
if (fclose(cf->dfp)) {
|
||||||
fprintf(stderr, "Data_write(): fclose(): %s\n", strerror(errno));
|
fprintf(stderr, "Data_write(): fclose(): %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Cache_free(cf);
|
return Cache_free(cf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,7 +717,7 @@ long Cache_read(Cache *cf, char *output_buf, off_t len, off_t offset)
|
||||||
cf->blksz);
|
cf->blksz);
|
||||||
return path_download(cf->path, output_buf, len, offset);
|
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)) {
|
if (Seg_exist(cf, offset)) {
|
||||||
/*
|
/*
|
||||||
* The metadata shows the segment already exists. This part is easy,
|
* 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);
|
recv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&(cf->rw_lock));
|
pthread_mutex_unlock(&cf->rw_lock);
|
||||||
return sent;
|
return sent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ typedef struct {
|
||||||
long time; /**<the modified time of the file */
|
long time; /**<the modified time of the file */
|
||||||
off_t content_length; /**<the size of the file */
|
off_t content_length; /**<the size of the file */
|
||||||
pthread_mutex_t rw_lock; /**< mutex for disk operation */
|
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*/
|
FILE *dfp; /**< The FILE pointer for the cache data file*/
|
||||||
Link *link; /**< The Link associated with this cache data set */
|
Link *link; /**< The Link associated with this cache data set */
|
||||||
int blksz; /**<the block size of the data file */
|
int blksz; /**<the block size of the data file */
|
||||||
|
|
|
@ -8,9 +8,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.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)
|
static void *fs_init(struct fuse_conn_info *conn)
|
||||||
{
|
{
|
||||||
(void) conn;
|
(void) conn;
|
||||||
|
@ -22,9 +19,7 @@ static int fs_release(const char *path, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
(void) path;
|
(void) path;
|
||||||
if (CACHE_SYSTEM_INIT) {
|
if (CACHE_SYSTEM_INIT) {
|
||||||
pthread_mutex_lock(&close_lock);
|
|
||||||
Cache_close((Cache *)fi->fh);
|
Cache_close((Cache *)fi->fh);
|
||||||
pthread_mutex_unlock(&close_lock);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -89,13 +84,10 @@ static int fs_open(const char *path, struct fuse_file_info *fi)
|
||||||
if (!link) {
|
if (!link) {
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fi->flags & 3) != O_RDONLY) {
|
if ((fi->flags & 3) != O_RDONLY) {
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CACHE_SYSTEM_INIT) {
|
if (CACHE_SYSTEM_INIT) {
|
||||||
pthread_mutex_lock(&open_lock);
|
|
||||||
fi->fh = (uint64_t) Cache_open(path);
|
fi->fh = (uint64_t) Cache_open(path);
|
||||||
if (!fi->fh) {
|
if (!fi->fh) {
|
||||||
/*
|
/*
|
||||||
|
@ -112,10 +104,7 @@ static int fs_open(const char *path, struct fuse_file_info *fi)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&open_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,9 +241,9 @@ LinkTable *network_init(const char *url)
|
||||||
curl_multi_setopt(curl_multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
curl_multi_setopt(curl_multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX);
|
||||||
|
|
||||||
/* ------------ Initialise locks ---------*/
|
/* ------------ Initialise locks ---------*/
|
||||||
if (pthread_mutex_init(&transfer_lock, NULL) != 0) {
|
if (pthread_mutex_init(&transfer_lock, NULL)) {
|
||||||
printf(
|
fprintf(stderr,
|
||||||
"network_init(): transfer_lock initialisation failed!\n");
|
"network_init(): transfer_lock initialisation failed!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue