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:
cinap_lenrek 2012-11-21 19:22:46 +01:00
parent 73744b9f48
commit 40d11cea3f
6 changed files with 74 additions and 39 deletions

View file

@ -46,6 +46,9 @@ struct Revlog
int nmap;
Revmap *map;
int tfd;
int tid;
};
struct Revnode

View file

@ -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);

View file

@ -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*

View file

@ -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;

View file

@ -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:

View file

@ -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;