{"thread":{"id":"5767","subject":"[PATCH 2/2] refs: minor restructuring of cached refs data.","startedAt":"2006-09-30T19:49:03Z","lastAt":"2006-09-30T19:49:03Z","messageCount":1,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"28033","messageId":"7vr6xtcez4.fsf@assigned-by-dhcp.cox.net","threadId":"5767","inReplyTo":null,"subject":"[PATCH 2/2] refs: minor restructuring of cached refs data.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-09-30T19:49:03Z","receivedAt":"2006-09-30T19:49:03Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Once we read packed and loose refs, for_each_ref() and friends\nkept using them even after write_ref_sha1() and delete_ref()\nchanged the refs.  This adds invalidate_cached_refs() as a way\nto flush the cached information.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n * This should not change the behaviour of the existing code in\n   any way, but is a necessary step to handle ref deletion\n   correctly.\n\n refs.c |   56 +++++++++++++++++++++++++++++++++++++++++++-------------\n 1 files changed, 43 insertions(+), 13 deletions(-)\n\ndiff --git a/refs.c b/refs.c\nindex b433c0c..6ee5f96 100644\n--- a/refs.c\n+++ b/refs.c\n@@ -66,12 +66,42 @@ static struct ref_list *add_ref(const ch\n \treturn list;\n }\n \n-static struct ref_list *get_packed_refs(void)\n+/*\n+ * Future: need to be in \"struct repository\"\n+ * when doing a full libification.\n+ */\n+struct cached_refs {\n+\tchar did_loose;\n+\tchar did_packed;\n+\tstruct ref_list *loose;\n+\tstruct ref_list *packed;\n+} cached_refs;\n+\n+static void free_ref_list(struct ref_list *list)\n+{\n+\tstruct ref_list *next;\n+\tfor ( ; list; list = next) {\n+\t\tnext = list->next;\n+\t\tfree(list);\n+\t}\n+}\n+\n+static void invalidate_cached_refs(void)\n {\n-\tstatic int did_refs = 0;\n-\tstatic struct ref_list *refs = NULL;\n+\tstruct cached_refs *ca = &cached_refs;\n+\n+\tif (ca->did_loose && ca->loose)\n+\t\tfree_ref_list(ca->loose);\n+\tif (ca->did_packed && ca->packed)\n+\t\tfree_ref_list(ca->packed);\n+\tca->loose = ca->packed = NULL;\n+\tca->did_loose = ca->did_packed = 0;\n+}\n \n-\tif (!did_refs) {\n+static struct ref_list *get_packed_refs(void)\n+{\n+\tif (!cached_refs.did_packed) {\n+\t\tstruct ref_list *refs = NULL;\n \t\tFILE *f = fopen(git_path(\"packed-refs\"), \"r\");\n \t\tif (f) {\n \t\t\tstruct ref_list *list = NULL;\n@@ -86,9 +116,10 @@ static struct ref_list *get_packed_refs(\n \t\t\tfclose(f);\n \t\t\trefs = list;\n \t\t}\n-\t\tdid_refs = 1;\n+\t\tcached_refs.packed = refs;\n+\t\tcached_refs.did_packed = 1;\n \t}\n-\treturn refs;\n+\treturn cached_refs.packed;\n }\n \n static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)\n@@ -138,14 +169,11 @@ static struct ref_list *get_ref_dir(cons\n \n static struct ref_list *get_loose_refs(void)\n {\n-\tstatic int did_refs = 0;\n-\tstatic struct ref_list *refs = NULL;\n-\n-\tif (!did_refs) {\n-\t\trefs = get_ref_dir(\"refs\", NULL);\n-\t\tdid_refs = 1;\n+\tif (!cached_refs.did_loose) {\n+\t\tcached_refs.loose = get_ref_dir(\"refs\", NULL);\n+\t\tcached_refs.did_loose = 1;\n \t}\n-\treturn refs;\n+\treturn cached_refs.loose;\n }\n \n /* We allow \"recursive\" symbolic refs. Only within reason, though */\n@@ -401,6 +429,7 @@ int delete_ref(const char *refname, unsi\n \t\tfprintf(stderr, \"warning: unlink(%s) failed: %s\",\n \t\t\tlock->log_file, strerror(errno));\n \n+\tinvalidate_cached_refs();\n \treturn ret;\n }\n \n@@ -665,6 +694,7 @@ int write_ref_sha1(struct ref_lock *lock\n \t\tunlock_ref(lock);\n \t\treturn -1;\n \t}\n+\tinvalidate_cached_refs();\n \tif (log_ref_write(lock, sha1, logmsg) < 0) {\n \t\tunlock_ref(lock);\n \t\treturn -1;\n-- \n1.4.2.1.g5a98f\n"}]}