{"thread":{"id":"222","subject":"[PATCH 15/19] introduce a cache struct and move the various cache globals into it.","startedAt":"2005-04-21T18:38:20Z","lastAt":"2005-04-21T18:38:20Z","messageCount":1,"participants":["Brad Roberts"],"isPatch":true,"patchVersion":1,"patchTotal":19},"messages":[{"id":"1171","messageId":"200504211838.j3LIcKph027789@gameboy2.puremagic.com","threadId":"222","inReplyTo":null,"subject":"[PATCH 15/19] introduce a cache struct and move the various cache globals into it.","fromName":"Brad Roberts","fromEmail":"braddr@gameboy2.puremagic.com","sentAt":"2005-04-21T18:38:20Z","receivedAt":"2005-04-21T18:38:20Z","isPatch":true,"sender":{"key":"braddr@gameboy2.puremagic.com","avatar":null},"body":"tree c806c7328a6c9297df108ab00ebe1c4014496cb0\nparent b7d4fa53d4ee449b4b9b4f3c9dd40d6c99db4bc1\nauthor Brad Roberts <braddr@puremagic.com> 1114086327 -0700\ncommitter Brad Roberts <braddr@gameboy2.puremagic.com> 1114086327 -0700\n\n[PATCH] introduce a cache struct and move the various cache globals into it.\n\nNew elements in the cache struct that previously were discarded:\n  - the cache headers\n  - the mmap info so we can cleanup later\n\nFor this stage, the cache itself is still a global variable.  That will change.\n\nSigned-off-by: Brad Roberts <braddr@puremagic.com>\n---\n\n cache.h      |    1 \n read-cache.c |  127 ++++++++++++++++++++++++++++++++++-------------------------\n 2 files changed, 76 insertions(+), 52 deletions(-)\n\nIndex: cache.h\n===================================================================\n--- b7d4fa53d4ee449b4b9b4f3c9dd40d6c99db4bc1:1/cache.h  (mode:100644 sha1:74d6c4d25c564e08eadc04aaef31a711d0645a43)\n+++ f07f7073f45a7f81e5b6cf26f5181e14fd051d81:1/cache.h  (mode:100644 sha1:a3018f9e12bfdd1a5273b20fcab5062667c6caec)\n@@ -72,6 +72,7 @@\n /* Initialize and use the cache information */\n extern int read_cache(void);\n extern int write_cache(int newfd);\n+extern void free_cache();\n extern int cache_name_pos(const char *name, int namelen);\n extern int add_cache_entry(struct cache_entry *ce, int ok_to_add);\n extern int remove_file_from_cache(char *path);\nIndex: read-cache.c\n===================================================================\n--- b7d4fa53d4ee449b4b9b4f3c9dd40d6c99db4bc1:1/read-cache.c  (mode:100644 sha1:b16a72dc4e4525a7df060b3a43722217db7869c2)\n+++ f07f7073f45a7f81e5b6cf26f5181e14fd051d81:1/read-cache.c  (mode:100644 sha1:c399f8e497441147afe630ca080558a8c6c79c78)\n@@ -17,8 +17,20 @@\n \tunsigned int hdr_entries;\n };\n \n-static struct cache_entry **active_cache = NULL;\n-static unsigned int active_nr = 0, active_alloc = 0;\n+struct mmap_holder {\n+\tvoid * ptr;\n+\tsize_t size;\n+};\n+\n+struct cache {\n+\tstruct mmap_holder   map;\n+\tstruct cache_header *header;\n+\tstruct cache_entry **entries;\n+\tunsigned int num_entries;\n+\tunsigned int allocated_entries;\n+};\n+\n+static struct cache * cache = NULL;\n \n int cache_match_stat(struct cache_entry *ce, struct stat *st)\n {\n@@ -81,10 +93,10 @@\n \tint first, last;\n \n \tfirst = 0;\n-\tlast = active_nr;\n+\tlast = cache->num_entries;\n \twhile (last > first) {\n \t\tint next = (last + first) >> 1;\n-\t\tstruct cache_entry *ce = active_cache[next];\n+\t\tstruct cache_entry *ce = cache->entries[next];\n \t\tint cmp = cache_name_compare(name, namelen, ce->name, htons(ce->ce_flags));\n \t\tif (!cmp)\n \t\t\treturn next;\n@@ -100,10 +112,10 @@\n /* Remove entry, return true if there are more entries to go.. */\n int remove_cache_entry_at(int pos)\n {\n-\tactive_nr--;\n-\tif (pos >= active_nr)\n+\tcache->num_entries--;\n+\tif (pos >= cache->num_entries)\n \t\treturn 0;\n-\tmemmove(active_cache + pos, active_cache + pos + 1, (active_nr - pos) * sizeof(struct cache_entry *));\n+\tmemmove(cache->entries + pos, cache->entries + pos + 1, (cache->num_entries - pos) * sizeof(struct cache_entry *));\n \treturn 1;\n }\n \n@@ -123,20 +135,20 @@\n \n int get_num_cache_entries()\n {\n-\treturn active_nr;\n+\treturn cache->num_entries;\n }\n \n struct cache_entry * get_cache_entry(int pos)\n {\n-\treturn active_cache[pos];\n+\treturn cache->entries[pos];\n }\n \n void set_cache_entry(struct cache_entry *ce, int pos)\n {\n-\t/* You can NOT just free active_cache[i] here, since it\n+\t/* You can NOT just free cache->entries[i] here, since it\n \t * might not be necessarily malloc()ed but can also come\n \t * from mmap(). */\n-\tactive_cache[pos] = ce;\n+\tcache->entries[pos] = ce;\n }\n \n int add_cache_entry(struct cache_entry *ce, int ok_to_add)\n@@ -147,7 +159,7 @@\n \n \t/* existing match? Just replace it */\n \tif (pos >= 0) {\n-\t\tactive_cache[pos] = ce;\n+\t\tcache->entries[pos] = ce;\n \t\treturn 0;\n \t}\n \tpos = -pos-1;\n@@ -156,8 +168,8 @@\n \t * Inserting a merged entry (\"stage 0\") into the index\n \t * will always replace all non-merged entries..\n \t */\n-\tif (pos < active_nr && ce_stage(ce) == 0) {\n-\t\twhile (same_name(active_cache[pos], ce)) {\n+\tif (pos < cache->num_entries && ce_stage(ce) == 0) {\n+\t\twhile (same_name(cache->entries[pos], ce)) {\n \t\t\tok_to_add = 1;\n \t\t\tif (!remove_cache_entry_at(pos))\n \t\t\t\tbreak;\n@@ -168,16 +180,16 @@\n \t\treturn -1;\n \n \t/* Make sure the array is big enough .. */\n-\tif (active_nr == active_alloc) {\n-\t\tactive_alloc = alloc_nr(active_alloc);\n-\t\tactive_cache = realloc(active_cache, active_alloc * sizeof(struct cache_entry *));\n+\tif (cache->num_entries == cache->allocated_entries) {\n+\t\tcache->allocated_entries = alloc_nr(cache->allocated_entries);\n+\t\tcache->entries = realloc(cache->entries, cache->allocated_entries * sizeof(struct cache_entry *));\n \t}\n \n \t/* Add it in.. */\n-\tactive_nr++;\n-\tif (active_nr > pos)\n-\t\tmemmove(active_cache + pos + 1, active_cache + pos, (active_nr - pos - 1) * sizeof(ce));\n-\tactive_cache[pos] = ce;\n+\tcache->num_entries++;\n+\tif (cache->num_entries > pos)\n+\t\tmemmove(cache->entries + pos + 1, cache->entries + pos, (cache->num_entries - pos - 1) * sizeof(ce));\n+\tcache->entries[pos] = ce;\n \treturn 0;\n }\n \n@@ -202,12 +214,10 @@\n {\n \tint fd, i;\n \tstruct stat st;\n-\tunsigned long size, offset;\n-\tvoid *map;\n-\tstruct cache_header *hdr;\n+\tunsigned long offset;\n \n \terrno = EBUSY;\n-\tif (active_cache)\n+\tif (cache)\n \t\treturn error(\"more than one cachefile\");\n \terrno = ENOENT;\n \tsha1_file_directory = getenv(DB_ENVIRONMENT);\n@@ -219,38 +229,44 @@\n \tif (fd < 0)\n \t\treturn (errno == ENOENT) ? 0 : error(\"open failed\");\n \n-\tsize = 0; /* avoid gcc warning */\n-\tmap = (void *)-1;\n+\terrno = ENOMEM;\n+\tcache = (struct cache*)malloc(sizeof(struct cache));\n+\tif (!cache)\n+\t\treturn error(\"unable to allocate cache\");\n+\n+\tcache->map.size = 0; /* avoid gcc warning */\n+\tcache->map.ptr = (void *)-1;\n \tif (!fstat(fd, &st)) {\n-\t\tsize = st.st_size;\n+\t\tcache->map.size = st.st_size;\n \t\terrno = EINVAL;\n-\t\tif (size >= sizeof(struct cache_header) + 20)\n-\t\t\tmap = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);\n+\t\tif (cache->map.size >= sizeof(struct cache_header) + 20)\n+\t\t\tcache->map.ptr = mmap(NULL, cache->map.size, PROT_READ, MAP_PRIVATE, fd, 0);\n \t}\n \tclose(fd);\n-\tif (-1 == (int)(long)map)\n+\tif (-1 == (int)(long)cache->map.ptr) {\n+\t\tfree(cache);\n+\t\tcache = NULL;\n \t\treturn error(\"mmap failed\");\n+\t}\n \n-\thdr = map;\n-\tif (verify_hdr(hdr, size) < 0)\n-\t\tgoto unmap;\n-\n-\tactive_nr = ntohl(hdr->hdr_entries);\n-\tactive_alloc = alloc_nr(active_nr);\n-\tactive_cache = calloc(active_alloc, sizeof(struct cache_entry *));\n-\n-\toffset = sizeof(*hdr);\n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = map + offset;\n-\t\toffset = offset + ce_size(ce);\n-\t\tactive_cache[i] = ce;\n+\tcache->header = cache->map.ptr;\n+\tif (verify_hdr(cache->header, cache->map.size) < 0) {\n+\t\tfree_cache();\n+\t\terrno = EINVAL;\n+\t\treturn error(\"verify header failed\");\n \t}\n-\treturn active_nr;\n \n-unmap:\n-\tmunmap(map, size);\n-\terrno = EINVAL;\n-\treturn error(\"verify header failed\");\n+\tcache->num_entries = ntohl(cache->header->hdr_entries);\n+\tcache->allocated_entries = alloc_nr(cache->num_entries);\n+\tcache->entries = calloc(cache->allocated_entries, sizeof(struct cache_entry *));\n+\n+\toffset = sizeof(*cache->header);\n+\tfor (i = 0; i < cache->num_entries; i++) {\n+\t\tstruct cache_entry *ce = cache->map.ptr + offset;\n+\t\toffset = offset + ce_size(ce);\n+\t\tcache->entries[i] = ce;\n+\t}\n+\treturn cache->num_entries;\n }\n \n #define WRITE_BUFFER_SIZE 8192\n@@ -304,16 +320,23 @@\n \n \thdr.hdr_signature = htonl(CACHE_SIGNATURE);\n \thdr.hdr_version = htonl(2);\n-\thdr.hdr_entries = htonl(active_nr);\n+\thdr.hdr_entries = htonl(cache->num_entries);\n \n \tSHA1_Init(&c);\n \tif (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)\n \t\treturn -1;\n \n-\tfor (i = 0; i < active_nr; i++) {\n-\t\tstruct cache_entry *ce = active_cache[i];\n+\tfor (i = 0; i < cache->num_entries; i++) {\n+\t\tstruct cache_entry *ce = cache->entries[i];\n \t\tif (ce_write(&c, newfd, ce, ce_size(ce)) < 0)\n \t\t\treturn -1;\n \t}\n \treturn ce_flush(&c, newfd);\n }\n+\n+void free_cache()\n+{\n+\tmunmap(cache->map.ptr, cache->map.size);\n+\tfree(cache);\n+\tcache = NULL;\n+}\n\n"}]}