2019-04-09 13:51:15 +02:00
|
|
|
#ifndef CACHE_H
|
|
|
|
#define CACHE_H
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \file cache.h
|
|
|
|
* \brief cache related structures and functions
|
2019-04-18 10:48:40 +02:00
|
|
|
* \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)
|
|
|
|
*
|
2019-04-17 18:38:27 +02:00
|
|
|
* \note
|
|
|
|
* - apologies for whoever is going to be reading this. Sorry for being so
|
2019-04-09 13:51:15 +02:00
|
|
|
* verbose in this header file, this is probably one of the most challenging
|
|
|
|
* thing I have ever written so far! Yes I am doing a PhD in computer science,
|
|
|
|
* but it doesn't imply that I am good at computer science or programming!
|
2019-04-17 18:38:27 +02:00
|
|
|
* - We are using 'long' to store file size, because the offset in fseek() is
|
|
|
|
* in long, because the way we use the cache system, you cannot seek past
|
|
|
|
* long. So the biggest file size has to be able to be stored in long. This
|
|
|
|
* makes this program architecturally dependent, but this is due to the
|
|
|
|
* dependency to fseek().
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
|
|
|
|
2019-04-12 13:41:07 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief a cache segment
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2019-04-18 10:48:40 +02:00
|
|
|
long start;
|
|
|
|
long end;
|
2019-04-12 13:41:07 +02:00
|
|
|
} Seg;
|
|
|
|
|
2019-04-09 13:51:15 +02:00
|
|
|
/**
|
|
|
|
* \brief cache metadata structure
|
2019-04-11 09:44:49 +02:00
|
|
|
* \note fanf2@cam.ac.uk told me to use an array rather than linked list!
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
2019-04-12 13:41:07 +02:00
|
|
|
typedef struct {
|
2019-04-18 10:48:40 +02:00
|
|
|
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 */
|
2019-04-12 13:41:07 +02:00
|
|
|
int nseg; /**<the number of segments */
|
|
|
|
Seg *seg; /**< the detail of each segment */
|
|
|
|
} Cache;
|
2019-04-09 13:51:15 +02:00
|
|
|
|
2019-04-18 10:48:40 +02:00
|
|
|
/***************************** To be completed ******************************/
|
2019-04-12 13:41:07 +02:00
|
|
|
|
|
|
|
/**
|
2019-04-18 10:48:40 +02:00
|
|
|
* \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
|
2019-04-12 13:41:07 +02:00
|
|
|
*/
|
2019-04-17 18:38:27 +02:00
|
|
|
long Cache_read(const char *filepath, long offset, long len);
|
2019-04-09 13:51:15 +02:00
|
|
|
|
|
|
|
/**
|
2019-04-18 10:48:40 +02:00
|
|
|
* \brief Write to a cache file set
|
|
|
|
* \details This function performs the following two things:
|
|
|
|
* - Write to the data file
|
|
|
|
* - Update the metadata file
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
2019-04-17 18:38:27 +02:00
|
|
|
long Cache_write(const char *filepath, long offset, long len,
|
2019-04-12 13:41:07 +02:00
|
|
|
const uint8_t *content);
|
|
|
|
|
2019-04-09 13:51:15 +02:00
|
|
|
/**
|
2019-04-12 13:41:07 +02:00
|
|
|
* \brief create a cache file
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
2019-04-18 10:48:40 +02:00
|
|
|
Cache *Cache_create(const char *filepath, long len);
|
2019-04-09 13:51:15 +02:00
|
|
|
|
|
|
|
/**
|
2019-04-12 13:41:07 +02:00
|
|
|
* \brief open a cache file
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
2019-04-12 13:41:07 +02:00
|
|
|
Cache *Cache_open(const char *filepath);
|
2019-04-09 13:51:15 +02:00
|
|
|
|
2019-04-18 10:48:40 +02:00
|
|
|
/**************************** Completed functions ****************************/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief free a cache data structure
|
|
|
|
*/
|
|
|
|
void Cache_free(Cache *cf);
|
|
|
|
|
2019-04-12 13:41:07 +02:00
|
|
|
/**
|
|
|
|
* \brief write a metadata file
|
|
|
|
*/
|
2019-04-18 10:48:40 +02:00
|
|
|
int Meta_write(const Cache *cf);
|
2019-04-12 13:41:07 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief read a metadata file
|
|
|
|
*/
|
|
|
|
int Meta_read(Cache *cf);
|
|
|
|
|
2019-04-18 10:48:40 +02:00
|
|
|
/**
|
|
|
|
* \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);
|
|
|
|
|
2019-04-12 13:41:07 +02:00
|
|
|
/**
|
|
|
|
* \brief read a data file
|
2019-04-17 18:38:27 +02:00
|
|
|
* \return -1 when the data file does not exist
|
2019-04-12 13:41:07 +02:00
|
|
|
*/
|
2019-04-18 10:48:40 +02:00
|
|
|
long Data_read(const Cache *cf, long offset, long len,
|
|
|
|
uint8_t *buf);
|
2019-04-12 13:41:07 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief write to a data file
|
|
|
|
*/
|
2019-04-18 10:48:40 +02:00
|
|
|
long Data_write(const Cache *cf, long offset, long len,
|
2019-04-17 18:38:27 +02:00
|
|
|
const uint8_t *buf);
|
2019-04-18 10:48:40 +02:00
|
|
|
|
2019-04-09 13:51:15 +02:00
|
|
|
#endif
|