hgfs: various improvements
lazily close revlog files and keep up to 8 revlogs arround. also cache the latest extracted file descriptor of a revision in the revlog. this avoids the quite expensive reextracting/patching when we reopen the same file revision. dont use the racy mktemp()/create, instead create a uniqueue name and create with OEXCL. this also avoids a bunch of access() calls. fix eof case and use pread() in fcopy() to avoid the seeks. dont modify changelog temp file but simulate trailing newline instead.
This commit is contained in:
parent
73744b9f48
commit
40d11cea3f
6 changed files with 74 additions and 39 deletions
|
@ -46,6 +46,9 @@ struct Revlog
|
|||
|
||||
int nmap;
|
||||
Revmap *map;
|
||||
|
||||
int tfd;
|
||||
int tid;
|
||||
};
|
||||
|
||||
struct Revnode
|
||||
|
|
|
@ -6,6 +6,7 @@ int fhash(int fd, uchar p1[], uchar p2[], uchar h[]);
|
|||
int readhash(char *path, char *name, uchar hash[]);
|
||||
|
||||
/* patch */
|
||||
int fcopy(int dfd, int sfd, vlong off, vlong len);
|
||||
int fpatchmark(int pfd, char *mark);
|
||||
int fpatch(int ofd, int bfd, int pfd);
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ static char *nametab[] = {
|
|||
static Revlog changelog;
|
||||
static Revlog manifest;
|
||||
static Revlog *revlogs;
|
||||
static int nfreerevlogs = 0;
|
||||
|
||||
static char workdir[MAXPATH];
|
||||
static int mangle = 0;
|
||||
|
@ -51,16 +52,28 @@ static Revlog*
|
|||
getrevlog(Revnode *nd)
|
||||
{
|
||||
char buf[MAXPATH];
|
||||
Revlog *rl;
|
||||
Revlog *rl, **link;
|
||||
int mang;
|
||||
|
||||
mang = mangle;
|
||||
Again:
|
||||
nodepath(seprint(buf, buf+sizeof(buf), "%s/.hg/store/data", workdir),
|
||||
buf+sizeof(buf), nd, mang);
|
||||
for(rl = revlogs; rl; rl = rl->next)
|
||||
if(strcmp(buf, rl->path) == 0)
|
||||
link = &revlogs;
|
||||
while(rl = *link){
|
||||
if(strcmp(buf, rl->path) == 0){
|
||||
if(rl->ref == 0) nfreerevlogs--;
|
||||
break;
|
||||
}
|
||||
if(nfreerevlogs > 8 && rl->ref == 0){
|
||||
*link = rl->next;
|
||||
nfreerevlogs--;
|
||||
revlogclose(rl);
|
||||
free(rl);
|
||||
continue;
|
||||
}
|
||||
link = &rl->next;
|
||||
}
|
||||
if(rl == nil){
|
||||
rl = emalloc9p(sizeof(*rl));
|
||||
memset(rl, 0, sizeof(*rl));
|
||||
|
@ -83,18 +96,8 @@ Again:
|
|||
static void
|
||||
closerevlog(Revlog *rl)
|
||||
{
|
||||
Revlog **pp;
|
||||
|
||||
if(rl == nil || decref(rl))
|
||||
return;
|
||||
for(pp = &revlogs; *pp; pp = &((*pp)->next)){
|
||||
if(*pp == rl){
|
||||
*pp = rl->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
revlogclose(rl);
|
||||
free(rl);
|
||||
if(rl != nil && decref(rl) == 0)
|
||||
nfreerevlogs++;
|
||||
}
|
||||
|
||||
static Revinfo*
|
||||
|
|
|
@ -8,16 +8,13 @@ Revinfo*
|
|||
loadrevinfo(Revlog *changelog, int rev)
|
||||
{
|
||||
char buf[BUFSZ], *p, *e;
|
||||
int fd, line, inmsg, n;
|
||||
int fd, line, eof, inmsg, n;
|
||||
Revinfo *ri;
|
||||
vlong off;
|
||||
|
||||
if((fd = revlogopentemp(changelog, rev)) < 0)
|
||||
return nil;
|
||||
|
||||
seek(fd, 0, 2);
|
||||
write(fd, "\n", 1);
|
||||
|
||||
off = fmetaheader(fd);
|
||||
seek(fd, off, 0);
|
||||
|
||||
|
@ -26,11 +23,19 @@ loadrevinfo(Revlog *changelog, int rev)
|
|||
|
||||
memmove(ri->chash, changelog->map[rev].hash, HASHSZ);
|
||||
|
||||
eof = 0;
|
||||
line = 0;
|
||||
inmsg = 0;
|
||||
p = buf;
|
||||
e = buf + BUFSZ;
|
||||
while((n = read(fd, p, e - p)) > 0){
|
||||
while(eof == 0){
|
||||
if((n = read(fd, p, e - p)) < 0)
|
||||
break;
|
||||
if(n == 0){
|
||||
eof = 1;
|
||||
*p = '\n';
|
||||
n++;
|
||||
}
|
||||
p += n;
|
||||
while((p > buf) && (e = memchr(buf, '\n', p - buf))){
|
||||
*e++ = 0;
|
||||
|
|
|
@ -5,19 +5,25 @@
|
|||
#include "fns.h"
|
||||
|
||||
int
|
||||
fcopy(int dfd, int sfd, vlong len)
|
||||
fcopy(int dfd, int sfd, vlong off, vlong len)
|
||||
{
|
||||
uchar buf[BUFSZ];
|
||||
int n;
|
||||
|
||||
while(len > 0){
|
||||
if((n = BUFSZ) > len)
|
||||
while(len != 0){
|
||||
n = BUFSZ;
|
||||
if(len > 0 && n > len)
|
||||
n = len;
|
||||
if((n = read(sfd, buf, n)) < 0)
|
||||
if((n = pread(sfd, buf, n, off)) < 0)
|
||||
return -1;
|
||||
if(n == 0)
|
||||
return len > 0 ? -1 : 0;
|
||||
if(write(dfd, buf, n) != n)
|
||||
return -1;
|
||||
len -= n;
|
||||
if(off >= 0)
|
||||
off += n;
|
||||
if(len > 0)
|
||||
len -= n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,6 +64,8 @@ fpatch(int ofd, int bfd, int pfd)
|
|||
|
||||
if(bfd >= 0){
|
||||
h = malloc(sizeof(Frag));
|
||||
if(h == nil)
|
||||
goto errout;
|
||||
h->next = nil;
|
||||
h->off = 0;
|
||||
h->fd = bfd;
|
||||
|
@ -101,6 +109,8 @@ fpatch(int ofd, int bfd, int pfd)
|
|||
back = end < fend;
|
||||
if(front && back){
|
||||
p = malloc(sizeof(Frag));
|
||||
if(p == nil)
|
||||
goto errout;
|
||||
*p = *f;
|
||||
f->next = p;
|
||||
f->len = start - fstart;
|
||||
|
@ -123,6 +133,8 @@ fpatch(int ofd, int bfd, int pfd)
|
|||
fstart += f->len;
|
||||
|
||||
f = malloc(sizeof(Frag));
|
||||
if(f == nil)
|
||||
goto errout;
|
||||
f->fd = pfd;
|
||||
f->len = len;
|
||||
f->off = seek(f->fd, 0, 1);
|
||||
|
@ -141,12 +153,9 @@ fpatch(int ofd, int bfd, int pfd)
|
|||
goto errout;
|
||||
}
|
||||
|
||||
for(f = h; f; f = f->next){
|
||||
if(seek(f->fd, f->off, 0) < 0)
|
||||
for(f = h; f; f = f->next)
|
||||
if(fcopy(ofd, f->fd, f->off, f->len) < 0)
|
||||
goto errout;
|
||||
if(fcopy(ofd, f->fd, f->len) < 0)
|
||||
goto errout;
|
||||
}
|
||||
err = 0;
|
||||
|
||||
errout:
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
int
|
||||
fmktemp(void)
|
||||
{
|
||||
char temp[MAXPATH];
|
||||
|
||||
snprint(temp, sizeof(temp), "/tmp/hgXXXXXXXXXXX");
|
||||
return create(mktemp(temp), OTRUNC|ORCLOSE|ORDWR, 0666);
|
||||
static ulong id = 1;
|
||||
char path[MAXPATH];
|
||||
snprint(path, sizeof(path), "/tmp/hg%.12d%.8lux", getpid(), id++);
|
||||
return create(path, OEXCL|OTRUNC|ORDWR|ORCLOSE, 0600);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -65,6 +65,8 @@ revlogopen(Revlog *r, char *path, int mode)
|
|||
{
|
||||
r->ifd = -1;
|
||||
r->dfd = -1;
|
||||
r->tfd = -1;
|
||||
r->tid = -1;
|
||||
path = smprint("%s.i", path);
|
||||
if((r->ifd = open(path, mode)) < 0){
|
||||
free(path);
|
||||
|
@ -94,6 +96,11 @@ revlogclose(Revlog *r)
|
|||
close(r->dfd);
|
||||
r->dfd = -1;
|
||||
}
|
||||
if(r->tfd >= 0){
|
||||
close(r->tfd);
|
||||
r->tfd = -1;
|
||||
}
|
||||
r->tid = -1;
|
||||
free(r->map);
|
||||
r->map = nil;
|
||||
r->nmap = 0;
|
||||
|
@ -269,12 +276,19 @@ revlogopentemp(Revlog *r, int rev)
|
|||
{
|
||||
int fd;
|
||||
|
||||
if((fd = fmktemp()) < 0)
|
||||
return -1;
|
||||
if(revlogextract(r, rev, fd) < 0){
|
||||
close(fd);
|
||||
return -1;
|
||||
if(r->tfd < 0 || rev != r->tid){
|
||||
if((fd = fmktemp()) < 0)
|
||||
return -1;
|
||||
if(revlogextract(r, rev, fd) < 0){
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
if(r->tfd >= 0)
|
||||
close(r->tfd);
|
||||
r->tfd = fd;
|
||||
r->tid = rev;
|
||||
}
|
||||
fd = dup(r->tfd, -1);
|
||||
if(seek(fd, 0, 0) < 0){
|
||||
close(fd);
|
||||
return -1;
|
||||
|
|
Loading…
Reference in a new issue