#include <unistd.h> /* for unlink() */
#include "wimlib/assert.h"
+#include "wimlib/bitops.h"
#include "wimlib/blob_table.h"
#include "wimlib/encoding.h"
#include "wimlib/endianness.h"
struct blob_table {
struct hlist_head *array;
size_t num_blobs;
- size_t capacity;
+ size_t mask; /* capacity - 1; capacity is a power of 2 */
};
+static size_t
+next_power_of_2(size_t n)
+{
+ if (n <= 1)
+ return 1;
+ return (size_t)1 << (1 + flsw(n - 1));
+}
+
struct blob_table *
new_blob_table(size_t capacity)
{
struct blob_table *table;
struct hlist_head *array;
+ capacity = next_power_of_2(capacity);
+
table = MALLOC(sizeof(struct blob_table));
if (table == NULL)
goto oom;
}
table->num_blobs = 0;
- table->capacity = capacity;
+ table->mask = capacity - 1;
table->array = array;
return table;
static void
blob_table_insert_raw(struct blob_table *table, struct blob_descriptor *blob)
{
- size_t i = blob->hash_short % table->capacity;
+ size_t i = blob->hash_short & table->mask;
hlist_add_head(&blob->hash_list, &table->array[i]);
}
struct hlist_node *tmp;
size_t i;
- old_capacity = table->capacity;
+ old_capacity = table->mask + 1;
new_capacity = old_capacity * 2;
new_array = CALLOC(new_capacity, sizeof(struct hlist_head));
if (new_array == NULL)
return;
old_array = table->array;
table->array = new_array;
- table->capacity = new_capacity;
+ table->mask = new_capacity - 1;
- for (i = 0; i < old_capacity; i++) {
- hlist_for_each_entry_safe(blob, tmp, &old_array[i], hash_list) {
- hlist_del(&blob->hash_list);
+ for (i = 0; i < old_capacity; i++)
+ hlist_for_each_entry_safe(blob, tmp, &old_array[i], hash_list)
blob_table_insert_raw(table, blob);
- }
- }
FREE(old_array);
}
blob_table_insert(struct blob_table *table, struct blob_descriptor *blob)
{
blob_table_insert_raw(table, blob);
- if (++table->num_blobs > table->capacity)
+ if (table->num_blobs++ > table->mask)
enlarge_blob_table(table);
}
size_t i;
struct blob_descriptor *blob;
- i = load_size_t_unaligned(hash) % table->capacity;
+ i = load_size_t_unaligned(hash) & table->mask;
hlist_for_each_entry(blob, &table->array[i], hash_list)
if (hashes_equal(hash, blob->hash))
return blob;
struct hlist_node *tmp;
int ret;
- for (size_t i = 0; i < table->capacity; i++) {
+ for (size_t i = 0; i <= table->mask; i++) {
hlist_for_each_entry_safe(blob, tmp, &table->array[i],
hash_list)
{
BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZX != 2);
BUILD_BUG_ON(WIMLIB_COMPRESSION_TYPE_LZMS != 3);
rdesc->compression_type = le32_to_cpu(hdr.compression_format);
-
rdesc->chunk_size = le32_to_cpu(hdr.chunk_size);
-
- DEBUG("Solid resource %zu/%zu: %"PRIu64" => %"PRIu64" "
- "(%"TS"/%"PRIu32") @ +%"PRIu64"",
- i + 1, num_rdescs,
- rdesc->uncompressed_size,
- rdesc->size_in_wim,
- wimlib_get_compression_type_string(rdesc->compression_type),
- rdesc->chunk_size,
- rdesc->offset_in_wim);
}
return 0;
}
struct wim_resource_descriptor **cur_solid_rdescs = NULL;
size_t cur_num_solid_rdescs = 0;
- DEBUG("Reading blob table.");
-
/* Calculate the number of entries in the blob table. */
num_entries = wim->hdr.blob_table_reshdr.uncompressed_size /
sizeof(struct blob_descriptor_disk);
/* Allocate a hash table to map SHA-1 message digests into blob
* descriptors. This is the in-memory "blob table". */
- table = new_blob_table(num_entries * 2 + 1);
+ table = new_blob_table(num_entries);
if (!table)
goto oom;
/* Get the resource header */
get_wim_reshdr(&disk_entry->reshdr, &reshdr);
- DEBUG("reshdr: size_in_wim=%"PRIu64", "
- "uncompressed_size=%"PRIu64", "
- "offset_in_wim=%"PRIu64", "
- "flags=0x%02x",
- reshdr.size_in_wim, reshdr.uncompressed_size,
- reshdr.offset_in_wim, reshdr.flags);
-
/* Ignore SOLID flag if it isn't supposed to be used in this WIM
* version. */
if (wim->hdr.wim_version == WIM_VERSION_DEFAULT)
if (!rdesc)
goto oom;
- wim_reshdr_to_desc(&reshdr, wim, rdesc);
-
- blob_set_is_located_in_nonsolid_wim_resource(cur_blob, rdesc);
+ wim_reshdr_to_desc_and_blob(&reshdr, wim, rdesc, cur_blob);
}
/* cur_blob is now a blob bound to a resource. */
* this overrides the actual locations of the metadata
* resources themselves in the WIM file as well as any
* information written in the XML data. */
- DEBUG("Found metadata resource for image %"PRIu32" at "
- "offset %"PRIu64".",
- image_index + 1,
- reshdr.offset_in_wim);
-
wim->image_metadata[image_index++]->metadata_blob = cur_blob;
} else {
/* Blob table entry for a non-metadata blob. */
num_wrong_part_blobs);
}
- DEBUG("Done reading blob table.");
wim->blob_table = table;
ret = 0;
goto out_free_buf;
}
}
- DEBUG("Writing WIM blob table (size=%zu, offset=%"PRIu64")",
- table_size, out_fd->offset);
-
table_buf = MALLOC(table_size);
if (table_buf == NULL) {
ERROR("Failed to allocate %zu bytes for temporary blob table",
NULL,
write_resource_flags);
FREE(table_buf);
- DEBUG("ret=%d", ret);
return ret;
}