Completed metadata read/write functions
This commit is contained in:
parent
8d10316b95
commit
7cafdbf7d4
124
src/cache.c
124
src/cache.c
|
@ -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)
|
||||
|
|
74
src/cache.h
74
src/cache.h
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue