summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/cvs/resp.c91
1 files changed, 61 insertions, 30 deletions
diff --git a/usr.bin/cvs/resp.c b/usr.bin/cvs/resp.c
index e62610614e8..b74f197c797 100644
--- a/usr.bin/cvs/resp.c
+++ b/usr.bin/cvs/resp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: resp.c,v 1.41 2005/05/31 08:58:48 xsa Exp $ */
+/* $OpenBSD: resp.c,v 1.42 2005/06/10 21:13:40 joris Exp $ */
/*
* Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
* All rights reserved.
@@ -112,7 +112,15 @@ struct cvs_resphdlr {
{ cvs_resp_m },
};
-
+/*
+ * Instead of opening and closing the Entry file all the time,
+ * which caused a huge CPU load and slowed down everything,
+ * we keep the Entry file for the directory we are working in
+ * open until we encounter a new directory.
+ */
+static char cvs_resp_lastdir[MAXPATHLEN] = "";
+static CVSENTRIES *cvs_resp_lastent = NULL;
+static int resp_check_dir(const char *);
/*
* The MT command uses scoping to tag the data. Whenever we encouter a '+',
@@ -292,6 +300,11 @@ cvs_resp_m(struct cvsroot *root, int type, char *line)
static int
cvs_resp_ok(struct cvsroot *root, int type, char *line)
{
+ /*
+ * If we still have an Entry file open, close it now.
+ */
+ if (cvs_resp_lastent != NULL)
+ cvs_ent_close(cvs_resp_lastent);
return (1);
}
@@ -463,7 +476,6 @@ cvs_resp_newentry(struct cvsroot *root, int type, char *line)
{
char entbuf[128];
struct cvs_ent *ent;
- CVSENTRIES *entfile;
/* get the remote path */
cvs_getln(root, entbuf, sizeof(entbuf));
@@ -472,16 +484,15 @@ cvs_resp_newentry(struct cvsroot *root, int type, char *line)
if (cvs_getln(root, entbuf, sizeof(entbuf)) < 0)
return (-1);
- entfile = cvs_ent_open(line, O_WRONLY);
- if (entfile == NULL)
+ if (resp_check_dir(line) < 0)
return (-1);
+
if (type == CVS_RESP_NEWENTRY) {
- cvs_ent_addln(entfile, entbuf);
+ cvs_ent_addln(cvs_resp_lastent, entbuf);
} else if (type == CVS_RESP_CHECKEDIN) {
ent = cvs_ent_parse(entbuf);
if (ent == NULL) {
cvs_log(LP_ERR, "failed to parse entry");
- cvs_ent_close(entfile);
return (-1);
}
@@ -489,11 +500,10 @@ cvs_resp_newentry(struct cvsroot *root, int type, char *line)
ent->ce_mtime = time(&(ent->ce_mtime));
/* replace the current entry with the one we just received */
- (void)cvs_ent_remove(entfile, ent->ce_name);
+ (void)cvs_ent_remove(cvs_resp_lastent, ent->ce_name);
- cvs_ent_add(entfile, ent);
+ cvs_ent_add(cvs_resp_lastent, ent);
}
- cvs_ent_close(entfile);
return (0);
}
@@ -600,7 +610,6 @@ cvs_resp_updated(struct cvsroot *root, int type, char *line)
mode_t fmode;
char path[MAXPATHLEN], cksum_buf[CVS_CKSUM_LEN];
BUF *fbuf;
- CVSENTRIES *entfile;
struct cvs_ent *ep;
struct timeval tv[2];
@@ -623,11 +632,8 @@ cvs_resp_updated(struct cvsroot *root, int type, char *line)
}
ret = 0;
- entfile = cvs_ent_open(line, O_WRONLY);
- if (entfile == NULL) {
- cvs_ent_free(ep);
+ if (resp_check_dir(line) < 0)
return (-1);
- }
if (cvs_modtime != CVS_DATE_DMSEC) {
ep->ce_mtime = cvs_modtime;
@@ -636,21 +642,18 @@ cvs_resp_updated(struct cvsroot *root, int type, char *line)
if ((type == CVS_RESP_UPDEXIST) || (type == CVS_RESP_UPDATED) ||
(type == CVS_RESP_MERGED) || (type == CVS_RESP_CREATED)) {
- if ((cvs_ent_remove(entfile, ep->ce_name) < 0) &&
+ if ((cvs_ent_remove(cvs_resp_lastent, ep->ce_name) < 0) &&
(type != CVS_RESP_CREATED)) {
cvs_log(LP_WARN, "failed to remove entry for '%s`",
ep->ce_name);
}
}
- if (cvs_ent_add(entfile, ep) < 0) {
+ if (cvs_ent_add(cvs_resp_lastent, ep) < 0) {
cvs_ent_free(ep);
- cvs_ent_close(entfile);
return (-1);
}
- cvs_ent_close(entfile);
-
if ((fbuf = cvs_recvfile(root, &fmode)) == NULL)
return (-1);
if (cvs_buf_write(fbuf, path, fmode) < 0) {
@@ -702,7 +705,6 @@ cvs_resp_removed(struct cvsroot *root, int type, char *line)
{
int l;
char buf[MAXPATHLEN], base[MAXPATHLEN], fpath[MAXPATHLEN], *file;
- CVSENTRIES *ef;
if (cvs_getln(root, buf, sizeof(buf)) < 0)
return (-1);
@@ -715,16 +717,10 @@ cvs_resp_removed(struct cvsroot *root, int type, char *line)
return (-1);
}
- ef = cvs_ent_open(line, O_RDWR);
- if (ef == NULL) {
- cvs_log(LP_ERR, "error handling `Removed' response");
- if (type == CVS_RESP_RMENTRY)
- return (-1);
- } else {
- (void)cvs_ent_remove(ef, file);
- cvs_ent_close(ef);
- }
+ if (resp_check_dir(line) < 0)
+ return (-1);
+ (void)cvs_ent_remove(cvs_resp_lastent, file);
if ((type == CVS_RESP_REMOVED) && ((unlink(fpath) == -1) &&
errno != ENOENT)) {
cvs_log(LP_ERRNO, "failed to unlink `%s'", file);
@@ -853,3 +849,38 @@ cvs_resp_template(struct cvsroot *root, int type, char *line)
return (0);
}
+
+/*
+ * Check if <dir> is the same as the last
+ * received directory, if it's not, switch Entry files.
+ */
+static int
+resp_check_dir(const char *dir)
+{
+ size_t len;
+
+ if (strcmp(dir, cvs_resp_lastdir)) {
+ if (cvs_resp_lastent != NULL)
+ cvs_ent_close(cvs_resp_lastent);
+ cvs_resp_lastent = cvs_ent_open(dir, O_WRONLY);
+ if (cvs_resp_lastent == NULL)
+ return (-1);
+
+ len = strlcpy(cvs_resp_lastdir, dir, sizeof(cvs_resp_lastdir));
+ if (len >= sizeof(cvs_resp_lastdir)) {
+ errno = ENAMETOOLONG;
+ cvs_log(LP_ERRNO, "%s", cvs_resp_lastdir);
+ return (-1);
+ }
+ } else {
+ /* make sure the old one is still open */
+ if (cvs_resp_lastent == NULL) {
+ cvs_resp_lastent = cvs_ent_open(cvs_resp_lastdir,
+ O_WRONLY);
+ if (cvs_resp_lastent == NULL)
+ return (-1);
+ }
+ }
+
+ return (0);
+}