2026-01-18 10:56:52 +01:00
|
|
|
#include "amduat/fed/ingest.h"
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
|
|
static bool amduat_fed_record_id_eq(const amduat_fed_record_id_t *a,
|
|
|
|
|
const amduat_fed_record_id_t *b) {
|
|
|
|
|
if (a->type != b->type) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return amduat_reference_eq(a->ref, b->ref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool amduat_fed_record_equivalent(const amduat_fed_record_t *a,
|
|
|
|
|
const amduat_fed_record_t *b) {
|
|
|
|
|
return a->meta.domain_id == b->meta.domain_id &&
|
|
|
|
|
a->meta.visibility == b->meta.visibility &&
|
|
|
|
|
a->meta.has_source == b->meta.has_source &&
|
|
|
|
|
a->meta.source_domain == b->meta.source_domain &&
|
2026-01-18 11:25:39 +01:00
|
|
|
a->location.domain_id == b->location.domain_id &&
|
|
|
|
|
amduat_reference_eq(a->location.ref, b->location.ref) &&
|
2026-01-18 10:56:52 +01:00
|
|
|
a->logseq == b->logseq &&
|
|
|
|
|
a->snapshot_id == b->snapshot_id &&
|
|
|
|
|
a->log_prefix == b->log_prefix;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
amduat_fed_ingest_error_t amduat_fed_ingest_validate(
|
|
|
|
|
const amduat_fed_record_t *records,
|
|
|
|
|
size_t count,
|
|
|
|
|
size_t *out_error_index,
|
|
|
|
|
size_t *out_conflict_index) {
|
|
|
|
|
size_t i;
|
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
|
|
if (out_error_index != NULL) {
|
|
|
|
|
*out_error_index = (size_t)-1;
|
|
|
|
|
}
|
|
|
|
|
if (out_conflict_index != NULL) {
|
|
|
|
|
*out_conflict_index = (size_t)-1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (records == NULL && count != 0u) {
|
|
|
|
|
return AMDUAT_FED_INGEST_ERR_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < count; ++i) {
|
|
|
|
|
const amduat_fed_record_t *record = &records[i];
|
|
|
|
|
|
|
|
|
|
if (!amduat_fed_record_validate(record)) {
|
|
|
|
|
if (out_error_index != NULL) {
|
|
|
|
|
*out_error_index = i;
|
|
|
|
|
}
|
|
|
|
|
return AMDUAT_FED_INGEST_ERR_INVALID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j < i; ++j) {
|
|
|
|
|
const amduat_fed_record_t *other = &records[j];
|
|
|
|
|
|
|
|
|
|
if (!amduat_fed_record_id_eq(&record->id, &other->id)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (!amduat_fed_record_equivalent(record, other)) {
|
|
|
|
|
if (out_error_index != NULL) {
|
|
|
|
|
*out_error_index = i;
|
|
|
|
|
}
|
|
|
|
|
if (out_conflict_index != NULL) {
|
|
|
|
|
*out_conflict_index = j;
|
|
|
|
|
}
|
|
|
|
|
return AMDUAT_FED_INGEST_ERR_CONFLICT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return AMDUAT_FED_INGEST_OK;
|
|
|
|
|
}
|