mirror of
https://github.com/git/git
synced 2024-10-29 17:08:46 +00:00
vcs-svn: implement perfect hash for node-prop keys
Instead of interning property names and comparing their string_pool keys, look them up in a table by string length, which should be about as fast. This is a small step towards removing dependence on string_pool. Signed-off-by: David Barr <david.barr@cordelta.com> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
This commit is contained in:
parent
c9d1c8ba05
commit
044ad2906a
1 changed files with 43 additions and 19 deletions
|
@ -14,6 +14,12 @@
|
|||
#include "obj_pool.h"
|
||||
#include "string_pool.h"
|
||||
|
||||
/*
|
||||
* Compare start of string to literal of equal length;
|
||||
* must be guarded by length test.
|
||||
*/
|
||||
#define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1)
|
||||
|
||||
#define NODEACT_REPLACE 4
|
||||
#define NODEACT_DELETE 3
|
||||
#define NODEACT_ADD 2
|
||||
|
@ -58,8 +64,7 @@ static struct {
|
|||
} dump_ctx;
|
||||
|
||||
static struct {
|
||||
uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
|
||||
revision_number, node_path, node_kind, node_action,
|
||||
uint32_t uuid, revision_number, node_path, node_kind, node_action,
|
||||
node_copyfrom_path, node_copyfrom_rev, text_content_length,
|
||||
prop_content_length, content_length, svn_fs_dump_format_version,
|
||||
/* version 3 format */
|
||||
|
@ -96,11 +101,6 @@ static void reset_dump_ctx(uint32_t url)
|
|||
|
||||
static void init_keys(void)
|
||||
{
|
||||
keys.svn_log = pool_intern("svn:log");
|
||||
keys.svn_author = pool_intern("svn:author");
|
||||
keys.svn_date = pool_intern("svn:date");
|
||||
keys.svn_executable = pool_intern("svn:executable");
|
||||
keys.svn_special = pool_intern("svn:special");
|
||||
keys.uuid = pool_intern("UUID");
|
||||
keys.revision_number = pool_intern("Revision-number");
|
||||
keys.node_path = pool_intern("Node-path");
|
||||
|
@ -117,22 +117,43 @@ static void init_keys(void)
|
|||
keys.prop_delta = pool_intern("Prop-delta");
|
||||
}
|
||||
|
||||
static void handle_property(uint32_t key, const char *val, uint32_t len,
|
||||
static void handle_property(const struct strbuf *key_buf,
|
||||
const char *val, uint32_t len,
|
||||
uint32_t *type_set)
|
||||
{
|
||||
if (key == keys.svn_log) {
|
||||
const char *key = key_buf->buf;
|
||||
size_t keylen = key_buf->len;
|
||||
|
||||
switch (keylen + 1) {
|
||||
case sizeof("svn:log"):
|
||||
if (constcmp(key, "svn:log"))
|
||||
break;
|
||||
if (!val)
|
||||
die("invalid dump: unsets svn:log");
|
||||
/* Value length excludes terminating nul. */
|
||||
rev_ctx.log = log_copy(len + 1, val);
|
||||
} else if (key == keys.svn_author) {
|
||||
break;
|
||||
case sizeof("svn:author"):
|
||||
if (constcmp(key, "svn:author"))
|
||||
break;
|
||||
rev_ctx.author = pool_intern(val);
|
||||
} else if (key == keys.svn_date) {
|
||||
break;
|
||||
case sizeof("svn:date"):
|
||||
if (constcmp(key, "svn:date"))
|
||||
break;
|
||||
if (!val)
|
||||
die("invalid dump: unsets svn:date");
|
||||
if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
|
||||
warning("invalid timestamp: %s", val);
|
||||
} else if (key == keys.svn_executable || key == keys.svn_special) {
|
||||
break;
|
||||
case sizeof("svn:executable"):
|
||||
case sizeof("svn:special"):
|
||||
if (keylen == strlen("svn:executable") &&
|
||||
constcmp(key, "svn:executable"))
|
||||
break;
|
||||
if (keylen == strlen("svn:special") &&
|
||||
constcmp(key, "svn:special"))
|
||||
break;
|
||||
if (*type_set) {
|
||||
if (!val)
|
||||
return;
|
||||
|
@ -143,7 +164,7 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
|
|||
return;
|
||||
}
|
||||
*type_set = 1;
|
||||
node_ctx.type = key == keys.svn_executable ?
|
||||
node_ctx.type = keylen == strlen("svn:executable") ?
|
||||
REPO_MODE_EXE :
|
||||
REPO_MODE_LNK;
|
||||
}
|
||||
|
@ -158,7 +179,7 @@ static void die_short_read(void)
|
|||
|
||||
static void read_props(void)
|
||||
{
|
||||
uint32_t key = ~0;
|
||||
static struct strbuf key = STRBUF_INIT;
|
||||
const char *t;
|
||||
/*
|
||||
* NEEDSWORK: to support simple mode changes like
|
||||
|
@ -195,16 +216,19 @@ static void read_props(void)
|
|||
|
||||
switch (type) {
|
||||
case 'K':
|
||||
key = pool_intern(val);
|
||||
continue;
|
||||
case 'D':
|
||||
key = pool_intern(val);
|
||||
strbuf_reset(&key);
|
||||
if (val)
|
||||
strbuf_add(&key, val, len);
|
||||
if (type == 'K')
|
||||
continue;
|
||||
assert(type == 'D');
|
||||
val = NULL;
|
||||
len = 0;
|
||||
/* fall through */
|
||||
case 'V':
|
||||
handle_property(key, val, len, &type_set);
|
||||
key = ~0;
|
||||
handle_property(&key, val, len, &type_set);
|
||||
strbuf_reset(&key);
|
||||
continue;
|
||||
default:
|
||||
die("invalid property line: %s\n", t);
|
||||
|
|
Loading…
Reference in a new issue