summaryrefslogtreecommitdiff
path: root/sys/src/cmd/hgfs
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-11-21 19:22:46 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2012-11-21 19:22:46 +0100
commit40d11cea3fac49a660b5714b18393c2e74487d54 (patch)
tree09ae5180eaeefffa293cec6d2e71765e0e951f9b /sys/src/cmd/hgfs
parent73744b9f4896c513d4d7c40ef4ce1d24703810e9 (diff)
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.
Diffstat (limited to 'sys/src/cmd/hgfs')
-rw-r--r--sys/src/cmd/hgfs/dat.h3
-rw-r--r--sys/src/cmd/hgfs/fns.h1
-rw-r--r--sys/src/cmd/hgfs/fs.c33
-rw-r--r--sys/src/cmd/hgfs/info.c15
-rw-r--r--sys/src/cmd/hgfs/patch.c29
-rw-r--r--sys/src/cmd/hgfs/revlog.c32
6 files changed, 74 insertions, 39 deletions
diff --git a/sys/src/cmd/hgfs/dat.h b/sys/src/cmd/hgfs/dat.h
index 17cc05e91..70d5ccbc2 100644
--- a/sys/src/cmd/hgfs/dat.h
+++ b/sys/src/cmd/hgfs/dat.h
@@ -46,6 +46,9 @@ struct Revlog
int nmap;
Revmap *map;
+
+ int tfd;
+ int tid;
};
struct Revnode
diff --git a/sys/src/cmd/hgfs/fns.h b/sys/src/cmd/hgfs/fns.h
index 42c6f736f..6145330b0 100644
--- a/sys/src/cmd/hgfs/fns.h
+++ b/sys/src/cmd/hgfs/fns.h
@@ -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);
diff --git a/sys/src/cmd/hgfs/fs.c b/sys/src/cmd/hgfs/fs.c
index 9c61233c3..727cf64d3 100644
--- a/sys/src/cmd/hgfs/fs.c
+++ b/sys/src/cmd/hgfs/fs.c
@@ -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*
diff --git a/sys/src/cmd/hgfs/info.c b/sys/src/cmd/hgfs/info.c
index 6a17a8fcc..45877f957 100644
--- a/sys/src/cmd/hgfs/info.c
+++ b/sys/src/cmd/hgfs/info.c
@@ -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;
diff --git a/sys/src/cmd/hgfs/patch.c b/sys/src/cmd/hgfs/patch.c
index a3d6ef37a..a9d93aa1a 100644
--- a/sys/src/cmd/hgfs/patch.c
+++ b/sys/src/cmd/hgfs/patch.c
@@ -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:
diff --git a/sys/src/cmd/hgfs/revlog.c b/sys/src/cmd/hgfs/revlog.c
index ab4ef1d9f..a90363b2e 100644
--- a/sys/src/cmd/hgfs/revlog.c
+++ b/sys/src/cmd/hgfs/revlog.c
@@ -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;