mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 23:19:28 +00:00
Add an io caching layer to the gitfo api
The idea is taken from Junio's work in read-cache.c, where it's used for writing out the index without tap-dancing on the poor harddrive. Since it's almost certainly useful for cached writing of packfiles too, we turn it into a generic API, making it perfectly simple to reuse it later. gitfo_write_cached() has the same contract as gitfo_write(), it returns GIT_SUCCESS if all bytes are successfully written (or were at least buffered for later writing), and <0 if an error occurs during buffer writing. Signed-off-by: Andreas Ericsson <ae@op5.se> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
ec250c6e18
commit
4188d28f1c
@ -47,3 +47,90 @@ off_t gitfo_size(git_file fd)
|
||||
return -1;
|
||||
return sb.st_size;
|
||||
}
|
||||
|
||||
/* cached diskio */
|
||||
struct gitfo_cache {
|
||||
git_file fd;
|
||||
unsigned int cache_size, pos;
|
||||
void *cache;
|
||||
};
|
||||
|
||||
gitfo_cache *gitfo_enable_caching(git_file fd, size_t cache_size)
|
||||
{
|
||||
gitfo_cache *ioc;
|
||||
|
||||
ioc = malloc(sizeof(*ioc));
|
||||
if (!ioc)
|
||||
return NULL;
|
||||
|
||||
ioc->pos = 0;
|
||||
ioc->cache_size = cache_size;
|
||||
ioc->cache = malloc(cache_size);
|
||||
if (!ioc->cache) {
|
||||
free(ioc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ioc;
|
||||
}
|
||||
|
||||
static inline void gitfo_add_to_cache(gitfo_cache *ioc, void *buf, size_t len)
|
||||
{
|
||||
memcpy(ioc->cache + ioc->pos, buf, len);
|
||||
ioc->pos += len;
|
||||
}
|
||||
|
||||
int gitfo_flush_cached(gitfo_cache *ioc)
|
||||
{
|
||||
int result = GIT_SUCCESS;
|
||||
|
||||
if (ioc->pos) {
|
||||
result = gitfo_write(ioc->fd, ioc->cache, ioc->pos);
|
||||
ioc->pos = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int gitfo_write_cached(gitfo_cache *ioc, void *buf, size_t len)
|
||||
{
|
||||
for (;;) {
|
||||
size_t space_left = ioc->cache_size - ioc->pos;
|
||||
/* cache if it's small */
|
||||
if (space_left > len) {
|
||||
gitfo_add_to_cache(ioc, buf, len);
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* flush the cache if it doesn't fit */
|
||||
if (ioc->pos) {
|
||||
int rc;
|
||||
gitfo_add_to_cache(ioc, buf, space_left);
|
||||
rc = gitfo_flush_cached(ioc);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
len -= space_left;
|
||||
buf += space_left;
|
||||
}
|
||||
|
||||
/* write too-large chunks immediately */
|
||||
if (len > ioc->cache_size)
|
||||
return gitfo_write(ioc->fd, buf, len);
|
||||
}
|
||||
return GIT_SUCCESS;
|
||||
}
|
||||
|
||||
int gitfo_close_cached(gitfo_cache *ioc)
|
||||
{
|
||||
git_file fd;
|
||||
|
||||
if (gitfo_flush_cached(ioc) < 0)
|
||||
return -1;
|
||||
|
||||
fd = ioc->fd;
|
||||
free(ioc->cache);
|
||||
free(ioc);
|
||||
|
||||
return gitfo_close(fd);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
typedef int git_file;
|
||||
typedef struct stat gitfo_statbuf;
|
||||
typedef struct gitfo_cache gitfo_cache;
|
||||
|
||||
#define gitfo_open(path, flags) open(path, flags)
|
||||
#define gitfo_close(fd) close(fd)
|
||||
@ -34,4 +35,9 @@ extern off_t gitfo_size(git_file fd);
|
||||
#define gitfo_stat(path, buf) stat(path, buf)
|
||||
#define gitfo_fsync(fd) fsync(fd)
|
||||
|
||||
extern gitfo_cache *gitfo_enable_caching(git_file fd, size_t cache_size);
|
||||
extern int gitfo_write_cached(gitfo_cache *ioc, void *buf, size_t len);
|
||||
extern int gitfo_flush_cached(gitfo_cache *ioc);
|
||||
extern int gitfo_close_cached(gitfo_cache *ioc);
|
||||
|
||||
#endif /* INCLUDE_fileops_h__ */
|
||||
|
Loading…
Reference in New Issue
Block a user