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;
|
int nmap;
|
||||||
Revmap *map;
|
Revmap *map;
|
||||||
|
|
||||||
|
int tfd;
|
||||||
|
int tid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Revnode
|
struct Revnode
|
||||||
|
|
|
@ -6,6 +6,7 @@ int fhash(int fd, uchar p1[], uchar p2[], uchar h[]);
|
||||||
int readhash(char *path, char *name, uchar hash[]);
|
int readhash(char *path, char *name, uchar hash[]);
|
||||||
|
|
||||||
/* patch */
|
/* patch */
|
||||||
|
int fcopy(int dfd, int sfd, vlong off, vlong len);
|
||||||
int fpatchmark(int pfd, char *mark);
|
int fpatchmark(int pfd, char *mark);
|
||||||
int fpatch(int ofd, int bfd, int pfd);
|
int fpatch(int ofd, int bfd, int pfd);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ static char *nametab[] = {
|
||||||
static Revlog changelog;
|
static Revlog changelog;
|
||||||
static Revlog manifest;
|
static Revlog manifest;
|
||||||
static Revlog *revlogs;
|
static Revlog *revlogs;
|
||||||
|
static int nfreerevlogs = 0;
|
||||||
|
|
||||||
static char workdir[MAXPATH];
|
static char workdir[MAXPATH];
|
||||||
static int mangle = 0;
|
static int mangle = 0;
|
||||||
|
@ -51,16 +52,28 @@ static Revlog*
|
||||||
getrevlog(Revnode *nd)
|
getrevlog(Revnode *nd)
|
||||||
{
|
{
|
||||||
char buf[MAXPATH];
|
char buf[MAXPATH];
|
||||||
Revlog *rl;
|
Revlog *rl, **link;
|
||||||
int mang;
|
int mang;
|
||||||
|
|
||||||
mang = mangle;
|
mang = mangle;
|
||||||
Again:
|
Again:
|
||||||
nodepath(seprint(buf, buf+sizeof(buf), "%s/.hg/store/data", workdir),
|
nodepath(seprint(buf, buf+sizeof(buf), "%s/.hg/store/data", workdir),
|
||||||
buf+sizeof(buf), nd, mang);
|
buf+sizeof(buf), nd, mang);
|
||||||
for(rl = revlogs; rl; rl = rl->next)
|
link = &revlogs;
|
||||||
if(strcmp(buf, rl->path) == 0)
|
while(rl = *link){
|
||||||
|
if(strcmp(buf, rl->path) == 0){
|
||||||
|
if(rl->ref == 0) nfreerevlogs--;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if(nfreerevlogs > 8 && rl->ref == 0){
|
||||||
|
*link = rl->next;
|
||||||
|
nfreerevlogs--;
|
||||||
|
revlogclose(rl);
|
||||||
|
free(rl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
link = &rl->next;
|
||||||
|
}
|
||||||
if(rl == nil){
|
if(rl == nil){
|
||||||
rl = emalloc9p(sizeof(*rl));
|
rl = emalloc9p(sizeof(*rl));
|
||||||
memset(rl, 0, sizeof(*rl));
|
memset(rl, 0, sizeof(*rl));
|
||||||
|
@ -83,18 +96,8 @@ Again:
|
||||||
static void
|
static void
|
||||||
closerevlog(Revlog *rl)
|
closerevlog(Revlog *rl)
|
||||||
{
|
{
|
||||||
Revlog **pp;
|
if(rl != nil && decref(rl) == 0)
|
||||||
|
nfreerevlogs++;
|
||||||
if(rl == nil || decref(rl))
|
|
||||||
return;
|
|
||||||
for(pp = &revlogs; *pp; pp = &((*pp)->next)){
|
|
||||||
if(*pp == rl){
|
|
||||||
*pp = rl->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
revlogclose(rl);
|
|
||||||
free(rl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Revinfo*
|
static Revinfo*
|
||||||
|
|
|
@ -8,16 +8,13 @@ Revinfo*
|
||||||
loadrevinfo(Revlog *changelog, int rev)
|
loadrevinfo(Revlog *changelog, int rev)
|
||||||
{
|
{
|
||||||
char buf[BUFSZ], *p, *e;
|
char buf[BUFSZ], *p, *e;
|
||||||
int fd, line, inmsg, n;
|
int fd, line, eof, inmsg, n;
|
||||||
Revinfo *ri;
|
Revinfo *ri;
|
||||||
vlong off;
|
vlong off;
|
||||||
|
|
||||||
if((fd = revlogopentemp(changelog, rev)) < 0)
|
if((fd = revlogopentemp(changelog, rev)) < 0)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
seek(fd, 0, 2);
|
|
||||||
write(fd, "\n", 1);
|
|
||||||
|
|
||||||
off = fmetaheader(fd);
|
off = fmetaheader(fd);
|
||||||
seek(fd, off, 0);
|
seek(fd, off, 0);
|
||||||
|
|
||||||
|
@ -26,11 +23,19 @@ loadrevinfo(Revlog *changelog, int rev)
|
||||||
|
|
||||||
memmove(ri->chash, changelog->map[rev].hash, HASHSZ);
|
memmove(ri->chash, changelog->map[rev].hash, HASHSZ);
|
||||||
|
|
||||||
|
eof = 0;
|
||||||
line = 0;
|
line = 0;
|
||||||
inmsg = 0;
|
inmsg = 0;
|
||||||
p = buf;
|
p = buf;
|
||||||
e = buf + BUFSZ;
|
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;
|
p += n;
|
||||||
while((p > buf) && (e = memchr(buf, '\n', p - buf))){
|
while((p > buf) && (e = memchr(buf, '\n', p - buf))){
|
||||||
*e++ = 0;
|
*e++ = 0;
|
||||||
|
|
|
@ -5,18 +5,24 @@
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
|
||||||
int
|
int
|
||||||
fcopy(int dfd, int sfd, vlong len)
|
fcopy(int dfd, int sfd, vlong off, vlong len)
|
||||||
{
|
{
|
||||||
uchar buf[BUFSZ];
|
uchar buf[BUFSZ];
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while(len > 0){
|
while(len != 0){
|
||||||
if((n = BUFSZ) > len)
|
n = BUFSZ;
|
||||||
|
if(len > 0 && n > len)
|
||||||
n = len;
|
n = len;
|
||||||
if((n = read(sfd, buf, n)) < 0)
|
if((n = pread(sfd, buf, n, off)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
if(n == 0)
|
||||||
|
return len > 0 ? -1 : 0;
|
||||||
if(write(dfd, buf, n) != n)
|
if(write(dfd, buf, n) != n)
|
||||||
return -1;
|
return -1;
|
||||||
|
if(off >= 0)
|
||||||
|
off += n;
|
||||||
|
if(len > 0)
|
||||||
len -= n;
|
len -= n;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -58,6 +64,8 @@ fpatch(int ofd, int bfd, int pfd)
|
||||||
|
|
||||||
if(bfd >= 0){
|
if(bfd >= 0){
|
||||||
h = malloc(sizeof(Frag));
|
h = malloc(sizeof(Frag));
|
||||||
|
if(h == nil)
|
||||||
|
goto errout;
|
||||||
h->next = nil;
|
h->next = nil;
|
||||||
h->off = 0;
|
h->off = 0;
|
||||||
h->fd = bfd;
|
h->fd = bfd;
|
||||||
|
@ -101,6 +109,8 @@ fpatch(int ofd, int bfd, int pfd)
|
||||||
back = end < fend;
|
back = end < fend;
|
||||||
if(front && back){
|
if(front && back){
|
||||||
p = malloc(sizeof(Frag));
|
p = malloc(sizeof(Frag));
|
||||||
|
if(p == nil)
|
||||||
|
goto errout;
|
||||||
*p = *f;
|
*p = *f;
|
||||||
f->next = p;
|
f->next = p;
|
||||||
f->len = start - fstart;
|
f->len = start - fstart;
|
||||||
|
@ -123,6 +133,8 @@ fpatch(int ofd, int bfd, int pfd)
|
||||||
fstart += f->len;
|
fstart += f->len;
|
||||||
|
|
||||||
f = malloc(sizeof(Frag));
|
f = malloc(sizeof(Frag));
|
||||||
|
if(f == nil)
|
||||||
|
goto errout;
|
||||||
f->fd = pfd;
|
f->fd = pfd;
|
||||||
f->len = len;
|
f->len = len;
|
||||||
f->off = seek(f->fd, 0, 1);
|
f->off = seek(f->fd, 0, 1);
|
||||||
|
@ -141,12 +153,9 @@ fpatch(int ofd, int bfd, int pfd)
|
||||||
goto errout;
|
goto errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(f = h; f; f = f->next){
|
for(f = h; f; f = f->next)
|
||||||
if(seek(f->fd, f->off, 0) < 0)
|
if(fcopy(ofd, f->fd, f->off, f->len) < 0)
|
||||||
goto errout;
|
goto errout;
|
||||||
if(fcopy(ofd, f->fd, f->len) < 0)
|
|
||||||
goto errout;
|
|
||||||
}
|
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
errout:
|
errout:
|
||||||
|
|
|
@ -7,10 +7,10 @@
|
||||||
int
|
int
|
||||||
fmktemp(void)
|
fmktemp(void)
|
||||||
{
|
{
|
||||||
char temp[MAXPATH];
|
static ulong id = 1;
|
||||||
|
char path[MAXPATH];
|
||||||
snprint(temp, sizeof(temp), "/tmp/hgXXXXXXXXXXX");
|
snprint(path, sizeof(path), "/tmp/hg%.12d%.8lux", getpid(), id++);
|
||||||
return create(mktemp(temp), OTRUNC|ORCLOSE|ORDWR, 0666);
|
return create(path, OEXCL|OTRUNC|ORDWR|ORCLOSE, 0600);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -65,6 +65,8 @@ revlogopen(Revlog *r, char *path, int mode)
|
||||||
{
|
{
|
||||||
r->ifd = -1;
|
r->ifd = -1;
|
||||||
r->dfd = -1;
|
r->dfd = -1;
|
||||||
|
r->tfd = -1;
|
||||||
|
r->tid = -1;
|
||||||
path = smprint("%s.i", path);
|
path = smprint("%s.i", path);
|
||||||
if((r->ifd = open(path, mode)) < 0){
|
if((r->ifd = open(path, mode)) < 0){
|
||||||
free(path);
|
free(path);
|
||||||
|
@ -94,6 +96,11 @@ revlogclose(Revlog *r)
|
||||||
close(r->dfd);
|
close(r->dfd);
|
||||||
r->dfd = -1;
|
r->dfd = -1;
|
||||||
}
|
}
|
||||||
|
if(r->tfd >= 0){
|
||||||
|
close(r->tfd);
|
||||||
|
r->tfd = -1;
|
||||||
|
}
|
||||||
|
r->tid = -1;
|
||||||
free(r->map);
|
free(r->map);
|
||||||
r->map = nil;
|
r->map = nil;
|
||||||
r->nmap = 0;
|
r->nmap = 0;
|
||||||
|
@ -269,12 +276,19 @@ revlogopentemp(Revlog *r, int rev)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
if(r->tfd < 0 || rev != r->tid){
|
||||||
if((fd = fmktemp()) < 0)
|
if((fd = fmktemp()) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if(revlogextract(r, rev, fd) < 0){
|
if(revlogextract(r, rev, fd) < 0){
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
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){
|
if(seek(fd, 0, 0) < 0){
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue