提交 854b97f6 编写于 作者: J Junio C Hamano

git-pickaxe: fix origin refcounting

When we introduced the cached origin per commit, we gave up proper
garbage collecting because it meant that commits hold onto their
cached copy.  There is no need to do so.
Signed-off-by: NJunio C Hamano <junkio@cox.net>
上级 33494784
...@@ -168,23 +168,28 @@ static void coalesce(struct scoreboard *sb) ...@@ -168,23 +168,28 @@ static void coalesce(struct scoreboard *sb)
sanity_check_refcnt(sb); sanity_check_refcnt(sb);
} }
static struct origin *make_origin(struct commit *commit, const char *path)
{
struct origin *o;
o = xcalloc(1, sizeof(*o) + strlen(path) + 1);
o->commit = commit;
o->refcnt = 1;
strcpy(o->path, path);
return o;
}
static struct origin *get_origin(struct scoreboard *sb, static struct origin *get_origin(struct scoreboard *sb,
struct commit *commit, struct commit *commit,
const char *path) const char *path)
{ {
struct blame_entry *e; struct blame_entry *e;
struct origin *o;
for (e = sb->ent; e; e = e->next) { for (e = sb->ent; e; e = e->next) {
if (e->suspect->commit == commit && if (e->suspect->commit == commit &&
!strcmp(e->suspect->path, path)) !strcmp(e->suspect->path, path))
return origin_incref(e->suspect); return origin_incref(e->suspect);
} }
o = xcalloc(1, sizeof(*o) + strlen(path) + 1); return make_origin(commit, path);
o->commit = commit;
o->refcnt = 1;
strcpy(o->path, path);
return o;
} }
static int fill_blob_sha1(struct origin *origin) static int fill_blob_sha1(struct origin *origin)
...@@ -216,9 +221,19 @@ static struct origin *find_origin(struct scoreboard *sb, ...@@ -216,9 +221,19 @@ static struct origin *find_origin(struct scoreboard *sb,
const char *paths[2]; const char *paths[2];
if (parent->util) { if (parent->util) {
/* This is a freestanding copy of origin and not
* refcounted.
*/
struct origin *cached = parent->util; struct origin *cached = parent->util;
if (!strcmp(cached->path, origin->path)) if (!strcmp(cached->path, origin->path)) {
return origin_incref(cached); porigin = get_origin(sb, parent, cached->path);
if (porigin->refcnt == 1)
hashcpy(porigin->blob_sha1, cached->blob_sha1);
return porigin;
}
/* otherwise it was not very useful; free it */
free(parent->util);
parent->util = NULL;
} }
/* See if the origin->path is different between parent /* See if the origin->path is different between parent
...@@ -268,10 +283,10 @@ static struct origin *find_origin(struct scoreboard *sb, ...@@ -268,10 +283,10 @@ static struct origin *find_origin(struct scoreboard *sb,
} }
diff_flush(&diff_opts); diff_flush(&diff_opts);
if (porigin) { if (porigin) {
origin_incref(porigin); struct origin *cached;
if (parent->util) cached = make_origin(porigin->commit, porigin->path);
origin_decref(parent->util); hashcpy(cached->blob_sha1, porigin->blob_sha1);
parent->util = porigin; parent->util = cached;
} }
return porigin; return porigin;
} }
...@@ -1434,8 +1449,13 @@ static void sanity_check_refcnt(struct scoreboard *sb) ...@@ -1434,8 +1449,13 @@ static void sanity_check_refcnt(struct scoreboard *sb)
for (ent = sb->ent; ent; ent = ent->next) { for (ent = sb->ent; ent; ent = ent->next) {
/* Nobody should have zero or negative refcnt */ /* Nobody should have zero or negative refcnt */
if (ent->suspect->refcnt <= 0) if (ent->suspect->refcnt <= 0) {
fprintf(stderr, "%s in %s has negative refcnt %d\n",
ent->suspect->path,
sha1_to_hex(ent->suspect->commit->object.sha1),
ent->suspect->refcnt);
baa = 1; baa = 1;
}
} }
for (ent = sb->ent; ent; ent = ent->next) { for (ent = sb->ent; ent; ent = ent->next) {
/* Mark the ones that haven't been checked */ /* Mark the ones that haven't been checked */
...@@ -1444,9 +1464,7 @@ static void sanity_check_refcnt(struct scoreboard *sb) ...@@ -1444,9 +1464,7 @@ static void sanity_check_refcnt(struct scoreboard *sb)
} }
for (ent = sb->ent; ent; ent = ent->next) { for (ent = sb->ent; ent; ent = ent->next) {
/* then pick each and see if they have the the correct /* then pick each and see if they have the the correct
* refcnt; note that ->util caching means origin's refcnt * refcnt.
* may well be greater than the number of blame entries
* that use it.
*/ */
int found; int found;
struct blame_entry *e; struct blame_entry *e;
...@@ -1460,14 +1478,19 @@ static void sanity_check_refcnt(struct scoreboard *sb) ...@@ -1460,14 +1478,19 @@ static void sanity_check_refcnt(struct scoreboard *sb)
continue; continue;
found++; found++;
} }
if (suspect->refcnt < found) if (suspect->refcnt != found) {
baa = 1; fprintf(stderr, "%s in %s has refcnt %d, not %d\n",
ent->suspect->path,
sha1_to_hex(ent->suspect->commit->object.sha1),
ent->suspect->refcnt, found);
baa = 2;
}
} }
if (baa) { if (baa) {
int opt = 0160; int opt = 0160;
find_alignment(sb, &opt); find_alignment(sb, &opt);
output(sb, opt); output(sb, opt);
die("Baa!"); die("Baa %d!", baa);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册