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
@ -14,6 +14,12 @@
|
|||||||
#include "obj_pool.h"
|
#include "obj_pool.h"
|
||||||
#include "string_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_REPLACE 4
|
||||||
#define NODEACT_DELETE 3
|
#define NODEACT_DELETE 3
|
||||||
#define NODEACT_ADD 2
|
#define NODEACT_ADD 2
|
||||||
@ -58,8 +64,7 @@ static struct {
|
|||||||
} dump_ctx;
|
} dump_ctx;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
|
uint32_t uuid, revision_number, node_path, node_kind, node_action,
|
||||||
revision_number, node_path, node_kind, node_action,
|
|
||||||
node_copyfrom_path, node_copyfrom_rev, text_content_length,
|
node_copyfrom_path, node_copyfrom_rev, text_content_length,
|
||||||
prop_content_length, content_length, svn_fs_dump_format_version,
|
prop_content_length, content_length, svn_fs_dump_format_version,
|
||||||
/* version 3 format */
|
/* version 3 format */
|
||||||
@ -96,11 +101,6 @@ static void reset_dump_ctx(uint32_t url)
|
|||||||
|
|
||||||
static void init_keys(void)
|
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.uuid = pool_intern("UUID");
|
||||||
keys.revision_number = pool_intern("Revision-number");
|
keys.revision_number = pool_intern("Revision-number");
|
||||||
keys.node_path = pool_intern("Node-path");
|
keys.node_path = pool_intern("Node-path");
|
||||||
@ -117,22 +117,43 @@ static void init_keys(void)
|
|||||||
keys.prop_delta = pool_intern("Prop-delta");
|
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)
|
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)
|
if (!val)
|
||||||
die("invalid dump: unsets svn:log");
|
die("invalid dump: unsets svn:log");
|
||||||
/* Value length excludes terminating nul. */
|
/* Value length excludes terminating nul. */
|
||||||
rev_ctx.log = log_copy(len + 1, val);
|
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);
|
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)
|
if (!val)
|
||||||
die("invalid dump: unsets svn:date");
|
die("invalid dump: unsets svn:date");
|
||||||
if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
|
if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
|
||||||
warning("invalid timestamp: %s", val);
|
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 (*type_set) {
|
||||||
if (!val)
|
if (!val)
|
||||||
return;
|
return;
|
||||||
@ -143,7 +164,7 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*type_set = 1;
|
*type_set = 1;
|
||||||
node_ctx.type = key == keys.svn_executable ?
|
node_ctx.type = keylen == strlen("svn:executable") ?
|
||||||
REPO_MODE_EXE :
|
REPO_MODE_EXE :
|
||||||
REPO_MODE_LNK;
|
REPO_MODE_LNK;
|
||||||
}
|
}
|
||||||
@ -158,7 +179,7 @@ static void die_short_read(void)
|
|||||||
|
|
||||||
static void read_props(void)
|
static void read_props(void)
|
||||||
{
|
{
|
||||||
uint32_t key = ~0;
|
static struct strbuf key = STRBUF_INIT;
|
||||||
const char *t;
|
const char *t;
|
||||||
/*
|
/*
|
||||||
* NEEDSWORK: to support simple mode changes like
|
* NEEDSWORK: to support simple mode changes like
|
||||||
@ -195,16 +216,19 @@ static void read_props(void)
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'K':
|
case 'K':
|
||||||
key = pool_intern(val);
|
|
||||||
continue;
|
|
||||||
case 'D':
|
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;
|
val = NULL;
|
||||||
len = 0;
|
len = 0;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 'V':
|
case 'V':
|
||||||
handle_property(key, val, len, &type_set);
|
handle_property(&key, val, len, &type_set);
|
||||||
key = ~0;
|
strbuf_reset(&key);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
die("invalid property line: %s\n", t);
|
die("invalid property line: %s\n", t);
|
||||||
|
Loading…
Reference in New Issue
Block a user