Simplify pre-allocating BOM indexes and BOM tree entries.

Use a single reserve method to reserve space in BOM indexes or in a
BOM tree's entry index, rather than specifying on initialization.
This better supports reserving additional space after allocation,
which is needed in any case, without sacrificing performance.
This commit is contained in:
Grant Paul 2016-08-31 17:09:07 -07:00
parent 8e36066203
commit 57e8d04685
6 changed files with 59 additions and 67 deletions

View File

@ -41,12 +41,6 @@ struct bom_context;
struct bom_context *
bom_alloc_empty(struct bom_context_memory memory);
struct bom_context *
bom_alloc_empty2(struct bom_context_memory memory, uint32_t index_count);
void
bom_alloc_indexes(struct bom_context *context, uint32_t index_count);
struct bom_context *
bom_alloc_load(struct bom_context_memory memory);
@ -67,6 +61,9 @@ bom_index_iterate(struct bom_context *context, bom_index_iterator iterator, void
void *
bom_index_get(struct bom_context *context, uint32_t index, size_t *data_len);
void
bom_index_reserve(struct bom_context *context, size_t count);
uint32_t
bom_index_add(struct bom_context *context, const void *data, size_t data_len);
@ -95,15 +92,9 @@ struct bom_tree_context;
struct bom_tree_context *
bom_tree_alloc_empty(struct bom_context *context, const char *variable_name);
struct bom_tree_context *
bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, uint32_t index_count);
struct bom_tree_context *
bom_tree_alloc_load(struct bom_context *context, const char *variable_name);
void
bom_tree_clear(struct bom_tree_context *tree);
void
bom_tree_free(struct bom_tree_context *tree);
@ -118,6 +109,9 @@ typedef void (*bom_tree_iterator)(struct bom_tree_context *tree, void *key, size
void
bom_tree_iterate(struct bom_tree_context *tree, bom_tree_iterator iterator, void *ctx);
void
bom_tree_reserve(struct bom_tree_context *tree, size_t count);
void
bom_tree_add(struct bom_tree_context *tree, const void *key, size_t key_len, const void *value, size_t value_len);

View File

@ -58,7 +58,7 @@ extern "C" {
*
* Some BOM variables contain trees, most commonly the "Paths" variable
* found in standard BOM archives. BOM trees are a header in the variable's
* data section, has an index pointing to the root of the tree. Each item
* data section with an index pointing to the root of the tree. Each item
* in the tree has indexes pointing to both key and value data for that item.
*/

View File

@ -39,12 +39,6 @@ _bom_alloc(struct bom_context_memory memory)
struct bom_context *
bom_alloc_empty(struct bom_context_memory memory)
{
return bom_alloc_empty2(memory, 2);
}
struct bom_context *
bom_alloc_empty2(struct bom_context_memory memory, uint32_t index_count)
{
struct bom_context *context = _bom_alloc(memory);
if (context == NULL) {
@ -54,7 +48,7 @@ bom_alloc_empty2(struct bom_context_memory memory, uint32_t index_count)
size_t header_size = sizeof(struct bom_header);
size_t index_size = sizeof(struct bom_index_header);
size_t freelist_size = sizeof(struct bom_index_header) + sizeof(struct bom_index) * (index_count + 2);
size_t freelist_size = sizeof(struct bom_index_header) + sizeof(struct bom_index) * 2;
size_t variables_size = sizeof(struct bom_variables);
context->memory.resize(&context->memory, header_size + index_size + freelist_size + variables_size);
@ -241,6 +235,24 @@ bom_index_get(struct bom_context *context, uint32_t index, size_t *data_len)
return (void *)header + ioffset;
}
void
bom_index_reserve(struct bom_context *context, size_t count)
{
assert(context != NULL);
assert(context->iteration_count == 0 && "cannot mutate while iterating");
struct bom_header *header = (struct bom_header *)context->memory.data;
/* Insert space for extra indexes at the end of the currently allocated space. */
uint32_t index_point = ntohl(header->index_offset) + ntohl(header->index_length);
size_t new_index_length = ntohl(header->index_length) + sizeof(struct bom_index) * count;
ptrdiff_t index_delta = sizeof(struct bom_index) * count;
_bom_address_resize(context, index_point, index_delta);
/* Re-fetch, invalidated by resize. */
header = (struct bom_header *)context->memory.data;
header->index_length = htonl(new_index_length);
}
uint32_t
bom_index_add(struct bom_context *context, const void *data, size_t data_len)
{
@ -412,21 +424,3 @@ bom_variable_add(struct bom_context *context, const char *name, int data_index)
header->trailer_len = htonl(ntohl(header->trailer_len) + variable_delta);
}
void
bom_alloc_indexes(struct bom_context *context, uint32_t index_count)
{
assert(context != NULL);
assert(context->iteration_count == 0 && "cannot mutate while iterating");
struct bom_header *header = (struct bom_header *)context->memory.data;
/* Insert space for extra indexes at the end of the currently allocated space. */
uint32_t index_point = ntohl(header->index_offset) + ntohl(header->index_length);
size_t new_index_length = ntohl(header->index_length) + sizeof(struct bom_index) * index_count;
ptrdiff_t index_delta = sizeof(struct bom_index) * index_count;
_bom_address_resize(context, index_point, index_delta);
/* Re-fetch, invalidated by resize. */
header = (struct bom_header *)context->memory.data;
header->index_length = htonl(new_index_length);
}

View File

@ -52,12 +52,6 @@ _bom_tree_alloc(struct bom_context *context, const char *variable_name)
struct bom_tree_context *
bom_tree_alloc_empty(struct bom_context *context, const char *variable_name)
{
return bom_tree_alloc_empty2(context, variable_name, 0);
}
struct bom_tree_context *
bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, uint32_t index_count)
{
struct bom_tree_context *tree_context = _bom_tree_alloc(context, variable_name);
if (tree_context == NULL) {
@ -65,8 +59,7 @@ bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, ui
}
size_t entry_size = sizeof(struct bom_tree_entry) + (sizeof(struct bom_tree_entry_indexes) * index_count);
struct bom_tree_entry *entry = malloc(entry_size);
struct bom_tree_entry *entry = malloc(sizeof(*entry));
if (entry == NULL) {
bom_tree_free(tree_context);
return NULL;
@ -83,7 +76,7 @@ bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, ui
entry->count = htons(0);
entry->forward = htonl(0);
entry->backward = htonl(0);
int entry_index = bom_index_add(tree_context->context, entry, entry_size);
uint32_t entry_index = bom_index_add(tree_context->context, entry, sizeof(*entry));
free(entry);
strncpy(tree->magic, "tree", 4);
@ -92,7 +85,7 @@ bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, ui
tree->node_size = htonl(4096); // todo
tree->path_count = htonl(0);
tree->unknown3 = 0;
int tree_index = bom_index_add(tree_context->context, tree, sizeof(*tree));
uint32_t tree_index = bom_index_add(tree_context->context, tree, sizeof(*tree));
free(tree);
bom_variable_add(tree_context->context, tree_context->variable_name, tree_index);
@ -108,7 +101,7 @@ bom_tree_alloc_load(struct bom_context *context, const char *variable_name)
return NULL;
}
int tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
if (tree_index == -1) {
bom_tree_free(tree_context);
return NULL;
@ -124,9 +117,6 @@ bom_tree_alloc_load(struct bom_context *context, const char *variable_name)
return tree_context;
}
void
bom_tree_clear(struct bom_tree_context *tree_context);
void
bom_tree_free(struct bom_tree_context *tree_context)
{
@ -138,8 +128,6 @@ bom_tree_free(struct bom_tree_context *tree_context)
free(tree_context);
}
struct bom_context *
bom_tree_context_get(struct bom_tree_context *tree_context)
{
@ -154,7 +142,6 @@ bom_tree_variable_get(struct bom_tree_context *tree_context)
return tree_context->variable_name;
}
void
bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterator, void *ctx)
{
@ -162,7 +149,7 @@ bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterat
tree_context->tree_iterating++;
int tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
struct bom_tree *tree = (struct bom_tree *)bom_index_get(tree_context->context, tree_index, NULL);
struct bom_tree_entry *paths = (struct bom_tree_entry *)bom_index_get(tree_context->context, ntohl(tree->child), NULL);
@ -173,7 +160,7 @@ bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterat
}
while (paths != NULL) {
for (unsigned int i = 0; i < ntohs(paths->count); i++) {
for (size_t i = 0; i < ntohs(paths->count); i++) {
struct bom_tree_entry_indexes *indexes = &paths->indexes[i];
size_t key_len;
@ -196,6 +183,19 @@ bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterat
tree_context->tree_iterating--;
}
void
bom_tree_reserve(struct bom_tree_context *tree_context, size_t count)
{
assert(tree_context != NULL);
assert(tree_context->tree_iterating == 0);
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
struct bom_tree *tree = (struct bom_tree *)bom_index_get(tree_context->context, tree_index, NULL);
uint32_t paths_index = ntohl(tree->child);
bom_index_append(tree_context->context, paths_index, sizeof(struct bom_tree_entry_indexes) * count);
}
void
bom_tree_add(struct bom_tree_context *tree_context, const void *key, size_t key_len, const void *value, size_t value_len)
{
@ -204,13 +204,13 @@ bom_tree_add(struct bom_tree_context *tree_context, const void *key, size_t key_
assert(value != NULL);
assert(tree_context->tree_iterating == 0);
int key_index = bom_index_add(tree_context->context, key, key_len);
int value_index = bom_index_add(tree_context->context, value, value_len);
uint32_t key_index = bom_index_add(tree_context->context, key, key_len);
uint32_t value_index = bom_index_add(tree_context->context, value, value_len);
int tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
struct bom_tree *tree = (struct bom_tree *)bom_index_get(tree_context->context, tree_index, NULL);
int paths_index = ntohl(tree->child);
uint32_t paths_index = ntohl(tree->child);
size_t paths_length;
struct bom_tree_entry *paths = (struct bom_tree_entry *)bom_index_get(tree_context->context, paths_index, &paths_length);
@ -224,7 +224,7 @@ bom_tree_add(struct bom_tree_context *tree_context, const void *key, size_t key_
paths = (struct bom_tree_entry *)bom_index_get(tree_context->context, paths_index, &paths_length);
}
int entry_index = ntohs(paths->count);
size_t entry_index = ntohs(paths->count);
/* Set the indexes for the inserted entry. */
struct bom_tree_entry_indexes *indexes = &paths->indexes[entry_index];

View File

@ -89,7 +89,7 @@ write() const
uint32_t facet_count = _facets.size();
uint32_t rendition_count = _renditions.size() + _rawRenditions.size();
uint32_t bom_index_count = 6 + facet_count * 2 + rendition_count * 2;
bom_alloc_indexes(_bom.get(), bom_index_count);
bom_index_reserve(_bom.get(), bom_index_count);
/* Write header. */
struct car_header *header = (struct car_header *)malloc(sizeof(struct car_header));
@ -142,7 +142,8 @@ write() const
bom_variable_add(_bom.get(), car_key_format_variable, key_format_index);
/* Write facets. */
struct bom_tree_context *facets_tree_context = bom_tree_alloc_empty2(_bom.get(), car_facet_keys_variable, facet_count);
struct bom_tree_context *facets_tree_context = bom_tree_alloc_empty(_bom.get(), car_facet_keys_variable);
bom_tree_reserve(facets_tree_context, facet_count);
if (facets_tree_context != NULL) {
for (auto const &item : _facets) {
auto facet_value = item.second.write();
@ -157,7 +158,8 @@ write() const
}
/* Write renditions. */
struct bom_tree_context *renditions_tree_context = bom_tree_alloc_empty2(_bom.get(), car_renditions_variable, rendition_count);
struct bom_tree_context *renditions_tree_context = bom_tree_alloc_empty(_bom.get(), car_renditions_variable);
bom_tree_reserve(renditions_tree_context, rendition_count);
if (renditions_tree_context != NULL) {
for (auto const &item : _renditions) {
auto attributes_value = item.second.attributes().write(keyfmt->num_identifiers, keyfmt->identifier_list);

View File

@ -110,7 +110,8 @@ TEST(Writer, TestWriter100)
/* Write out. */
/* Write with half the required number of pre-allocated indexes */
int preallocated_index_count = 6 + create_facet_count * 2 + create_rendition_count * 2;
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty2(bom_context_memory(NULL, 0), preallocated_index_count / 2), bom_free);
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty(bom_context_memory(NULL, 0)), bom_free);
bom_index_reserve(writer_bom.get(), preallocated_index_count / 2);
EXPECT_NE(writer_bom, nullptr);
auto writer = car::Writer::Create(std::move(writer_bom));
@ -188,7 +189,8 @@ TEST(Writer, TestWriter100Optimal)
* Each tree entry (facet or rendition) requires 2: one key index, one value index.
*/
unsigned int preallocated_index_count = 6 + create_facet_count * 2 + create_rendition_count * 2;
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty2(bom_context_memory(NULL, 0), preallocated_index_count), bom_free);
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty(bom_context_memory(NULL, 0)), bom_free);
bom_index_reserve(writer_bom.get(), preallocated_index_count);
EXPECT_NE(writer_bom, nullptr);
auto writer = car::Writer::Create(std::move(writer_bom));