2019-04-09 13:51:15 +02:00
|
|
|
#ifndef CACHE_H
|
|
|
|
#define CACHE_H
|
|
|
|
|
2019-04-20 03:04:29 +02:00
|
|
|
#include <stdint.h>
|
2019-04-09 13:51:15 +02:00
|
|
|
#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)
|
2019-04-20 09:31:16 +02:00
|
|
|
* - CURLINFO_FILETIME
|
2019-04-18 10:48:40 +02:00
|
|
|
* - segment count (int)
|
|
|
|
* - individual segments (array of seg)
|
2019-04-17 18:38:27 +02:00
|
|
|
* \note
|
|
|
|
* - 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
|
2019-04-21 11:57:00 +02:00
|
|
|
* makes this program architecturally dependent, i.e. i386 vs amd64
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
|
|
|
|
2019-04-12 13:41:07 +02:00
|
|
|
/**
|
2019-04-21 11:57:00 +02:00
|
|
|
* \brief Type definition for a cache segment
|
2019-04-12 13:41:07 +02:00
|
|
|
*/
|
2019-04-21 11:57:00 +02:00
|
|
|
typedef uint8_t Seg;
|
2019-04-12 13:41:07 +02:00
|
|
|
|
2019-04-09 13:51:15 +02:00
|
|
|
/**
|
2019-04-20 09:31:16 +02:00
|
|
|
* \brief cache in-memory data structure
|
2019-04-09 13:51:15 +02:00
|
|
|
*/
|
2019-04-12 13:41:07 +02:00
|
|
|
typedef struct {
|
2019-04-20 03:04:29 +02:00
|
|
|
char *filename; /**< the filename from the http server */
|
|
|
|
long time; /**<the modified time of the file */
|
2019-04-21 11:57:00 +02:00
|
|
|
long len; /**<the size of the file */
|
|
|
|
int blksz; /**<the block size of the data file */
|
2019-04-21 21:48:44 +02:00
|
|
|
long segbc; /**<segment array byte count */
|
2019-04-12 13:41:07 +02:00
|
|
|
Seg *seg; /**< the detail of each segment */
|
2019-04-20 03:04:29 +02:00
|
|
|
} 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-20 03:04:29 +02:00
|
|
|
long Cache_read(const char *fn, long offset, long len, uint8_t *buf);
|
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-20 03:04:29 +02:00
|
|
|
long Cache_write(const char *fn, long offset, long len,
|
|
|
|
const uint8_t *buf);
|
2019-04-21 11:57:00 +02:00
|
|
|
|
2019-04-20 03:04:29 +02:00
|
|
|
/****************************** Work in progress *****************************/
|
2019-04-12 13:41:07 +02:00
|
|
|
|
2019-04-20 09:31:16 +02:00
|
|
|
|
2019-04-18 10:48:40 +02:00
|
|
|
/**************************** Completed functions ****************************/
|
|
|
|
|
2019-04-20 03:04:29 +02:00
|
|
|
/**
|
2019-04-21 21:48:44 +02:00
|
|
|
* \brief initialise the cache system directories
|
2019-04-20 03:04:29 +02:00
|
|
|
* \details This function basically sets up the following variables:
|
|
|
|
* - META_DIR
|
|
|
|
* - DATA_DIR
|
2019-04-21 21:48:44 +02:00
|
|
|
*
|
|
|
|
* If these directories do not exist, they will be created.
|
2019-04-20 03:04:29 +02:00
|
|
|
*/
|
2019-04-21 21:48:44 +02:00
|
|
|
void CacheSystem_init(const char *dir);
|
2019-04-21 00:46:08 +02:00
|
|
|
|
2019-04-21 01:42:32 +02:00
|
|
|
/**
|
2019-04-21 21:48:44 +02:00
|
|
|
* \brief Check if a segment exists.
|
2019-04-21 01:42:32 +02:00
|
|
|
*/
|
2019-04-21 21:48:44 +02:00
|
|
|
int Seg_exist(Cache *cf, long start);
|
2019-04-21 01:42:32 +02:00
|
|
|
|
2019-04-21 11:57:00 +02:00
|
|
|
/**
|
2019-04-21 21:48:44 +02:00
|
|
|
* \brief Set the existence of a segment
|
|
|
|
* \param[in] start the starting position of the segment.
|
|
|
|
* \param[in] i 1 for exist, 0 for doesn't exist
|
2019-04-21 11:57:00 +02:00
|
|
|
*/
|
2019-04-21 21:48:44 +02:00
|
|
|
void Seg_set(Cache *cf, long start, int i);
|
2019-04-21 11:57:00 +02:00
|
|
|
|
2019-04-21 00:46:08 +02:00
|
|
|
|
2019-04-21 01:42:32 +02:00
|
|
|
/**
|
|
|
|
* \brief create a metadata file
|
2019-04-21 11:57:00 +02:00
|
|
|
* \details We set the followings here:
|
|
|
|
* - block size
|
|
|
|
* - the number of segments
|
|
|
|
*
|
|
|
|
* The number of segments depends on the block size. The block size is set to
|
|
|
|
* 128KiB for now. In future support for different block size may be
|
|
|
|
* implemented.
|
2019-04-21 01:42:32 +02:00
|
|
|
*/
|
2019-04-21 21:48:44 +02:00
|
|
|
int Meta_create(Cache *cf);
|
2019-04-21 01:42:32 +02:00
|
|
|
|
2019-04-12 13:41:07 +02:00
|
|
|
/**
|
|
|
|
* \brief write a metadata file
|
2019-04-21 00:46:08 +02:00
|
|
|
* \return
|
|
|
|
* - -1 on error,
|
|
|
|
* - 0 on success
|
2019-04-12 13:41:07 +02:00
|
|
|
*/
|
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
|
2019-04-21 00:46:08 +02:00
|
|
|
* \return
|
2019-04-21 21:48:44 +02:00
|
|
|
* - -1 on fread error,
|
|
|
|
* - -2 on metadata internal inconsistency
|
2019-04-21 00:46:08 +02:00
|
|
|
* - 0 on success
|
2019-04-12 13:41:07 +02:00
|
|
|
*/
|
|
|
|
int Meta_read(Cache *cf);
|
|
|
|
|
2019-04-18 10:48:40 +02:00
|
|
|
/**
|
|
|
|
* \brief create a data file
|
|
|
|
* \details We use sparse creation here
|
2019-04-20 03:04:29 +02:00
|
|
|
* \return
|
2019-04-21 01:42:32 +02:00
|
|
|
* - 0 on successful creation of the data file, note that the result of
|
2019-04-20 03:04:29 +02:00
|
|
|
* the ftruncate() is ignored.
|
2019-04-21 01:42:32 +02:00
|
|
|
* - -1 on failure to create the data file.
|
2019-04-18 10:48:40 +02:00
|
|
|
*/
|
2019-04-20 03:04:29 +02:00
|
|
|
int Data_create(Cache *cf);
|
2019-04-18 10:48:40 +02:00
|
|
|
|
2019-04-21 00:46:08 +02:00
|
|
|
/**
|
|
|
|
* \brief obtain the data file size
|
|
|
|
*/
|
|
|
|
long Data_size(const char *fn);
|
|
|
|
|
2019-04-12 13:41:07 +02:00
|
|
|
/**
|
|
|
|
* \brief read a data file
|
2019-04-20 03:04:29 +02:00
|
|
|
* \return
|
|
|
|
* - -1 when the data file does not exist
|
|
|
|
* - otherwise, the number of bytes read.
|
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-20 03:04:29 +02:00
|
|
|
* \return
|
|
|
|
* - -1 when the data file does not exist
|
|
|
|
* - otherwise, the number of bytes written.
|
2019-04-12 13:41:07 +02:00
|
|
|
*/
|
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-22 02:50:05 +02:00
|
|
|
/**
|
|
|
|
* \brief Create directories under the cache directory structure, if they do
|
|
|
|
* not already exist
|
|
|
|
* \return
|
|
|
|
* - -1 failed to create metadata directory.
|
|
|
|
* - -2 failed to create data directory.
|
|
|
|
* - -3 failed to create both metadata and data directory.
|
|
|
|
* \note This should be called every time a new LinkTable is created.
|
|
|
|
*/
|
|
|
|
int CacheDir_create(const char *fn);
|
|
|
|
|
2019-04-21 21:48:44 +02:00
|
|
|
/**
|
|
|
|
* \brief Allocate a new cache data structure
|
|
|
|
*/
|
|
|
|
Cache *Cache_alloc();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief free a cache data structure
|
|
|
|
*/
|
|
|
|
void Cache_free(Cache *cf);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Check if both metadata and data file exist, otherwise perform cleanup.
|
|
|
|
* \details
|
|
|
|
* This function checks if both metadata file and the data file exist. If that
|
|
|
|
* is not the case, clean up is performed - the existing unpaired metadata file
|
|
|
|
* or data file is deleted.
|
|
|
|
* \return
|
|
|
|
* - 0, if both metadata and cache file exist
|
|
|
|
* - -1, otherwise
|
|
|
|
*/
|
|
|
|
int Cache_exist(const char *fn);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief create a cache file set
|
|
|
|
*/
|
|
|
|
Cache *Cache_create(const char *fn, long len, long time);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief delete a cache file set
|
|
|
|
*/
|
|
|
|
void Cache_delete(const char *fn);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief open a cache file set
|
|
|
|
*/
|
|
|
|
Cache *Cache_open(const char *fn);
|
2019-04-09 13:51:15 +02:00
|
|
|
#endif
|