Completed metadata read/write functions

This commit is contained in:
Fufu Fang 2019-04-18 09:48:40 +01:00
parent 8d10316b95
commit 7cafdbf7d4
3 changed files with 163 additions and 37 deletions

View File

@ -9,39 +9,102 @@ long Cache_write(const char *filepath, long offset, long len,
{
}
int Cache_create(const char *filepath, long len)
Cache *Cache_create(const char *filepath, long len)
{
}
Cache *Cache_open(const char *filepath)
{
}
int Meta_write(Cache *cf)
void Cache_free(Cache *cf)
{
free(cf->filename);
free(cf->metapath);
free(cf->datapath);
free(cf->seg);
free(cf);
}
int Meta_read(Cache *cf)
{
FILE *fp;
fp = fopen(cf->metapath, "r");
if (!fp) {
/* The metadata file does not exist */
fprintf(stderr, "Meta_read(): fopen(): %s\n", strerror(errno));
return -1;
}
fread((void *) &(cf->len), sizeof(long), 1, fp);
fread((void *) &(cf->nseg), sizeof(int), 1, fp);
/* Allocate some memory for the segment */
cf->seg = malloc(cf->nseg * sizeof(Seg));
/* Read all the segment */
fread((void *) cf->seg, sizeof(Seg), cf->nseg, fp);
/* Simplified error checking */
if (ferror(fp)) {
fprintf(stderr,
"Meta_read(): fread(): encountered error (from ferror)!\n");
}
if (fclose(fp)) {
fprintf(stderr, "Meta_read(): fclose(): %s\n", strerror(errno));
return -1;
}
}
int Meta_write(const Cache *cf)
{
FILE *fp;
fp = fopen(cf->metapath, "w");
long Data_read(Cache *cf, long offset, long len,
const uint8_t *buf);
if (!fp) {
/* The metadata file does not exist */
fprintf(stderr, "Meta_write(): fopen(): %s\n", strerror(errno));
return -1;
}
/* We log the length of the file just in case */
fwrite((const void *) cf->len, sizeof(long), 1, fp);
fwrite((const void *) cf->nseg, sizeof(int), 1, fp);
/* Finally write segments to the file */
fwrite((const void *) cf->seg, sizeof(Seg), cf->nseg, fp);
/* Simplified error checking */
if (ferror(fp)) {
fprintf(stderr,
"Meta_write(): fwrite(): encountered error (from ferror)!\n");
}
if (fclose(fp)) {
fprintf(stderr, "Meta_write(): fclose(): %s\n", strerror(errno));
return -1;
}
}
long Data_read(const Cache *cf, long offset, long len,
uint8_t *buf);
{
if (len == 0) {
fprintf(stderr, "Data_read(): fseek(): requested to read 0 byte!\n");
fprintf(stderr, "Data_read(): requested to read 0 byte!\n");
return -1;
}
FILE *fp;
fp = fopen(cf->filepath, "r");
fp = fopen(cf->datapath, "r");
if (!fp) {
/* The data file does not exist */
fprintf(stderr, "Data_read(): fopen(): %s\n", strerror(errno));
return -1;
}
@ -51,16 +114,18 @@ long Data_read(Cache *cf, long offset, long len,
return -1;
}
long byte_read = fread((void*) buf, sizeof(uint8_t), len, fp);
long byte_read = fread((void *) buf, sizeof(uint8_t), len, fp);
if (byte_read != len) {
fprintf(stderr,
"Data_read(): fread(): requested %ld, returned %llu!\n",
len, byte_read);
if (feof(fp)) {
/* reached EOF */
fprintf(stderr,
"Data_read(): fread(): reached the end of the file!\n");
}
if (ferror(fp)) {
/* filesystem error */
fprintf(stderr,
"Data_read(): fread(): encountered error (from ferror)!\n");
}
@ -71,9 +136,48 @@ long Data_read(Cache *cf, long offset, long len,
}
}
long Data_write(Cache *cf, long offset, long len,
long Data_write(const Cache *cf, long offset, long len,
const uint8_t *buf);
{
if (len == 0) {
fprintf(stderr, "Data_write(): requested to write 0 byte!\n");
return -1;
}
FILE *fp;
fp = fopen(cf->datapath, "r+");
if (!fp) {
/* The data file does not exist */
return -1;
}
if (fseek(fp, offset, SEEK_SET) == -1) {
/* fseek failed */
fprintf(stderr, "Data_write(): fseek(): %s\n", strerror(errno));
return -1;
}
long byte_written = fwrite((const void *) buf, sizeof(uint8_t), len, fp);
if (byte_written != len) {
fprintf(stderr,
"Data_write(): fwrite(): requested %ld, returned %llu!\n",
len, byte_written);
if (feof(fp)) {
/* reached EOF */
fprintf(stderr,
"Data_write(): fwrite(): reached the end of the file!\n");
}
if (ferror(fp)) {
/* filesystem error */
fprintf(stderr,
"Data_write(): fwrite(): encountered error (from ferror)!\n");
}
}
if (fclose(fp)) {
fprintf(stderr, "Data_write(): fclose(): %s\n", strerror(errno));
return -1;
}
}
int Data_create(Cache *cf, long len)

View File

@ -6,7 +6,15 @@
/**
* \file cache.h
* \brief cache related structures and functions
* \details think of these as some sort of generic caching layer.
* \details
* Metadata:
* - We store the metadata and the actual data separately in two
* different folders.
* - The metadata file should follow the following format:
* - file length (long)
* - segment count (int)
* - individual segments (array of seg)
*
* \note
* - apologies for whoever is going to be reading this. Sorry for being so
* verbose in this header file, this is probably one of the most challenging
@ -24,8 +32,8 @@
* \brief a cache segment
*/
typedef struct {
long *start;
long *end;
long start;
long end;
} Seg;
/**
@ -33,65 +41,79 @@ typedef struct {
* \note fanf2@cam.ac.uk told me to use an array rather than linked list!
*/
typedef struct {
const char* filepath;
long len;
FILE *data_fd; /**< the file descriptor for the data file */
FILE *meta_fd; /**< the file descriptor for the meta file */
const char *filename; /**< the filename from the http server */
const char *metapath; /**< the path to the metadata file*/
const char *datapath; /**< the path to the cache file */
long len; /**<the size of the file */
int nseg; /**<the number of segments */
Seg *seg; /**< the detail of each segment */
} Cache;
/**************************** External functions ******************************/
/***************************** To be completed ******************************/
/**
* \brief read from a cache file
* \brief Read from a cache file set
* \details This function performs the following two things:
* - check again the metafile to see which segments are available
* - return the available segments
*/
long Cache_read(const char *filepath, long offset, long len);
/**
* \brief write to a cache file
* \brief Write to a cache file set
* \details This function performs the following two things:
* - Write to the data file
* - Update the metadata file
*/
long Cache_write(const char *filepath, long offset, long len,
const uint8_t *content);
/**************************** Internal functions ******************************/
/**
* \brief create a cache file
*/
int Cache_create(const char *filepath, long len);
Cache *Cache_create(const char *filepath, long len);
/**
* \brief open a cache file
*/
Cache *Cache_open(const char *filepath);
/**************************** Completed functions ****************************/
/**
* \brief free a cache data structure
*/
void Cache_free(Cache *cf);
/**
* \brief write a metadata file
*/
int Meta_write(Cache *cf);
int Meta_write(const Cache *cf);
/**
* \brief read a metadata file
*/
int Meta_read(Cache *cf);
/**
* \brief read a data file
* \return -1 when the data file does not exist
*/
long Data_read(Cache *cf, long offset, long len,
const uint8_t *buf);
/**
* \brief write to a data file
*/
long Data_write(Cache *cf, long offset, long len,
const uint8_t *buf);
/**
* \brief create a data file
* \details We use sparse creation here
* \return 1 on success, 0 on failure
*/
int Data_create(Cache *cf, long len);
/**
* \brief read a data file
* \return -1 when the data file does not exist
*/
long Data_read(const Cache *cf, long offset, long len,
uint8_t *buf);
/**
* \brief write to a data file
*/
long Data_write(const Cache *cf, long offset, long len,
const uint8_t *buf);
#endif

View File

@ -50,7 +50,7 @@ static void HTML_to_LinkTable(GumboNode *node, LinkTable *linktbl)
/* Note the recursive call, lol. */
GumboVector *children = &node->v.element.children;
for (size_t i = 0; i < children->length; ++i) {
HTML_to_LinkTable((GumboNode*)children->data[i], linktbl);
HTML_to_LinkTable((GumboNode *)children->data[i], linktbl);
}
return;
}