mkndx, adb: fix index searching
Additioal logic is needed to search objects on array: the object comparer needs separate modes to match index, template or exact object template. This should fix mkndx to be able to use old index. fixes #10828cute-signatures
parent
950972a56b
commit
c6b9297bcb
122
src/adb.c
122
src/adb.c
|
@ -472,72 +472,109 @@ struct adb_obj *adb_ro_obj(const struct adb_obj *o, unsigned i, struct adb_obj *
|
|||
return adb_r_obj(o->db, adb_ro_val(o, i), no, schema);
|
||||
}
|
||||
|
||||
int adb_ro_cmp(const struct adb_obj *o1, const struct adb_obj *o2, unsigned i)
|
||||
int adb_ro_cmpobj(const struct adb_obj *tmpl, const struct adb_obj *obj, unsigned mode)
|
||||
{
|
||||
assert(o1->schema->kind == ADB_KIND_OBJECT);
|
||||
assert(o1->schema == o2->schema);
|
||||
assert(i > 0 && i < o1->schema->num_fields);
|
||||
const struct adb_object_schema *schema = obj->schema;
|
||||
int is_set, r = 0;
|
||||
|
||||
switch (*o1->schema->fields[i-1].kind) {
|
||||
assert(schema->kind == ADB_KIND_OBJECT);
|
||||
assert(schema == tmpl->schema);
|
||||
|
||||
for (unsigned int i = ADBI_FIRST; i <= adb_ro_num(tmpl); i++) {
|
||||
is_set = adb_ro_val(tmpl, i) != ADB_VAL_NULL;
|
||||
if (mode == ADB_OBJCMP_EXACT || is_set) {
|
||||
r = adb_ro_cmp(tmpl, obj, i, mode);
|
||||
if (r) return r;
|
||||
}
|
||||
if (mode == ADB_OBJCMP_INDEX && !is_set)
|
||||
return 0;
|
||||
if (mode != ADB_OBJCMP_EXACT && i >= schema->num_compare)
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int adb_ro_cmp(const struct adb_obj *tmpl, const struct adb_obj *obj, unsigned i, unsigned mode)
|
||||
{
|
||||
const struct adb_object_schema *schema = obj->schema;
|
||||
|
||||
assert(schema->kind == ADB_KIND_OBJECT);
|
||||
assert(schema == tmpl->schema);
|
||||
assert(i > 0 && i < schema->num_fields);
|
||||
|
||||
switch (*schema->fields[i-1].kind) {
|
||||
case ADB_KIND_BLOB:
|
||||
case ADB_KIND_INT:
|
||||
return container_of(o1->schema->fields[i-1].kind, struct adb_scalar_schema, kind)->compare(
|
||||
o1->db, adb_ro_val(o1, i),
|
||||
o2->db, adb_ro_val(o2, i));
|
||||
return container_of(schema->fields[i-1].kind, struct adb_scalar_schema, kind)->compare(
|
||||
tmpl->db, adb_ro_val(tmpl, i),
|
||||
obj->db, adb_ro_val(obj, i));
|
||||
case ADB_KIND_OBJECT: {
|
||||
struct adb_obj so1, so2;
|
||||
adb_ro_obj(o1, i, &so1);
|
||||
adb_ro_obj(o2, i, &so2);
|
||||
return so1.schema->compare(&so1, &so2);
|
||||
struct adb_obj stmpl, sobj;
|
||||
adb_ro_obj(tmpl, i, &stmpl);
|
||||
adb_ro_obj(obj, i, &sobj);
|
||||
return adb_ro_cmpobj(&stmpl, &sobj, mode);
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static struct adb *__db1, *__db2;
|
||||
static const struct adb_object_schema *__schema;
|
||||
static struct wacmp_param {
|
||||
struct adb *db1, *db2;
|
||||
const struct adb_object_schema *schema;
|
||||
int mode;
|
||||
} __wacmp_param;
|
||||
|
||||
static int wacmp(const void *p1, const void *p2)
|
||||
{
|
||||
struct wacmp_param *wp = &__wacmp_param;
|
||||
struct adb_obj o1, o2;
|
||||
adb_r_obj(__db1, *(adb_val_t *)p1, &o1, __schema);
|
||||
adb_r_obj(__db2, *(adb_val_t *)p2, &o2, __schema);
|
||||
return o1.schema->compare(&o1, &o2);
|
||||
adb_r_obj(wp->db1, *(adb_val_t *)p1, &o1, wp->schema);
|
||||
adb_r_obj(wp->db2, *(adb_val_t *)p2, &o2, wp->schema);
|
||||
return adb_ro_cmpobj(&o1, &o2, wp->mode);
|
||||
}
|
||||
|
||||
static int wadbcmp(const void *p1, const void *p2)
|
||||
{
|
||||
struct wacmp_param *wp = &__wacmp_param;
|
||||
struct adb a1, a2;
|
||||
struct adb_obj o1, o2;
|
||||
adb_m_blob(&a1, adb_r_blob(__db1, *(adb_val_t *)p1), 0);
|
||||
adb_m_blob(&a2, adb_r_blob(__db2, *(adb_val_t *)p2), 0);
|
||||
adb_r_rootobj(&a1, &o1, __schema);
|
||||
adb_r_rootobj(&a2, &o2, __schema);
|
||||
return __schema->compare(&o1, &o2);
|
||||
adb_m_blob(&a1, adb_r_blob(wp->db1, *(adb_val_t *)p1), 0);
|
||||
adb_m_blob(&a2, adb_r_blob(wp->db2, *(adb_val_t *)p2), 0);
|
||||
adb_r_rootobj(&a1, &o1, wp->schema);
|
||||
adb_r_rootobj(&a2, &o2, wp->schema);
|
||||
return adb_ro_cmpobj(&o1, &o2, wp->mode);
|
||||
}
|
||||
|
||||
int adb_ra_find(struct adb_obj *arr, int cur, struct adb *db, adb_val_t val)
|
||||
int adb_ra_find(struct adb_obj *arr, int cur, struct adb_obj *tmpl)
|
||||
{
|
||||
adb_val_t *ndx;
|
||||
const struct adb_object_schema *schema = arr->schema, *item_schema;
|
||||
struct adb_obj obj;
|
||||
|
||||
__db1 = db;
|
||||
__db2 = arr->db;
|
||||
__schema = arr->schema;
|
||||
assert(__schema->kind == ADB_KIND_ARRAY);
|
||||
__schema = container_of(__schema->fields[0].kind, struct adb_object_schema, kind);
|
||||
assert(schema->kind == ADB_KIND_ARRAY);
|
||||
assert(*schema->fields[0].kind == ADB_KIND_OBJECT);
|
||||
item_schema = container_of(schema->fields[0].kind, struct adb_object_schema, kind),
|
||||
assert(item_schema == tmpl->schema);
|
||||
|
||||
if (cur == 0) {
|
||||
ndx = bsearch(&val, &arr->obj[ADBI_FIRST], adb_ra_num(arr), sizeof(arr->obj[0]), wacmp);
|
||||
if (!ndx) return -1;
|
||||
cur = ndx - arr->obj;
|
||||
while (cur > 1 && wacmp(&val, &arr->obj[cur-1]) == 0) cur--;
|
||||
unsigned m, l = ADBI_FIRST, r = adb_ra_num(arr) + 1;
|
||||
while (l < r) {
|
||||
m = (l + r) / 2;
|
||||
if (adb_ro_cmpobj(tmpl, adb_ro_obj(arr, m, &obj), ADB_OBJCMP_INDEX) < 0)
|
||||
r = m;
|
||||
else
|
||||
l = m + 1;
|
||||
}
|
||||
cur = r - 1;
|
||||
} else {
|
||||
cur++;
|
||||
if (wacmp(&val, &arr->obj[cur]) != 0)
|
||||
return -1;
|
||||
}
|
||||
return cur;
|
||||
|
||||
for (; cur <= adb_ra_num(arr); cur++) {
|
||||
adb_ro_obj(arr, cur, &obj);
|
||||
if (adb_ro_cmpobj(tmpl, &obj, ADB_OBJCMP_TEMPLATE) == 0) return cur;
|
||||
if (adb_ro_cmpobj(tmpl, &obj, ADB_OBJCMP_INDEX) != 0) return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write interface */
|
||||
|
@ -939,15 +976,20 @@ adb_val_t adb_wa_append_fromstring(struct adb_obj *o, apk_blob_t b)
|
|||
|
||||
void adb_wa_sort(struct adb_obj *arr)
|
||||
{
|
||||
assert(arr->schema->kind == ADB_KIND_ARRAY);
|
||||
__db1 = __db2 = arr->db;
|
||||
const struct adb_object_schema *schema = arr->schema;
|
||||
assert(schema->kind == ADB_KIND_ARRAY);
|
||||
__wacmp_param = (struct wacmp_param) {
|
||||
.db1 = arr->db,
|
||||
.db2 = arr->db,
|
||||
.mode = ADB_OBJCMP_EXACT,
|
||||
};
|
||||
switch (*arr->schema->fields[0].kind) {
|
||||
case ADB_KIND_OBJECT:
|
||||
__schema = container_of(arr->schema->fields[0].kind, struct adb_object_schema, kind);
|
||||
__wacmp_param.schema = container_of(arr->schema->fields[0].kind, struct adb_object_schema, kind);
|
||||
qsort(&arr->obj[ADBI_FIRST], adb_ra_num(arr), sizeof(arr->obj[0]), wacmp);
|
||||
break;
|
||||
case ADB_KIND_ADB:
|
||||
__schema = container_of(arr->schema->fields[0].kind, struct adb_adb_schema, kind)->schema;
|
||||
__wacmp_param.schema = container_of(arr->schema->fields[0].kind, struct adb_adb_schema, kind)->schema;
|
||||
qsort(&arr->obj[ADBI_FIRST], adb_ra_num(arr), sizeof(arr->obj[0]), wadbcmp);
|
||||
break;
|
||||
default:
|
||||
|
|
11
src/adb.h
11
src/adb.h
|
@ -105,13 +105,17 @@ struct adb_sign_v0 {
|
|||
#define ADB_ARRAY_ITEM(_t) { { .kind = &(_t).kind } }
|
||||
#define ADB_FIELD(_i, _n, _t) [(_i)-1] = { .name = _n, .kind = &(_t).kind }
|
||||
|
||||
#define ADB_OBJCMP_EXACT 0 // match all fields
|
||||
#define ADB_OBJCMP_TEMPLATE 1 // match fields set on template
|
||||
#define ADB_OBJCMP_INDEX 2 // match fields until first non-set one
|
||||
|
||||
struct adb_object_schema {
|
||||
uint8_t kind;
|
||||
uint16_t num_fields;
|
||||
uint16_t num_compare;
|
||||
|
||||
apk_blob_t (*tostring)(struct adb_obj *, char *, size_t);
|
||||
int (*fromstring)(struct adb_obj *, apk_blob_t);
|
||||
int (*compare)(const struct adb_obj *, const struct adb_obj *);
|
||||
void (*pre_commit)(struct adb_obj *);
|
||||
|
||||
struct {
|
||||
|
@ -192,8 +196,9 @@ adb_val_t adb_ro_val(const struct adb_obj *o, unsigned i);
|
|||
uint32_t adb_ro_int(const struct adb_obj *o, unsigned i);
|
||||
apk_blob_t adb_ro_blob(const struct adb_obj *o, unsigned i);
|
||||
struct adb_obj *adb_ro_obj(const struct adb_obj *o, unsigned i, struct adb_obj *);
|
||||
int adb_ro_cmp(const struct adb_obj *o1, const struct adb_obj *o2, unsigned i);
|
||||
int adb_ra_find(struct adb_obj *arr, int cur, struct adb *db, adb_val_t val);
|
||||
int adb_ro_cmpobj(const struct adb_obj *o1, const struct adb_obj *o2, unsigned mode);
|
||||
int adb_ro_cmp(const struct adb_obj *o1, const struct adb_obj *o2, unsigned i, unsigned mode);
|
||||
int adb_ra_find(struct adb_obj *arr, int cur, struct adb_obj *tmpl);
|
||||
|
||||
/* Primitive write */
|
||||
void adb_w_root(struct adb *, adb_val_t);
|
||||
|
|
|
@ -341,17 +341,12 @@ fail:
|
|||
return -APKE_DEPENDENCY_FORMAT;
|
||||
}
|
||||
|
||||
static int dependency_cmp(const struct adb_obj *o1, const struct adb_obj *o2)
|
||||
{
|
||||
return adb_ro_cmp(o1, o2, ADBI_DEP_NAME);
|
||||
}
|
||||
|
||||
const struct adb_object_schema schema_dependency = {
|
||||
.kind = ADB_KIND_OBJECT,
|
||||
.num_fields = ADBI_DEP_MAX,
|
||||
.num_compare = ADBI_DEP_NAME,
|
||||
.tostring = dependency_tostring,
|
||||
.fromstring = dependency_fromstring,
|
||||
.compare = dependency_cmp,
|
||||
.fields = {
|
||||
ADB_FIELD(ADBI_DEP_NAME, "name", scalar_string),
|
||||
ADB_FIELD(ADBI_DEP_VERSION, "version", scalar_version),
|
||||
|
@ -383,20 +378,10 @@ const struct adb_object_schema schema_dependency_array = {
|
|||
.fields = ADB_ARRAY_ITEM(schema_dependency),
|
||||
};
|
||||
|
||||
static int pkginfo_cmp(const struct adb_obj *o1, const struct adb_obj *o2)
|
||||
{
|
||||
int r;
|
||||
r = adb_ro_cmp(o1, o2, ADBI_PI_NAME);
|
||||
if (r) return r;
|
||||
r = adb_ro_cmp(o1, o2, ADBI_PI_VERSION);
|
||||
if (r) return r;
|
||||
return adb_ro_cmp(o1, o2, ADBI_PI_UNIQUE_ID);
|
||||
}
|
||||
|
||||
const struct adb_object_schema schema_pkginfo = {
|
||||
.kind = ADB_KIND_OBJECT,
|
||||
.num_fields = ADBI_PI_MAX,
|
||||
.compare = pkginfo_cmp,
|
||||
.num_compare = ADBI_PI_UNIQUE_ID,
|
||||
.fields = {
|
||||
ADB_FIELD(ADBI_PI_NAME, "name", scalar_string),
|
||||
ADB_FIELD(ADBI_PI_VERSION, "version", scalar_version),
|
||||
|
@ -448,15 +433,10 @@ const struct adb_object_schema schema_acl = {
|
|||
},
|
||||
};
|
||||
|
||||
static int file_cmp(const struct adb_obj *o1, const struct adb_obj *o2)
|
||||
{
|
||||
return adb_ro_cmp(o1, o2, ADBI_FI_NAME);
|
||||
}
|
||||
|
||||
const struct adb_object_schema schema_file = {
|
||||
.kind = ADB_KIND_OBJECT,
|
||||
.num_fields = ADBI_FI_MAX,
|
||||
.compare = file_cmp,
|
||||
.num_compare = ADBI_FI_NAME,
|
||||
.fields = {
|
||||
ADB_FIELD(ADBI_FI_NAME, "name", scalar_string),
|
||||
ADB_FIELD(ADBI_FI_ACL, "acl", schema_acl),
|
||||
|
@ -477,7 +457,7 @@ const struct adb_object_schema schema_file_array = {
|
|||
const struct adb_object_schema schema_dir = {
|
||||
.kind = ADB_KIND_OBJECT,
|
||||
.num_fields = ADBI_DI_MAX,
|
||||
.compare = file_cmp,
|
||||
.num_compare = ADBI_DI_NAME,
|
||||
.fields = {
|
||||
ADB_FIELD(ADBI_DI_NAME, "name", scalar_string),
|
||||
ADB_FIELD(ADBI_DI_ACL, "acl", schema_acl),
|
||||
|
@ -506,15 +486,10 @@ const struct adb_object_schema schema_scripts = {
|
|||
},
|
||||
};
|
||||
|
||||
static int package_cmp(const struct adb_obj *o1, const struct adb_obj *o2)
|
||||
{
|
||||
return adb_ro_cmp(o1, o2, ADBI_PKG_PKGINFO);
|
||||
}
|
||||
|
||||
const struct adb_object_schema schema_package = {
|
||||
.kind = ADB_KIND_OBJECT,
|
||||
.num_fields = ADBI_PKG_MAX,
|
||||
.compare = package_cmp,
|
||||
.num_compare = ADBI_PKG_PKGINFO,
|
||||
.fields = {
|
||||
ADB_FIELD(ADBI_PKG_PKGINFO, "info", schema_pkginfo),
|
||||
ADB_FIELD(ADBI_PKG_PATHS, "paths", schema_dir_array),
|
||||
|
|
|
@ -208,7 +208,7 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
adb_w_init_tmp(&tmpdb, 200);
|
||||
adb_wo_alloca(&tmpl, &schema_pkginfo, &tmpdb);
|
||||
|
||||
adb_w_init_alloca(&ctx->db, ADB_SCHEMA_INDEX, 1000);
|
||||
adb_w_init_alloca(&ctx->db, ADB_SCHEMA_INDEX, 8000);
|
||||
adb_wo_alloca(&ndx, &schema_index, &ctx->db);
|
||||
adb_wo_alloca(&ctx->pkgs, &schema_pkginfo_array, &ctx->db);
|
||||
adb_wo_alloca(&ctx->pkginfo, &schema_pkginfo, &ctx->db);
|
||||
|
@ -240,7 +240,6 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
if (index_mtime >= fi.mtime) {
|
||||
char *fname, *fend;
|
||||
apk_blob_t bname, bver;
|
||||
adb_val_t match;
|
||||
int i;
|
||||
|
||||
/* Check that it looks like a package name */
|
||||
|
@ -260,15 +259,13 @@ static int mkndx_main(void *pctx, struct apk_ctx *ac, struct apk_string_array *a
|
|||
adb_wo_blob(&tmpl, ADBI_PI_NAME, bname);
|
||||
adb_wo_blob(&tmpl, ADBI_PI_VERSION, bver);
|
||||
adb_wo_int(&tmpl, ADBI_PI_FILE_SIZE, fi.size);
|
||||
match = adb_w_obj(&tmpl);
|
||||
|
||||
if ((i = adb_ra_find(&opkgs, 0, &tmpdb, match)) > 0) {
|
||||
if ((i = adb_ra_find(&opkgs, 0, &tmpl)) > 0) {
|
||||
struct adb_obj pkg;
|
||||
adb_ro_obj(&opkgs, i, &pkg);
|
||||
|
||||
val = adb_wa_append(&ctx->pkgs, adb_w_copy(&ctx->db, &odb, adb_ro_val(&opkgs, i)));
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
|
|
Loading…
Reference in New Issue