db: keep only filename in file entries, hash by both directory and file
parent
3309eaa900
commit
15b547c55b
3
TODO
3
TODO
|
@ -1,9 +1,6 @@
|
||||||
- confirm whether to act (show changeset-size, installed, removed) if
|
- confirm whether to act (show changeset-size, installed, removed) if
|
||||||
other packages affected then the ones explicitly specified
|
other packages affected then the ones explicitly specified
|
||||||
|
|
||||||
- complete lbu replacement
|
|
||||||
- links for lbu* and apk_*
|
|
||||||
|
|
||||||
- Index/pkginfo reader: same field multiple times -> memleak
|
- Index/pkginfo reader: same field multiple times -> memleak
|
||||||
|
|
||||||
- Compress 'installed' and 'scripts'
|
- Compress 'installed' and 'scripts'
|
||||||
|
|
|
@ -20,6 +20,7 @@ typedef void *apk_hash_item;
|
||||||
|
|
||||||
typedef unsigned long (*apk_hash_f)(apk_blob_t);
|
typedef unsigned long (*apk_hash_f)(apk_blob_t);
|
||||||
typedef int (*apk_hash_compare_f)(apk_blob_t, apk_blob_t);
|
typedef int (*apk_hash_compare_f)(apk_blob_t, apk_blob_t);
|
||||||
|
typedef int (*apk_hash_compare_item_f)(apk_hash_item, apk_blob_t);
|
||||||
typedef void (*apk_hash_delete_f)(apk_hash_item);
|
typedef void (*apk_hash_delete_f)(apk_hash_item);
|
||||||
typedef int (*apk_hash_enumerator_f)(apk_hash_item, void *ctx);
|
typedef int (*apk_hash_enumerator_f)(apk_hash_item, void *ctx);
|
||||||
|
|
||||||
|
@ -27,7 +28,9 @@ struct apk_hash_ops {
|
||||||
ptrdiff_t node_offset;
|
ptrdiff_t node_offset;
|
||||||
apk_blob_t (*get_key)(apk_hash_item item);
|
apk_blob_t (*get_key)(apk_hash_item item);
|
||||||
unsigned long (*hash_key)(apk_blob_t key);
|
unsigned long (*hash_key)(apk_blob_t key);
|
||||||
int (*compare)(apk_blob_t key, apk_blob_t itemkey);
|
unsigned long (*hash_item)(apk_hash_item item);
|
||||||
|
int (*compare)(apk_blob_t itemkey, apk_blob_t key);
|
||||||
|
int (*compare_item)(apk_hash_item item, apk_blob_t key);
|
||||||
void (*delete_item)(apk_hash_item item);
|
void (*delete_item)(apk_hash_item item);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ int apk_blob_rsplit(apk_blob_t blob, char split, apk_blob_t *l, apk_blob_t *r)
|
||||||
if (l != NULL)
|
if (l != NULL)
|
||||||
*l = APK_BLOB_PTR_PTR(blob.ptr, sep - 1);
|
*l = APK_BLOB_PTR_PTR(blob.ptr, sep - 1);
|
||||||
if (r != NULL)
|
if (r != NULL)
|
||||||
*r = APK_BLOB_PTR_PTR(sep + 1, blob.ptr + blob.len);
|
*r = APK_BLOB_PTR_PTR(sep + 1, blob.ptr + blob.len - 1);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,16 +86,45 @@ static const struct apk_hash_ops dir_hash_ops = {
|
||||||
.delete_item = (apk_hash_delete_f) free,
|
.delete_item = (apk_hash_delete_f) free,
|
||||||
};
|
};
|
||||||
|
|
||||||
static apk_blob_t apk_db_file_get_key(apk_hash_item item)
|
struct apk_db_file_hash_key {
|
||||||
|
apk_blob_t dirname;
|
||||||
|
apk_blob_t filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned long apk_db_file_hash_key(apk_blob_t _key)
|
||||||
{
|
{
|
||||||
return APK_BLOB_STR(((struct apk_db_file *) item)->filename);
|
struct apk_db_file_hash_key *key = (struct apk_db_file_hash_key *) _key.ptr;
|
||||||
|
|
||||||
|
return apk_blob_hash(key->dirname) ^
|
||||||
|
apk_blob_hash(key->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long apk_db_file_hash_item(apk_hash_item item)
|
||||||
|
{
|
||||||
|
struct apk_db_file *dbf = (struct apk_db_file *) item;
|
||||||
|
|
||||||
|
return apk_blob_hash(APK_BLOB_STR(dbf->diri->dir->dirname)) ^
|
||||||
|
apk_blob_hash(APK_BLOB_STR(dbf->filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int apk_db_file_compare_item(apk_hash_item item, apk_blob_t _key)
|
||||||
|
{
|
||||||
|
struct apk_db_file *dbf = (struct apk_db_file *) item;
|
||||||
|
struct apk_db_file_hash_key *key = (struct apk_db_file_hash_key *) _key.ptr;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = apk_blob_compare(key->dirname, APK_BLOB_STR(dbf->diri->dir->dirname));
|
||||||
|
if (r != 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return apk_blob_compare(key->filename, APK_BLOB_STR(dbf->filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct apk_hash_ops file_hash_ops = {
|
static const struct apk_hash_ops file_hash_ops = {
|
||||||
.node_offset = offsetof(struct apk_db_file, hash_node),
|
.node_offset = offsetof(struct apk_db_file, hash_node),
|
||||||
.get_key = apk_db_file_get_key,
|
.hash_key = apk_db_file_hash_key,
|
||||||
.hash_key = apk_blob_hash,
|
.hash_item = apk_db_file_hash_item,
|
||||||
.compare = apk_blob_compare,
|
.compare_item = apk_db_file_compare_item,
|
||||||
.delete_item = (apk_hash_delete_f) free,
|
.delete_item = (apk_hash_delete_f) free,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -242,25 +271,29 @@ static void apk_db_diri_free(struct apk_database *db,
|
||||||
free(diri);
|
free(diri);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct apk_db_file *apk_db_file_query(struct apk_database *db,
|
|
||||||
apk_blob_t name)
|
|
||||||
{
|
|
||||||
return (struct apk_db_file *) apk_hash_get(&db->installed.files, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct apk_db_file *apk_db_file_get(struct apk_database *db,
|
static struct apk_db_file *apk_db_file_get(struct apk_database *db,
|
||||||
|
struct apk_db_dir_instance *diri,
|
||||||
apk_blob_t name)
|
apk_blob_t name)
|
||||||
{
|
{
|
||||||
struct apk_db_file *file;
|
struct apk_db_file *file;
|
||||||
|
struct apk_db_file_hash_key key;
|
||||||
|
|
||||||
file = apk_db_file_query(db, name);
|
key = (struct apk_db_file_hash_key) {
|
||||||
|
.dirname = APK_BLOB_STR(diri->dir->dirname),
|
||||||
|
.filename = name,
|
||||||
|
};
|
||||||
|
|
||||||
|
file = (struct apk_db_file *) apk_hash_get(&db->installed.files,
|
||||||
|
APK_BLOB_BUF(&key));
|
||||||
if (file != NULL)
|
if (file != NULL)
|
||||||
return file;
|
return file;
|
||||||
|
|
||||||
file = calloc(1, sizeof(*file) + name.len + 1);
|
file = calloc(1, sizeof(*file) + name.len + 1);
|
||||||
memcpy(file->filename, name.ptr, name.len);
|
memcpy(file->filename, name.ptr, name.len);
|
||||||
file->filename[name.len] = 0;
|
file->filename[name.len] = 0;
|
||||||
|
file->diri = diri;
|
||||||
apk_hash_insert(&db->installed.files, file);
|
apk_hash_insert(&db->installed.files, file);
|
||||||
|
file->diri = NULL;
|
||||||
|
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
@ -305,9 +338,8 @@ static int apk_db_index_read(struct apk_database *db, struct apk_istream *is, in
|
||||||
struct hlist_node **file_diri_node = NULL;
|
struct hlist_node **file_diri_node = NULL;
|
||||||
|
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char tmp[512];
|
|
||||||
apk_blob_t l, r;
|
apk_blob_t l, r;
|
||||||
int n, field, i;
|
int n, field;
|
||||||
|
|
||||||
r = APK_BLOB_PTR_LEN(buf, 0);
|
r = APK_BLOB_PTR_LEN(buf, 0);
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -384,9 +416,7 @@ static int apk_db_index_read(struct apk_database *db, struct apk_istream *is, in
|
||||||
apk_error("FDB file entry before directory entry");
|
apk_error("FDB file entry before directory entry");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
i = snprintf(tmp, sizeof(tmp), "%s/%.*s",
|
file = apk_db_file_get(db, diri, l);
|
||||||
diri->dir->dirname, l.len, l.ptr);
|
|
||||||
file = apk_db_file_get(db, APK_BLOB_PTR_LEN(tmp, i));
|
|
||||||
apk_db_file_set_owner(db, file, diri, file_diri_node);
|
apk_db_file_set_owner(db, file, diri, file_diri_node);
|
||||||
file_diri_node = &file->diri_files_list.next;
|
file_diri_node = &file->diri_files_list.next;
|
||||||
break;
|
break;
|
||||||
|
@ -701,11 +731,16 @@ struct apk_package *apk_db_get_file_owner(struct apk_database *db,
|
||||||
apk_blob_t filename)
|
apk_blob_t filename)
|
||||||
{
|
{
|
||||||
struct apk_db_file *dbf;
|
struct apk_db_file *dbf;
|
||||||
|
struct apk_db_file_hash_key key;
|
||||||
|
|
||||||
if (filename.len && filename.ptr[0] == '/')
|
if (filename.len && filename.ptr[0] == '/')
|
||||||
filename.len--, filename.ptr++;
|
filename.len--, filename.ptr++;
|
||||||
|
|
||||||
dbf = apk_db_file_query(db, filename);
|
if (!apk_blob_rsplit(filename, '/', &key.dirname, &key.filename))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dbf = (struct apk_db_file *) apk_hash_get(&db->installed.files,
|
||||||
|
APK_BLOB_BUF(&key));
|
||||||
if (dbf == NULL)
|
if (dbf == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -913,7 +948,7 @@ static int apk_db_install_archive_entry(void *_ctx,
|
||||||
ctx->diri = diri;
|
ctx->diri = diri;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = apk_db_file_get(db, name);
|
file = apk_db_file_get(db, diri, bfile);
|
||||||
if (file == NULL) {
|
if (file == NULL) {
|
||||||
apk_error("%s: Failed to create fdb entry for '%*s'\n",
|
apk_error("%s: Failed to create fdb entry for '%*s'\n",
|
||||||
pkg->name->name, name.len, name.ptr);
|
pkg->name->name, name.len, name.ptr);
|
||||||
|
|
16
src/hash.c
16
src/hash.c
|
@ -52,24 +52,34 @@ apk_hash_item apk_hash_get(struct apk_hash *h, apk_blob_t key)
|
||||||
apk_blob_t itemkey;
|
apk_blob_t itemkey;
|
||||||
|
|
||||||
hash = h->ops->hash_key(key) % h->buckets->num;
|
hash = h->ops->hash_key(key) % h->buckets->num;
|
||||||
|
if (h->ops->compare_item != NULL) {
|
||||||
|
hlist_for_each(pos, &h->buckets->item[hash]) {
|
||||||
|
item = ((void *) pos) - offset;
|
||||||
|
if (h->ops->compare_item(item, key) == 0)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
hlist_for_each(pos, &h->buckets->item[hash]) {
|
hlist_for_each(pos, &h->buckets->item[hash]) {
|
||||||
item = ((void *) pos) - offset;
|
item = ((void *) pos) - offset;
|
||||||
itemkey = h->ops->get_key(item);
|
itemkey = h->ops->get_key(item);
|
||||||
if (h->ops->compare(key, itemkey) == 0)
|
if (h->ops->compare(key, itemkey) == 0)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
|
void apk_hash_insert(struct apk_hash *h, apk_hash_item item)
|
||||||
{
|
{
|
||||||
apk_blob_t key;
|
|
||||||
unsigned long hash;
|
unsigned long hash;
|
||||||
apk_hash_node *node;
|
apk_hash_node *node;
|
||||||
|
|
||||||
key = h->ops->get_key(item);
|
if (h->ops->hash_item == NULL)
|
||||||
hash = h->ops->hash_key(key) % h->buckets->num;
|
hash = h->ops->hash_key(h->ops->get_key(item));
|
||||||
|
else
|
||||||
|
hash = h->ops->hash_item(item);
|
||||||
|
hash %= h->buckets->num;
|
||||||
node = (apk_hash_node *) (item + h->ops->node_offset);
|
node = (apk_hash_node *) (item + h->ops->node_offset);
|
||||||
hlist_add_head(node, &h->buckets->item[hash]);
|
hlist_add_head(node, &h->buckets->item[hash]);
|
||||||
h->num_items++;
|
h->num_items++;
|
||||||
|
|
Loading…
Reference in New Issue