mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-07 21:56:44 +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 -1;
|
||||||
return sb.st_size;
|
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 int git_file;
|
||||||
typedef struct stat gitfo_statbuf;
|
typedef struct stat gitfo_statbuf;
|
||||||
|
typedef struct gitfo_cache gitfo_cache;
|
||||||
|
|
||||||
#define gitfo_open(path, flags) open(path, flags)
|
#define gitfo_open(path, flags) open(path, flags)
|
||||||
#define gitfo_close(fd) close(fd)
|
#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_stat(path, buf) stat(path, buf)
|
||||||
#define gitfo_fsync(fd) fsync(fd)
|
#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__ */
|
#endif /* INCLUDE_fileops_h__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user