diff options
Diffstat (limited to 'src/storage/store.c')
| -rw-r--r-- | src/storage/store.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/src/storage/store.c b/src/storage/store.c index 5701578..060c6f6 100644 --- a/src/storage/store.c +++ b/src/storage/store.c @@ -645,6 +645,72 @@ metadata_targets_valid(tiny_store_t *store, const char *self_id, const tiny_meta return true; } +static bool +prune_metadata_references(tiny_store_t *store, tiny_message_t *message) +{ + size_t index, write_index; + bool changed = false; + if (!store || !message) + { + return false; + } + /* Prune relations whose targets are deleted or missing. */ + for (index = 0, write_index = 0; index < message->metadata.relation_count; ++index) + { + tiny_store_entry_t *target = find_entry(store, message->metadata.relations[index].message_id); + if (target && !target->deleted) + { + if (write_index != index) + { + message->metadata.relations[write_index] = message->metadata.relations[index]; + } + write_index++; + } + else + { + changed = true; + } + } + if (changed) + { + message->metadata.relation_count = write_index; + if (write_index == 0) + { + free(message->metadata.relations); + message->metadata.relations = NULL; + } + } + /* Prune sources whose targets are deleted or missing. */ + changed = false; + for (index = 0, write_index = 0; index < message->metadata.source_count; ++index) + { + tiny_store_entry_t *target = find_entry(store, message->metadata.source_message_ids[index]); + if (target && !target->deleted) + { + if (write_index != index) + { + message->metadata.source_message_ids[write_index] + = message->metadata.source_message_ids[index]; + } + write_index++; + } + else + { + changed = true; + } + } + if (changed) + { + message->metadata.source_count = write_index; + if (write_index == 0) + { + free(message->metadata.source_message_ids); + message->metadata.source_message_ids = NULL; + } + } + return true; +} + static tiny_store_status_t prepare_update(tiny_store_t *store, tiny_store_entry_t *entry, @@ -1262,7 +1328,8 @@ write_snapshot(tiny_store_t *store) { unsigned char prefix[16], *payload = NULL; uint32_t length = 0; - if (!serialize_put(&store->entries[index].message, &payload, &length)) + if (!prune_metadata_references(store, &store->entries[index].message) + || !serialize_put(&store->entries[index].message, &payload, &length)) { ok = false; break; @@ -1773,7 +1840,8 @@ tiny_store_rebuild(tiny_store_t *store, tiny_rebuild_report_t *report) { unsigned char *payload = NULL; uint32_t length = 0; - if (!serialize_put(&store->entries[read_index].message, &payload, &length)) + if (!prune_metadata_references(store, &store->entries[read_index].message) + || !serialize_put(&store->entries[read_index].message, &payload, &length)) { status = TINY_STORE_NO_MEMORY; break; |
