diff options
-rw-r--r-- | include/str_table.h | 7 | ||||
-rw-r--r-- | lib/fstree/xattr.c | 17 | ||||
-rw-r--r-- | lib/util/str_table.c | 46 |
3 files changed, 68 insertions, 2 deletions
diff --git a/include/str_table.h b/include/str_table.h index db36c5b..56b601a 100644 --- a/include/str_table.h +++ b/include/str_table.h @@ -6,6 +6,7 @@ typedef struct str_bucket_t { struct str_bucket_t *next; char *str; size_t index; + size_t refcount; } str_bucket_t; /* Stores strings in a hash table and assigns an incremental, unique ID to @@ -34,4 +35,10 @@ int str_table_get_index(str_table_t *table, const char *str, size_t *idx); Returns NULL if the ID is unknown, i.e. out of bounds. */ const char *str_table_get_string(str_table_t *table, size_t index); +void str_table_reset_ref_count(str_table_t *table); + +void str_table_add_ref(str_table_t *table, size_t index); + +size_t str_table_get_ref_count(str_table_t *table, size_t index); + #endif /* STR_TABLE_H */ diff --git a/lib/fstree/xattr.c b/lib/fstree/xattr.c index 38f7703..4597d9d 100644 --- a/lib/fstree/xattr.c +++ b/lib/fstree/xattr.c @@ -102,11 +102,24 @@ static int cmp_u64(const void *lhs, const void *rhs) void fstree_xattr_reindex(fstree_t *fs) { + uint32_t key_idx, value_idx; + size_t i, index = 0; tree_xattr_t *it; - size_t index = 0; - for (it = fs->xattr; it != NULL; it = it->next) + str_table_reset_ref_count(&fs->xattr_keys); + str_table_reset_ref_count(&fs->xattr_values); + + for (it = fs->xattr; it != NULL; it = it->next) { it->index = index++; + + for (i = 0; i < it->num_attr; ++i) { + key_idx = (it->ref[i] >> 32) & 0x00000000FFFFFFFF; + value_idx = it->ref[i] & 0x00000000FFFFFFFF; + + str_table_add_ref(&fs->xattr_keys, key_idx); + str_table_add_ref(&fs->xattr_values, value_idx); + } + } } void fstree_xattr_deduplicate(fstree_t *fs) diff --git a/lib/util/str_table.c b/lib/util/str_table.c index a9d91e5..72579ce 100644 --- a/lib/util/str_table.c +++ b/lib/util/str_table.c @@ -128,3 +128,49 @@ const char *str_table_get_string(str_table_t *table, size_t index) return table->strings[index]; } + +static str_bucket_t *bucket_by_index(str_table_t *table, size_t index) +{ + str_bucket_t *bucket = NULL; + uint32_t hash; + + if (index < table->num_strings) { + hash = strhash(table->strings[index]); + bucket = table->buckets[hash % table->num_buckets]; + + while (bucket != NULL && bucket->index != index) + bucket = bucket->next; + } + + return bucket; +} + +void str_table_reset_ref_count(str_table_t *table) +{ + str_bucket_t *bucket; + size_t i; + + for (i = 0; i < table->num_buckets; ++i) { + bucket = table->buckets[i]; + + while (bucket != NULL) { + bucket->refcount = 0; + bucket = bucket->next; + } + } +} + +void str_table_add_ref(str_table_t *table, size_t index) +{ + str_bucket_t *bucket = bucket_by_index(table, index); + + if (bucket != NULL && bucket->refcount < ~((size_t)0)) + bucket->refcount += 1; +} + +size_t str_table_get_ref_count(str_table_t *table, size_t index) +{ + str_bucket_t *bucket = bucket_by_index(table, index); + + return bucket != NULL ? bucket->refcount : 0; +} |