Improve ASL store index lifecycle
This commit is contained in:
parent
0a118b9841
commit
dde532d68f
|
|
@ -18,15 +18,30 @@ typedef struct {
|
||||||
uint64_t idle_time_ns;
|
uint64_t idle_time_ns;
|
||||||
} amduat_asl_store_index_fs_snapshot_policy_t;
|
} amduat_asl_store_index_fs_snapshot_policy_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t max_segment_records;
|
||||||
|
uint64_t max_segment_bytes;
|
||||||
|
uint64_t small_artifact_threshold;
|
||||||
|
bool allow_deferred_visibility;
|
||||||
|
} amduat_asl_store_index_fs_segment_policy_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t segment_domain_id;
|
||||||
|
uint8_t record_visibility;
|
||||||
|
} amduat_asl_store_index_fs_visibility_policy_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
amduat_asl_store_config_t config;
|
amduat_asl_store_config_t config;
|
||||||
amduat_asl_store_index_fs_snapshot_policy_t snapshot_policy;
|
amduat_asl_store_index_fs_snapshot_policy_t snapshot_policy;
|
||||||
|
amduat_asl_store_index_fs_segment_policy_t segment_policy;
|
||||||
|
amduat_asl_store_index_fs_visibility_policy_t visibility_policy;
|
||||||
uint16_t shard_count;
|
uint16_t shard_count;
|
||||||
char root_path[AMDUAT_ASL_STORE_INDEX_FS_ROOT_MAX];
|
char root_path[AMDUAT_ASL_STORE_INDEX_FS_ROOT_MAX];
|
||||||
uint64_t pending_snapshot_bytes;
|
uint64_t pending_snapshot_bytes;
|
||||||
uint64_t last_ingest_time_ns;
|
uint64_t last_ingest_time_ns;
|
||||||
amduat_asl_snapshot_id_t next_snapshot_id;
|
amduat_asl_snapshot_id_t next_snapshot_id;
|
||||||
bool snapshot_state_initialized;
|
bool snapshot_state_initialized;
|
||||||
|
void *open_segments;
|
||||||
} amduat_asl_store_index_fs_t;
|
} amduat_asl_store_index_fs_t;
|
||||||
|
|
||||||
bool amduat_asl_store_index_fs_init(amduat_asl_store_index_fs_t *fs,
|
bool amduat_asl_store_index_fs_init(amduat_asl_store_index_fs_t *fs,
|
||||||
|
|
@ -37,6 +52,14 @@ void amduat_asl_store_index_fs_set_snapshot_policy(
|
||||||
amduat_asl_store_index_fs_t *fs,
|
amduat_asl_store_index_fs_t *fs,
|
||||||
amduat_asl_store_index_fs_snapshot_policy_t policy);
|
amduat_asl_store_index_fs_snapshot_policy_t policy);
|
||||||
|
|
||||||
|
void amduat_asl_store_index_fs_set_segment_policy(
|
||||||
|
amduat_asl_store_index_fs_t *fs,
|
||||||
|
amduat_asl_store_index_fs_segment_policy_t policy);
|
||||||
|
|
||||||
|
void amduat_asl_store_index_fs_set_visibility_policy(
|
||||||
|
amduat_asl_store_index_fs_t *fs,
|
||||||
|
amduat_asl_store_index_fs_visibility_policy_t policy);
|
||||||
|
|
||||||
void amduat_asl_store_index_fs_set_shard_count(
|
void amduat_asl_store_index_fs_set_shard_count(
|
||||||
amduat_asl_store_index_fs_t *fs,
|
amduat_asl_store_index_fs_t *fs,
|
||||||
uint16_t shard_count);
|
uint16_t shard_count);
|
||||||
|
|
@ -47,6 +70,14 @@ amduat_asl_store_error_t amduat_asl_store_index_fs_snapshot_create(
|
||||||
amduat_asl_log_position_t *out_logseq,
|
amduat_asl_log_position_t *out_logseq,
|
||||||
uint8_t out_root_hash[32]);
|
uint8_t out_root_hash[32]);
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_store_index_fs_flush(
|
||||||
|
amduat_asl_store_index_fs_t *fs,
|
||||||
|
amduat_asl_index_state_t *out_state);
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_store_index_fs_gc(
|
||||||
|
amduat_asl_store_index_fs_t *fs,
|
||||||
|
const amduat_asl_index_state_t *state);
|
||||||
|
|
||||||
amduat_asl_store_ops_t amduat_asl_store_index_fs_ops(void);
|
amduat_asl_store_ops_t amduat_asl_store_index_fs_ops(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#define AMDUAT_ASL_STORE_H
|
#define AMDUAT_ASL_STORE_H
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
#include "amduat/asl/core.h"
|
||||||
|
#include "amduat/enc/asl_log.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
@ -48,6 +49,20 @@ typedef struct {
|
||||||
amduat_reference_t ref,
|
amduat_reference_t ref,
|
||||||
amduat_asl_index_state_t state,
|
amduat_asl_index_state_t state,
|
||||||
amduat_artifact_t *out_artifact);
|
amduat_artifact_t *out_artifact);
|
||||||
|
amduat_asl_store_error_t (*tombstone)(void *ctx,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
uint32_t scope,
|
||||||
|
uint32_t reason_code,
|
||||||
|
amduat_asl_index_state_t *out_state);
|
||||||
|
amduat_asl_store_error_t (*tombstone_lift)(
|
||||||
|
void *ctx,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
amduat_asl_log_position_t tombstone_logseq,
|
||||||
|
amduat_asl_index_state_t *out_state);
|
||||||
|
amduat_asl_store_error_t (*log_scan)(
|
||||||
|
void *ctx,
|
||||||
|
amduat_asl_log_record_t **out_records,
|
||||||
|
size_t *out_count);
|
||||||
bool (*current_state)(void *ctx, amduat_asl_index_state_t *out_state);
|
bool (*current_state)(void *ctx, amduat_asl_index_state_t *out_state);
|
||||||
amduat_asl_store_error_t (*validate_config)(
|
amduat_asl_store_error_t (*validate_config)(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
|
|
@ -62,6 +77,9 @@ static inline void amduat_asl_store_ops_init(amduat_asl_store_ops_t *ops) {
|
||||||
ops->get = NULL;
|
ops->get = NULL;
|
||||||
ops->put_indexed = NULL;
|
ops->put_indexed = NULL;
|
||||||
ops->get_indexed = NULL;
|
ops->get_indexed = NULL;
|
||||||
|
ops->tombstone = NULL;
|
||||||
|
ops->tombstone_lift = NULL;
|
||||||
|
ops->log_scan = NULL;
|
||||||
ops->current_state = NULL;
|
ops->current_state = NULL;
|
||||||
ops->validate_config = NULL;
|
ops->validate_config = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +115,24 @@ amduat_asl_store_error_t amduat_asl_store_get_indexed(
|
||||||
amduat_asl_index_state_t state,
|
amduat_asl_index_state_t state,
|
||||||
amduat_artifact_t *out_artifact);
|
amduat_artifact_t *out_artifact);
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_store_tombstone(
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
uint32_t scope,
|
||||||
|
uint32_t reason_code,
|
||||||
|
amduat_asl_index_state_t *out_state);
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_store_tombstone_lift(
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
amduat_asl_log_position_t tombstone_logseq,
|
||||||
|
amduat_asl_index_state_t *out_state);
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_log_scan(
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
amduat_asl_log_record_t **out_records,
|
||||||
|
size_t *out_count);
|
||||||
|
|
||||||
bool amduat_asl_index_current_state(amduat_asl_store_t *store,
|
bool amduat_asl_index_current_state(amduat_asl_store_t *store,
|
||||||
amduat_asl_index_state_t *out_state);
|
amduat_asl_index_state_t *out_state);
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -106,6 +106,66 @@ amduat_asl_store_error_t amduat_asl_store_get_indexed(
|
||||||
return store->ops.get_indexed(store->ctx, ref, state, out_artifact);
|
return store->ops.get_indexed(store->ctx, ref, state, out_artifact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_store_tombstone(
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
uint32_t scope,
|
||||||
|
uint32_t reason_code,
|
||||||
|
amduat_asl_index_state_t *out_state) {
|
||||||
|
amduat_asl_store_error_t cfg_err;
|
||||||
|
|
||||||
|
if (store == NULL || store->ops.tombstone == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (ref.hash_id != store->config.hash_id) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
cfg_err = amduat_asl_store_validate_config(store);
|
||||||
|
if (cfg_err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
return cfg_err;
|
||||||
|
}
|
||||||
|
return store->ops.tombstone(store->ctx, ref, scope, reason_code, out_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_store_tombstone_lift(
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
amduat_asl_log_position_t tombstone_logseq,
|
||||||
|
amduat_asl_index_state_t *out_state) {
|
||||||
|
amduat_asl_store_error_t cfg_err;
|
||||||
|
|
||||||
|
if (store == NULL || store->ops.tombstone_lift == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (ref.hash_id != store->config.hash_id) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
cfg_err = amduat_asl_store_validate_config(store);
|
||||||
|
if (cfg_err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
return cfg_err;
|
||||||
|
}
|
||||||
|
return store->ops.tombstone_lift(store->ctx,
|
||||||
|
ref,
|
||||||
|
tombstone_logseq,
|
||||||
|
out_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
amduat_asl_store_error_t amduat_asl_log_scan(
|
||||||
|
amduat_asl_store_t *store,
|
||||||
|
amduat_asl_log_record_t **out_records,
|
||||||
|
size_t *out_count) {
|
||||||
|
amduat_asl_store_error_t cfg_err;
|
||||||
|
|
||||||
|
if (store == NULL || store->ops.log_scan == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
cfg_err = amduat_asl_store_validate_config(store);
|
||||||
|
if (cfg_err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
return cfg_err;
|
||||||
|
}
|
||||||
|
return store->ops.log_scan(store->ctx, out_records, out_count);
|
||||||
|
}
|
||||||
|
|
||||||
bool amduat_asl_index_current_state(amduat_asl_store_t *store,
|
bool amduat_asl_index_current_state(amduat_asl_store_t *store,
|
||||||
amduat_asl_index_state_t *out_state) {
|
amduat_asl_index_state_t *out_state) {
|
||||||
amduat_asl_store_error_t cfg_err;
|
amduat_asl_store_error_t cfg_err;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "amduat/asl/store.h"
|
#include "amduat/asl/store.h"
|
||||||
#include "amduat/enc/asl1_core.h"
|
#include "amduat/enc/asl1_core.h"
|
||||||
#include "amduat/enc/asl_core_index.h"
|
#include "amduat/enc/asl_core_index.h"
|
||||||
|
#include "amduat/enc/asl_log.h"
|
||||||
#include "amduat/format/ref.h"
|
#include "amduat/format/ref.h"
|
||||||
#include "amduat/hash/asl1.h"
|
#include "amduat/hash/asl1.h"
|
||||||
|
|
||||||
|
|
@ -250,6 +251,13 @@ static uint64_t fnv1a64(const uint8_t *data, size_t len, uint64_t seed) {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint64_t load_u64_le(const uint8_t *data) {
|
||||||
|
return (uint64_t)data[0] | ((uint64_t)data[1] << 8) |
|
||||||
|
((uint64_t)data[2] << 16) | ((uint64_t)data[3] << 24) |
|
||||||
|
((uint64_t)data[4] << 32) | ((uint64_t)data[5] << 40) |
|
||||||
|
((uint64_t)data[6] << 48) | ((uint64_t)data[7] << 56);
|
||||||
|
}
|
||||||
|
|
||||||
static uint16_t ref_shard(amduat_reference_t ref, uint16_t shard_count) {
|
static uint16_t ref_shard(amduat_reference_t ref, uint16_t shard_count) {
|
||||||
uint64_t hash;
|
uint64_t hash;
|
||||||
uint8_t hash_id_bytes[2];
|
uint8_t hash_id_bytes[2];
|
||||||
|
|
@ -739,6 +747,343 @@ cleanup:
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int test_segment_batch_packing(void) {
|
||||||
|
amduat_asl_store_config_t config;
|
||||||
|
amduat_asl_store_index_fs_t fs;
|
||||||
|
amduat_asl_store_t store;
|
||||||
|
amduat_asl_store_index_fs_segment_policy_t segment_policy;
|
||||||
|
amduat_asl_store_index_fs_visibility_policy_t visibility_policy;
|
||||||
|
amduat_asl_store_error_t err;
|
||||||
|
amduat_asl_index_state_t state_a;
|
||||||
|
amduat_asl_index_state_t state_b;
|
||||||
|
amduat_artifact_t artifact_a;
|
||||||
|
amduat_artifact_t artifact_b;
|
||||||
|
amduat_artifact_t loaded;
|
||||||
|
amduat_reference_t ref_a;
|
||||||
|
amduat_reference_t ref_b;
|
||||||
|
uint8_t payload_a[3] = {0x01, 0x02, 0x03};
|
||||||
|
uint8_t payload_b[4] = {0x10, 0x11, 0x12, 0x13};
|
||||||
|
char *root;
|
||||||
|
amduat_asl_log_record_t *records = NULL;
|
||||||
|
size_t record_count = 0u;
|
||||||
|
uint64_t segment_id = 0u;
|
||||||
|
char *segment_path = NULL;
|
||||||
|
uint8_t *segment_bytes = NULL;
|
||||||
|
size_t segment_len = 0u;
|
||||||
|
amduat_asl_core_index_segment_t segment;
|
||||||
|
int exit_code = 1;
|
||||||
|
|
||||||
|
root = make_temp_root();
|
||||||
|
if (root == NULL) {
|
||||||
|
fprintf(stderr, "temp root failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
config.encoding_profile_id = AMDUAT_ENC_ASL1_CORE_V1;
|
||||||
|
config.hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
|
||||||
|
if (!amduat_asl_store_index_fs_init(&fs, config, root)) {
|
||||||
|
fprintf(stderr, "index fs init failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
segment_policy.max_segment_records = 2u;
|
||||||
|
segment_policy.max_segment_bytes = 0u;
|
||||||
|
segment_policy.small_artifact_threshold = 1024u;
|
||||||
|
segment_policy.allow_deferred_visibility = true;
|
||||||
|
amduat_asl_store_index_fs_set_segment_policy(&fs, segment_policy);
|
||||||
|
visibility_policy.segment_domain_id = 7u;
|
||||||
|
visibility_policy.record_visibility = 1u;
|
||||||
|
amduat_asl_store_index_fs_set_visibility_policy(&fs, visibility_policy);
|
||||||
|
amduat_asl_store_init(&store, config, amduat_asl_store_index_fs_ops(), &fs);
|
||||||
|
|
||||||
|
artifact_a = amduat_artifact(amduat_octets(payload_a, sizeof(payload_a)));
|
||||||
|
artifact_b = amduat_artifact(amduat_octets(payload_b, sizeof(payload_b)));
|
||||||
|
ref_a = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||||
|
ref_b = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||||
|
|
||||||
|
err = amduat_asl_store_put_indexed(&store, artifact_a, &ref_a, &state_a);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "put_indexed a failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref_a, state_a, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_ERR_NOT_FOUND) {
|
||||||
|
fprintf(stderr, "expected a to be pending before seal: %d\n", err);
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
err = amduat_asl_store_put_indexed(&store, artifact_b, &ref_b, &state_b);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "put_indexed b failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref_a, state_b, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "get_indexed a after seal failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref_b, state_b, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "get_indexed b after seal failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
err = amduat_asl_log_scan(&store, &records, &record_count);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK || record_count != 1u ||
|
||||||
|
records[0].record_type != AMDUAT_ASL_LOG_RECORD_SEGMENT_SEAL) {
|
||||||
|
fprintf(stderr, "log scan expected one segment seal\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (records[0].payload.len < 8u) {
|
||||||
|
fprintf(stderr, "segment seal payload too small\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
segment_id = load_u64_le(records[0].payload.data);
|
||||||
|
|
||||||
|
memset(&segment, 0, sizeof(segment));
|
||||||
|
if (!build_segment_path(root, segment_id, &segment_path)) {
|
||||||
|
fprintf(stderr, "segment path build failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!read_file(segment_path, &segment_bytes, &segment_len)) {
|
||||||
|
fprintf(stderr, "segment read failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!amduat_enc_asl_core_index_decode_v1(
|
||||||
|
amduat_octets(segment_bytes, segment_len), &segment)) {
|
||||||
|
fprintf(stderr, "segment decode failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (segment.record_count != 2u || segment.extent_count != 2u) {
|
||||||
|
fprintf(stderr, "segment record/extent count mismatch\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (segment.header.segment_visibility != 1u ||
|
||||||
|
segment.header.segment_domain_id != 7u) {
|
||||||
|
fprintf(stderr, "segment visibility metadata mismatch\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (segment.records[0].visibility != 1u ||
|
||||||
|
segment.records[1].visibility != 1u ||
|
||||||
|
segment.records[0].domain_id != 7u ||
|
||||||
|
segment.records[1].domain_id != 7u) {
|
||||||
|
fprintf(stderr, "record visibility metadata mismatch\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_code = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
amduat_enc_asl_core_index_free(&segment);
|
||||||
|
free(segment_path);
|
||||||
|
free(segment_bytes);
|
||||||
|
amduat_enc_asl_log_free(records, record_count);
|
||||||
|
amduat_reference_free(&ref_a);
|
||||||
|
amduat_reference_free(&ref_b);
|
||||||
|
if (!remove_tree(root)) {
|
||||||
|
fprintf(stderr, "cleanup failed\n");
|
||||||
|
exit_code = 1;
|
||||||
|
}
|
||||||
|
free(root);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_tombstone_round_trip(void) {
|
||||||
|
amduat_asl_store_config_t config;
|
||||||
|
amduat_asl_store_index_fs_t fs;
|
||||||
|
amduat_asl_store_t store;
|
||||||
|
amduat_asl_store_error_t err;
|
||||||
|
amduat_asl_index_state_t state;
|
||||||
|
amduat_asl_index_state_t tombstone_state;
|
||||||
|
amduat_asl_index_state_t lift_state;
|
||||||
|
amduat_artifact_t artifact;
|
||||||
|
amduat_artifact_t loaded;
|
||||||
|
amduat_reference_t ref;
|
||||||
|
uint8_t payload[4];
|
||||||
|
char *root;
|
||||||
|
amduat_asl_log_record_t *records = NULL;
|
||||||
|
size_t record_count = 0u;
|
||||||
|
int exit_code = 1;
|
||||||
|
|
||||||
|
root = make_temp_root();
|
||||||
|
if (root == NULL) {
|
||||||
|
fprintf(stderr, "temp root failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
config.encoding_profile_id = AMDUAT_ENC_ASL1_CORE_V1;
|
||||||
|
config.hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
|
||||||
|
if (!amduat_asl_store_index_fs_init(&fs, config, root)) {
|
||||||
|
fprintf(stderr, "index fs init failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_asl_store_init(&store, config, amduat_asl_store_index_fs_ops(), &fs);
|
||||||
|
|
||||||
|
memset(payload, 0x2a, sizeof(payload));
|
||||||
|
artifact = amduat_artifact(amduat_octets(payload, sizeof(payload)));
|
||||||
|
ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||||
|
|
||||||
|
err = amduat_asl_store_put_indexed(&store, artifact, &ref, &state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "put_indexed failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref, state, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "get_indexed failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
err = amduat_asl_store_tombstone(&store, ref, 7u, 9u, &tombstone_state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "tombstone failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (tombstone_state.log_position <= state.log_position) {
|
||||||
|
fprintf(stderr, "tombstone did not advance log position\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_asl_index_current_state(&store, &state)) {
|
||||||
|
fprintf(stderr, "current_state failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref, state, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_ERR_NOT_FOUND) {
|
||||||
|
fprintf(stderr, "get_indexed after tombstone expected not found: %d\n", err);
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
err = amduat_asl_store_tombstone_lift(&store,
|
||||||
|
ref,
|
||||||
|
tombstone_state.log_position,
|
||||||
|
&lift_state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "tombstone_lift failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (lift_state.log_position <= tombstone_state.log_position) {
|
||||||
|
fprintf(stderr, "tombstone_lift did not advance log position\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_asl_index_current_state(&store, &state)) {
|
||||||
|
fprintf(stderr, "current_state failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref, state, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "get_indexed after tombstone lift failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
err = amduat_asl_log_scan(&store, &records, &record_count);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "log scan failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (record_count < 3u ||
|
||||||
|
records[record_count - 1u].record_type !=
|
||||||
|
AMDUAT_ASL_LOG_RECORD_TOMBSTONE_LIFT) {
|
||||||
|
fprintf(stderr, "log scan missing tombstone lift record\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_code = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
amduat_enc_asl_log_free(records, record_count);
|
||||||
|
amduat_reference_free(&ref);
|
||||||
|
if (!remove_tree(root)) {
|
||||||
|
fprintf(stderr, "cleanup failed\n");
|
||||||
|
exit_code = 1;
|
||||||
|
}
|
||||||
|
free(root);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_gc_keeps_visible(void) {
|
||||||
|
amduat_asl_store_config_t config;
|
||||||
|
amduat_asl_store_index_fs_t fs;
|
||||||
|
amduat_asl_store_t store;
|
||||||
|
amduat_asl_store_error_t err;
|
||||||
|
amduat_asl_index_state_t state;
|
||||||
|
amduat_artifact_t artifact;
|
||||||
|
amduat_artifact_t loaded;
|
||||||
|
amduat_reference_t ref;
|
||||||
|
uint8_t payload[5];
|
||||||
|
char *root;
|
||||||
|
int exit_code = 1;
|
||||||
|
|
||||||
|
root = make_temp_root();
|
||||||
|
if (root == NULL) {
|
||||||
|
fprintf(stderr, "temp root failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
config.encoding_profile_id = AMDUAT_ENC_ASL1_CORE_V1;
|
||||||
|
config.hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
|
||||||
|
if (!amduat_asl_store_index_fs_init(&fs, config, root)) {
|
||||||
|
fprintf(stderr, "index fs init failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_asl_store_init(&store, config, amduat_asl_store_index_fs_ops(), &fs);
|
||||||
|
|
||||||
|
memset(payload, 0x77, sizeof(payload));
|
||||||
|
artifact = amduat_artifact(amduat_octets(payload, sizeof(payload)));
|
||||||
|
ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_put_indexed(&store, artifact, &ref, &state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "put_indexed failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = amduat_asl_store_index_fs_gc(&fs, &state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "gc failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
||||||
|
err = amduat_asl_store_get_indexed(&store, ref, state, &loaded);
|
||||||
|
if (err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
fprintf(stderr, "get_indexed after gc failed: %d\n", err);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
amduat_artifact_free(&loaded);
|
||||||
|
|
||||||
|
exit_code = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
amduat_reference_free(&ref);
|
||||||
|
if (!remove_tree(root)) {
|
||||||
|
fprintf(stderr, "cleanup failed\n");
|
||||||
|
exit_code = 1;
|
||||||
|
}
|
||||||
|
free(root);
|
||||||
|
return exit_code;
|
||||||
|
}
|
||||||
|
|
||||||
static int test_large_round_trip_perf(void) {
|
static int test_large_round_trip_perf(void) {
|
||||||
enum { k_artifact_count_default = 10000, k_payload_max = 64 };
|
enum { k_artifact_count_default = 10000, k_payload_max = 64 };
|
||||||
amduat_asl_store_config_t config;
|
amduat_asl_store_config_t config;
|
||||||
|
|
@ -1278,6 +1623,15 @@ int main(void) {
|
||||||
if (test_snapshot_truncation() != 0) {
|
if (test_snapshot_truncation() != 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (test_segment_batch_packing() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (test_tombstone_round_trip() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (test_gc_keeps_visible() != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if (test_large_round_trip_perf() != 0) {
|
if (test_large_round_trip_perf() != 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,26 @@ static int test_indexed_ops_unsupported(void) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = amduat_asl_store_tombstone(&store, ref, 0u, 0u, &state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_ERR_UNSUPPORTED) {
|
||||||
|
fprintf(stderr, "tombstone missing ops should be unsupported: %d\n", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = amduat_asl_store_tombstone_lift(&store, ref, 1u, &state);
|
||||||
|
if (err != AMDUAT_ASL_STORE_ERR_UNSUPPORTED) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"tombstone_lift missing ops should be unsupported: %d\n",
|
||||||
|
err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = amduat_asl_log_scan(&store, NULL, NULL);
|
||||||
|
if (err != AMDUAT_ASL_STORE_ERR_UNSUPPORTED) {
|
||||||
|
fprintf(stderr, "log_scan missing ops should be unsupported: %d\n", err);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue