Compare commits
No commits in common. "main" and "qbits" have entirely different histories.
|
|
@ -57,13 +57,10 @@ set(AMDUAT_UTIL_SRCS
|
||||||
src/internal/varint.c
|
src/internal/varint.c
|
||||||
src/internal/endian.c
|
src/internal/endian.c
|
||||||
src/internal/hex.c
|
src/internal/hex.c
|
||||||
src/internal/log.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(AMDUAT_ASL_SRCS
|
set(AMDUAT_ASL_SRCS
|
||||||
src/kernel/asl/core.c
|
src/kernel/asl/core.c
|
||||||
src/near_core/asl/collection_view.c
|
|
||||||
src/near_core/asl/none.c
|
|
||||||
src/near_core/asl/artifact_io.c
|
src/near_core/asl/artifact_io.c
|
||||||
src/near_core/asl/io.c
|
src/near_core/asl/io.c
|
||||||
src/near_core/asl/index_accel.c
|
src/near_core/asl/index_accel.c
|
||||||
|
|
@ -77,18 +74,6 @@ set(AMDUAT_ASL_SRCS
|
||||||
src/near_core/asl/registry.c
|
src/near_core/asl/registry.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(AMDUAT_ASL_LOG_STORE_SRCS
|
|
||||||
src/core/asl_log_store.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(AMDUAT_ASL_RECORD_SRCS
|
|
||||||
src/core/asl_record.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(AMDUAT_ASL_COLLECTION_SRCS
|
|
||||||
src/core/asl_collection.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(AMDUAT_HASH_ASL1_SRCS
|
set(AMDUAT_HASH_ASL1_SRCS
|
||||||
src/near_core/hash/asl1.c
|
src/near_core/hash/asl1.c
|
||||||
src/near_core/hash/sha256.c
|
src/near_core/hash/sha256.c
|
||||||
|
|
@ -120,7 +105,6 @@ set(AMDUAT_FORMAT_SRCS
|
||||||
|
|
||||||
set(AMDUAT_PEL_SRCS
|
set(AMDUAT_PEL_SRCS
|
||||||
src/kernel/pel/core.c
|
src/kernel/pel/core.c
|
||||||
src/core/derivation_sid.c
|
|
||||||
src/pel_stack/decode.c
|
src/pel_stack/decode.c
|
||||||
src/pel_stack/surf/surf.c
|
src/pel_stack/surf/surf.c
|
||||||
src/pel_stack/program_dag/program_dag.c
|
src/pel_stack/program_dag/program_dag.c
|
||||||
|
|
@ -129,7 +113,6 @@ set(AMDUAT_PEL_SRCS
|
||||||
src/pel_stack/trace_dag/trace_dag.c
|
src/pel_stack/trace_dag/trace_dag.c
|
||||||
src/pel_stack/queue/queue.c
|
src/pel_stack/queue/queue.c
|
||||||
src/pel_stack/opreg/kernel.c
|
src/pel_stack/opreg/kernel.c
|
||||||
src/pel_stack/opreg/kernel_collection.c
|
|
||||||
src/pel_stack/opreg/kernel_params.c
|
src/pel_stack/opreg/kernel_params.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -161,14 +144,6 @@ set(AMDUAT_ASL_DERIVATION_INDEX_FS_SRCS
|
||||||
src/adapters/asl_derivation_index_fs/asl_derivation_index_fs.c
|
src/adapters/asl_derivation_index_fs/asl_derivation_index_fs.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(AMDUAT_ASL_MATERIALIZATION_CACHE_FS_SRCS
|
|
||||||
src/adapters/asl_materialization_cache_fs/asl_materialization_cache_fs.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(AMDUAT_ASL_POINTER_FS_SRCS
|
|
||||||
src/adapters/asl_pointer_fs/asl_pointer_fs.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(AMDUAT_TGK_STORE_MEM_SRCS
|
set(AMDUAT_TGK_STORE_MEM_SRCS
|
||||||
src/adapters/tgk_store_mem/tgk_store_mem.c
|
src/adapters/tgk_store_mem/tgk_store_mem.c
|
||||||
)
|
)
|
||||||
|
|
@ -196,8 +171,7 @@ amduat_add_lib(format SRCS ${AMDUAT_FORMAT_SRCS})
|
||||||
amduat_link(format amduat_asl amduat_enc amduat_util)
|
amduat_link(format amduat_asl amduat_enc amduat_util)
|
||||||
|
|
||||||
amduat_add_lib(pel SRCS ${AMDUAT_PEL_SRCS})
|
amduat_add_lib(pel SRCS ${AMDUAT_PEL_SRCS})
|
||||||
amduat_link(pel amduat_asl_materialization_cache_fs amduat_asl_collection
|
amduat_link(pel amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
||||||
amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
|
||||||
|
|
||||||
amduat_add_lib(tgk SRCS ${AMDUAT_TGK_SRCS})
|
amduat_add_lib(tgk SRCS ${AMDUAT_TGK_SRCS})
|
||||||
amduat_link(tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
amduat_link(tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
||||||
|
|
@ -217,23 +191,6 @@ amduat_add_lib(asl_derivation_index_fs SRCS ${AMDUAT_ASL_DERIVATION_INDEX_FS_SRC
|
||||||
amduat_link(asl_derivation_index_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
amduat_link(asl_derivation_index_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
||||||
target_compile_definitions(amduat_asl_derivation_index_fs_obj PRIVATE _POSIX_C_SOURCE=200809L)
|
target_compile_definitions(amduat_asl_derivation_index_fs_obj PRIVATE _POSIX_C_SOURCE=200809L)
|
||||||
|
|
||||||
amduat_add_lib(asl_materialization_cache_fs SRCS ${AMDUAT_ASL_MATERIALIZATION_CACHE_FS_SRCS})
|
|
||||||
amduat_link(asl_materialization_cache_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
|
||||||
target_compile_definitions(amduat_asl_materialization_cache_fs_obj PRIVATE _POSIX_C_SOURCE=200809L)
|
|
||||||
|
|
||||||
amduat_add_lib(asl_pointer_fs SRCS ${AMDUAT_ASL_POINTER_FS_SRCS})
|
|
||||||
amduat_link(asl_pointer_fs amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
|
||||||
target_compile_definitions(amduat_asl_pointer_fs_obj PRIVATE _POSIX_C_SOURCE=200809L)
|
|
||||||
|
|
||||||
amduat_add_lib(asl_log_store SRCS ${AMDUAT_ASL_LOG_STORE_SRCS})
|
|
||||||
amduat_link(asl_log_store amduat_asl_pointer_fs amduat_asl amduat_enc amduat_util)
|
|
||||||
|
|
||||||
amduat_add_lib(asl_record SRCS ${AMDUAT_ASL_RECORD_SRCS})
|
|
||||||
amduat_link(asl_record amduat_asl amduat_enc amduat_util)
|
|
||||||
|
|
||||||
amduat_add_lib(asl_collection SRCS ${AMDUAT_ASL_COLLECTION_SRCS})
|
|
||||||
amduat_link(asl_collection amduat_asl_log_store amduat_asl_record amduat_asl_pointer_fs
|
|
||||||
amduat_asl amduat_enc amduat_util)
|
|
||||||
amduat_add_lib(tgk_store_mem SRCS ${AMDUAT_TGK_STORE_MEM_SRCS})
|
amduat_add_lib(tgk_store_mem SRCS ${AMDUAT_TGK_STORE_MEM_SRCS})
|
||||||
amduat_link(tgk_store_mem amduat_tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
amduat_link(tgk_store_mem amduat_tgk amduat_asl amduat_enc amduat_hash_asl1 amduat_util)
|
||||||
|
|
||||||
|
|
@ -287,8 +244,6 @@ target_include_directories(amduat_pel_cli
|
||||||
)
|
)
|
||||||
target_link_libraries(amduat_pel_cli
|
target_link_libraries(amduat_pel_cli
|
||||||
PRIVATE amduat_format amduat_pel amduat_asl_store_fs
|
PRIVATE amduat_format amduat_pel amduat_asl_store_fs
|
||||||
amduat_asl_collection amduat_asl_record amduat_asl_log_store
|
|
||||||
amduat_asl_pointer_fs
|
|
||||||
amduat_asl_derivation_index_fs amduat_asl amduat_enc
|
amduat_asl_derivation_index_fs amduat_asl amduat_enc
|
||||||
amduat_hash_asl1 amduat_util
|
amduat_hash_asl1 amduat_util
|
||||||
)
|
)
|
||||||
|
|
@ -300,7 +255,7 @@ target_include_directories(amduat_pel_build
|
||||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(amduat_pel_build
|
target_link_libraries(amduat_pel_build
|
||||||
PRIVATE amduat_pel amduat_asl_store_fs amduat_asl amduat_enc amduat_util
|
PRIVATE amduat_pel amduat_asl amduat_enc amduat_util
|
||||||
)
|
)
|
||||||
set_target_properties(amduat_pel_build PROPERTIES OUTPUT_NAME amduat-pel-build)
|
set_target_properties(amduat_pel_build PROPERTIES OUTPUT_NAME amduat-pel-build)
|
||||||
|
|
||||||
|
|
@ -334,8 +289,7 @@ target_include_directories(amduat_test_pel_program_build_concat
|
||||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(amduat_test_pel_program_build_concat
|
target_link_libraries(amduat_test_pel_program_build_concat
|
||||||
PRIVATE amduat_pel amduat_asl_store_fs amduat_asl amduat_enc
|
PRIVATE amduat_pel amduat_asl amduat_enc amduat_hash_asl1 amduat_util
|
||||||
amduat_hash_asl1 amduat_util
|
|
||||||
)
|
)
|
||||||
add_test(NAME pel_program_build_concat COMMAND amduat_test_pel_program_build_concat)
|
add_test(NAME pel_program_build_concat COMMAND amduat_test_pel_program_build_concat)
|
||||||
|
|
||||||
|
|
@ -509,36 +463,6 @@ set_tests_properties(asl_store_index_fs PROPERTIES
|
||||||
TIMEOUT 120
|
TIMEOUT 120
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(amduat_test_asl_log_store_index_fs
|
|
||||||
tests/asl/test_asl_log_store_index_fs.c)
|
|
||||||
target_include_directories(amduat_test_asl_log_store_index_fs
|
|
||||||
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
|
||||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
|
||||||
)
|
|
||||||
target_compile_definitions(amduat_test_asl_log_store_index_fs
|
|
||||||
PRIVATE _POSIX_C_SOURCE=200809L
|
|
||||||
)
|
|
||||||
target_link_libraries(amduat_test_asl_log_store_index_fs
|
|
||||||
PRIVATE amduat_asl_log_store amduat_asl_store_index_fs amduat_format pthread
|
|
||||||
)
|
|
||||||
add_test(NAME asl_log_store_index_fs COMMAND amduat_test_asl_log_store_index_fs)
|
|
||||||
set_tests_properties(asl_log_store_index_fs PROPERTIES TIMEOUT 30)
|
|
||||||
|
|
||||||
add_executable(amduat_test_asl_index_put_get_consistency
|
|
||||||
tests/asl/test_asl_index_put_get_consistency.c)
|
|
||||||
target_include_directories(amduat_test_asl_index_put_get_consistency
|
|
||||||
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
|
||||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
|
||||||
)
|
|
||||||
target_compile_definitions(amduat_test_asl_index_put_get_consistency
|
|
||||||
PRIVATE _POSIX_C_SOURCE=200809L
|
|
||||||
)
|
|
||||||
target_link_libraries(amduat_test_asl_index_put_get_consistency
|
|
||||||
PRIVATE amduat_asl_store_index_fs amduat_format pthread
|
|
||||||
)
|
|
||||||
add_test(NAME asl_index_put_get_consistency
|
|
||||||
COMMAND amduat_test_asl_index_put_get_consistency)
|
|
||||||
|
|
||||||
add_executable(amduat_test_asl_index_accel tests/asl/test_asl_index_accel.c)
|
add_executable(amduat_test_asl_index_accel tests/asl/test_asl_index_accel.c)
|
||||||
target_include_directories(amduat_test_asl_index_accel
|
target_include_directories(amduat_test_asl_index_accel
|
||||||
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
||||||
|
|
@ -571,7 +495,7 @@ target_include_directories(amduat_test_pel_program_dag_exec
|
||||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(amduat_test_pel_program_dag_exec
|
target_link_libraries(amduat_test_pel_program_dag_exec
|
||||||
PRIVATE amduat_pel amduat_asl_store_fs
|
PRIVATE amduat_pel
|
||||||
)
|
)
|
||||||
add_test(NAME pel_program_dag_exec COMMAND amduat_test_pel_program_dag_exec)
|
add_test(NAME pel_program_dag_exec COMMAND amduat_test_pel_program_dag_exec)
|
||||||
|
|
||||||
|
|
@ -603,7 +527,7 @@ target_include_directories(amduat_test_pel_surf_run
|
||||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(amduat_test_pel_surf_run
|
target_link_libraries(amduat_test_pel_surf_run
|
||||||
PRIVATE amduat_pel amduat_asl_store_fs
|
PRIVATE amduat_pel
|
||||||
)
|
)
|
||||||
add_test(NAME pel_surf_run COMMAND amduat_test_pel_surf_run)
|
add_test(NAME pel_surf_run COMMAND amduat_test_pel_surf_run)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_MATERIALIZATION_CACHE_FS_H
|
|
||||||
#define AMDUAT_ASL_MATERIALIZATION_CACHE_FS_H
|
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
#include "amduat/asl/store.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { AMDUAT_ASL_MATERIALIZATION_CACHE_FS_ROOT_MAX = 1024 };
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char root_path[AMDUAT_ASL_MATERIALIZATION_CACHE_FS_ROOT_MAX];
|
|
||||||
} amduat_asl_materialization_cache_fs_t;
|
|
||||||
|
|
||||||
bool amduat_asl_materialization_cache_fs_init(
|
|
||||||
amduat_asl_materialization_cache_fs_t *cache,
|
|
||||||
const char *root_path);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_materialization_cache_fs_get(
|
|
||||||
amduat_asl_materialization_cache_fs_t *cache,
|
|
||||||
amduat_octets_t sid,
|
|
||||||
amduat_reference_t **out_refs,
|
|
||||||
size_t *out_refs_len);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_materialization_cache_fs_put(
|
|
||||||
amduat_asl_materialization_cache_fs_t *cache,
|
|
||||||
amduat_octets_t sid,
|
|
||||||
const amduat_reference_t *refs,
|
|
||||||
size_t refs_len);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_MATERIALIZATION_CACHE_FS_H */
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_POINTER_FS_H
|
|
||||||
#define AMDUAT_ASL_POINTER_FS_H
|
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_POINTER_FS_ROOT_MAX = 1024,
|
|
||||||
AMDUAT_ASL_POINTER_NAME_MAX = 512
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AMDUAT_ASL_POINTER_OK = 0,
|
|
||||||
AMDUAT_ASL_POINTER_ERR_NOT_FOUND = 1,
|
|
||||||
AMDUAT_ASL_POINTER_ERR_IO = 2,
|
|
||||||
AMDUAT_ASL_POINTER_ERR_INVALID_NAME = 3,
|
|
||||||
AMDUAT_ASL_POINTER_ERR_INTEGRITY = 4
|
|
||||||
} amduat_asl_pointer_error_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char root_path[AMDUAT_ASL_POINTER_FS_ROOT_MAX];
|
|
||||||
} amduat_asl_pointer_store_t;
|
|
||||||
|
|
||||||
/* Pointers are generic control-plane names for artifacts (e.g. dataset heads).
|
|
||||||
* Example names:
|
|
||||||
* - space/123/dataset/calendar_types/head
|
|
||||||
* - space/123/collection/events/head
|
|
||||||
*/
|
|
||||||
bool amduat_asl_pointer_store_init(amduat_asl_pointer_store_t *ps,
|
|
||||||
const char *root_path);
|
|
||||||
|
|
||||||
amduat_asl_pointer_error_t amduat_asl_pointer_get(
|
|
||||||
const amduat_asl_pointer_store_t *ps,
|
|
||||||
const char *name,
|
|
||||||
bool *out_exists,
|
|
||||||
amduat_reference_t *out_ref);
|
|
||||||
|
|
||||||
amduat_asl_pointer_error_t amduat_asl_pointer_cas(
|
|
||||||
const amduat_asl_pointer_store_t *ps,
|
|
||||||
const char *name,
|
|
||||||
bool expected_exists,
|
|
||||||
const amduat_reference_t *expected_ref,
|
|
||||||
const amduat_reference_t *new_ref,
|
|
||||||
bool *out_swapped);
|
|
||||||
|
|
||||||
bool amduat_asl_pointer_name_is_valid(const char *name);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_POINTER_FS_H */
|
|
||||||
|
|
@ -3,10 +3,8 @@
|
||||||
|
|
||||||
#include "amduat/asl/store.h"
|
#include "amduat/asl/store.h"
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -44,9 +42,6 @@ typedef struct {
|
||||||
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;
|
void *open_segments;
|
||||||
pthread_mutex_t write_mutex;
|
|
||||||
uint32_t write_depth;
|
|
||||||
int write_lock_fd;
|
|
||||||
} 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,
|
||||||
|
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_COLLECTION_H
|
|
||||||
#define AMDUAT_ASL_COLLECTION_H
|
|
||||||
|
|
||||||
#include "amduat/asl/asl_pointer_fs.h"
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
#include "amduat/asl/log_store.h"
|
|
||||||
#include "amduat/asl/record.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AMDUAT_ASL_COLLECTION_OK = 0,
|
|
||||||
AMDUAT_ASL_COLLECTION_ERR_INVALID_NAME = 1,
|
|
||||||
AMDUAT_ASL_COLLECTION_ERR_IO = 2,
|
|
||||||
AMDUAT_ASL_COLLECTION_ERR_INTEGRITY = 3,
|
|
||||||
AMDUAT_ASL_COLLECTION_ERR_CAS_MISMATCH = 4
|
|
||||||
} amduat_asl_collection_error_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
amduat_asl_store_t *store;
|
|
||||||
amduat_asl_log_store_t log_store;
|
|
||||||
amduat_asl_pointer_store_t pointer_store;
|
|
||||||
} amduat_asl_collection_store_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t snapshot_offset;
|
|
||||||
amduat_reference_t *refs;
|
|
||||||
size_t refs_len;
|
|
||||||
} amduat_asl_collection_snapshot_payload_t;
|
|
||||||
|
|
||||||
bool amduat_asl_collection_store_init(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *root_path,
|
|
||||||
amduat_asl_store_t *store);
|
|
||||||
|
|
||||||
amduat_asl_collection_error_t amduat_asl_collection_append(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *collection_name,
|
|
||||||
amduat_reference_t record_ref,
|
|
||||||
uint16_t kind,
|
|
||||||
amduat_octets_t actor,
|
|
||||||
uint64_t *out_offset);
|
|
||||||
|
|
||||||
amduat_asl_collection_error_t amduat_asl_collection_snapshot(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *collection_name,
|
|
||||||
uint64_t up_to_offset,
|
|
||||||
amduat_reference_t *out_snapshot_ref,
|
|
||||||
bool *out_swapped);
|
|
||||||
|
|
||||||
amduat_asl_collection_error_t amduat_asl_collection_read(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *collection_name,
|
|
||||||
uint64_t from_offset,
|
|
||||||
size_t limit,
|
|
||||||
amduat_reference_t **out_record_refs,
|
|
||||||
size_t *out_len,
|
|
||||||
uint64_t *out_next_offset,
|
|
||||||
bool *out_end);
|
|
||||||
|
|
||||||
void amduat_asl_collection_refs_free(amduat_reference_t *refs,
|
|
||||||
size_t refs_len);
|
|
||||||
|
|
||||||
bool amduat_asl_collection_snapshot_payload_decode_v1(
|
|
||||||
amduat_octets_t payload,
|
|
||||||
amduat_asl_collection_snapshot_payload_t *out_snapshot);
|
|
||||||
|
|
||||||
void amduat_asl_collection_snapshot_payload_free(
|
|
||||||
amduat_asl_collection_snapshot_payload_t *snapshot);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_COLLECTION_H */
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_COLLECTION_VIEW_H
|
|
||||||
#define AMDUAT_ASL_COLLECTION_VIEW_H
|
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { TYPE_TAG_ASL_COLLECTION_VIEW_1 = 0x00000403u };
|
|
||||||
enum { AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1 = TYPE_TAG_ASL_COLLECTION_VIEW_1 };
|
|
||||||
enum { TYPE_TAG_ASL_SNAPSHOT_INFO_1 = 0x00000405u };
|
|
||||||
enum { AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1 = TYPE_TAG_ASL_SNAPSHOT_INFO_1 };
|
|
||||||
enum { TYPE_TAG_ASL_LOG_RANGE_1 = 0x00000406u };
|
|
||||||
enum { AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1 = TYPE_TAG_ASL_LOG_RANGE_1 };
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t snapshot_at_offset;
|
|
||||||
amduat_reference_t *refs;
|
|
||||||
size_t refs_len;
|
|
||||||
} amduat_asl_collection_snapshot_info_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t start_offset;
|
|
||||||
uint64_t next_offset;
|
|
||||||
amduat_reference_t *refs;
|
|
||||||
size_t refs_len;
|
|
||||||
} amduat_asl_log_range_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t computed_from_offset;
|
|
||||||
uint64_t computed_up_to_offset;
|
|
||||||
amduat_reference_t *refs;
|
|
||||||
size_t refs_len;
|
|
||||||
} amduat_asl_collection_view_t;
|
|
||||||
|
|
||||||
bool amduat_asl_collection_snapshot_info_encode_v1(
|
|
||||||
const amduat_asl_collection_snapshot_info_t *info,
|
|
||||||
amduat_octets_t *out_bytes);
|
|
||||||
|
|
||||||
bool amduat_asl_collection_snapshot_info_decode_v1(
|
|
||||||
amduat_octets_t bytes,
|
|
||||||
amduat_asl_collection_snapshot_info_t *out_info);
|
|
||||||
|
|
||||||
void amduat_asl_collection_snapshot_info_free(
|
|
||||||
amduat_asl_collection_snapshot_info_t *info);
|
|
||||||
|
|
||||||
bool amduat_asl_log_range_encode_v1(const amduat_asl_log_range_t *range,
|
|
||||||
amduat_octets_t *out_bytes);
|
|
||||||
|
|
||||||
bool amduat_asl_log_range_decode_v1(amduat_octets_t bytes,
|
|
||||||
amduat_asl_log_range_t *out_range);
|
|
||||||
|
|
||||||
void amduat_asl_log_range_free(amduat_asl_log_range_t *range);
|
|
||||||
|
|
||||||
bool amduat_asl_collection_view_encode_v1(
|
|
||||||
const amduat_asl_collection_view_t *view,
|
|
||||||
amduat_octets_t *out_bytes);
|
|
||||||
|
|
||||||
bool amduat_asl_collection_view_decode_v1(
|
|
||||||
amduat_octets_t bytes,
|
|
||||||
amduat_asl_collection_view_t *out_view);
|
|
||||||
|
|
||||||
void amduat_asl_collection_view_free(amduat_asl_collection_view_t *view);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_COLLECTION_VIEW_H */
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_LOG_STORE_H
|
|
||||||
#define AMDUAT_ASL_LOG_STORE_H
|
|
||||||
|
|
||||||
#include "amduat/asl/asl_pointer_fs.h"
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
#include "amduat/asl/store.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { TYPE_TAG_ASL_LOG_CHUNK_1 = 0x00000401u };
|
|
||||||
enum { AMDUAT_TYPE_TAG_ASL_LOG_CHUNK_1 = TYPE_TAG_ASL_LOG_CHUNK_1 };
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t kind;
|
|
||||||
bool has_timestamp;
|
|
||||||
uint64_t timestamp;
|
|
||||||
amduat_reference_t payload_ref;
|
|
||||||
bool has_actor;
|
|
||||||
amduat_octets_t actor;
|
|
||||||
} amduat_asl_log_entry_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool has_prev;
|
|
||||||
amduat_reference_t prev_ref;
|
|
||||||
uint64_t base_offset;
|
|
||||||
uint32_t entry_count;
|
|
||||||
bool has_timestamp;
|
|
||||||
bool has_actor;
|
|
||||||
amduat_asl_log_entry_t *entries;
|
|
||||||
} amduat_asl_log_chunk_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
amduat_asl_store_t *store;
|
|
||||||
amduat_asl_pointer_store_t pointer_store;
|
|
||||||
} amduat_asl_log_store_t;
|
|
||||||
|
|
||||||
bool amduat_asl_log_store_init(amduat_asl_log_store_t *log_store,
|
|
||||||
const char *root_path,
|
|
||||||
amduat_asl_store_t *store,
|
|
||||||
const amduat_asl_pointer_store_t *pointer_store);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_log_append(
|
|
||||||
amduat_asl_log_store_t *log_store,
|
|
||||||
const char *log_name,
|
|
||||||
const amduat_asl_log_entry_t *entries,
|
|
||||||
size_t entries_len,
|
|
||||||
uint64_t *out_first_offset);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_log_read(
|
|
||||||
amduat_asl_log_store_t *log_store,
|
|
||||||
const char *log_name,
|
|
||||||
uint64_t from_offset,
|
|
||||||
size_t max_entries,
|
|
||||||
amduat_asl_log_entry_t **out_entries,
|
|
||||||
size_t *out_len,
|
|
||||||
uint64_t *out_next_offset,
|
|
||||||
bool *out_end);
|
|
||||||
|
|
||||||
void amduat_asl_log_entries_free(amduat_asl_log_entry_t *entries,
|
|
||||||
size_t entries_len);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_log_chunk_decode_v1(
|
|
||||||
amduat_octets_t bytes,
|
|
||||||
amduat_asl_log_chunk_t *out_chunk);
|
|
||||||
|
|
||||||
void amduat_asl_log_chunk_free(amduat_asl_log_chunk_t *chunk);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_LOG_STORE_H */
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_NONE_H
|
|
||||||
#define AMDUAT_ASL_NONE_H
|
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { TYPE_TAG_ASL_NONE_1 = 0x00000404u };
|
|
||||||
enum { AMDUAT_TYPE_TAG_ASL_NONE_1 = TYPE_TAG_ASL_NONE_1 };
|
|
||||||
|
|
||||||
bool amduat_asl_none_encode_v1(amduat_octets_t *out_bytes);
|
|
||||||
|
|
||||||
bool amduat_asl_none_decode_v1(amduat_octets_t bytes);
|
|
||||||
|
|
||||||
bool amduat_asl_none_is_artifact(const amduat_artifact_t *artifact);
|
|
||||||
|
|
||||||
bool amduat_asl_none_artifact(amduat_artifact_t *out_artifact);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_NONE_H */
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
#ifndef AMDUAT_ASL_RECORD_H
|
|
||||||
#define AMDUAT_ASL_RECORD_H
|
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
#include "amduat/asl/store.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum { TYPE_TAG_ASL_RECORD_1 = 0x00000402u };
|
|
||||||
enum { AMDUAT_TYPE_TAG_ASL_RECORD_1 = TYPE_TAG_ASL_RECORD_1 };
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
amduat_octets_t schema;
|
|
||||||
amduat_octets_t payload;
|
|
||||||
} amduat_asl_record_t;
|
|
||||||
|
|
||||||
bool amduat_asl_record_encode_v1(const amduat_asl_record_t *record,
|
|
||||||
amduat_octets_t *out_bytes);
|
|
||||||
|
|
||||||
bool amduat_asl_record_decode_v1(amduat_octets_t bytes,
|
|
||||||
amduat_asl_record_t *out_record);
|
|
||||||
|
|
||||||
void amduat_asl_record_free(amduat_asl_record_t *record);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_record_store_put(
|
|
||||||
amduat_asl_store_t *store,
|
|
||||||
amduat_octets_t schema,
|
|
||||||
amduat_octets_t payload,
|
|
||||||
amduat_reference_t *out_ref);
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_record_store_get(
|
|
||||||
amduat_asl_store_t *store,
|
|
||||||
amduat_reference_t ref,
|
|
||||||
amduat_asl_record_t *out_record);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_RECORD_H */
|
|
||||||
|
|
@ -38,14 +38,6 @@ bool amduat_enc_asl_log_decode_v1(amduat_octets_t bytes,
|
||||||
void amduat_enc_asl_log_free(amduat_asl_log_record_t *records,
|
void amduat_enc_asl_log_free(amduat_asl_log_record_t *records,
|
||||||
size_t record_count);
|
size_t record_count);
|
||||||
|
|
||||||
/* Caller owns out_ref digest; free with amduat_reference_free. */
|
|
||||||
bool amduat_asl_log_decode_artifact_ref(amduat_octets_t payload,
|
|
||||||
amduat_reference_t *out_ref);
|
|
||||||
|
|
||||||
/* Caller owns out_bytes; free with amduat_octets_free. */
|
|
||||||
bool amduat_asl_log_encode_artifact_ref(amduat_reference_t ref,
|
|
||||||
amduat_octets_t *out_bytes);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef AMDUAT_PEL_DERIVATION_SID_H
|
|
||||||
#define AMDUAT_PEL_DERIVATION_SID_H
|
|
||||||
|
|
||||||
#include "amduat/asl/core.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
amduat_reference_t program_ref;
|
|
||||||
const amduat_reference_t *input_refs;
|
|
||||||
size_t input_refs_len;
|
|
||||||
bool has_params_ref;
|
|
||||||
amduat_reference_t params_ref;
|
|
||||||
bool has_exec_profile;
|
|
||||||
amduat_octets_t exec_profile;
|
|
||||||
} amduat_pel_derivation_sid_input_t;
|
|
||||||
|
|
||||||
bool amduat_pel_derivation_sid_compute(
|
|
||||||
const amduat_pel_derivation_sid_input_t *in,
|
|
||||||
amduat_octets_t *out_sid);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_PEL_DERIVATION_SID_H */
|
|
||||||
|
|
@ -17,11 +17,6 @@ extern "C" {
|
||||||
#define AMDUAT_PEL_KERNEL_OP_HASH_ASL1_NAME "pel.bytes.hash.asl1"
|
#define AMDUAT_PEL_KERNEL_OP_HASH_ASL1_NAME "pel.bytes.hash.asl1"
|
||||||
#define AMDUAT_PEL_KERNEL_OP_PARAMS_NAME "pel.bytes.params"
|
#define AMDUAT_PEL_KERNEL_OP_PARAMS_NAME "pel.bytes.params"
|
||||||
#define AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME "pel.format.encode"
|
#define AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME "pel.format.encode"
|
||||||
#define AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME \
|
|
||||||
"collection.snapshot_decode_v1"
|
|
||||||
#define AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME "log.read_range_v1"
|
|
||||||
#define AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME \
|
|
||||||
"collection.merge_refs_v1"
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_CONCAT = 0x0001u,
|
AMDUAT_PEL_KERNEL_OP_CODE_CONCAT = 0x0001u,
|
||||||
|
|
@ -29,10 +24,7 @@ enum {
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_CONST = 0x0003u,
|
AMDUAT_PEL_KERNEL_OP_CODE_CONST = 0x0003u,
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_HASH_ASL1 = 0x0004u,
|
AMDUAT_PEL_KERNEL_OP_CODE_HASH_ASL1 = 0x0004u,
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_PARAMS = 0x0005u,
|
AMDUAT_PEL_KERNEL_OP_CODE_PARAMS = 0x0005u,
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_FORMAT_ENCODE = 0x0006u,
|
AMDUAT_PEL_KERNEL_OP_CODE_FORMAT_ENCODE = 0x0006u
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_SNAPSHOT_DECODE = 0x0007u,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_LOG_READ_RANGE = 0x0008u,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_MERGE_REFS = 0x0009u
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -43,13 +35,7 @@ enum {
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_SCHEMA_INVALID = 0x00030001u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_SCHEMA_INVALID = 0x00030001u,
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_REGISTRY_INVALID = 0x00030002u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_REGISTRY_INVALID = 0x00030002u,
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_MISSING_FIELD = 0x00030003u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_MISSING_FIELD = 0x00030003u,
|
||||||
AMDUAT_PEL_KERNEL_STATUS_FORMAT_TYPE_UNSUPPORTED = 0x00030004u,
|
AMDUAT_PEL_KERNEL_STATUS_FORMAT_TYPE_UNSUPPORTED = 0x00030004u
|
||||||
AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID = 0x00040001u,
|
|
||||||
AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID = 0x00040002u,
|
|
||||||
AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID = 0x00040003u,
|
|
||||||
AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID = 0x00040004u,
|
|
||||||
AMDUAT_PEL_KERNEL_STATUS_COLLECTION_VIEW_INVALID = 0x00040005u,
|
|
||||||
AMDUAT_PEL_KERNEL_STATUS_REF_RESOLVE_FAILED = 0x00040006u
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|
@ -58,10 +44,7 @@ typedef enum {
|
||||||
AMDUAT_PEL_KERNEL_OP_CONST = 3,
|
AMDUAT_PEL_KERNEL_OP_CONST = 3,
|
||||||
AMDUAT_PEL_KERNEL_OP_HASH_ASL1 = 4,
|
AMDUAT_PEL_KERNEL_OP_HASH_ASL1 = 4,
|
||||||
AMDUAT_PEL_KERNEL_OP_PARAMS = 5,
|
AMDUAT_PEL_KERNEL_OP_PARAMS = 5,
|
||||||
AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE = 6,
|
AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE = 6
|
||||||
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE = 7,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE = 8,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS = 9
|
|
||||||
} amduat_pel_kernel_op_kind_t;
|
} amduat_pel_kernel_op_kind_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -75,11 +58,6 @@ typedef struct {
|
||||||
struct amduat_pel_kernel_params;
|
struct amduat_pel_kernel_params;
|
||||||
typedef struct amduat_pel_kernel_params amduat_pel_kernel_params_t;
|
typedef struct amduat_pel_kernel_params amduat_pel_kernel_params_t;
|
||||||
|
|
||||||
typedef bool (*amduat_pel_kernel_artifact_resolver_t)(
|
|
||||||
amduat_reference_t ref,
|
|
||||||
amduat_artifact_t *out_artifact,
|
|
||||||
void *ctx);
|
|
||||||
|
|
||||||
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
||||||
amduat_octets_t name,
|
amduat_octets_t name,
|
||||||
uint32_t version);
|
uint32_t version);
|
||||||
|
|
@ -89,15 +67,6 @@ const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_descs(
|
||||||
|
|
||||||
const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind);
|
const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind);
|
||||||
|
|
||||||
void amduat_pel_kernel_set_artifact_resolver(
|
|
||||||
amduat_pel_kernel_artifact_resolver_t resolver,
|
|
||||||
void *ctx);
|
|
||||||
|
|
||||||
void amduat_pel_kernel_clear_artifact_resolver(void);
|
|
||||||
|
|
||||||
bool amduat_pel_kernel_resolve_artifact(amduat_reference_t ref,
|
|
||||||
amduat_artifact_t *out_artifact);
|
|
||||||
|
|
||||||
bool amduat_pel_kernel_op_eval(
|
bool amduat_pel_kernel_op_eval(
|
||||||
const amduat_pel_kernel_op_desc_t *desc,
|
const amduat_pel_kernel_op_desc_t *desc,
|
||||||
const amduat_artifact_t *inputs,
|
const amduat_artifact_t *inputs,
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#ifndef AMDUAT_UTIL_LOG_H
|
|
||||||
#define AMDUAT_UTIL_LOG_H
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AMDUAT_LOG_ERROR = 0,
|
|
||||||
AMDUAT_LOG_WARN = 1,
|
|
||||||
AMDUAT_LOG_INFO = 2,
|
|
||||||
AMDUAT_LOG_DEBUG = 3
|
|
||||||
} amduat_log_level_t;
|
|
||||||
|
|
||||||
void amduat_log(amduat_log_level_t level, const char *fmt, ...);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* AMDUAT_UTIL_LOG_H */
|
|
||||||
|
|
@ -1,716 +0,0 @@
|
||||||
#include "amduat/asl/asl_materialization_cache_fs.h"
|
|
||||||
|
|
||||||
#include "amduat/enc/asl1_core_codec.h"
|
|
||||||
#include "amduat/util/log.h"
|
|
||||||
#include "amduat/util/hex.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_VERSION = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_materialization_magic[
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN] = {'A', 'S', 'L', 'M',
|
|
||||||
'A', 'T', '1', '\0'};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_FLAG_TIMESTAMP = 1u << 0,
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_FLAG_PEL_VERSION = 1u << 1
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const uint8_t *data;
|
|
||||||
size_t len;
|
|
||||||
size_t offset;
|
|
||||||
} amduat_asl_materialization_cursor_t;
|
|
||||||
|
|
||||||
static void amduat_asl_materialization_store_u32_le(uint8_t *out,
|
|
||||||
uint32_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_read_u32_le(
|
|
||||||
amduat_asl_materialization_cursor_t *cur,
|
|
||||||
uint32_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (cur->len - cur->offset < 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = cur->data + cur->offset;
|
|
||||||
*out = (uint32_t)data[0] | ((uint32_t)data[1] << 8) |
|
|
||||||
((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
|
|
||||||
cur->offset += 4u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_read_u64_le(
|
|
||||||
amduat_asl_materialization_cursor_t *cur,
|
|
||||||
uint64_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (cur->len - cur->offset < 8u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = cur->data + cur->offset;
|
|
||||||
*out = (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);
|
|
||||||
cur->offset += 8u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_read_u16_le(
|
|
||||||
amduat_asl_materialization_cursor_t *cur,
|
|
||||||
uint16_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (cur->len - cur->offset < 2u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = cur->data + cur->offset;
|
|
||||||
*out = (uint16_t)data[0] | ((uint16_t)data[1] << 8);
|
|
||||||
cur->offset += 2u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_read_u8(
|
|
||||||
amduat_asl_materialization_cursor_t *cur,
|
|
||||||
uint8_t *out) {
|
|
||||||
if (cur->len - cur->offset < 1u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = cur->data[cur->offset++];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_join_path(const char *base,
|
|
||||||
const char *segment,
|
|
||||||
char **out_path) {
|
|
||||||
size_t base_len;
|
|
||||||
size_t segment_len;
|
|
||||||
bool needs_sep;
|
|
||||||
size_t total_len;
|
|
||||||
char *buffer;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
if (base == NULL || segment == NULL || out_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (base[0] == '\0' || segment[0] == '\0') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
base_len = strlen(base);
|
|
||||||
segment_len = strlen(segment);
|
|
||||||
needs_sep = base[base_len - 1u] != '/';
|
|
||||||
total_len = base_len + (needs_sep ? 1u : 0u) + segment_len + 1u;
|
|
||||||
|
|
||||||
buffer = (char *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = 0u;
|
|
||||||
memcpy(buffer + offset, base, base_len);
|
|
||||||
offset += base_len;
|
|
||||||
if (needs_sep) {
|
|
||||||
buffer[offset++] = '/';
|
|
||||||
}
|
|
||||||
memcpy(buffer + offset, segment, segment_len);
|
|
||||||
offset += segment_len;
|
|
||||||
buffer[offset] = '\0';
|
|
||||||
|
|
||||||
*out_path = buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_ensure_directory(const char *path) {
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (path == NULL || path[0] == '\0') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (stat(path, &st) == 0) {
|
|
||||||
return S_ISDIR(st.st_mode);
|
|
||||||
}
|
|
||||||
if (errno != ENOENT) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mkdir(path, 0755) != 0) {
|
|
||||||
if (errno == EEXIST) {
|
|
||||||
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_hex_byte(uint8_t value, char out[3]) {
|
|
||||||
static const char k_hex[] = "0123456789abcdef";
|
|
||||||
out[0] = k_hex[value >> 4u];
|
|
||||||
out[1] = k_hex[value & 0x0fu];
|
|
||||||
out[2] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *amduat_asl_materialization_parent_dir(const char *path) {
|
|
||||||
const char *slash;
|
|
||||||
size_t len;
|
|
||||||
char *dir;
|
|
||||||
|
|
||||||
if (path == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
slash = strrchr(path, '/');
|
|
||||||
if (slash == NULL || slash == path) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
len = (size_t)(slash - path);
|
|
||||||
dir = (char *)malloc(len + 1u);
|
|
||||||
if (dir == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(dir, path, len);
|
|
||||||
dir[len] = '\0';
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_fsync_directory(const char *path) {
|
|
||||||
int fd;
|
|
||||||
int flags = O_RDONLY;
|
|
||||||
|
|
||||||
if (path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef O_DIRECTORY
|
|
||||||
flags |= O_DIRECTORY;
|
|
||||||
#endif
|
|
||||||
fd = open(path, flags);
|
|
||||||
if (fd < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fsync(fd) != 0) {
|
|
||||||
close(fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return close(fd) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_build_sid_path(
|
|
||||||
const char *root_path,
|
|
||||||
amduat_octets_t sid,
|
|
||||||
bool ensure_dirs,
|
|
||||||
char **out_path) {
|
|
||||||
char *index_path = NULL;
|
|
||||||
char *materializations_path = NULL;
|
|
||||||
char *by_sid_path = NULL;
|
|
||||||
char *prefix_a_path = NULL;
|
|
||||||
char *prefix_b_path = NULL;
|
|
||||||
char *sid_hex = NULL;
|
|
||||||
char prefix_a[3];
|
|
||||||
char prefix_b[3];
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
if (root_path == NULL || out_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_path = NULL;
|
|
||||||
|
|
||||||
if (sid.len < 2u || sid.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_hex_encode_alloc(sid.data, sid.len, &sid_hex)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
amduat_asl_materialization_hex_byte(sid.data[0], prefix_a);
|
|
||||||
amduat_asl_materialization_hex_byte(sid.data[1], prefix_b);
|
|
||||||
|
|
||||||
if (!amduat_asl_materialization_join_path(root_path, "index", &index_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_materialization_join_path(index_path, "materializations",
|
|
||||||
&materializations_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_materialization_join_path(materializations_path, "by_sid",
|
|
||||||
&by_sid_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_materialization_join_path(by_sid_path, prefix_a,
|
|
||||||
&prefix_a_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_materialization_join_path(prefix_a_path, prefix_b,
|
|
||||||
&prefix_b_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_materialization_join_path(prefix_b_path, sid_hex,
|
|
||||||
out_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ensure_dirs) {
|
|
||||||
if (!amduat_asl_materialization_ensure_directory(index_path) ||
|
|
||||||
!amduat_asl_materialization_ensure_directory(materializations_path) ||
|
|
||||||
!amduat_asl_materialization_ensure_directory(by_sid_path) ||
|
|
||||||
!amduat_asl_materialization_ensure_directory(prefix_a_path) ||
|
|
||||||
!amduat_asl_materialization_ensure_directory(prefix_b_path)) {
|
|
||||||
free(*out_path);
|
|
||||||
*out_path = NULL;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = true;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
free(index_path);
|
|
||||||
free(materializations_path);
|
|
||||||
free(by_sid_path);
|
|
||||||
free(prefix_a_path);
|
|
||||||
free(prefix_b_path);
|
|
||||||
free(sid_hex);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_materialization_cache_fs_init(
|
|
||||||
amduat_asl_materialization_cache_fs_t *cache,
|
|
||||||
const char *root_path) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (cache == NULL || root_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
len = strlen(root_path);
|
|
||||||
if (len == 0u || len >= AMDUAT_ASL_MATERIALIZATION_CACHE_FS_ROOT_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(cache->root_path, root_path, len);
|
|
||||||
cache->root_path[len] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_materialization_decode_refs(
|
|
||||||
amduat_asl_materialization_cursor_t *cur,
|
|
||||||
uint32_t count,
|
|
||||||
amduat_reference_t **out_refs,
|
|
||||||
size_t *out_refs_len) {
|
|
||||||
amduat_reference_t *refs;
|
|
||||||
uint32_t i;
|
|
||||||
|
|
||||||
if (out_refs == NULL || out_refs_len == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
*out_refs = NULL;
|
|
||||||
*out_refs_len = 0u;
|
|
||||||
|
|
||||||
if (count == 0u) {
|
|
||||||
return AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
if (count > SIZE_MAX / sizeof(*refs)) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
refs = (amduat_reference_t *)calloc(count, sizeof(*refs));
|
|
||||||
if (refs == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0u; i < count; ++i) {
|
|
||||||
uint32_t ref_len;
|
|
||||||
amduat_octets_t ref_bytes;
|
|
||||||
|
|
||||||
if (!amduat_asl_materialization_read_u32_le(cur, &ref_len)) {
|
|
||||||
goto decode_error;
|
|
||||||
}
|
|
||||||
if (ref_len < 2u || cur->len - cur->offset < ref_len) {
|
|
||||||
goto decode_error;
|
|
||||||
}
|
|
||||||
ref_bytes = amduat_octets(cur->data + cur->offset, ref_len);
|
|
||||||
if (!amduat_enc_asl1_core_decode_reference_v1(ref_bytes, &refs[i])) {
|
|
||||||
goto decode_error;
|
|
||||||
}
|
|
||||||
cur->offset += ref_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_refs = refs;
|
|
||||||
*out_refs_len = count;
|
|
||||||
return AMDUAT_ASL_STORE_OK;
|
|
||||||
|
|
||||||
decode_error:
|
|
||||||
for (uint32_t j = 0u; j < i; ++j) {
|
|
||||||
amduat_reference_free(&refs[j]);
|
|
||||||
}
|
|
||||||
free(refs);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_asl_materialization_refs_free(amduat_reference_t *refs,
|
|
||||||
size_t refs_len) {
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (refs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_reference_free(&refs[i]);
|
|
||||||
}
|
|
||||||
free(refs);
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_materialization_cache_fs_get(
|
|
||||||
amduat_asl_materialization_cache_fs_t *cache,
|
|
||||||
amduat_octets_t sid,
|
|
||||||
amduat_reference_t **out_refs,
|
|
||||||
size_t *out_refs_len) {
|
|
||||||
char *path = NULL;
|
|
||||||
FILE *fp = NULL;
|
|
||||||
uint8_t *buffer = NULL;
|
|
||||||
long file_size;
|
|
||||||
amduat_asl_materialization_cursor_t cur;
|
|
||||||
uint8_t flags;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t sid_len;
|
|
||||||
uint32_t output_count;
|
|
||||||
amduat_asl_store_error_t err = AMDUAT_ASL_STORE_ERR_NOT_FOUND;
|
|
||||||
|
|
||||||
if (out_refs == NULL || out_refs_len == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
*out_refs = NULL;
|
|
||||||
*out_refs_len = 0u;
|
|
||||||
|
|
||||||
if (cache == NULL || sid.len == 0u || sid.data == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_materialization_build_sid_path(cache->root_path, sid, false,
|
|
||||||
&path)) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fopen(path, "rb");
|
|
||||||
if (fp == NULL) {
|
|
||||||
free(path);
|
|
||||||
return errno == ENOENT ? AMDUAT_ASL_STORE_ERR_NOT_FOUND
|
|
||||||
: AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
|
||||||
fclose(fp);
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
file_size = ftell(fp);
|
|
||||||
if (file_size < 0) {
|
|
||||||
fclose(fp);
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fseek(fp, 0, SEEK_SET) != 0) {
|
|
||||||
fclose(fp);
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc((size_t)file_size);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
fclose(fp);
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fread(buffer, 1u, (size_t)file_size, fp) != (size_t)file_size) {
|
|
||||||
free(buffer);
|
|
||||||
fclose(fp);
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
free(path);
|
|
||||||
|
|
||||||
cur.data = buffer;
|
|
||||||
cur.len = (size_t)file_size;
|
|
||||||
cur.offset = 0u;
|
|
||||||
|
|
||||||
if (cur.len < AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN + 4u) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (memcmp(cur.data, k_amduat_asl_materialization_magic,
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN) != 0) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
cur.offset += AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_materialization_read_u32_le(&cur, &version) ||
|
|
||||||
version != AMDUAT_ASL_MATERIALIZATION_VERSION) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_materialization_read_u32_le(&cur, &sid_len)) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (sid_len != sid.len || cur.len - cur.offset < sid_len) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (memcmp(cur.data + cur.offset, sid.data, sid.len) != 0) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
cur.offset += sid_len;
|
|
||||||
if (!amduat_asl_materialization_read_u32_le(&cur, &output_count)) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = amduat_asl_materialization_decode_refs(&cur, output_count, out_refs,
|
|
||||||
out_refs_len);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_materialization_read_u8(&cur, &flags)) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (flags & AMDUAT_ASL_MATERIALIZATION_FLAG_TIMESTAMP) {
|
|
||||||
uint64_t ignored;
|
|
||||||
if (!amduat_asl_materialization_read_u64_le(&cur, &ignored)) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flags & AMDUAT_ASL_MATERIALIZATION_FLAG_PEL_VERSION) {
|
|
||||||
uint16_t ignored;
|
|
||||||
if (!amduat_asl_materialization_read_u16_le(&cur, &ignored)) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur.offset != cur.len) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = AMDUAT_ASL_STORE_OK;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
amduat_asl_materialization_refs_free(*out_refs, *out_refs_len);
|
|
||||||
*out_refs = NULL;
|
|
||||||
*out_refs_len = 0u;
|
|
||||||
}
|
|
||||||
free(buffer);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_materialization_refs_equal(
|
|
||||||
const amduat_reference_t *a,
|
|
||||||
size_t a_len,
|
|
||||||
const amduat_reference_t *b,
|
|
||||||
size_t b_len) {
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (a_len != b_len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (i = 0; i < a_len; ++i) {
|
|
||||||
if (!amduat_reference_eq(a[i], b[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_materialization_write_record(
|
|
||||||
FILE *fp,
|
|
||||||
amduat_octets_t sid,
|
|
||||||
const amduat_reference_t *refs,
|
|
||||||
size_t refs_len) {
|
|
||||||
uint8_t header[AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN + 4u];
|
|
||||||
uint8_t flags = 0u;
|
|
||||||
uint32_t count_u32;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (sid.len > UINT32_MAX || refs_len > UINT32_MAX) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(header, k_amduat_asl_materialization_magic,
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN);
|
|
||||||
amduat_asl_materialization_store_u32_le(
|
|
||||||
header + AMDUAT_ASL_MATERIALIZATION_MAGIC_LEN,
|
|
||||||
AMDUAT_ASL_MATERIALIZATION_VERSION);
|
|
||||||
if (fwrite(header, 1u, sizeof(header), fp) != sizeof(header)) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_materialization_store_u32_le(header, (uint32_t)sid.len);
|
|
||||||
if (fwrite(header, 1u, 4u, fp) != 4u) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (sid.len != 0u &&
|
|
||||||
fwrite(sid.data, 1u, sid.len, fp) != sid.len) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
count_u32 = (uint32_t)refs_len;
|
|
||||||
amduat_asl_materialization_store_u32_le(header, count_u32);
|
|
||||||
if (fwrite(header, 1u, 4u, fp) != 4u) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
uint8_t len_buf[4u];
|
|
||||||
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
amduat_asl_materialization_store_u32_le(len_buf,
|
|
||||||
(uint32_t)ref_bytes.len);
|
|
||||||
if (fwrite(len_buf, 1u, 4u, fp) != 4u ||
|
|
||||||
(ref_bytes.len != 0u &&
|
|
||||||
fwrite(ref_bytes.data, 1u, ref_bytes.len, fp) != ref_bytes.len)) {
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fwrite(&flags, 1u, 1u, fp) != 1u) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_materialization_cache_fs_put(
|
|
||||||
amduat_asl_materialization_cache_fs_t *cache,
|
|
||||||
amduat_octets_t sid,
|
|
||||||
const amduat_reference_t *refs,
|
|
||||||
size_t refs_len) {
|
|
||||||
amduat_reference_t *existing_refs = NULL;
|
|
||||||
size_t existing_len = 0u;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
char *path = NULL;
|
|
||||||
char *tmp_path = NULL;
|
|
||||||
FILE *fp = NULL;
|
|
||||||
size_t tmp_len;
|
|
||||||
|
|
||||||
if (cache == NULL || sid.len == 0u || sid.data == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (refs_len != 0u && refs == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = amduat_asl_materialization_cache_fs_get(cache, sid,
|
|
||||||
&existing_refs, &existing_len);
|
|
||||||
if (err == AMDUAT_ASL_STORE_OK) {
|
|
||||||
bool same = amduat_asl_materialization_refs_equal(
|
|
||||||
existing_refs, existing_len, refs, refs_len);
|
|
||||||
amduat_asl_materialization_refs_free(existing_refs, existing_len);
|
|
||||||
if (!same) {
|
|
||||||
amduat_log(AMDUAT_LOG_ERROR,
|
|
||||||
"materialization cache SID collision with mismatched outputs");
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
return AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
if (err != AMDUAT_ASL_STORE_ERR_NOT_FOUND) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_materialization_build_sid_path(cache->root_path, sid, true,
|
|
||||||
&path)) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp_len = strlen(path) + 5u;
|
|
||||||
tmp_path = (char *)malloc(tmp_len);
|
|
||||||
if (tmp_path == NULL) {
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
snprintf(tmp_path, tmp_len, "%s.tmp", path);
|
|
||||||
|
|
||||||
fp = fopen(tmp_path, "wb");
|
|
||||||
if (fp == NULL) {
|
|
||||||
free(tmp_path);
|
|
||||||
free(path);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Crash consistency: write + fsync temp file, rename, then fsync parent
|
|
||||||
* directory. Failure only affects cache persistence, not correctness.
|
|
||||||
*/
|
|
||||||
err = amduat_asl_materialization_write_record(fp, sid, refs, refs_len);
|
|
||||||
if (fflush(fp) != 0) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_STORE_OK && fsync(fileno(fp)) != 0) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fclose(fp) != 0) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
fp = NULL;
|
|
||||||
|
|
||||||
if (err == AMDUAT_ASL_STORE_OK && rename(tmp_path, path) != 0) {
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_STORE_OK) {
|
|
||||||
char *parent_dir = amduat_asl_materialization_parent_dir(path);
|
|
||||||
if (parent_dir != NULL) {
|
|
||||||
if (!amduat_asl_materialization_fsync_directory(parent_dir)) {
|
|
||||||
amduat_log(AMDUAT_LOG_WARN,
|
|
||||||
"materialization cache fsync dir failed for %s",
|
|
||||||
parent_dir);
|
|
||||||
err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
free(parent_dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
(void)remove(tmp_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (err == AMDUAT_ASL_STORE_OK) {
|
|
||||||
amduat_reference_t *check_refs = NULL;
|
|
||||||
size_t check_len = 0u;
|
|
||||||
amduat_asl_store_error_t check_err =
|
|
||||||
amduat_asl_materialization_cache_fs_get(cache, sid, &check_refs,
|
|
||||||
&check_len);
|
|
||||||
assert(check_err == AMDUAT_ASL_STORE_OK);
|
|
||||||
assert(amduat_asl_materialization_refs_equal(
|
|
||||||
check_refs, check_len, refs, refs_len));
|
|
||||||
amduat_asl_materialization_refs_free(check_refs, check_len);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
free(tmp_path);
|
|
||||||
free(path);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
@ -1,753 +0,0 @@
|
||||||
#include "amduat/asl/asl_pointer_fs.h"
|
|
||||||
|
|
||||||
#include "amduat/enc/asl1_core_codec.h"
|
|
||||||
#include "amduat/util/log.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_POINTER_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_POINTER_VERSION = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_pointer_magic[AMDUAT_ASL_POINTER_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'P', 'T', 'R', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
enum { AMDUAT_ASL_POINTER_FLAG_HAS_EXPECTED = 1u << 0,
|
|
||||||
AMDUAT_ASL_POINTER_FLAG_HAS_PREV = 1u << 1 };
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const uint8_t *data;
|
|
||||||
size_t len;
|
|
||||||
size_t offset;
|
|
||||||
} amduat_asl_pointer_cursor_t;
|
|
||||||
|
|
||||||
static void amduat_asl_pointer_store_u32_le(uint8_t *out, uint32_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_pointer_read_u32_le(amduat_asl_pointer_cursor_t *cur,
|
|
||||||
uint32_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (cur->len - cur->offset < 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = cur->data + cur->offset;
|
|
||||||
*out = (uint32_t)data[0] | ((uint32_t)data[1] << 8) |
|
|
||||||
((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 24);
|
|
||||||
cur->offset += 4u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_pointer_read_u8(amduat_asl_pointer_cursor_t *cur,
|
|
||||||
uint8_t *out) {
|
|
||||||
if (cur->len - cur->offset < 1u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = cur->data[cur->offset++];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_pointer_join_path(const char *base,
|
|
||||||
const char *segment,
|
|
||||||
char **out_path) {
|
|
||||||
size_t base_len;
|
|
||||||
size_t segment_len;
|
|
||||||
bool needs_sep;
|
|
||||||
size_t total_len;
|
|
||||||
char *buffer;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
if (base == NULL || segment == NULL || out_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (base[0] == '\0' || segment[0] == '\0') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
base_len = strlen(base);
|
|
||||||
segment_len = strlen(segment);
|
|
||||||
needs_sep = base[base_len - 1u] != '/';
|
|
||||||
total_len = base_len + (needs_sep ? 1u : 0u) + segment_len + 1u;
|
|
||||||
|
|
||||||
buffer = (char *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = 0u;
|
|
||||||
memcpy(buffer + offset, base, base_len);
|
|
||||||
offset += base_len;
|
|
||||||
if (needs_sep) {
|
|
||||||
buffer[offset++] = '/';
|
|
||||||
}
|
|
||||||
memcpy(buffer + offset, segment, segment_len);
|
|
||||||
offset += segment_len;
|
|
||||||
buffer[offset] = '\0';
|
|
||||||
|
|
||||||
*out_path = buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_pointer_ensure_directory(const char *path) {
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (path == NULL || path[0] == '\0') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (stat(path, &st) == 0) {
|
|
||||||
return S_ISDIR(st.st_mode);
|
|
||||||
}
|
|
||||||
if (errno != ENOENT) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (mkdir(path, 0755) != 0) {
|
|
||||||
if (errno == EEXIST) {
|
|
||||||
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *amduat_asl_pointer_parent_dir(const char *path) {
|
|
||||||
const char *slash;
|
|
||||||
size_t len;
|
|
||||||
char *dir;
|
|
||||||
|
|
||||||
if (path == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
slash = strrchr(path, '/');
|
|
||||||
if (slash == NULL || slash == path) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
len = (size_t)(slash - path);
|
|
||||||
dir = (char *)malloc(len + 1u);
|
|
||||||
if (dir == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(dir, path, len);
|
|
||||||
dir[len] = '\0';
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_pointer_fsync_directory(const char *path) {
|
|
||||||
int fd;
|
|
||||||
int flags = O_RDONLY;
|
|
||||||
|
|
||||||
if (path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#ifdef O_DIRECTORY
|
|
||||||
flags |= O_DIRECTORY;
|
|
||||||
#endif
|
|
||||||
fd = open(path, flags);
|
|
||||||
if (fd < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fsync(fd) != 0) {
|
|
||||||
close(fd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return close(fd) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_pointer_name_is_valid(const char *name) {
|
|
||||||
size_t len;
|
|
||||||
size_t seg_start = 0u;
|
|
||||||
|
|
||||||
if (name == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
len = strlen(name);
|
|
||||||
if (len == 0u || len > AMDUAT_ASL_POINTER_NAME_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (name[0] == '/' || name[len - 1u] == '/') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0u; i < len; ++i) {
|
|
||||||
char c = name[i];
|
|
||||||
bool ok = (c >= 'A' && c <= 'Z') ||
|
|
||||||
(c >= 'a' && c <= 'z') ||
|
|
||||||
(c >= '0' && c <= '9') ||
|
|
||||||
c == '.' || c == '_' || c == '-' || c == '/';
|
|
||||||
if (!ok) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (c == '/') {
|
|
||||||
size_t seg_len = i - seg_start;
|
|
||||||
if (seg_len == 0u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (seg_len == 2u && name[seg_start] == '.' &&
|
|
||||||
name[seg_start + 1u] == '.') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
seg_start = i + 1u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
size_t seg_len = len - seg_start;
|
|
||||||
if (seg_len == 0u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (seg_len == 2u && name[seg_start] == '.' &&
|
|
||||||
name[seg_start + 1u] == '.') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_pointer_build_head_path(const char *root_path,
|
|
||||||
const char *name,
|
|
||||||
bool ensure_dirs,
|
|
||||||
char **out_path) {
|
|
||||||
char *pointers_path = NULL;
|
|
||||||
char *cursor_path = NULL;
|
|
||||||
char *head_path = NULL;
|
|
||||||
const char *segment_start;
|
|
||||||
const char *segment_end;
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
if (root_path == NULL || name == NULL || out_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_path = NULL;
|
|
||||||
|
|
||||||
if (!amduat_asl_pointer_join_path(root_path, "pointers", &pointers_path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ensure_dirs &&
|
|
||||||
!amduat_asl_pointer_ensure_directory(pointers_path)) {
|
|
||||||
free(pointers_path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor_path = pointers_path;
|
|
||||||
pointers_path = NULL;
|
|
||||||
|
|
||||||
segment_start = name;
|
|
||||||
while (*segment_start != '\0') {
|
|
||||||
segment_end = strchr(segment_start, '/');
|
|
||||||
if (segment_end == NULL) {
|
|
||||||
segment_end = segment_start + strlen(segment_start);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
size_t seg_len = (size_t)(segment_end - segment_start);
|
|
||||||
char *segment = (char *)malloc(seg_len + 1u);
|
|
||||||
char *next_path = NULL;
|
|
||||||
if (segment == NULL) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
memcpy(segment, segment_start, seg_len);
|
|
||||||
segment[seg_len] = '\0';
|
|
||||||
if (!amduat_asl_pointer_join_path(cursor_path, segment, &next_path)) {
|
|
||||||
free(segment);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
free(segment);
|
|
||||||
if (ensure_dirs &&
|
|
||||||
!amduat_asl_pointer_ensure_directory(next_path)) {
|
|
||||||
free(next_path);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
free(cursor_path);
|
|
||||||
cursor_path = next_path;
|
|
||||||
}
|
|
||||||
if (*segment_end == '\0') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
segment_start = segment_end + 1u;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_pointer_join_path(cursor_path, "head", &head_path)) {
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_path = head_path;
|
|
||||||
head_path = NULL;
|
|
||||||
ok = true;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
free(pointers_path);
|
|
||||||
free(cursor_path);
|
|
||||||
free(head_path);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_pointer_store_init(amduat_asl_pointer_store_t *ps,
|
|
||||||
const char *root_path) {
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (ps == NULL || root_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
len = strlen(root_path);
|
|
||||||
if (len == 0u || len >= AMDUAT_ASL_POINTER_FS_ROOT_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(ps->root_path, root_path, len);
|
|
||||||
ps->root_path[len] = '\0';
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static amduat_asl_pointer_error_t amduat_asl_pointer_read_head(
|
|
||||||
const char *path,
|
|
||||||
const char *name,
|
|
||||||
bool *out_exists,
|
|
||||||
amduat_reference_t *out_ref,
|
|
||||||
amduat_reference_t *out_prev_ref,
|
|
||||||
bool *out_has_prev) {
|
|
||||||
FILE *fp;
|
|
||||||
uint8_t *buffer;
|
|
||||||
long file_size;
|
|
||||||
amduat_asl_pointer_cursor_t cur;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t name_len;
|
|
||||||
uint32_t ref_len;
|
|
||||||
uint32_t prev_len;
|
|
||||||
uint8_t flags;
|
|
||||||
amduat_octets_t ref_bytes;
|
|
||||||
amduat_octets_t prev_bytes;
|
|
||||||
|
|
||||||
if (out_exists == NULL || out_ref == NULL) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
*out_exists = false;
|
|
||||||
memset(out_ref, 0, sizeof(*out_ref));
|
|
||||||
if (out_prev_ref != NULL) {
|
|
||||||
memset(out_prev_ref, 0, sizeof(*out_prev_ref));
|
|
||||||
}
|
|
||||||
if (out_has_prev != NULL) {
|
|
||||||
*out_has_prev = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fp = fopen(path, "rb");
|
|
||||||
if (fp == NULL) {
|
|
||||||
return errno == ENOENT ? AMDUAT_ASL_POINTER_ERR_NOT_FOUND
|
|
||||||
: AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fseek(fp, 0, SEEK_END) != 0) {
|
|
||||||
fclose(fp);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
file_size = ftell(fp);
|
|
||||||
if (file_size < 0) {
|
|
||||||
fclose(fp);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (file_size == 0) {
|
|
||||||
fclose(fp);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
if (fseek(fp, 0, SEEK_SET) != 0) {
|
|
||||||
fclose(fp);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc((size_t)file_size);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
fclose(fp);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fread(buffer, 1u, (size_t)file_size, fp) != (size_t)file_size) {
|
|
||||||
free(buffer);
|
|
||||||
fclose(fp);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
cur.data = buffer;
|
|
||||||
cur.len = (size_t)file_size;
|
|
||||||
cur.offset = 0u;
|
|
||||||
|
|
||||||
if (cur.len < AMDUAT_ASL_POINTER_MAGIC_LEN + 4u + 1u) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (memcmp(cur.data, k_amduat_asl_pointer_magic,
|
|
||||||
AMDUAT_ASL_POINTER_MAGIC_LEN) != 0) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
cur.offset += AMDUAT_ASL_POINTER_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_pointer_read_u32_le(&cur, &version) ||
|
|
||||||
version != AMDUAT_ASL_POINTER_VERSION) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_read_u8(&cur, &flags)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_read_u32_le(&cur, &name_len)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (cur.len - cur.offset < name_len) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (strlen(name) != name_len ||
|
|
||||||
memcmp(cur.data + cur.offset, name, name_len) != 0) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
cur.offset += name_len;
|
|
||||||
if (!amduat_asl_pointer_read_u32_le(&cur, &ref_len)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (cur.len - cur.offset < ref_len || ref_len < 2u) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
ref_bytes = amduat_octets(cur.data + cur.offset, ref_len);
|
|
||||||
if (!amduat_enc_asl1_core_decode_reference_v1(ref_bytes, out_ref)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
cur.offset += ref_len;
|
|
||||||
|
|
||||||
if (!amduat_asl_pointer_read_u32_le(&cur, &prev_len)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (prev_len != 0u) {
|
|
||||||
if (!(flags & AMDUAT_ASL_POINTER_FLAG_HAS_PREV)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (cur.len - cur.offset < prev_len || prev_len < 2u) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
prev_bytes = amduat_octets(cur.data + cur.offset, prev_len);
|
|
||||||
if (out_prev_ref != NULL &&
|
|
||||||
!amduat_enc_asl1_core_decode_reference_v1(prev_bytes, out_prev_ref)) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
cur.offset += prev_len;
|
|
||||||
if (out_has_prev != NULL) {
|
|
||||||
*out_has_prev = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur.offset != cur.len) {
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_exists = true;
|
|
||||||
free(buffer);
|
|
||||||
return AMDUAT_ASL_POINTER_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static amduat_asl_pointer_error_t amduat_asl_pointer_write_head(
|
|
||||||
const char *path,
|
|
||||||
const char *name,
|
|
||||||
const amduat_reference_t *ref,
|
|
||||||
const amduat_reference_t *prev_ref,
|
|
||||||
bool has_prev) {
|
|
||||||
char *tmp_path;
|
|
||||||
char *parent_dir = NULL;
|
|
||||||
size_t tmp_len;
|
|
||||||
int tmp_fd;
|
|
||||||
FILE *fp;
|
|
||||||
uint8_t header[AMDUAT_ASL_POINTER_MAGIC_LEN + 4u + 1u];
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
amduat_octets_t prev_bytes = amduat_octets(NULL, 0u);
|
|
||||||
uint32_t name_len;
|
|
||||||
uint32_t ref_len;
|
|
||||||
uint32_t prev_len;
|
|
||||||
uint8_t flags = 0u;
|
|
||||||
amduat_asl_pointer_error_t err = AMDUAT_ASL_POINTER_OK;
|
|
||||||
|
|
||||||
if (ref == NULL || name == NULL) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
name_len = (uint32_t)strlen(name);
|
|
||||||
if (!amduat_enc_asl1_core_encode_reference_v1(*ref, &ref_bytes)) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
ref_len = (uint32_t)ref_bytes.len;
|
|
||||||
|
|
||||||
if (has_prev) {
|
|
||||||
if (prev_ref == NULL ||
|
|
||||||
!amduat_enc_asl1_core_encode_reference_v1(*prev_ref, &prev_bytes)) {
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
prev_len = (uint32_t)prev_bytes.len;
|
|
||||||
flags |= AMDUAT_ASL_POINTER_FLAG_HAS_PREV;
|
|
||||||
} else {
|
|
||||||
prev_len = 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp_len = strlen(path) + sizeof(".tmp.XXXXXX");
|
|
||||||
tmp_path = (char *)malloc(tmp_len);
|
|
||||||
if (tmp_path == NULL) {
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
free((void *)prev_bytes.data);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
parent_dir = amduat_asl_pointer_parent_dir(path);
|
|
||||||
if (parent_dir == NULL || !amduat_asl_pointer_ensure_directory(parent_dir)) {
|
|
||||||
free(parent_dir);
|
|
||||||
free(tmp_path);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
free((void *)prev_bytes.data);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
snprintf(tmp_path, tmp_len, "%s.tmp.XXXXXX", path);
|
|
||||||
tmp_fd = mkstemp(tmp_path);
|
|
||||||
if (tmp_fd < 0 && errno == ENOENT &&
|
|
||||||
amduat_asl_pointer_ensure_directory(parent_dir)) {
|
|
||||||
tmp_fd = mkstemp(tmp_path);
|
|
||||||
}
|
|
||||||
if (tmp_fd < 0) {
|
|
||||||
free(parent_dir);
|
|
||||||
free(tmp_path);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
free((void *)prev_bytes.data);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
fp = fdopen(tmp_fd, "wb");
|
|
||||||
if (fp == NULL) {
|
|
||||||
close(tmp_fd);
|
|
||||||
(void)remove(tmp_path);
|
|
||||||
free(tmp_path);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
free((void *)prev_bytes.data);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(header, k_amduat_asl_pointer_magic, AMDUAT_ASL_POINTER_MAGIC_LEN);
|
|
||||||
amduat_asl_pointer_store_u32_le(
|
|
||||||
header + AMDUAT_ASL_POINTER_MAGIC_LEN, AMDUAT_ASL_POINTER_VERSION);
|
|
||||||
header[AMDUAT_ASL_POINTER_MAGIC_LEN + 4u] = flags;
|
|
||||||
if (fwrite(header, 1u, sizeof(header), fp) != sizeof(header)) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK) {
|
|
||||||
uint8_t len_buf[4u];
|
|
||||||
amduat_asl_pointer_store_u32_le(len_buf, name_len);
|
|
||||||
if (fwrite(len_buf, 1u, 4u, fp) != 4u ||
|
|
||||||
fwrite(name, 1u, name_len, fp) != name_len) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK) {
|
|
||||||
uint8_t len_buf[4u];
|
|
||||||
amduat_asl_pointer_store_u32_le(len_buf, ref_len);
|
|
||||||
if (fwrite(len_buf, 1u, 4u, fp) != 4u ||
|
|
||||||
fwrite(ref_bytes.data, 1u, ref_len, fp) != ref_len) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK) {
|
|
||||||
uint8_t len_buf[4u];
|
|
||||||
amduat_asl_pointer_store_u32_le(len_buf, prev_len);
|
|
||||||
if (fwrite(len_buf, 1u, 4u, fp) != 4u) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK && prev_len != 0u &&
|
|
||||||
fwrite(prev_bytes.data, 1u, prev_len, fp) != prev_len) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK && fflush(fp) != 0) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK && fsync(fileno(fp)) != 0) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fclose(fp) != 0) {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK && rename(tmp_path, path) != 0) {
|
|
||||||
if (errno == ENOENT && amduat_asl_pointer_ensure_directory(parent_dir) &&
|
|
||||||
rename(tmp_path, path) == 0) {
|
|
||||||
/* Recovered after recreating parent directory. */
|
|
||||||
} else {
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK) {
|
|
||||||
if (!amduat_asl_pointer_fsync_directory(parent_dir)) {
|
|
||||||
amduat_log(AMDUAT_LOG_WARN,
|
|
||||||
"pointer fsync dir failed for %s", parent_dir);
|
|
||||||
err = AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err != AMDUAT_ASL_POINTER_OK) {
|
|
||||||
(void)remove(tmp_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(parent_dir);
|
|
||||||
free(tmp_path);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
free((void *)prev_bytes.data);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_pointer_error_t amduat_asl_pointer_get(
|
|
||||||
const amduat_asl_pointer_store_t *ps,
|
|
||||||
const char *name,
|
|
||||||
bool *out_exists,
|
|
||||||
amduat_reference_t *out_ref) {
|
|
||||||
char *head_path = NULL;
|
|
||||||
amduat_asl_pointer_error_t err;
|
|
||||||
|
|
||||||
if (ps == NULL || name == NULL) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(name)) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INVALID_NAME;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_build_head_path(ps->root_path, name, false,
|
|
||||||
&head_path)) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = amduat_asl_pointer_read_head(head_path, name, out_exists, out_ref,
|
|
||||||
NULL, NULL);
|
|
||||||
if (err == AMDUAT_ASL_POINTER_ERR_NOT_FOUND) {
|
|
||||||
*out_exists = false;
|
|
||||||
err = AMDUAT_ASL_POINTER_OK;
|
|
||||||
}
|
|
||||||
free(head_path);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_pointer_error_t amduat_asl_pointer_cas(
|
|
||||||
const amduat_asl_pointer_store_t *ps,
|
|
||||||
const char *name,
|
|
||||||
bool expected_exists,
|
|
||||||
const amduat_reference_t *expected_ref,
|
|
||||||
const amduat_reference_t *new_ref,
|
|
||||||
bool *out_swapped) {
|
|
||||||
char *head_path = NULL;
|
|
||||||
int lock_fd = -1;
|
|
||||||
struct flock lock;
|
|
||||||
bool exists = false;
|
|
||||||
amduat_reference_t current_ref;
|
|
||||||
amduat_reference_t prev_ref;
|
|
||||||
bool has_prev = false;
|
|
||||||
char *lock_path = NULL;
|
|
||||||
amduat_asl_pointer_error_t err;
|
|
||||||
|
|
||||||
if (out_swapped == NULL) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
*out_swapped = false;
|
|
||||||
if (ps == NULL || name == NULL || new_ref == NULL) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(name)) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INVALID_NAME;
|
|
||||||
}
|
|
||||||
if (expected_exists && expected_ref == NULL) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_pointer_build_head_path(ps->root_path, name, true,
|
|
||||||
&head_path)) {
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock_path = (char *)malloc(strlen(head_path) + sizeof(".lock"));
|
|
||||||
if (lock_path == NULL) {
|
|
||||||
free(head_path);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
snprintf(lock_path, strlen(head_path) + sizeof(".lock"), "%s.lock",
|
|
||||||
head_path);
|
|
||||||
|
|
||||||
/* Lock a stable sidecar file so lock ownership survives head-file renames. */
|
|
||||||
lock_fd = open(lock_path, O_RDWR | O_CREAT, 0644);
|
|
||||||
if (lock_fd < 0) {
|
|
||||||
free(lock_path);
|
|
||||||
free(head_path);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&lock, 0, sizeof(lock));
|
|
||||||
lock.l_type = F_WRLCK;
|
|
||||||
lock.l_whence = SEEK_SET;
|
|
||||||
lock.l_start = 0;
|
|
||||||
lock.l_len = 0;
|
|
||||||
if (fcntl(lock_fd, F_SETLKW, &lock) != 0) {
|
|
||||||
close(lock_fd);
|
|
||||||
free(lock_path);
|
|
||||||
free(head_path);
|
|
||||||
return AMDUAT_ASL_POINTER_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = amduat_asl_pointer_read_head(head_path, name, &exists, ¤t_ref,
|
|
||||||
&prev_ref, &has_prev);
|
|
||||||
if (err == AMDUAT_ASL_POINTER_ERR_NOT_FOUND) {
|
|
||||||
exists = false;
|
|
||||||
err = AMDUAT_ASL_POINTER_OK;
|
|
||||||
}
|
|
||||||
if (err != AMDUAT_ASL_POINTER_OK) {
|
|
||||||
close(lock_fd);
|
|
||||||
free(lock_path);
|
|
||||||
free(head_path);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expected_exists != exists) {
|
|
||||||
close(lock_fd);
|
|
||||||
free(lock_path);
|
|
||||||
free(head_path);
|
|
||||||
return AMDUAT_ASL_POINTER_OK;
|
|
||||||
}
|
|
||||||
if (expected_exists && !amduat_reference_eq(*expected_ref, current_ref)) {
|
|
||||||
close(lock_fd);
|
|
||||||
free(lock_path);
|
|
||||||
free(head_path);
|
|
||||||
return AMDUAT_ASL_POINTER_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = amduat_asl_pointer_write_head(head_path, name, new_ref,
|
|
||||||
expected_exists ? ¤t_ref : NULL,
|
|
||||||
expected_exists);
|
|
||||||
if (err == AMDUAT_ASL_POINTER_OK) {
|
|
||||||
*out_swapped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
amduat_reference_free(¤t_ref);
|
|
||||||
}
|
|
||||||
if (has_prev) {
|
|
||||||
amduat_reference_free(&prev_ref);
|
|
||||||
}
|
|
||||||
close(lock_fd);
|
|
||||||
free(lock_path);
|
|
||||||
free(head_path);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
@ -16,13 +16,11 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/file.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
@ -132,92 +130,6 @@ static bool amduat_asl_store_index_fs_current_state_impl(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
amduat_asl_index_state_t *out_state);
|
amduat_asl_index_state_t *out_state);
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_put_indexed_impl(
|
|
||||||
void *ctx,
|
|
||||||
amduat_artifact_t artifact,
|
|
||||||
amduat_reference_t *out_ref,
|
|
||||||
amduat_asl_index_state_t *out_state);
|
|
||||||
|
|
||||||
static int amduat_asl_store_index_fs_lockfile_acquire(
|
|
||||||
amduat_asl_store_index_fs_t *fs) {
|
|
||||||
char lock_path[AMDUAT_ASL_STORE_INDEX_FS_ROOT_MAX + 32];
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (fs == NULL || fs->root_path[0] == '\0') {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (snprintf(lock_path, sizeof(lock_path), "%s/.index-write.lock",
|
|
||||||
fs->root_path) >= (int)sizeof(lock_path)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
fd = open(lock_path, O_CREAT | O_RDWR, 0644);
|
|
||||||
if (fd < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while (flock(fd, LOCK_EX) != 0) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_asl_store_index_fs_lockfile_release(int fd) {
|
|
||||||
if (fd < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (flock(fd, LOCK_UN) != 0) {
|
|
||||||
if (errno == EINTR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_begin_write(
|
|
||||||
amduat_asl_store_index_fs_t *fs) {
|
|
||||||
int lock_fd;
|
|
||||||
|
|
||||||
if (fs == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (pthread_mutex_lock(&fs->write_mutex) != 0) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
if (fs->write_depth == 0u) {
|
|
||||||
lock_fd = amduat_asl_store_index_fs_lockfile_acquire(fs);
|
|
||||||
if (lock_fd < 0) {
|
|
||||||
pthread_mutex_unlock(&fs->write_mutex);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
fs->write_lock_fd = lock_fd;
|
|
||||||
}
|
|
||||||
fs->write_depth += 1u;
|
|
||||||
return AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_asl_store_index_fs_end_write(amduat_asl_store_index_fs_t *fs) {
|
|
||||||
int lock_fd;
|
|
||||||
|
|
||||||
if (fs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fs->write_depth == 0u) {
|
|
||||||
pthread_mutex_unlock(&fs->write_mutex);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fs->write_depth -= 1u;
|
|
||||||
if (fs->write_depth == 0u) {
|
|
||||||
lock_fd = fs->write_lock_fd;
|
|
||||||
fs->write_lock_fd = -1;
|
|
||||||
amduat_asl_store_index_fs_lockfile_release(lock_fd);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&fs->write_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_store_index_fs_log_magic[
|
static const uint8_t k_amduat_asl_store_index_fs_log_magic[
|
||||||
AMDUAT_ASL_STORE_INDEX_FS_LOG_MAGIC_LEN] = {'A', 'S', 'L', 'L',
|
AMDUAT_ASL_STORE_INDEX_FS_LOG_MAGIC_LEN] = {'A', 'S', 'L', 'L',
|
||||||
'O', 'G', '0', '1'};
|
'O', 'G', '0', '1'};
|
||||||
|
|
@ -1250,7 +1162,7 @@ static bool amduat_asl_store_index_fs_encode_artifact_ref(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_append_log_record_unlocked(
|
static amduat_asl_store_error_t amduat_asl_store_index_fs_append_log_record(
|
||||||
amduat_asl_store_index_fs_t *fs,
|
amduat_asl_store_index_fs_t *fs,
|
||||||
uint32_t record_type,
|
uint32_t record_type,
|
||||||
const uint8_t *payload,
|
const uint8_t *payload,
|
||||||
|
|
@ -1362,30 +1274,6 @@ static amduat_asl_store_error_t amduat_asl_store_index_fs_append_log_record_unlo
|
||||||
return AMDUAT_ASL_STORE_OK;
|
return AMDUAT_ASL_STORE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_append_log_record(
|
|
||||||
amduat_asl_store_index_fs_t *fs,
|
|
||||||
uint32_t record_type,
|
|
||||||
const uint8_t *payload,
|
|
||||||
size_t payload_len,
|
|
||||||
amduat_asl_index_state_t *out_state) {
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
if (fs == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
err = amduat_asl_store_index_fs_begin_write(fs);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = amduat_asl_store_index_fs_append_log_record_unlocked(fs,
|
|
||||||
record_type,
|
|
||||||
payload,
|
|
||||||
payload_len,
|
|
||||||
out_state);
|
|
||||||
amduat_asl_store_index_fs_end_write(fs);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_store_index_fs_open_segment_contains(
|
static bool amduat_asl_store_index_fs_open_segment_contains(
|
||||||
const amduat_asl_store_index_fs_open_segment_t *segment,
|
const amduat_asl_store_index_fs_open_segment_t *segment,
|
||||||
amduat_reference_t ref) {
|
amduat_reference_t ref) {
|
||||||
|
|
@ -3197,15 +3085,11 @@ static void amduat_asl_store_index_fs_maybe_snapshot_idle(
|
||||||
if (fs->next_snapshot_id == 0u) {
|
if (fs->next_snapshot_id == 0u) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (amduat_asl_store_index_fs_begin_write(fs) != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (amduat_asl_store_index_fs_snapshot_create(
|
if (amduat_asl_store_index_fs_snapshot_create(
|
||||||
fs, fs->next_snapshot_id, NULL, NULL) == AMDUAT_ASL_STORE_OK) {
|
fs, fs->next_snapshot_id, NULL, NULL) == AMDUAT_ASL_STORE_OK) {
|
||||||
fs->next_snapshot_id += 1u;
|
fs->next_snapshot_id += 1u;
|
||||||
fs->pending_snapshot_bytes = 0u;
|
fs->pending_snapshot_bytes = 0u;
|
||||||
}
|
}
|
||||||
amduat_asl_store_index_fs_end_write(fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amduat_asl_store_index_fs_maybe_snapshot_size(
|
static void amduat_asl_store_index_fs_maybe_snapshot_size(
|
||||||
|
|
@ -3230,15 +3114,11 @@ static void amduat_asl_store_index_fs_maybe_snapshot_size(
|
||||||
if (fs->next_snapshot_id == 0u) {
|
if (fs->next_snapshot_id == 0u) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (amduat_asl_store_index_fs_begin_write(fs) != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (amduat_asl_store_index_fs_snapshot_create(
|
if (amduat_asl_store_index_fs_snapshot_create(
|
||||||
fs, fs->next_snapshot_id, NULL, NULL) == AMDUAT_ASL_STORE_OK) {
|
fs, fs->next_snapshot_id, NULL, NULL) == AMDUAT_ASL_STORE_OK) {
|
||||||
fs->next_snapshot_id += 1u;
|
fs->next_snapshot_id += 1u;
|
||||||
fs->pending_snapshot_bytes = 0u;
|
fs->pending_snapshot_bytes = 0u;
|
||||||
}
|
}
|
||||||
amduat_asl_store_index_fs_end_write(fs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static amduat_asl_store_error_t
|
static amduat_asl_store_error_t
|
||||||
|
|
@ -3802,6 +3682,7 @@ static bool amduat_asl_store_index_fs_current_state_impl(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fs = (amduat_asl_store_index_fs_t *)ctx;
|
fs = (amduat_asl_store_index_fs_t *)ctx;
|
||||||
|
amduat_asl_store_index_fs_maybe_snapshot_idle(fs);
|
||||||
|
|
||||||
if (!amduat_asl_store_index_fs_layout_build_log_path(fs->root_path,
|
if (!amduat_asl_store_index_fs_layout_build_log_path(fs->root_path,
|
||||||
&log_path)) {
|
&log_path)) {
|
||||||
|
|
@ -3828,12 +3709,10 @@ static bool amduat_asl_store_index_fs_current_state_impl(
|
||||||
if (amduat_asl_store_index_fs_find_latest_snapshot_id(fs, &snapshot_id) &&
|
if (amduat_asl_store_index_fs_find_latest_snapshot_id(fs, &snapshot_id) &&
|
||||||
amduat_asl_store_index_fs_load_snapshot_manifest(
|
amduat_asl_store_index_fs_load_snapshot_manifest(
|
||||||
fs->root_path, snapshot_id, &manifest, manifest_hash)) {
|
fs->root_path, snapshot_id, &manifest, manifest_hash)) {
|
||||||
if (manifest.anchor_logseq <= last_logseq) {
|
|
||||||
out_state->snapshot_id = manifest.snapshot_id;
|
out_state->snapshot_id = manifest.snapshot_id;
|
||||||
if (manifest.anchor_logseq > out_state->log_position) {
|
if (manifest.anchor_logseq > out_state->log_position) {
|
||||||
out_state->log_position = manifest.anchor_logseq;
|
out_state->log_position = manifest.anchor_logseq;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
amduat_asl_snapshot_manifest_free(&manifest);
|
amduat_asl_snapshot_manifest_free(&manifest);
|
||||||
} else if (record_count != 0u &&
|
} else if (record_count != 0u &&
|
||||||
amduat_asl_store_index_fs_find_latest_anchor(records,
|
amduat_asl_store_index_fs_find_latest_anchor(records,
|
||||||
|
|
@ -3886,6 +3765,7 @@ static amduat_asl_store_error_t amduat_asl_store_index_fs_get_indexed_impl(
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
return AMDUAT_ASL_STORE_ERR_IO;
|
||||||
}
|
}
|
||||||
fs = (amduat_asl_store_index_fs_t *)ctx;
|
fs = (amduat_asl_store_index_fs_t *)ctx;
|
||||||
|
amduat_asl_store_index_fs_maybe_snapshot_idle(fs);
|
||||||
|
|
||||||
if (fs->config.encoding_profile_id != AMDUAT_ENC_ASL1_CORE_V1) {
|
if (fs->config.encoding_profile_id != AMDUAT_ENC_ASL1_CORE_V1) {
|
||||||
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
|
@ -4096,6 +3976,7 @@ static amduat_asl_store_error_t amduat_asl_store_index_fs_log_scan_impl(
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
return AMDUAT_ASL_STORE_ERR_IO;
|
||||||
}
|
}
|
||||||
fs = (amduat_asl_store_index_fs_t *)ctx;
|
fs = (amduat_asl_store_index_fs_t *)ctx;
|
||||||
|
amduat_asl_store_index_fs_maybe_snapshot_idle(fs);
|
||||||
|
|
||||||
if (!amduat_asl_store_index_fs_layout_build_log_path(fs->root_path,
|
if (!amduat_asl_store_index_fs_layout_build_log_path(fs->root_path,
|
||||||
&log_path)) {
|
&log_path)) {
|
||||||
|
|
@ -4106,7 +3987,7 @@ static amduat_asl_store_error_t amduat_asl_store_index_fs_log_scan_impl(
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_put_indexed_unlocked_impl(
|
static amduat_asl_store_error_t amduat_asl_store_index_fs_put_indexed_impl(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
amduat_artifact_t artifact,
|
amduat_artifact_t artifact,
|
||||||
amduat_reference_t *out_ref,
|
amduat_reference_t *out_ref,
|
||||||
|
|
@ -4614,30 +4495,6 @@ static amduat_asl_store_error_t amduat_asl_store_index_fs_put_impl(
|
||||||
&state);
|
&state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_put_indexed_impl(
|
|
||||||
void *ctx,
|
|
||||||
amduat_artifact_t artifact,
|
|
||||||
amduat_reference_t *out_ref,
|
|
||||||
amduat_asl_index_state_t *out_state) {
|
|
||||||
amduat_asl_store_index_fs_t *fs;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
if (ctx == NULL || out_ref == NULL || out_state == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
}
|
|
||||||
fs = (amduat_asl_store_index_fs_t *)ctx;
|
|
||||||
err = amduat_asl_store_index_fs_begin_write(fs);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = amduat_asl_store_index_fs_put_indexed_unlocked_impl(ctx,
|
|
||||||
artifact,
|
|
||||||
out_ref,
|
|
||||||
out_state);
|
|
||||||
amduat_asl_store_index_fs_end_write(fs);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static amduat_asl_store_error_t amduat_asl_store_index_fs_get_impl(
|
static amduat_asl_store_error_t amduat_asl_store_index_fs_get_impl(
|
||||||
void *ctx,
|
void *ctx,
|
||||||
amduat_reference_t ref,
|
amduat_reference_t ref,
|
||||||
|
|
@ -5188,7 +5045,6 @@ bool amduat_asl_store_index_fs_init(amduat_asl_store_index_fs_t *fs,
|
||||||
amduat_asl_store_config_t config,
|
amduat_asl_store_config_t config,
|
||||||
const char *root_path) {
|
const char *root_path) {
|
||||||
size_t len;
|
size_t len;
|
||||||
pthread_mutexattr_t mutex_attr;
|
|
||||||
|
|
||||||
if (fs == NULL || root_path == NULL) {
|
if (fs == NULL || root_path == NULL) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -5218,20 +5074,6 @@ bool amduat_asl_store_index_fs_init(amduat_asl_store_index_fs_t *fs,
|
||||||
fs->next_snapshot_id = 0u;
|
fs->next_snapshot_id = 0u;
|
||||||
fs->snapshot_state_initialized = false;
|
fs->snapshot_state_initialized = false;
|
||||||
fs->open_segments = NULL;
|
fs->open_segments = NULL;
|
||||||
fs->write_depth = 0u;
|
|
||||||
fs->write_lock_fd = -1;
|
|
||||||
if (pthread_mutexattr_init(&mutex_attr) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
|
|
||||||
pthread_mutexattr_destroy(&mutex_attr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pthread_mutex_init(&fs->write_mutex, &mutex_attr) != 0) {
|
|
||||||
pthread_mutexattr_destroy(&mutex_attr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pthread_mutexattr_destroy(&mutex_attr);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,607 +0,0 @@
|
||||||
#include "amduat/asl/collection.h"
|
|
||||||
|
|
||||||
#include "amduat/enc/asl1_core_codec.h"
|
|
||||||
#include "amduat/util/log.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_COLLECTION_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_COLLECTION_VERSION = 1,
|
|
||||||
AMDUAT_ASL_COLLECTION_READ_BATCH = 1024u
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_collection_magic[
|
|
||||||
AMDUAT_ASL_COLLECTION_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'C', 'O', 'L', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static void amduat_asl_collection_store_u32_le(uint8_t *out, uint32_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_asl_collection_store_u64_le(uint8_t *out, uint64_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
out[4] = (uint8_t)((value >> 32) & 0xffu);
|
|
||||||
out[5] = (uint8_t)((value >> 40) & 0xffu);
|
|
||||||
out[6] = (uint8_t)((value >> 48) & 0xffu);
|
|
||||||
out[7] = (uint8_t)((value >> 56) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_collection_read_u32_le(const uint8_t *data,
|
|
||||||
size_t len,
|
|
||||||
size_t *offset,
|
|
||||||
uint32_t *out) {
|
|
||||||
if (len - *offset < 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = (uint32_t)data[*offset] |
|
|
||||||
((uint32_t)data[*offset + 1u] << 8) |
|
|
||||||
((uint32_t)data[*offset + 2u] << 16) |
|
|
||||||
((uint32_t)data[*offset + 3u] << 24);
|
|
||||||
*offset += 4u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_collection_read_u64_le(const uint8_t *data,
|
|
||||||
size_t len,
|
|
||||||
size_t *offset,
|
|
||||||
uint64_t *out) {
|
|
||||||
if (len - *offset < 8u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = (uint64_t)data[*offset] |
|
|
||||||
((uint64_t)data[*offset + 1u] << 8) |
|
|
||||||
((uint64_t)data[*offset + 2u] << 16) |
|
|
||||||
((uint64_t)data[*offset + 3u] << 24) |
|
|
||||||
((uint64_t)data[*offset + 4u] << 32) |
|
|
||||||
((uint64_t)data[*offset + 5u] << 40) |
|
|
||||||
((uint64_t)data[*offset + 6u] << 48) |
|
|
||||||
((uint64_t)data[*offset + 7u] << 56);
|
|
||||||
*offset += 8u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_collection_add_size(size_t *acc, size_t add) {
|
|
||||||
if (*acc > SIZE_MAX - add) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*acc += add;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_collection_build_log_name(const char *name,
|
|
||||||
char **out_name) {
|
|
||||||
size_t name_len;
|
|
||||||
size_t total_len;
|
|
||||||
char *buffer;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
if (name == NULL || out_name == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
name_len = strlen(name);
|
|
||||||
total_len = 11u + name_len + 4u + 1u;
|
|
||||||
buffer = (char *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset = 0u;
|
|
||||||
memcpy(buffer + offset, "collection/", 11u);
|
|
||||||
offset += 11u;
|
|
||||||
memcpy(buffer + offset, name, name_len);
|
|
||||||
offset += name_len;
|
|
||||||
memcpy(buffer + offset, "/log", 4u);
|
|
||||||
offset += 4u;
|
|
||||||
buffer[offset] = '\0';
|
|
||||||
*out_name = buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_collection_build_head_name(const char *name,
|
|
||||||
char **out_name) {
|
|
||||||
size_t name_len;
|
|
||||||
size_t total_len;
|
|
||||||
char *buffer;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
if (name == NULL || out_name == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(name)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
name_len = strlen(name);
|
|
||||||
total_len = 11u + name_len + 5u + 1u;
|
|
||||||
buffer = (char *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset = 0u;
|
|
||||||
memcpy(buffer + offset, "collection/", 11u);
|
|
||||||
offset += 11u;
|
|
||||||
memcpy(buffer + offset, name, name_len);
|
|
||||||
offset += name_len;
|
|
||||||
memcpy(buffer + offset, "/head", 5u);
|
|
||||||
offset += 5u;
|
|
||||||
buffer[offset] = '\0';
|
|
||||||
*out_name = buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_collection_encode_snapshot_payload(
|
|
||||||
uint64_t snapshot_offset,
|
|
||||||
const amduat_reference_t *refs,
|
|
||||||
size_t refs_len,
|
|
||||||
amduat_octets_t *out_payload) {
|
|
||||||
size_t total_len = 0u;
|
|
||||||
uint8_t *buffer;
|
|
||||||
size_t offset = 0u;
|
|
||||||
|
|
||||||
if (out_payload == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_payload->data = NULL;
|
|
||||||
out_payload->len = 0u;
|
|
||||||
|
|
||||||
if (refs_len > UINT32_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_collection_add_size(
|
|
||||||
&total_len, AMDUAT_ASL_COLLECTION_MAGIC_LEN + 4u + 8u + 4u)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_add_size(&total_len, 4u + ref_bytes.len)) {
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer + offset, k_amduat_asl_collection_magic,
|
|
||||||
AMDUAT_ASL_COLLECTION_MAGIC_LEN);
|
|
||||||
offset += AMDUAT_ASL_COLLECTION_MAGIC_LEN;
|
|
||||||
amduat_asl_collection_store_u32_le(buffer + offset,
|
|
||||||
AMDUAT_ASL_COLLECTION_VERSION);
|
|
||||||
offset += 4u;
|
|
||||||
amduat_asl_collection_store_u64_le(buffer + offset, snapshot_offset);
|
|
||||||
offset += 8u;
|
|
||||||
amduat_asl_collection_store_u32_le(buffer + offset, (uint32_t)refs_len);
|
|
||||||
offset += 4u;
|
|
||||||
|
|
||||||
for (size_t i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
amduat_asl_collection_store_u32_le(buffer + offset,
|
|
||||||
(uint32_t)ref_bytes.len);
|
|
||||||
offset += 4u;
|
|
||||||
memcpy(buffer + offset, ref_bytes.data, ref_bytes.len);
|
|
||||||
offset += ref_bytes.len;
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset != total_len) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_payload = amduat_octets(buffer, total_len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_collection_store_init(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *root_path,
|
|
||||||
amduat_asl_store_t *store) {
|
|
||||||
if (collection_store == NULL || root_path == NULL || store == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
collection_store->store = store;
|
|
||||||
if (!amduat_asl_pointer_store_init(&collection_store->pointer_store,
|
|
||||||
root_path)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_log_store_init(&collection_store->log_store, root_path,
|
|
||||||
store, &collection_store->pointer_store)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_collection_error_t amduat_asl_collection_append(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *collection_name,
|
|
||||||
amduat_reference_t record_ref,
|
|
||||||
uint16_t kind,
|
|
||||||
amduat_octets_t actor,
|
|
||||||
uint64_t *out_offset) {
|
|
||||||
char *log_name = NULL;
|
|
||||||
amduat_asl_log_entry_t entry;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
if (collection_store == NULL || collection_store->store == NULL ||
|
|
||||||
collection_name == NULL) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(collection_name)) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INVALID_NAME;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_build_log_name(collection_name, &log_name)) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&entry, 0, sizeof(entry));
|
|
||||||
entry.kind = kind;
|
|
||||||
entry.payload_ref = record_ref;
|
|
||||||
entry.has_actor = actor.len != 0u;
|
|
||||||
entry.actor = actor;
|
|
||||||
|
|
||||||
err = amduat_asl_log_append(&collection_store->log_store, log_name,
|
|
||||||
&entry, 1u, out_offset);
|
|
||||||
free(log_name);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
return AMDUAT_ASL_COLLECTION_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_collection_error_t amduat_asl_collection_snapshot(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *collection_name,
|
|
||||||
uint64_t up_to_offset,
|
|
||||||
amduat_reference_t *out_snapshot_ref,
|
|
||||||
bool *out_swapped) {
|
|
||||||
char *log_name = NULL;
|
|
||||||
char *head_name = NULL;
|
|
||||||
amduat_reference_t *refs = NULL;
|
|
||||||
size_t refs_len = 0u;
|
|
||||||
uint64_t from = 0u;
|
|
||||||
bool end = false;
|
|
||||||
uint64_t next_offset = 0u;
|
|
||||||
amduat_asl_record_t snapshot_record;
|
|
||||||
amduat_octets_t payload = amduat_octets(NULL, 0u);
|
|
||||||
amduat_reference_t snapshot_ref;
|
|
||||||
amduat_asl_pointer_error_t ptr_err;
|
|
||||||
bool head_exists = false;
|
|
||||||
amduat_reference_t head_ref;
|
|
||||||
bool swapped = false;
|
|
||||||
|
|
||||||
if (out_snapshot_ref != NULL) {
|
|
||||||
out_snapshot_ref->hash_id = 0u;
|
|
||||||
out_snapshot_ref->digest = amduat_octets(NULL, 0u);
|
|
||||||
}
|
|
||||||
if (out_swapped != NULL) {
|
|
||||||
*out_swapped = false;
|
|
||||||
}
|
|
||||||
if (collection_store == NULL || collection_store->store == NULL ||
|
|
||||||
collection_name == NULL) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(collection_name)) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INVALID_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_collection_build_log_name(collection_name, &log_name) ||
|
|
||||||
!amduat_asl_collection_build_head_name(collection_name, &head_name)) {
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!end && (up_to_offset == UINT64_MAX || from <= up_to_offset)) {
|
|
||||||
size_t limit = AMDUAT_ASL_COLLECTION_READ_BATCH;
|
|
||||||
amduat_asl_log_entry_t *entries = NULL;
|
|
||||||
size_t entries_len = 0u;
|
|
||||||
amduat_asl_store_error_t err = amduat_asl_log_read(
|
|
||||||
&collection_store->log_store, log_name, from, limit, &entries,
|
|
||||||
&entries_len, &next_offset, &end);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < entries_len; ++i) {
|
|
||||||
uint64_t offset = from + i;
|
|
||||||
if (up_to_offset != UINT64_MAX && offset > up_to_offset) {
|
|
||||||
end = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
amduat_reference_t *next =
|
|
||||||
(amduat_reference_t *)realloc(
|
|
||||||
refs, (refs_len + 1u) * sizeof(*refs));
|
|
||||||
if (next == NULL) {
|
|
||||||
amduat_asl_log_entries_free(entries, entries_len);
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
refs = next;
|
|
||||||
refs[refs_len] = entries[i].payload_ref;
|
|
||||||
if (!amduat_octets_clone(entries[i].payload_ref.digest,
|
|
||||||
&refs[refs_len].digest)) {
|
|
||||||
amduat_asl_log_entries_free(entries, entries_len);
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
refs_len++;
|
|
||||||
}
|
|
||||||
amduat_asl_log_entries_free(entries, entries_len);
|
|
||||||
from = next_offset;
|
|
||||||
if (entries_len == 0u) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
uint64_t snapshot_offset = from;
|
|
||||||
if (up_to_offset != UINT64_MAX &&
|
|
||||||
up_to_offset < UINT64_MAX &&
|
|
||||||
snapshot_offset > up_to_offset + 1u) {
|
|
||||||
snapshot_offset = up_to_offset + 1u;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_encode_snapshot_payload(
|
|
||||||
snapshot_offset, refs, refs_len, &payload)) {
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.len == 0u || payload.data == NULL) {
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
amduat_asl_store_error_t err = amduat_asl_record_store_put(
|
|
||||||
collection_store->store,
|
|
||||||
amduat_octets("collection/snapshot",
|
|
||||||
strlen("collection/snapshot")),
|
|
||||||
payload,
|
|
||||||
&snapshot_ref);
|
|
||||||
amduat_octets_free(&payload);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ptr_err = amduat_asl_pointer_get(&collection_store->pointer_store, head_name,
|
|
||||||
&head_exists, &head_ref);
|
|
||||||
if (ptr_err != AMDUAT_ASL_POINTER_OK) {
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
ptr_err = amduat_asl_pointer_cas(&collection_store->pointer_store, head_name,
|
|
||||||
head_exists,
|
|
||||||
head_exists ? &head_ref : NULL,
|
|
||||||
&snapshot_ref, &swapped);
|
|
||||||
if (head_exists) {
|
|
||||||
amduat_reference_free(&head_ref);
|
|
||||||
}
|
|
||||||
if (ptr_err != AMDUAT_ASL_POINTER_OK) {
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out_swapped != NULL) {
|
|
||||||
*out_swapped = swapped;
|
|
||||||
}
|
|
||||||
if (out_snapshot_ref != NULL) {
|
|
||||||
*out_snapshot_ref = snapshot_ref;
|
|
||||||
}
|
|
||||||
if (!swapped) {
|
|
||||||
amduat_log(AMDUAT_LOG_DEBUG, "collection snapshot CAS mismatch");
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_CAS_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_collection_refs_free(refs, refs_len);
|
|
||||||
free(log_name);
|
|
||||||
free(head_name);
|
|
||||||
return AMDUAT_ASL_COLLECTION_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_collection_error_t amduat_asl_collection_read(
|
|
||||||
amduat_asl_collection_store_t *collection_store,
|
|
||||||
const char *collection_name,
|
|
||||||
uint64_t from_offset,
|
|
||||||
size_t limit,
|
|
||||||
amduat_reference_t **out_record_refs,
|
|
||||||
size_t *out_len,
|
|
||||||
uint64_t *out_next_offset,
|
|
||||||
bool *out_end) {
|
|
||||||
char *log_name = NULL;
|
|
||||||
amduat_asl_log_entry_t *entries = NULL;
|
|
||||||
size_t entries_len = 0u;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
if (out_record_refs == NULL || out_len == NULL ||
|
|
||||||
out_next_offset == NULL || out_end == NULL) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
*out_record_refs = NULL;
|
|
||||||
*out_len = 0u;
|
|
||||||
|
|
||||||
if (collection_store == NULL || collection_store->store == NULL ||
|
|
||||||
collection_name == NULL) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_pointer_name_is_valid(collection_name)) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_INVALID_NAME;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_build_log_name(collection_name, &log_name)) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = amduat_asl_log_read(&collection_store->log_store, log_name,
|
|
||||||
from_offset, limit, &entries, &entries_len,
|
|
||||||
out_next_offset, out_end);
|
|
||||||
free(log_name);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entries_len != 0u) {
|
|
||||||
amduat_reference_t *refs =
|
|
||||||
(amduat_reference_t *)calloc(entries_len, sizeof(*refs));
|
|
||||||
if (refs == NULL) {
|
|
||||||
amduat_asl_log_entries_free(entries, entries_len);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < entries_len; ++i) {
|
|
||||||
refs[i].hash_id = entries[i].payload_ref.hash_id;
|
|
||||||
if (!amduat_octets_clone(entries[i].payload_ref.digest,
|
|
||||||
&refs[i].digest)) {
|
|
||||||
amduat_asl_collection_refs_free(refs, i);
|
|
||||||
amduat_asl_log_entries_free(entries, entries_len);
|
|
||||||
return AMDUAT_ASL_COLLECTION_ERR_IO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*out_record_refs = refs;
|
|
||||||
*out_len = entries_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_log_entries_free(entries, entries_len);
|
|
||||||
return AMDUAT_ASL_COLLECTION_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_asl_collection_refs_free(amduat_reference_t *refs,
|
|
||||||
size_t refs_len) {
|
|
||||||
if (refs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_reference_free(&refs[i]);
|
|
||||||
}
|
|
||||||
free(refs);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_collection_snapshot_payload_decode_v1(
|
|
||||||
amduat_octets_t payload,
|
|
||||||
amduat_asl_collection_snapshot_payload_t *out_snapshot) {
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t version = 0u;
|
|
||||||
uint32_t entry_count = 0u;
|
|
||||||
|
|
||||||
if (out_snapshot == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_snapshot->snapshot_offset = 0u;
|
|
||||||
out_snapshot->refs = NULL;
|
|
||||||
out_snapshot->refs_len = 0u;
|
|
||||||
|
|
||||||
if (payload.len < AMDUAT_ASL_COLLECTION_MAGIC_LEN + 4u + 8u + 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (payload.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(payload.data, k_amduat_asl_collection_magic,
|
|
||||||
AMDUAT_ASL_COLLECTION_MAGIC_LEN) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset += AMDUAT_ASL_COLLECTION_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
|
|
||||||
&offset, &version) ||
|
|
||||||
version != AMDUAT_ASL_COLLECTION_VERSION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_read_u64_le(payload.data, payload.len,
|
|
||||||
&offset,
|
|
||||||
&out_snapshot->snapshot_offset)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
|
|
||||||
&offset, &entry_count)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (entry_count == 0u) {
|
|
||||||
return offset == payload.len;
|
|
||||||
}
|
|
||||||
if (entry_count > SIZE_MAX / sizeof(amduat_reference_t)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_snapshot->refs =
|
|
||||||
(amduat_reference_t *)calloc(entry_count, sizeof(*out_snapshot->refs));
|
|
||||||
if (out_snapshot->refs == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_snapshot->refs_len = entry_count;
|
|
||||||
|
|
||||||
for (uint32_t i = 0u; i < entry_count; ++i) {
|
|
||||||
uint32_t ref_len = 0u;
|
|
||||||
amduat_octets_t ref_bytes;
|
|
||||||
if (!amduat_asl_collection_read_u32_le(payload.data, payload.len,
|
|
||||||
&offset, &ref_len)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (payload.len - offset < ref_len) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
ref_bytes = amduat_octets(payload.data + offset, ref_len);
|
|
||||||
if (!amduat_enc_asl1_core_decode_reference_v1(
|
|
||||||
ref_bytes, &out_snapshot->refs[i])) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
offset += ref_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset == payload.len;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
amduat_asl_collection_snapshot_payload_free(out_snapshot);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_asl_collection_snapshot_payload_free(
|
|
||||||
amduat_asl_collection_snapshot_payload_t *snapshot) {
|
|
||||||
if (snapshot == NULL || snapshot->refs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < snapshot->refs_len; ++i) {
|
|
||||||
amduat_reference_free(&snapshot->refs[i]);
|
|
||||||
}
|
|
||||||
free(snapshot->refs);
|
|
||||||
snapshot->refs = NULL;
|
|
||||||
snapshot->refs_len = 0u;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,268 +0,0 @@
|
||||||
#include "amduat/asl/record.h"
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_RECORD_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_RECORD_VERSION = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_record_magic[AMDUAT_ASL_RECORD_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'R', 'E', 'C', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static void amduat_asl_record_store_u32_le(uint8_t *out, uint32_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_record_read_u32_le(const uint8_t *data,
|
|
||||||
size_t len,
|
|
||||||
size_t *offset,
|
|
||||||
uint32_t *out) {
|
|
||||||
if (len - *offset < 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = (uint32_t)data[*offset] |
|
|
||||||
((uint32_t)data[*offset + 1u] << 8) |
|
|
||||||
((uint32_t)data[*offset + 2u] << 16) |
|
|
||||||
((uint32_t)data[*offset + 3u] << 24);
|
|
||||||
*offset += 4u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_record_add_size(size_t *acc, size_t add) {
|
|
||||||
if (*acc > SIZE_MAX - add) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*acc += add;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_record_schema_is_ascii(amduat_octets_t schema) {
|
|
||||||
if (schema.len == 0u || schema.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < schema.len; ++i) {
|
|
||||||
uint8_t c = schema.data[i];
|
|
||||||
if (c < 0x20u || c > 0x7eu) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_record_encode_v1(const amduat_asl_record_t *record,
|
|
||||||
amduat_octets_t *out_bytes) {
|
|
||||||
uint8_t *buffer;
|
|
||||||
size_t total_len = 0u;
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t schema_len;
|
|
||||||
uint32_t payload_len;
|
|
||||||
uint8_t flags = 0u;
|
|
||||||
|
|
||||||
if (out_bytes == NULL || record == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_bytes->data = NULL;
|
|
||||||
out_bytes->len = 0u;
|
|
||||||
|
|
||||||
if (!amduat_asl_record_schema_is_ascii(record->schema)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (record->payload.len != 0u && record->payload.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (record->schema.len > UINT32_MAX || record->payload.len > UINT32_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
schema_len = (uint32_t)record->schema.len;
|
|
||||||
payload_len = (uint32_t)record->payload.len;
|
|
||||||
|
|
||||||
if (!amduat_asl_record_add_size(&total_len,
|
|
||||||
AMDUAT_ASL_RECORD_MAGIC_LEN + 4u) ||
|
|
||||||
!amduat_asl_record_add_size(&total_len, 4u + schema_len) ||
|
|
||||||
!amduat_asl_record_add_size(&total_len, 4u + payload_len) ||
|
|
||||||
!amduat_asl_record_add_size(&total_len, 1u)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer + offset, k_amduat_asl_record_magic,
|
|
||||||
AMDUAT_ASL_RECORD_MAGIC_LEN);
|
|
||||||
offset += AMDUAT_ASL_RECORD_MAGIC_LEN;
|
|
||||||
amduat_asl_record_store_u32_le(buffer + offset, AMDUAT_ASL_RECORD_VERSION);
|
|
||||||
offset += 4u;
|
|
||||||
|
|
||||||
amduat_asl_record_store_u32_le(buffer + offset, schema_len);
|
|
||||||
offset += 4u;
|
|
||||||
memcpy(buffer + offset, record->schema.data, schema_len);
|
|
||||||
offset += schema_len;
|
|
||||||
|
|
||||||
amduat_asl_record_store_u32_le(buffer + offset, payload_len);
|
|
||||||
offset += 4u;
|
|
||||||
if (payload_len != 0u) {
|
|
||||||
memcpy(buffer + offset, record->payload.data, payload_len);
|
|
||||||
offset += payload_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[offset++] = flags;
|
|
||||||
|
|
||||||
if (offset != total_len) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_bytes->data = buffer;
|
|
||||||
out_bytes->len = total_len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_record_decode_v1(amduat_octets_t bytes,
|
|
||||||
amduat_asl_record_t *out_record) {
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t version;
|
|
||||||
uint32_t schema_len;
|
|
||||||
uint32_t payload_len;
|
|
||||||
uint8_t flags;
|
|
||||||
uint8_t *schema_bytes;
|
|
||||||
uint8_t *payload_bytes;
|
|
||||||
|
|
||||||
if (out_record == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_record->schema = amduat_octets(NULL, 0u);
|
|
||||||
out_record->payload = amduat_octets(NULL, 0u);
|
|
||||||
|
|
||||||
if (bytes.len < AMDUAT_ASL_RECORD_MAGIC_LEN + 4u + 1u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(bytes.data, k_amduat_asl_record_magic,
|
|
||||||
AMDUAT_ASL_RECORD_MAGIC_LEN) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset += AMDUAT_ASL_RECORD_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_record_read_u32_le(bytes.data, bytes.len, &offset,
|
|
||||||
&version) ||
|
|
||||||
version != AMDUAT_ASL_RECORD_VERSION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_record_read_u32_le(bytes.data, bytes.len, &offset,
|
|
||||||
&schema_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytes.len - offset < schema_len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
schema_bytes = NULL;
|
|
||||||
if (schema_len != 0u) {
|
|
||||||
schema_bytes = (uint8_t *)malloc(schema_len);
|
|
||||||
if (schema_bytes == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(schema_bytes, bytes.data + offset, schema_len);
|
|
||||||
}
|
|
||||||
offset += schema_len;
|
|
||||||
|
|
||||||
if (!amduat_asl_record_read_u32_le(bytes.data, bytes.len, &offset,
|
|
||||||
&payload_len)) {
|
|
||||||
free(schema_bytes);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytes.len - offset < payload_len + 1u) {
|
|
||||||
free(schema_bytes);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
payload_bytes = NULL;
|
|
||||||
if (payload_len != 0u) {
|
|
||||||
payload_bytes = (uint8_t *)malloc(payload_len);
|
|
||||||
if (payload_bytes == NULL) {
|
|
||||||
free(schema_bytes);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
memcpy(payload_bytes, bytes.data + offset, payload_len);
|
|
||||||
}
|
|
||||||
offset += payload_len;
|
|
||||||
flags = bytes.data[offset++];
|
|
||||||
(void)flags;
|
|
||||||
|
|
||||||
if (offset != bytes.len) {
|
|
||||||
free(schema_bytes);
|
|
||||||
free(payload_bytes);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
out_record->schema = amduat_octets(schema_bytes, schema_len);
|
|
||||||
out_record->payload = amduat_octets(payload_bytes, payload_len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_asl_record_free(amduat_asl_record_t *record) {
|
|
||||||
if (record == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
amduat_octets_free(&record->schema);
|
|
||||||
amduat_octets_free(&record->payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_record_store_put(
|
|
||||||
amduat_asl_store_t *store,
|
|
||||||
amduat_octets_t schema,
|
|
||||||
amduat_octets_t payload,
|
|
||||||
amduat_reference_t *out_ref) {
|
|
||||||
amduat_asl_record_t record;
|
|
||||||
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
|
||||||
amduat_artifact_t artifact;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
if (store == NULL || out_ref == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
record.schema = schema;
|
|
||||||
record.payload = payload;
|
|
||||||
if (!amduat_asl_record_encode_v1(&record, &encoded)) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
artifact = amduat_artifact_with_type(
|
|
||||||
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_RECORD_1));
|
|
||||||
err = amduat_asl_store_put(store, artifact, out_ref);
|
|
||||||
free((void *)encoded.data);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
amduat_asl_store_error_t amduat_asl_record_store_get(
|
|
||||||
amduat_asl_store_t *store,
|
|
||||||
amduat_reference_t ref,
|
|
||||||
amduat_asl_record_t *out_record) {
|
|
||||||
amduat_artifact_t artifact;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
if (store == NULL || out_record == NULL) {
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
err = amduat_asl_store_get(store, ref, &artifact);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (!artifact.has_type_tag ||
|
|
||||||
artifact.type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
|
|
||||||
amduat_artifact_free(&artifact);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_record_decode_v1(artifact.bytes, out_record)) {
|
|
||||||
amduat_artifact_free(&artifact);
|
|
||||||
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
|
||||||
}
|
|
||||||
amduat_artifact_free(&artifact);
|
|
||||||
return AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
@ -1,161 +0,0 @@
|
||||||
#include "amduat/pel/derivation_sid.h"
|
|
||||||
|
|
||||||
#include "amduat/enc/asl1_core_codec.h"
|
|
||||||
#include "amduat/hash/asl1.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static bool amduat_derivation_sid_check_ref(amduat_reference_t ref) {
|
|
||||||
const amduat_hash_asl1_desc_t *desc;
|
|
||||||
size_t digest_len;
|
|
||||||
|
|
||||||
if (ref.digest.len != 0 && ref.digest.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (amduat_hash_asl1_is_reserved(ref.hash_id)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc = amduat_hash_asl1_desc_lookup(ref.hash_id);
|
|
||||||
digest_len = ref.digest.len;
|
|
||||||
if (desc != NULL && desc->digest_len != 0) {
|
|
||||||
assert(desc->digest_len == digest_len);
|
|
||||||
if (desc->digest_len != digest_len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_pel_derivation_sid_compute(
|
|
||||||
const amduat_pel_derivation_sid_input_t *in,
|
|
||||||
amduat_octets_t *out_sid) {
|
|
||||||
amduat_hash_asl1_stream_t stream;
|
|
||||||
uint8_t marker;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (out_sid == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_sid->data = NULL;
|
|
||||||
out_sid->len = 0;
|
|
||||||
|
|
||||||
if (in == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (in->input_refs_len != 0 && in->input_refs == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (in->has_params_ref && !amduat_derivation_sid_check_ref(in->params_ref)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_derivation_sid_check_ref(in->program_ref)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (i = 0; i < in->input_refs_len; ++i) {
|
|
||||||
if (!amduat_derivation_sid_check_ref(in->input_refs[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_hash_asl1_stream_init(AMDUAT_HASH_ASL1_ID_SHA256, &stream)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
bool ok;
|
|
||||||
|
|
||||||
/* ReferenceBytes are self-delimiting because hash_id implies digest_len. */
|
|
||||||
ok = amduat_enc_asl1_core_encode_reference_v1(in->program_ref, &ref_bytes);
|
|
||||||
if (!ok ||
|
|
||||||
!amduat_hash_asl1_stream_update(&stream, ref_bytes)) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < in->input_refs_len; ++i) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
bool ok = amduat_enc_asl1_core_encode_reference_v1(in->input_refs[i],
|
|
||||||
&ref_bytes);
|
|
||||||
if (!ok ||
|
|
||||||
!amduat_hash_asl1_stream_update(&stream, ref_bytes)) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
marker = in->has_params_ref ? 0x01u : 0x00u;
|
|
||||||
if (!amduat_hash_asl1_stream_update(&stream,
|
|
||||||
amduat_octets(&marker, 1u))) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (in->has_params_ref) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
bool ok = amduat_enc_asl1_core_encode_reference_v1(in->params_ref,
|
|
||||||
&ref_bytes);
|
|
||||||
if (!ok ||
|
|
||||||
!amduat_hash_asl1_stream_update(&stream, ref_bytes)) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ExecProfile is currently absent; presence must be explicitly marked. */
|
|
||||||
marker = in->has_exec_profile ? 0x01u : 0x00u;
|
|
||||||
if (!amduat_hash_asl1_stream_update(&stream,
|
|
||||||
amduat_octets(&marker, 1u))) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (in->has_exec_profile) {
|
|
||||||
if (in->exec_profile.len != 0 && in->exec_profile.data == NULL) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_hash_asl1_stream_update(&stream, in->exec_profile)) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const amduat_hash_asl1_desc_t *desc =
|
|
||||||
amduat_hash_asl1_desc_lookup(AMDUAT_HASH_ASL1_ID_SHA256);
|
|
||||||
uint8_t *digest;
|
|
||||||
size_t digest_len;
|
|
||||||
|
|
||||||
if (desc == NULL || desc->digest_len == 0u) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
digest_len = desc->digest_len;
|
|
||||||
digest = (uint8_t *)malloc(digest_len);
|
|
||||||
if (digest == NULL) {
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_hash_asl1_stream_final(&stream, digest, digest_len)) {
|
|
||||||
free(digest);
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
amduat_hash_asl1_stream_destroy(&stream);
|
|
||||||
*out_sid = amduat_octets(digest, digest_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
#include "amduat/util/log.h"
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
static const char *amduat_log_level_label(amduat_log_level_t level) {
|
|
||||||
switch (level) {
|
|
||||||
case AMDUAT_LOG_ERROR:
|
|
||||||
return "ERROR";
|
|
||||||
case AMDUAT_LOG_WARN:
|
|
||||||
return "WARN";
|
|
||||||
case AMDUAT_LOG_INFO:
|
|
||||||
return "INFO";
|
|
||||||
case AMDUAT_LOG_DEBUG:
|
|
||||||
return "DEBUG";
|
|
||||||
default:
|
|
||||||
return "LOG";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_log_debug_enabled(void) {
|
|
||||||
#ifdef AMDUAT_LOG_ENABLE_DEBUG
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_log(amduat_log_level_t level, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
if (level == AMDUAT_LOG_DEBUG && !amduat_log_debug_enabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: ", amduat_log_level_label(level));
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vfprintf(stderr, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
fputc('\n', stderr);
|
|
||||||
}
|
|
||||||
|
|
@ -1,520 +0,0 @@
|
||||||
#include "amduat/asl/collection_view.h"
|
|
||||||
|
|
||||||
#include "amduat/enc/asl1_core_codec.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_VERSION = 1,
|
|
||||||
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_SNAPSHOT_INFO_VERSION = 1,
|
|
||||||
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_LOG_RANGE_VERSION = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_collection_view_magic[
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'C', 'V', 'W', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_snapshot_info_magic[
|
|
||||||
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'S', 'N', 'P', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_log_range_magic[
|
|
||||||
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'R', 'N', 'G', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static void amduat_asl_store_u32_le(uint8_t *out, uint32_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_asl_store_u64_le(uint8_t *out, uint64_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
out[4] = (uint8_t)((value >> 32) & 0xffu);
|
|
||||||
out[5] = (uint8_t)((value >> 40) & 0xffu);
|
|
||||||
out[6] = (uint8_t)((value >> 48) & 0xffu);
|
|
||||||
out[7] = (uint8_t)((value >> 56) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_read_u32_le(const uint8_t *data,
|
|
||||||
size_t len,
|
|
||||||
size_t *offset,
|
|
||||||
uint32_t *out) {
|
|
||||||
if (len - *offset < 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = (uint32_t)data[*offset] |
|
|
||||||
((uint32_t)data[*offset + 1u] << 8) |
|
|
||||||
((uint32_t)data[*offset + 2u] << 16) |
|
|
||||||
((uint32_t)data[*offset + 3u] << 24);
|
|
||||||
*offset += 4u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_read_u64_le(const uint8_t *data,
|
|
||||||
size_t len,
|
|
||||||
size_t *offset,
|
|
||||||
uint64_t *out) {
|
|
||||||
if (len - *offset < 8u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = (uint64_t)data[*offset] |
|
|
||||||
((uint64_t)data[*offset + 1u] << 8) |
|
|
||||||
((uint64_t)data[*offset + 2u] << 16) |
|
|
||||||
((uint64_t)data[*offset + 3u] << 24) |
|
|
||||||
((uint64_t)data[*offset + 4u] << 32) |
|
|
||||||
((uint64_t)data[*offset + 5u] << 40) |
|
|
||||||
((uint64_t)data[*offset + 6u] << 48) |
|
|
||||||
((uint64_t)data[*offset + 7u] << 56);
|
|
||||||
*offset += 8u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_add_size(size_t *acc, size_t add) {
|
|
||||||
if (*acc > SIZE_MAX - add) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*acc += add;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_encode_refs(const amduat_reference_t *refs,
|
|
||||||
size_t refs_len,
|
|
||||||
size_t *out_total_len) {
|
|
||||||
size_t total = 0u;
|
|
||||||
|
|
||||||
if (refs_len > UINT32_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_add_size(&total, 4u + ref_bytes.len)) {
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
*out_total_len = total;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_write_refs(uint8_t *buffer,
|
|
||||||
size_t total_len,
|
|
||||||
size_t *offset,
|
|
||||||
const amduat_reference_t *refs,
|
|
||||||
size_t refs_len) {
|
|
||||||
for (size_t i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_octets_t ref_bytes = amduat_octets(NULL, 0u);
|
|
||||||
if (!amduat_enc_asl1_core_encode_reference_v1(refs[i], &ref_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (total_len - *offset < 4u + ref_bytes.len) {
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
amduat_asl_store_u32_le(buffer + *offset, (uint32_t)ref_bytes.len);
|
|
||||||
*offset += 4u;
|
|
||||||
memcpy(buffer + *offset, ref_bytes.data, ref_bytes.len);
|
|
||||||
*offset += ref_bytes.len;
|
|
||||||
free((void *)ref_bytes.data);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_decode_refs(amduat_octets_t bytes,
|
|
||||||
size_t *offset,
|
|
||||||
uint32_t refs_len,
|
|
||||||
amduat_reference_t **out_refs,
|
|
||||||
size_t *out_refs_len) {
|
|
||||||
amduat_reference_t *refs = NULL;
|
|
||||||
|
|
||||||
if (out_refs == NULL || out_refs_len == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_refs = NULL;
|
|
||||||
*out_refs_len = 0u;
|
|
||||||
|
|
||||||
if (refs_len == 0u) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (refs_len > SIZE_MAX / sizeof(*refs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
refs = (amduat_reference_t *)calloc(refs_len, sizeof(*refs));
|
|
||||||
if (refs == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0u; i < refs_len; ++i) {
|
|
||||||
uint32_t ref_len = 0u;
|
|
||||||
amduat_octets_t ref_bytes;
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, offset, &ref_len)) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
if (bytes.len - *offset < ref_len) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
ref_bytes = amduat_octets(bytes.data + *offset, ref_len);
|
|
||||||
if (!amduat_enc_asl1_core_decode_reference_v1(ref_bytes, &refs[i])) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
*offset += ref_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_refs = refs;
|
|
||||||
*out_refs_len = refs_len;
|
|
||||||
return true;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
for (uint32_t i = 0u; i < refs_len; ++i) {
|
|
||||||
amduat_reference_free(&refs[i]);
|
|
||||||
}
|
|
||||||
free(refs);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_collection_snapshot_info_encode_v1(
|
|
||||||
const amduat_asl_collection_snapshot_info_t *info,
|
|
||||||
amduat_octets_t *out_bytes) {
|
|
||||||
uint8_t *buffer;
|
|
||||||
size_t total_len = 0u;
|
|
||||||
size_t refs_len_bytes = 0u;
|
|
||||||
size_t offset = 0u;
|
|
||||||
|
|
||||||
if (out_bytes == NULL || info == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_bytes->data = NULL;
|
|
||||||
out_bytes->len = 0u;
|
|
||||||
|
|
||||||
if (!amduat_asl_add_size(&total_len,
|
|
||||||
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN + 4u + 8u + 4u)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_encode_refs(info->refs, info->refs_len, &refs_len_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer + offset, k_amduat_asl_snapshot_info_magic,
|
|
||||||
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN);
|
|
||||||
offset += AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN;
|
|
||||||
amduat_asl_store_u32_le(buffer + offset, AMDUAT_ASL_SNAPSHOT_INFO_VERSION);
|
|
||||||
offset += 4u;
|
|
||||||
amduat_asl_store_u64_le(buffer + offset, info->snapshot_at_offset);
|
|
||||||
offset += 8u;
|
|
||||||
amduat_asl_store_u32_le(buffer + offset, (uint32_t)info->refs_len);
|
|
||||||
offset += 4u;
|
|
||||||
if (!amduat_asl_write_refs(buffer, total_len, &offset,
|
|
||||||
info->refs, info->refs_len)) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset != total_len) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_bytes = amduat_octets(buffer, total_len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_collection_snapshot_info_decode_v1(
|
|
||||||
amduat_octets_t bytes,
|
|
||||||
amduat_asl_collection_snapshot_info_t *out_info) {
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t version = 0u;
|
|
||||||
uint32_t refs_len = 0u;
|
|
||||||
|
|
||||||
if (out_info == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_info->snapshot_at_offset = 0u;
|
|
||||||
out_info->refs = NULL;
|
|
||||||
out_info->refs_len = 0u;
|
|
||||||
|
|
||||||
if (bytes.len < AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN + 4u + 8u + 4u ||
|
|
||||||
bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(bytes.data, k_amduat_asl_snapshot_info_magic,
|
|
||||||
AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset += AMDUAT_ASL_SNAPSHOT_INFO_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
|
|
||||||
version != AMDUAT_ASL_SNAPSHOT_INFO_VERSION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
|
||||||
&out_info->snapshot_at_offset)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
|
|
||||||
&out_info->refs, &out_info->refs_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return offset == bytes.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_asl_collection_snapshot_info_free(
|
|
||||||
amduat_asl_collection_snapshot_info_t *info) {
|
|
||||||
if (info == NULL || info->refs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < info->refs_len; ++i) {
|
|
||||||
amduat_reference_free(&info->refs[i]);
|
|
||||||
}
|
|
||||||
free(info->refs);
|
|
||||||
info->refs = NULL;
|
|
||||||
info->refs_len = 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_log_range_encode_v1(const amduat_asl_log_range_t *range,
|
|
||||||
amduat_octets_t *out_bytes) {
|
|
||||||
uint8_t *buffer;
|
|
||||||
size_t total_len = 0u;
|
|
||||||
size_t refs_len_bytes = 0u;
|
|
||||||
size_t offset = 0u;
|
|
||||||
|
|
||||||
if (out_bytes == NULL || range == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_bytes->data = NULL;
|
|
||||||
out_bytes->len = 0u;
|
|
||||||
|
|
||||||
if (!amduat_asl_add_size(&total_len,
|
|
||||||
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN + 4u + 8u + 8u + 4u)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_encode_refs(range->refs, range->refs_len, &refs_len_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer + offset, k_amduat_asl_log_range_magic,
|
|
||||||
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN);
|
|
||||||
offset += AMDUAT_ASL_LOG_RANGE_MAGIC_LEN;
|
|
||||||
amduat_asl_store_u32_le(buffer + offset, AMDUAT_ASL_LOG_RANGE_VERSION);
|
|
||||||
offset += 4u;
|
|
||||||
amduat_asl_store_u64_le(buffer + offset, range->start_offset);
|
|
||||||
offset += 8u;
|
|
||||||
amduat_asl_store_u64_le(buffer + offset, range->next_offset);
|
|
||||||
offset += 8u;
|
|
||||||
amduat_asl_store_u32_le(buffer + offset, (uint32_t)range->refs_len);
|
|
||||||
offset += 4u;
|
|
||||||
if (!amduat_asl_write_refs(buffer, total_len, &offset,
|
|
||||||
range->refs, range->refs_len)) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset != total_len) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_bytes = amduat_octets(buffer, total_len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_log_range_decode_v1(amduat_octets_t bytes,
|
|
||||||
amduat_asl_log_range_t *out_range) {
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t version = 0u;
|
|
||||||
uint32_t refs_len = 0u;
|
|
||||||
|
|
||||||
if (out_range == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_range->start_offset = 0u;
|
|
||||||
out_range->next_offset = 0u;
|
|
||||||
out_range->refs = NULL;
|
|
||||||
out_range->refs_len = 0u;
|
|
||||||
|
|
||||||
if (bytes.len <
|
|
||||||
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN + 4u + 8u + 8u + 4u ||
|
|
||||||
bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(bytes.data, k_amduat_asl_log_range_magic,
|
|
||||||
AMDUAT_ASL_LOG_RANGE_MAGIC_LEN) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset += AMDUAT_ASL_LOG_RANGE_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
|
|
||||||
version != AMDUAT_ASL_LOG_RANGE_VERSION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
|
||||||
&out_range->start_offset) ||
|
|
||||||
!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
|
||||||
&out_range->next_offset)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
|
|
||||||
&out_range->refs, &out_range->refs_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return offset == bytes.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_asl_log_range_free(amduat_asl_log_range_t *range) {
|
|
||||||
if (range == NULL || range->refs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < range->refs_len; ++i) {
|
|
||||||
amduat_reference_free(&range->refs[i]);
|
|
||||||
}
|
|
||||||
free(range->refs);
|
|
||||||
range->refs = NULL;
|
|
||||||
range->refs_len = 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_collection_view_encode_v1(
|
|
||||||
const amduat_asl_collection_view_t *view,
|
|
||||||
amduat_octets_t *out_bytes) {
|
|
||||||
uint8_t *buffer;
|
|
||||||
size_t total_len = 0u;
|
|
||||||
size_t refs_len_bytes = 0u;
|
|
||||||
size_t offset = 0u;
|
|
||||||
|
|
||||||
if (out_bytes == NULL || view == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_bytes->data = NULL;
|
|
||||||
out_bytes->len = 0u;
|
|
||||||
|
|
||||||
if (!amduat_asl_add_size(&total_len,
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN + 4u +
|
|
||||||
8u + 8u + 4u)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_encode_refs(view->refs, view->refs_len, &refs_len_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_add_size(&total_len, refs_len_bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer + offset, k_amduat_asl_collection_view_magic,
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN);
|
|
||||||
offset += AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN;
|
|
||||||
amduat_asl_store_u32_le(buffer + offset,
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_VERSION);
|
|
||||||
offset += 4u;
|
|
||||||
amduat_asl_store_u64_le(buffer + offset, view->computed_from_offset);
|
|
||||||
offset += 8u;
|
|
||||||
amduat_asl_store_u64_le(buffer + offset, view->computed_up_to_offset);
|
|
||||||
offset += 8u;
|
|
||||||
amduat_asl_store_u32_le(buffer + offset, (uint32_t)view->refs_len);
|
|
||||||
offset += 4u;
|
|
||||||
if (!amduat_asl_write_refs(buffer, total_len, &offset,
|
|
||||||
view->refs, view->refs_len)) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset != total_len) {
|
|
||||||
free(buffer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_bytes = amduat_octets(buffer, total_len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_collection_view_decode_v1(
|
|
||||||
amduat_octets_t bytes,
|
|
||||||
amduat_asl_collection_view_t *out_view) {
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t version = 0u;
|
|
||||||
uint32_t refs_len = 0u;
|
|
||||||
|
|
||||||
if (out_view == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_view->computed_from_offset = 0u;
|
|
||||||
out_view->computed_up_to_offset = 0u;
|
|
||||||
out_view->refs = NULL;
|
|
||||||
out_view->refs_len = 0u;
|
|
||||||
|
|
||||||
if (bytes.len <
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN + 4u + 8u + 8u + 4u ||
|
|
||||||
bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(bytes.data, k_amduat_asl_collection_view_magic,
|
|
||||||
AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset += AMDUAT_ASL_COLLECTION_VIEW_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &version) ||
|
|
||||||
version != AMDUAT_ASL_COLLECTION_VIEW_VERSION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
|
||||||
&out_view->computed_from_offset) ||
|
|
||||||
!amduat_asl_read_u64_le(bytes.data, bytes.len, &offset,
|
|
||||||
&out_view->computed_up_to_offset)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_read_u32_le(bytes.data, bytes.len, &offset, &refs_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_decode_refs(bytes, &offset, refs_len,
|
|
||||||
&out_view->refs, &out_view->refs_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return offset == bytes.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_asl_collection_view_free(amduat_asl_collection_view_t *view) {
|
|
||||||
if (view == NULL || view->refs == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (size_t i = 0u; i < view->refs_len; ++i) {
|
|
||||||
amduat_reference_free(&view->refs[i]);
|
|
||||||
}
|
|
||||||
free(view->refs);
|
|
||||||
view->refs = NULL;
|
|
||||||
view->refs_len = 0u;
|
|
||||||
}
|
|
||||||
|
|
@ -1,110 +0,0 @@
|
||||||
#include "amduat/asl/none.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
AMDUAT_ASL_NONE_MAGIC_LEN = 8,
|
|
||||||
AMDUAT_ASL_NONE_VERSION = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t k_amduat_asl_none_magic[AMDUAT_ASL_NONE_MAGIC_LEN] = {
|
|
||||||
'A', 'S', 'L', 'N', 'O', 'N', '1', '\0'
|
|
||||||
};
|
|
||||||
|
|
||||||
static void amduat_asl_none_store_u32_le(uint8_t *out, uint32_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
out[2] = (uint8_t)((value >> 16) & 0xffu);
|
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_none_read_u32_le(const uint8_t *data,
|
|
||||||
size_t len,
|
|
||||||
size_t *offset,
|
|
||||||
uint32_t *out) {
|
|
||||||
if (len - *offset < 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out = (uint32_t)data[*offset] |
|
|
||||||
((uint32_t)data[*offset + 1u] << 8) |
|
|
||||||
((uint32_t)data[*offset + 2u] << 16) |
|
|
||||||
((uint32_t)data[*offset + 3u] << 24);
|
|
||||||
*offset += 4u;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_none_encode_v1(amduat_octets_t *out_bytes) {
|
|
||||||
uint8_t *buffer;
|
|
||||||
size_t offset = 0u;
|
|
||||||
|
|
||||||
if (out_bytes == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
out_bytes->data = NULL;
|
|
||||||
out_bytes->len = 0u;
|
|
||||||
|
|
||||||
buffer = (uint8_t *)malloc(AMDUAT_ASL_NONE_MAGIC_LEN + 4u);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer + offset, k_amduat_asl_none_magic, AMDUAT_ASL_NONE_MAGIC_LEN);
|
|
||||||
offset += AMDUAT_ASL_NONE_MAGIC_LEN;
|
|
||||||
amduat_asl_none_store_u32_le(buffer + offset, AMDUAT_ASL_NONE_VERSION);
|
|
||||||
offset += 4u;
|
|
||||||
|
|
||||||
out_bytes->data = buffer;
|
|
||||||
out_bytes->len = offset;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_none_decode_v1(amduat_octets_t bytes) {
|
|
||||||
size_t offset = 0u;
|
|
||||||
uint32_t version = 0u;
|
|
||||||
|
|
||||||
if (bytes.len != AMDUAT_ASL_NONE_MAGIC_LEN + 4u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (memcmp(bytes.data, k_amduat_asl_none_magic,
|
|
||||||
AMDUAT_ASL_NONE_MAGIC_LEN) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset += AMDUAT_ASL_NONE_MAGIC_LEN;
|
|
||||||
if (!amduat_asl_none_read_u32_le(bytes.data, bytes.len, &offset, &version)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (version != AMDUAT_ASL_NONE_VERSION) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return offset == bytes.len;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_none_is_artifact(const amduat_artifact_t *artifact) {
|
|
||||||
if (artifact == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!artifact->has_type_tag ||
|
|
||||||
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_NONE_1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return amduat_asl_none_decode_v1(artifact->bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_none_artifact(amduat_artifact_t *out_artifact) {
|
|
||||||
amduat_octets_t bytes = amduat_octets(NULL, 0u);
|
|
||||||
|
|
||||||
if (out_artifact == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_none_encode_v1(&bytes)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_artifact =
|
|
||||||
amduat_artifact_with_type(bytes, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_NONE_1));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
@ -29,11 +29,6 @@ static void amduat_asl_log_store_u32_le(uint8_t *out, uint32_t value) {
|
||||||
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
out[3] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amduat_asl_log_store_u16_le(uint8_t *out, uint16_t value) {
|
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_asl_log_store_u64_le(uint8_t *out, uint64_t value) {
|
static void amduat_asl_log_store_u64_le(uint8_t *out, uint64_t value) {
|
||||||
out[0] = (uint8_t)(value & 0xffu);
|
out[0] = (uint8_t)(value & 0xffu);
|
||||||
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
out[1] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
|
@ -59,19 +54,6 @@ static bool amduat_asl_log_read_u32_le(amduat_asl_log_cursor_t *cur,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool amduat_asl_log_read_u16_le(amduat_asl_log_cursor_t *cur,
|
|
||||||
uint16_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (cur->len - cur->offset < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = cur->data + cur->offset;
|
|
||||||
*out = (uint16_t)data[0] | ((uint16_t)data[1] << 8);
|
|
||||||
cur->offset += 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_log_read_u64_le(amduat_asl_log_cursor_t *cur,
|
static bool amduat_asl_log_read_u64_le(amduat_asl_log_cursor_t *cur,
|
||||||
uint64_t *out) {
|
uint64_t *out) {
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
|
|
@ -110,67 +92,6 @@ static bool amduat_asl_log_is_known_record_type(uint32_t record_type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool amduat_asl_log_decode_artifact_ref(amduat_octets_t payload,
|
|
||||||
amduat_reference_t *out_ref) {
|
|
||||||
amduat_asl_log_cursor_t cur;
|
|
||||||
uint32_t hash_id_raw;
|
|
||||||
uint16_t digest_len;
|
|
||||||
uint16_t reserved0;
|
|
||||||
|
|
||||||
if (out_ref == NULL || payload.data == NULL || payload.len < 8u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cur.data = payload.data;
|
|
||||||
cur.len = payload.len;
|
|
||||||
cur.offset = 0;
|
|
||||||
|
|
||||||
if (!amduat_asl_log_read_u32_le(&cur, &hash_id_raw) ||
|
|
||||||
!amduat_asl_log_read_u16_le(&cur, &digest_len) ||
|
|
||||||
!amduat_asl_log_read_u16_le(&cur, &reserved0)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (hash_id_raw > UINT16_MAX || digest_len == 0 || reserved0 != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (cur.len - cur.offset < digest_len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
amduat_octets_t digest = amduat_octets(cur.data + cur.offset, digest_len);
|
|
||||||
amduat_reference_t tmp =
|
|
||||||
amduat_reference((amduat_hash_id_t)hash_id_raw, digest);
|
|
||||||
return amduat_reference_clone(tmp, out_ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_asl_log_encode_artifact_ref(amduat_reference_t ref,
|
|
||||||
amduat_octets_t *out_bytes) {
|
|
||||||
uint8_t *buf;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (out_bytes == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_bytes = amduat_octets(NULL, 0u);
|
|
||||||
if (ref.hash_id == 0 || ref.digest.data == NULL || ref.digest.len == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ref.digest.len > UINT16_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
len = 8u + ref.digest.len;
|
|
||||||
buf = (uint8_t *)malloc(len);
|
|
||||||
if (buf == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
amduat_asl_log_store_u32_le(buf, ref.hash_id);
|
|
||||||
amduat_asl_log_store_u16_le(buf + 4u, (uint16_t)ref.digest.len);
|
|
||||||
amduat_asl_log_store_u16_le(buf + 6u, 0u);
|
|
||||||
memcpy(buf + 8u, ref.digest.data, ref.digest.len);
|
|
||||||
*out_bytes = amduat_octets(buf, len);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_asl_log_hash_record(const uint8_t prev_hash[32],
|
static bool amduat_asl_log_hash_record(const uint8_t prev_hash[32],
|
||||||
uint64_t logseq,
|
uint64_t logseq,
|
||||||
uint32_t record_type,
|
uint32_t record_type,
|
||||||
|
|
|
||||||
|
|
@ -95,16 +95,6 @@ const char *amduat_format_pel_kernel_kind_name(
|
||||||
return "const";
|
return "const";
|
||||||
case AMDUAT_PEL_KERNEL_OP_HASH_ASL1:
|
case AMDUAT_PEL_KERNEL_OP_HASH_ASL1:
|
||||||
return "hash_asl1";
|
return "hash_asl1";
|
||||||
case AMDUAT_PEL_KERNEL_OP_PARAMS:
|
|
||||||
return "params";
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
|
||||||
return "format_encode";
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
|
||||||
return "collection_snapshot_decode";
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
|
||||||
return "log_read_range";
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
|
||||||
return "collection_merge_refs";
|
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#include "amduat/pel/opreg_kernel.h"
|
#include "amduat/pel/opreg_kernel.h"
|
||||||
#include "amduat/pel/opreg_kernel_params.h"
|
#include "amduat/pel/opreg_kernel_params.h"
|
||||||
#include "kernel_collection.h"
|
|
||||||
#include "amduat/hash/asl1.h"
|
#include "amduat/hash/asl1.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -65,32 +64,8 @@ static const amduat_pel_kernel_op_desc_t k_kernel_descs[] = {
|
||||||
3,
|
3,
|
||||||
1
|
1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_SNAPSHOT_DECODE,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_LOG_READ_RANGE,
|
|
||||||
3,
|
|
||||||
3,
|
|
||||||
1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_CODE_COLLECTION_MERGE_REFS,
|
|
||||||
4,
|
|
||||||
4,
|
|
||||||
1
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static amduat_pel_kernel_artifact_resolver_t g_resolver = NULL;
|
|
||||||
static void *g_resolver_ctx = NULL;
|
|
||||||
|
|
||||||
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
||||||
amduat_octets_t name,
|
amduat_octets_t name,
|
||||||
uint32_t version) {
|
uint32_t version) {
|
||||||
|
|
@ -115,16 +90,6 @@ const amduat_pel_kernel_op_desc_t *amduat_pel_kernel_op_lookup(
|
||||||
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME)) {
|
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME)) {
|
||||||
return &k_kernel_descs[5];
|
return &k_kernel_descs[5];
|
||||||
}
|
}
|
||||||
if (amduat_name_eq(name,
|
|
||||||
AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME)) {
|
|
||||||
return &k_kernel_descs[6];
|
|
||||||
}
|
|
||||||
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME)) {
|
|
||||||
return &k_kernel_descs[7];
|
|
||||||
}
|
|
||||||
if (amduat_name_eq(name, AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME)) {
|
|
||||||
return &k_kernel_descs[8];
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,37 +115,11 @@ const char *amduat_pel_kernel_op_name(amduat_pel_kernel_op_kind_t kind) {
|
||||||
return AMDUAT_PEL_KERNEL_OP_PARAMS_NAME;
|
return AMDUAT_PEL_KERNEL_OP_PARAMS_NAME;
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
return AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME;
|
return AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE_NAME;
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
|
||||||
return AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE_NAME;
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
|
||||||
return AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE_NAME;
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
|
||||||
return AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS_NAME;
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void amduat_pel_kernel_set_artifact_resolver(
|
|
||||||
amduat_pel_kernel_artifact_resolver_t resolver,
|
|
||||||
void *ctx) {
|
|
||||||
g_resolver = resolver;
|
|
||||||
g_resolver_ctx = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void amduat_pel_kernel_clear_artifact_resolver(void) {
|
|
||||||
g_resolver = NULL;
|
|
||||||
g_resolver_ctx = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_pel_kernel_resolve_artifact(amduat_reference_t ref,
|
|
||||||
amduat_artifact_t *out_artifact) {
|
|
||||||
if (g_resolver == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return g_resolver(ref, out_artifact, g_resolver_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_type_tags_match(const amduat_artifact_t *a,
|
static bool amduat_type_tags_match(const amduat_artifact_t *a,
|
||||||
const amduat_artifact_t *b) {
|
const amduat_artifact_t *b) {
|
||||||
if (a->has_type_tag != b->has_type_tag) {
|
if (a->has_type_tag != b->has_type_tag) {
|
||||||
|
|
@ -1598,15 +1537,6 @@ bool amduat_pel_kernel_op_eval(
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
return amduat_kernel_format_encode(inputs, inputs_len, out_outputs,
|
return amduat_kernel_format_encode(inputs, inputs_len, out_outputs,
|
||||||
out_outputs_len, out_status_code);
|
out_outputs_len, out_status_code);
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
|
||||||
return amduat_kernel_collection_snapshot_decode(
|
|
||||||
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
|
||||||
return amduat_kernel_log_read_range(
|
|
||||||
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
|
||||||
return amduat_kernel_collection_merge_refs(
|
|
||||||
inputs, inputs_len, out_outputs, out_outputs_len, out_status_code);
|
|
||||||
default:
|
default:
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -1,615 +0,0 @@
|
||||||
#include "kernel_collection.h"
|
|
||||||
|
|
||||||
#include "amduat/asl/collection.h"
|
|
||||||
#include "amduat/asl/collection_view.h"
|
|
||||||
#include "amduat/asl/log_store.h"
|
|
||||||
#include "amduat/asl/none.h"
|
|
||||||
#include "amduat/asl/record.h"
|
|
||||||
|
|
||||||
#include <limits.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static bool amduat_alloc_outputs(size_t count,
|
|
||||||
amduat_artifact_t **out_outputs) {
|
|
||||||
amduat_artifact_t *outputs;
|
|
||||||
|
|
||||||
if (out_outputs == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
outputs = (amduat_artifact_t *)calloc(count, sizeof(*outputs));
|
|
||||||
if (outputs == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_outputs = outputs;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_load_u64_le(amduat_octets_t bytes,
|
|
||||||
size_t offset,
|
|
||||||
uint64_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (out == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytes.len - offset < 8u || bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = bytes.data + offset;
|
|
||||||
*out = (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);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_load_u32_le(amduat_octets_t bytes,
|
|
||||||
size_t offset,
|
|
||||||
uint32_t *out) {
|
|
||||||
const uint8_t *data;
|
|
||||||
|
|
||||||
if (out == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bytes.len - offset < 4u || bytes.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
data = bytes.data + offset;
|
|
||||||
*out = (uint32_t)data[0] |
|
|
||||||
((uint32_t)data[1] << 8) |
|
|
||||||
((uint32_t)data[2] << 16) |
|
|
||||||
((uint32_t)data[3] << 24);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_decode_params(const amduat_artifact_t *artifact,
|
|
||||||
uint64_t *out_from,
|
|
||||||
uint32_t *out_limit) {
|
|
||||||
const char k_params_schema[] = "pel/params";
|
|
||||||
amduat_asl_record_t record;
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
if (artifact == NULL || out_from == NULL || out_limit == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!artifact->has_type_tag ||
|
|
||||||
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_record_decode_v1(artifact->bytes, &record)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (record.schema.len != strlen(k_params_schema) ||
|
|
||||||
record.schema.data == NULL ||
|
|
||||||
memcmp(record.schema.data, k_params_schema,
|
|
||||||
record.schema.len) != 0) {
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (record.payload.len != 12u) {
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_load_u64_le(record.payload, 0u, out_from) ||
|
|
||||||
!amduat_load_u32_le(record.payload, 8u, out_limit)) {
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ok = true;
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_log_chunk_from_artifact(
|
|
||||||
const amduat_artifact_t *artifact,
|
|
||||||
amduat_asl_log_chunk_t *out_chunk) {
|
|
||||||
if (artifact == NULL || out_chunk == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!artifact->has_type_tag ||
|
|
||||||
artifact->type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_CHUNK_1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return amduat_asl_log_chunk_decode_v1(artifact->bytes, out_chunk) ==
|
|
||||||
AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_kernel_collection_snapshot_decode(
|
|
||||||
const amduat_artifact_t *inputs,
|
|
||||||
size_t inputs_len,
|
|
||||||
amduat_artifact_t **out_outputs,
|
|
||||||
size_t *out_outputs_len,
|
|
||||||
uint32_t *out_status_code) {
|
|
||||||
amduat_asl_collection_snapshot_payload_t snapshot;
|
|
||||||
amduat_asl_collection_snapshot_info_t info;
|
|
||||||
amduat_asl_record_t record;
|
|
||||||
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
if (inputs == NULL || inputs_len != 1u) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&snapshot, 0, sizeof(snapshot));
|
|
||||||
memset(&info, 0, sizeof(info));
|
|
||||||
memset(&record, 0, sizeof(record));
|
|
||||||
|
|
||||||
if (amduat_asl_none_is_artifact(&inputs[0])) {
|
|
||||||
info.snapshot_at_offset = 0u;
|
|
||||||
info.refs = NULL;
|
|
||||||
info.refs_len = 0u;
|
|
||||||
} else {
|
|
||||||
if (!inputs[0].has_type_tag ||
|
|
||||||
inputs[0].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_RECORD_1) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_record_decode_v1(inputs[0].bytes, &record)) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (record.schema.len != strlen("collection/snapshot") ||
|
|
||||||
record.schema.data == NULL ||
|
|
||||||
memcmp(record.schema.data, "collection/snapshot",
|
|
||||||
record.schema.len) != 0) {
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_asl_collection_snapshot_payload_decode_v1(record.payload,
|
|
||||||
&snapshot)) {
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
info.snapshot_at_offset = snapshot.snapshot_offset;
|
|
||||||
info.refs = snapshot.refs;
|
|
||||||
info.refs_len = snapshot.refs_len;
|
|
||||||
amduat_asl_record_free(&record);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_collection_snapshot_info_encode_v1(&info, &encoded)) {
|
|
||||||
amduat_asl_collection_snapshot_payload_free(&snapshot);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_alloc_outputs(1u, out_outputs)) {
|
|
||||||
amduat_asl_collection_snapshot_payload_free(&snapshot);
|
|
||||||
free((void *)encoded.data);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*out_outputs)[0] = amduat_artifact_with_type(
|
|
||||||
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1));
|
|
||||||
if (out_outputs_len != NULL) {
|
|
||||||
*out_outputs_len = 1u;
|
|
||||||
}
|
|
||||||
ok = true;
|
|
||||||
|
|
||||||
amduat_asl_collection_snapshot_payload_free(&snapshot);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_kernel_log_read_range(
|
|
||||||
const amduat_artifact_t *inputs,
|
|
||||||
size_t inputs_len,
|
|
||||||
amduat_artifact_t **out_outputs,
|
|
||||||
size_t *out_outputs_len,
|
|
||||||
uint32_t *out_status_code) {
|
|
||||||
amduat_asl_log_range_t range;
|
|
||||||
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
|
||||||
uint64_t from_offset = 0u;
|
|
||||||
uint32_t limit = 0u;
|
|
||||||
uint64_t limit_from_offset = 0u;
|
|
||||||
uint32_t limit_value = 0u;
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
if (inputs == NULL || inputs_len != 3u) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_decode_params(&inputs[1], &from_offset, &limit_value)) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_decode_params(&inputs[2], &limit_from_offset, &limit)) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
(void)limit_from_offset;
|
|
||||||
(void)limit_value;
|
|
||||||
|
|
||||||
memset(&range, 0, sizeof(range));
|
|
||||||
range.start_offset = from_offset;
|
|
||||||
range.next_offset = from_offset;
|
|
||||||
range.refs = NULL;
|
|
||||||
range.refs_len = 0u;
|
|
||||||
|
|
||||||
if (limit == 0u || amduat_asl_none_is_artifact(&inputs[0])) {
|
|
||||||
goto encode_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
amduat_asl_log_chunk_t *chunks = NULL;
|
|
||||||
size_t chunks_len = 0u;
|
|
||||||
amduat_asl_log_chunk_t head_chunk;
|
|
||||||
uint64_t head_end_offset = 0u;
|
|
||||||
if (!amduat_log_chunk_from_artifact(&inputs[0], &head_chunk)) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (head_chunk.base_offset >
|
|
||||||
UINT64_MAX - (uint64_t)head_chunk.entry_count) {
|
|
||||||
amduat_asl_log_chunk_free(&head_chunk);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
head_end_offset = head_chunk.base_offset + head_chunk.entry_count;
|
|
||||||
|
|
||||||
{
|
|
||||||
amduat_asl_log_chunk_t *next =
|
|
||||||
(amduat_asl_log_chunk_t *)realloc(
|
|
||||||
chunks, (chunks_len + 1u) * sizeof(*chunks));
|
|
||||||
if (next == NULL) {
|
|
||||||
amduat_asl_log_chunk_free(&head_chunk);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
chunks = next;
|
|
||||||
chunks[chunks_len++] = head_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from_offset >= head_end_offset) {
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
range.next_offset = from_offset;
|
|
||||||
goto encode_range;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
amduat_asl_log_chunk_t chunk;
|
|
||||||
amduat_artifact_t prev_artifact;
|
|
||||||
|
|
||||||
if (chunks[chunks_len - 1u].base_offset <= from_offset ||
|
|
||||||
!chunks[chunks_len - 1u].has_prev) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&prev_artifact, 0, sizeof(prev_artifact));
|
|
||||||
if (!amduat_pel_kernel_resolve_artifact(
|
|
||||||
chunks[chunks_len - 1u].prev_ref, &prev_artifact)) {
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_REF_RESOLVE_FAILED;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!amduat_log_chunk_from_artifact(&prev_artifact, &chunk)) {
|
|
||||||
amduat_artifact_free(&prev_artifact);
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_CHUNK_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
amduat_artifact_free(&prev_artifact);
|
|
||||||
|
|
||||||
{
|
|
||||||
amduat_asl_log_chunk_t *next =
|
|
||||||
(amduat_asl_log_chunk_t *)realloc(
|
|
||||||
chunks, (chunks_len + 1u) * sizeof(*chunks));
|
|
||||||
if (next == NULL) {
|
|
||||||
amduat_asl_log_chunk_free(&chunk);
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
chunks = next;
|
|
||||||
chunks[chunks_len++] = chunk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (limit > SIZE_MAX) {
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (limit != 0u) {
|
|
||||||
range.refs = (amduat_reference_t *)calloc(limit, sizeof(*range.refs));
|
|
||||||
if (range.refs == NULL) {
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0u; i < chunks_len / 2u; ++i) {
|
|
||||||
amduat_asl_log_chunk_t tmp = chunks[i];
|
|
||||||
chunks[i] = chunks[chunks_len - 1u - i];
|
|
||||||
chunks[chunks_len - 1u - i] = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
range.refs_len = 0u;
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_t *chunk = &chunks[i];
|
|
||||||
for (uint32_t j = 0u; j < chunk->entry_count; ++j) {
|
|
||||||
uint64_t offset = chunk->base_offset + j;
|
|
||||||
if (offset < from_offset) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (range.refs_len == limit) {
|
|
||||||
goto done_collect;
|
|
||||||
}
|
|
||||||
if (!amduat_reference_clone(chunk->entries[j].payload_ref,
|
|
||||||
&range.refs[range.refs_len])) {
|
|
||||||
for (size_t k = 0u; k < chunks_len; ++k) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[k]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
amduat_asl_log_range_free(&range);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
range.refs_len++;
|
|
||||||
range.next_offset = offset + 1u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done_collect:
|
|
||||||
if (range.refs_len < limit) {
|
|
||||||
range.next_offset = head_end_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0u; i < chunks_len; ++i) {
|
|
||||||
amduat_asl_log_chunk_free(&chunks[i]);
|
|
||||||
}
|
|
||||||
free(chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
encode_range:
|
|
||||||
if (!amduat_asl_log_range_encode_v1(&range, &encoded)) {
|
|
||||||
amduat_asl_log_range_free(&range);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_alloc_outputs(1u, out_outputs)) {
|
|
||||||
amduat_asl_log_range_free(&range);
|
|
||||||
free((void *)encoded.data);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*out_outputs)[0] = amduat_artifact_with_type(
|
|
||||||
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1));
|
|
||||||
if (out_outputs_len != NULL) {
|
|
||||||
*out_outputs_len = 1u;
|
|
||||||
}
|
|
||||||
ok = true;
|
|
||||||
amduat_asl_log_range_free(&range);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool amduat_kernel_collection_merge_refs(
|
|
||||||
const amduat_artifact_t *inputs,
|
|
||||||
size_t inputs_len,
|
|
||||||
amduat_artifact_t **out_outputs,
|
|
||||||
size_t *out_outputs_len,
|
|
||||||
uint32_t *out_status_code) {
|
|
||||||
amduat_asl_collection_snapshot_info_t snapshot;
|
|
||||||
amduat_asl_log_range_t log_range;
|
|
||||||
amduat_asl_collection_view_t view;
|
|
||||||
amduat_octets_t encoded = amduat_octets(NULL, 0u);
|
|
||||||
uint64_t from_offset = 0u;
|
|
||||||
uint32_t limit = 0u;
|
|
||||||
uint64_t limit_from_offset = 0u;
|
|
||||||
uint32_t limit_value = 0u;
|
|
||||||
size_t total_refs = 0u;
|
|
||||||
size_t start_index = 0u;
|
|
||||||
size_t end_index = 0u;
|
|
||||||
bool ok = false;
|
|
||||||
|
|
||||||
if (inputs == NULL || inputs_len != 4u) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_INTERNAL;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_decode_params(&inputs[2], &from_offset, &limit_value) ||
|
|
||||||
!amduat_decode_params(&inputs[3], &limit_from_offset, &limit)) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_PARAMS_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
(void)limit_from_offset;
|
|
||||||
(void)limit_value;
|
|
||||||
|
|
||||||
memset(&snapshot, 0, sizeof(snapshot));
|
|
||||||
memset(&log_range, 0, sizeof(log_range));
|
|
||||||
memset(&view, 0, sizeof(view));
|
|
||||||
|
|
||||||
if (!inputs[0].has_type_tag ||
|
|
||||||
inputs[0].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_SNAPSHOT_INFO_1 ||
|
|
||||||
!amduat_asl_collection_snapshot_info_decode_v1(inputs[0].bytes,
|
|
||||||
&snapshot)) {
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_SNAPSHOT_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!inputs[1].has_type_tag ||
|
|
||||||
inputs[1].type_tag.tag_id != AMDUAT_TYPE_TAG_ASL_LOG_RANGE_1 ||
|
|
||||||
!amduat_asl_log_range_decode_v1(inputs[1].bytes, &log_range)) {
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_LOG_RANGE_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapshot.refs_len > SIZE_MAX - log_range.refs_len) {
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
amduat_asl_log_range_free(&log_range);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_COLLECTION_VIEW_INVALID;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
total_refs = snapshot.refs_len + log_range.refs_len;
|
|
||||||
if (from_offset > SIZE_MAX) {
|
|
||||||
start_index = total_refs;
|
|
||||||
} else {
|
|
||||||
start_index = (size_t)from_offset;
|
|
||||||
if (start_index > total_refs) {
|
|
||||||
start_index = total_refs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (limit > SIZE_MAX || start_index > SIZE_MAX - (size_t)limit) {
|
|
||||||
end_index = total_refs;
|
|
||||||
} else {
|
|
||||||
end_index = start_index + (size_t)limit;
|
|
||||||
if (end_index > total_refs) {
|
|
||||||
end_index = total_refs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view.refs_len = end_index - start_index;
|
|
||||||
view.refs = NULL;
|
|
||||||
if (view.refs_len != 0u) {
|
|
||||||
view.refs = (amduat_reference_t *)calloc(view.refs_len, sizeof(*view.refs));
|
|
||||||
if (view.refs == NULL) {
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
amduat_asl_log_range_free(&log_range);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0u; i < view.refs_len; ++i) {
|
|
||||||
size_t idx = start_index + i;
|
|
||||||
const amduat_reference_t *src =
|
|
||||||
(idx < snapshot.refs_len)
|
|
||||||
? &snapshot.refs[idx]
|
|
||||||
: &log_range.refs[idx - snapshot.refs_len];
|
|
||||||
if (!amduat_reference_clone(*src, &view.refs[i])) {
|
|
||||||
amduat_asl_collection_view_free(&view);
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
amduat_asl_log_range_free(&log_range);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
view.computed_from_offset = from_offset;
|
|
||||||
if (log_range.refs_len < limit) {
|
|
||||||
view.computed_up_to_offset = log_range.next_offset;
|
|
||||||
} else if (from_offset > UINT64_MAX - (uint64_t)view.refs_len) {
|
|
||||||
view.computed_up_to_offset = UINT64_MAX;
|
|
||||||
} else {
|
|
||||||
view.computed_up_to_offset = from_offset + (uint64_t)view.refs_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_asl_collection_view_encode_v1(&view, &encoded)) {
|
|
||||||
amduat_asl_collection_view_free(&view);
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
amduat_asl_log_range_free(&log_range);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!amduat_alloc_outputs(1u, out_outputs)) {
|
|
||||||
amduat_asl_collection_view_free(&view);
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
amduat_asl_log_range_free(&log_range);
|
|
||||||
free((void *)encoded.data);
|
|
||||||
if (out_status_code) {
|
|
||||||
*out_status_code = AMDUAT_PEL_KERNEL_STATUS_OOM;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*out_outputs)[0] = amduat_artifact_with_type(
|
|
||||||
encoded, amduat_type_tag(AMDUAT_TYPE_TAG_ASL_COLLECTION_VIEW_1));
|
|
||||||
if (out_outputs_len != NULL) {
|
|
||||||
*out_outputs_len = 1u;
|
|
||||||
}
|
|
||||||
ok = true;
|
|
||||||
|
|
||||||
amduat_asl_collection_view_free(&view);
|
|
||||||
amduat_asl_collection_snapshot_info_free(&snapshot);
|
|
||||||
amduat_asl_log_range_free(&log_range);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
#ifndef AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H
|
|
||||||
#define AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H
|
|
||||||
|
|
||||||
#include "amduat/pel/opreg_kernel.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
bool amduat_kernel_collection_snapshot_decode(
|
|
||||||
const amduat_artifact_t *inputs,
|
|
||||||
size_t inputs_len,
|
|
||||||
amduat_artifact_t **out_outputs,
|
|
||||||
size_t *out_outputs_len,
|
|
||||||
uint32_t *out_status_code);
|
|
||||||
|
|
||||||
bool amduat_kernel_log_read_range(
|
|
||||||
const amduat_artifact_t *inputs,
|
|
||||||
size_t inputs_len,
|
|
||||||
amduat_artifact_t **out_outputs,
|
|
||||||
size_t *out_outputs_len,
|
|
||||||
uint32_t *out_status_code);
|
|
||||||
|
|
||||||
bool amduat_kernel_collection_merge_refs(
|
|
||||||
const amduat_artifact_t *inputs,
|
|
||||||
size_t inputs_len,
|
|
||||||
amduat_artifact_t **out_outputs,
|
|
||||||
size_t *out_outputs_len,
|
|
||||||
uint32_t *out_status_code);
|
|
||||||
|
|
||||||
#endif /* AMDUAT_PEL_OPREG_KERNEL_COLLECTION_H */
|
|
||||||
|
|
@ -133,12 +133,6 @@ bool amduat_pel_kernel_params_decode(
|
||||||
return amduat_decode_unit(params_bytes);
|
return amduat_decode_unit(params_bytes);
|
||||||
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
case AMDUAT_PEL_KERNEL_OP_FORMAT_ENCODE:
|
||||||
return amduat_decode_unit(params_bytes);
|
return amduat_decode_unit(params_bytes);
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_SNAPSHOT_DECODE:
|
|
||||||
return amduat_decode_unit(params_bytes);
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_LOG_READ_RANGE:
|
|
||||||
return amduat_decode_unit(params_bytes);
|
|
||||||
case AMDUAT_PEL_KERNEL_OP_COLLECTION_MERGE_REFS:
|
|
||||||
return amduat_decode_unit(params_bytes);
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,12 @@
|
||||||
#include "amduat/pel/surf.h"
|
#include "amduat/pel/surf.h"
|
||||||
|
|
||||||
#include "amduat/asl/asl_materialization_cache_fs.h"
|
|
||||||
#include "amduat/asl/asl_store_fs.h"
|
|
||||||
#include "amduat/enc/pel1_result.h"
|
#include "amduat/enc/pel1_result.h"
|
||||||
#include "amduat/enc/pel_program_dag.h"
|
#include "amduat/enc/pel_program_dag.h"
|
||||||
#include "amduat/enc/pel_trace_dag.h"
|
#include "amduat/enc/pel_trace_dag.h"
|
||||||
#include "amduat/pel/derivation_sid.h"
|
|
||||||
#include "amduat/pel/opreg_kernel.h"
|
|
||||||
#include "amduat/util/log.h"
|
|
||||||
#include "pel_program_dag_internal.h"
|
#include "pel_program_dag_internal.h"
|
||||||
#include "amduat/pel/program_dag_desc.h"
|
#include "amduat/pel/program_dag_desc.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
@ -36,17 +30,6 @@ void amduat_pel_surf_free_ref(amduat_reference_t *ref) {
|
||||||
amduat_reference_free(ref);
|
amduat_reference_free(ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool amduat_pel_surf_resolve_artifact(amduat_reference_t ref,
|
|
||||||
amduat_artifact_t *out_artifact,
|
|
||||||
void *ctx) {
|
|
||||||
amduat_asl_store_t *store = (amduat_asl_store_t *)ctx;
|
|
||||||
if (store == NULL || out_artifact == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return amduat_asl_store_get(store, ref, out_artifact) ==
|
|
||||||
AMDUAT_ASL_STORE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void amduat_init_core_result(amduat_pel_execution_result_value_t *result,
|
static void amduat_init_core_result(amduat_pel_execution_result_value_t *result,
|
||||||
amduat_reference_t scheme_ref,
|
amduat_reference_t scheme_ref,
|
||||||
amduat_pel_execution_status_t status,
|
amduat_pel_execution_status_t status,
|
||||||
|
|
@ -234,37 +217,6 @@ static void amduat_trace_nodes_free(amduat_pel_node_trace_dag_t *nodes,
|
||||||
free(nodes);
|
free(nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char k_materialized_hit_op_name[] = "materialized_hit";
|
|
||||||
|
|
||||||
static bool amduat_pel_surf_store_fs_ctx(
|
|
||||||
const amduat_asl_store_t *store,
|
|
||||||
amduat_asl_store_fs_t **out_fs) {
|
|
||||||
amduat_asl_store_ops_t fs_ops;
|
|
||||||
|
|
||||||
if (out_fs == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_fs = NULL;
|
|
||||||
if (store == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs_ops = amduat_asl_store_fs_ops();
|
|
||||||
if (store->ops.put != fs_ops.put ||
|
|
||||||
store->ops.get != fs_ops.get ||
|
|
||||||
store->ops.put_indexed != fs_ops.put_indexed ||
|
|
||||||
store->ops.get_indexed != fs_ops.get_indexed ||
|
|
||||||
store->ops.tombstone != fs_ops.tombstone ||
|
|
||||||
store->ops.tombstone_lift != fs_ops.tombstone_lift ||
|
|
||||||
store->ops.log_scan != fs_ops.log_scan ||
|
|
||||||
store->ops.current_state != fs_ops.current_state ||
|
|
||||||
store->ops.validate_config != fs_ops.validate_config) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*out_fs = (amduat_asl_store_fs_t *)store->ctx;
|
|
||||||
return *out_fs != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool amduat_store_trace(
|
static bool amduat_store_trace(
|
||||||
amduat_asl_store_t *store,
|
amduat_asl_store_t *store,
|
||||||
amduat_reference_t scheme_ref,
|
amduat_reference_t scheme_ref,
|
||||||
|
|
@ -278,7 +230,6 @@ static bool amduat_store_trace(
|
||||||
const amduat_pel_execution_result_value_t *core_result,
|
const amduat_pel_execution_result_value_t *core_result,
|
||||||
const amduat_pel_program_t *program,
|
const amduat_pel_program_t *program,
|
||||||
const amduat_pel_program_dag_trace_t *trace_eval,
|
const amduat_pel_program_dag_trace_t *trace_eval,
|
||||||
bool materialized_hit,
|
|
||||||
amduat_reference_t *out_trace_ref) {
|
amduat_reference_t *out_trace_ref) {
|
||||||
amduat_pel_trace_dag_value_t trace;
|
amduat_pel_trace_dag_value_t trace;
|
||||||
amduat_pel_node_trace_dag_t *node_traces;
|
amduat_pel_node_trace_dag_t *node_traces;
|
||||||
|
|
@ -360,29 +311,6 @@ static bool amduat_store_trace(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (materialized_hit) {
|
|
||||||
amduat_pel_node_trace_dag_t *next;
|
|
||||||
|
|
||||||
/* Emit a synthetic trace entry to mark a materialization cache hit. */
|
|
||||||
next = (amduat_pel_node_trace_dag_t *)realloc(
|
|
||||||
node_traces, (node_count + 1u) * sizeof(*node_traces));
|
|
||||||
if (next == NULL) {
|
|
||||||
amduat_trace_nodes_free(node_traces, node_count);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
node_traces = next;
|
|
||||||
memset(&node_traces[node_count], 0, sizeof(*node_traces));
|
|
||||||
/* UINT32_MAX is a reserved sentinel; decoders treat node_id as opaque. */
|
|
||||||
node_traces[node_count].node_id = UINT32_MAX;
|
|
||||||
node_traces[node_count].op_name = amduat_octets(
|
|
||||||
(const uint8_t *)k_materialized_hit_op_name,
|
|
||||||
sizeof(k_materialized_hit_op_name) - 1u);
|
|
||||||
node_traces[node_count].op_version = 1u;
|
|
||||||
node_traces[node_count].status = AMDUAT_PEL_NODE_TRACE_SKIPPED;
|
|
||||||
node_traces[node_count].status_code = 0u;
|
|
||||||
node_count += 1u;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&trace, 0, sizeof(trace));
|
memset(&trace, 0, sizeof(trace));
|
||||||
trace.pel1_version = 1;
|
trace.pel1_version = 1;
|
||||||
trace.scheme_ref = scheme_ref;
|
trace.scheme_ref = scheme_ref;
|
||||||
|
|
@ -439,8 +367,6 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
size_t outputs_len;
|
size_t outputs_len;
|
||||||
amduat_reference_t *output_refs;
|
amduat_reference_t *output_refs;
|
||||||
size_t output_refs_len;
|
size_t output_refs_len;
|
||||||
amduat_asl_materialization_cache_fs_t mat_cache;
|
|
||||||
amduat_octets_t sid;
|
|
||||||
amduat_reference_t trace_ref;
|
amduat_reference_t trace_ref;
|
||||||
amduat_reference_t exec_result_ref;
|
amduat_reference_t exec_result_ref;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
@ -449,10 +375,6 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
bool exec_invoked = false;
|
bool exec_invoked = false;
|
||||||
bool trace_ok = false;
|
bool trace_ok = false;
|
||||||
bool has_exec_result_ref = false;
|
bool has_exec_result_ref = false;
|
||||||
bool mat_cache_ready = false;
|
|
||||||
bool materialized_hit = false;
|
|
||||||
bool cache_miss_due_missing = false;
|
|
||||||
bool executed = false;
|
|
||||||
|
|
||||||
if (store == NULL || out_output_refs == NULL ||
|
if (store == NULL || out_output_refs == NULL ||
|
||||||
out_output_refs_len == NULL || out_result_ref == NULL) {
|
out_output_refs_len == NULL || out_result_ref == NULL) {
|
||||||
|
|
@ -470,7 +392,6 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
trace_ref.digest = amduat_octets(NULL, 0);
|
trace_ref.digest = amduat_octets(NULL, 0);
|
||||||
exec_result_ref.hash_id = 0;
|
exec_result_ref.hash_id = 0;
|
||||||
exec_result_ref.digest = amduat_octets(NULL, 0);
|
exec_result_ref.digest = amduat_octets(NULL, 0);
|
||||||
sid = amduat_octets(NULL, 0);
|
|
||||||
|
|
||||||
if (!amduat_reference_eq(scheme_ref,
|
if (!amduat_reference_eq(scheme_ref,
|
||||||
amduat_pel_program_dag_scheme_ref())) {
|
amduat_pel_program_dag_scheme_ref())) {
|
||||||
|
|
@ -569,75 +490,6 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
has_params_artifact = true;
|
has_params_artifact = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Cache safety assumptions:
|
|
||||||
* - PEL DAG execution is deterministic for ProgramRef + Inputs + Params.
|
|
||||||
* - ExecProfile is currently absent and encoded as a marker only.
|
|
||||||
* - The store is single-tenant; SID collisions are treated as integrity errors.
|
|
||||||
* - This code path assumes amduat_asl_store_fs_t as the backing store.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
amduat_pel_derivation_sid_input_t sid_input;
|
|
||||||
|
|
||||||
memset(&sid_input, 0, sizeof(sid_input));
|
|
||||||
sid_input.program_ref = program_ref;
|
|
||||||
sid_input.input_refs = input_refs;
|
|
||||||
sid_input.input_refs_len = input_refs_len;
|
|
||||||
sid_input.has_params_ref = has_params_ref;
|
|
||||||
if (has_params_ref) {
|
|
||||||
sid_input.params_ref = params_ref;
|
|
||||||
}
|
|
||||||
sid_input.has_exec_profile = false;
|
|
||||||
sid_input.exec_profile = amduat_octets(NULL, 0u);
|
|
||||||
|
|
||||||
if (amduat_pel_derivation_sid_compute(&sid_input, &sid)) {
|
|
||||||
amduat_asl_store_fs_t *fs = NULL;
|
|
||||||
if (amduat_pel_surf_store_fs_ctx(store, &fs) &&
|
|
||||||
amduat_asl_materialization_cache_fs_init(&mat_cache,
|
|
||||||
fs->root_path)) {
|
|
||||||
mat_cache_ready = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mat_cache_ready) {
|
|
||||||
amduat_reference_t *cached_refs = NULL;
|
|
||||||
size_t cached_len = 0;
|
|
||||||
amduat_asl_store_error_t cache_err;
|
|
||||||
|
|
||||||
cache_err = amduat_asl_materialization_cache_fs_get(&mat_cache, sid,
|
|
||||||
&cached_refs,
|
|
||||||
&cached_len);
|
|
||||||
if (cache_err == AMDUAT_ASL_STORE_OK) {
|
|
||||||
bool cache_valid = true;
|
|
||||||
for (i = 0; i < cached_len; ++i) {
|
|
||||||
amduat_artifact_t cached_artifact;
|
|
||||||
if (amduat_asl_store_get(store, cached_refs[i],
|
|
||||||
&cached_artifact) !=
|
|
||||||
AMDUAT_ASL_STORE_OK) {
|
|
||||||
cache_valid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
amduat_artifact_free(&cached_artifact);
|
|
||||||
}
|
|
||||||
if (cache_valid) {
|
|
||||||
output_refs = cached_refs;
|
|
||||||
output_refs_len = cached_len;
|
|
||||||
materialized_hit = true;
|
|
||||||
exec_invoked = true;
|
|
||||||
amduat_init_core_result(&core_result, scheme_ref,
|
|
||||||
AMDUAT_PEL_EXEC_STATUS_OK,
|
|
||||||
AMDUAT_PEL_EXEC_ERROR_NONE, 0);
|
|
||||||
outputs = NULL;
|
|
||||||
outputs_len = 0;
|
|
||||||
amduat_artifact_free(&program_artifact);
|
|
||||||
goto cache_hit;
|
|
||||||
}
|
|
||||||
cache_miss_due_missing = true;
|
|
||||||
amduat_pel_surf_free_refs(cached_refs, cached_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exec_invoked = true;
|
exec_invoked = true;
|
||||||
outputs = NULL;
|
outputs = NULL;
|
||||||
outputs_len = 0;
|
outputs_len = 0;
|
||||||
|
|
@ -703,12 +555,9 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
program_decoded = true;
|
program_decoded = true;
|
||||||
const amduat_artifact_t *params_arg =
|
const amduat_artifact_t *params_arg =
|
||||||
has_params_artifact ? ¶ms_artifact : NULL;
|
has_params_artifact ? ¶ms_artifact : NULL;
|
||||||
amduat_pel_kernel_set_artifact_resolver(
|
|
||||||
amduat_pel_surf_resolve_artifact, store);
|
|
||||||
if (!amduat_pel_program_dag_exec_trace(
|
if (!amduat_pel_program_dag_exec_trace(
|
||||||
&program, input_artifacts, input_refs_len, params_arg, &outputs,
|
&program, input_artifacts, input_refs_len, params_arg, &outputs,
|
||||||
&outputs_len, &core_result, &trace_eval)) {
|
&outputs_len, &core_result, &trace_eval)) {
|
||||||
amduat_pel_kernel_clear_artifact_resolver();
|
|
||||||
amduat_artifact_free(&program_artifact);
|
amduat_artifact_free(&program_artifact);
|
||||||
amduat_enc_pel_program_dag_free(&program);
|
amduat_enc_pel_program_dag_free(&program);
|
||||||
for (i = 0; i < input_refs_len; ++i) {
|
for (i = 0; i < input_refs_len; ++i) {
|
||||||
|
|
@ -721,8 +570,6 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
amduat_pel_kernel_clear_artifact_resolver();
|
|
||||||
executed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -746,27 +593,6 @@ bool amduat_pel_surf_run(amduat_asl_store_t *store,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mat_cache_ready) {
|
|
||||||
(void)amduat_asl_materialization_cache_fs_put(&mat_cache, sid,
|
|
||||||
output_refs, output_refs_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_hit:
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (cache_miss_due_missing) {
|
|
||||||
assert(!materialized_hit);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (materialized_hit) {
|
|
||||||
amduat_log(AMDUAT_LOG_DEBUG, "pel surf: materialization hit");
|
|
||||||
} else if (executed) {
|
|
||||||
if (cache_miss_due_missing) {
|
|
||||||
amduat_log(AMDUAT_LOG_DEBUG,
|
|
||||||
"pel surf: executed (cache miss: missing outputs)");
|
|
||||||
} else {
|
|
||||||
amduat_log(AMDUAT_LOG_DEBUG, "pel surf: executed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
trace_ok = false;
|
trace_ok = false;
|
||||||
if (exec_invoked) {
|
if (exec_invoked) {
|
||||||
if (!amduat_store_surface_result(
|
if (!amduat_store_surface_result(
|
||||||
|
|
@ -781,9 +607,7 @@ cache_hit:
|
||||||
has_params_ref, params_ref, has_exec_result_ref, exec_result_ref,
|
has_params_ref, params_ref, has_exec_result_ref, exec_result_ref,
|
||||||
&core_result,
|
&core_result,
|
||||||
program_decoded ? &program : NULL,
|
program_decoded ? &program : NULL,
|
||||||
program_decoded ? &trace_eval : NULL,
|
program_decoded ? &trace_eval : NULL, &trace_ref);
|
||||||
materialized_hit,
|
|
||||||
&trace_ref);
|
|
||||||
if (!trace_ok) {
|
if (!trace_ok) {
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
@ -813,7 +637,6 @@ cache_hit:
|
||||||
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
||||||
amduat_pel_execution_result_free(&core_result);
|
amduat_pel_execution_result_free(&core_result);
|
||||||
amduat_pel_surf_free_ref(&exec_result_ref);
|
amduat_pel_surf_free_ref(&exec_result_ref);
|
||||||
amduat_octets_free(&sid);
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
@ -832,6 +655,5 @@ cleanup:
|
||||||
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
amduat_pel_program_dag_free_outputs(outputs, outputs_len);
|
||||||
amduat_pel_execution_result_free(&core_result);
|
amduat_pel_execution_result_free(&core_result);
|
||||||
amduat_pel_surf_free_ref(&exec_result_ref);
|
amduat_pel_surf_free_ref(&exec_result_ref);
|
||||||
amduat_octets_free(&sid);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,176 +0,0 @@
|
||||||
#include "amduat/asl/asl_store_index_fs.h"
|
|
||||||
#include "amduat/asl/store.h"
|
|
||||||
#include "amduat/enc/asl1_core.h"
|
|
||||||
#include "amduat/hash/asl1.h"
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static bool join_path(const char *base, const char *segment, char **out_path) {
|
|
||||||
size_t base_len;
|
|
||||||
size_t seg_len;
|
|
||||||
bool needs_sep;
|
|
||||||
size_t total_len;
|
|
||||||
char *buffer;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
if (base == NULL || segment == NULL || out_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
base_len = strlen(base);
|
|
||||||
seg_len = strlen(segment);
|
|
||||||
if (base_len == 0u || seg_len == 0u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
needs_sep = base[base_len - 1u] != '/';
|
|
||||||
total_len = base_len + (needs_sep ? 1u : 0u) + seg_len + 1u;
|
|
||||||
buffer = (char *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset = 0u;
|
|
||||||
memcpy(buffer + offset, base, base_len);
|
|
||||||
offset += base_len;
|
|
||||||
if (needs_sep) {
|
|
||||||
buffer[offset++] = '/';
|
|
||||||
}
|
|
||||||
memcpy(buffer + offset, segment, seg_len);
|
|
||||||
offset += seg_len;
|
|
||||||
buffer[offset] = '\0';
|
|
||||||
*out_path = buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool remove_tree(const char *path) {
|
|
||||||
struct stat st;
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
|
|
||||||
if (path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (lstat(path, &st) != 0) {
|
|
||||||
return errno == ENOENT;
|
|
||||||
}
|
|
||||||
if (!S_ISDIR(st.st_mode)) {
|
|
||||||
return unlink(path) == 0;
|
|
||||||
}
|
|
||||||
dir = opendir(path);
|
|
||||||
if (dir == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
|
||||||
char *child = NULL;
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!join_path(path, entry->d_name, &child)) {
|
|
||||||
closedir(dir);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!remove_tree(child)) {
|
|
||||||
free(child);
|
|
||||||
closedir(dir);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free(child);
|
|
||||||
}
|
|
||||||
if (closedir(dir) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return rmdir(path) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *make_temp_root(void) {
|
|
||||||
char *tmpl = NULL;
|
|
||||||
char *root = NULL;
|
|
||||||
|
|
||||||
tmpl = strdup("/tmp/amduat-index-putget-XXXXXX");
|
|
||||||
if (tmpl == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (mkdtemp(tmpl) == NULL) {
|
|
||||||
free(tmpl);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
root = tmpl;
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
amduat_asl_store_config_t config;
|
|
||||||
amduat_asl_store_index_fs_t fs;
|
|
||||||
amduat_asl_store_t store;
|
|
||||||
char *root = NULL;
|
|
||||||
int rc = 1;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
root = make_temp_root();
|
|
||||||
if (root == NULL) {
|
|
||||||
fprintf(stderr, "temp root creation 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);
|
|
||||||
|
|
||||||
for (i = 0u; i < 128u; ++i) {
|
|
||||||
char payload_buf[64];
|
|
||||||
size_t payload_len;
|
|
||||||
amduat_artifact_t artifact;
|
|
||||||
amduat_reference_t ref;
|
|
||||||
amduat_artifact_t loaded;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
payload_len = (size_t)snprintf(payload_buf, sizeof(payload_buf),
|
|
||||||
"payload-%zu", i);
|
|
||||||
if (payload_len == 0u || payload_len >= sizeof(payload_buf)) {
|
|
||||||
fprintf(stderr, "payload format failed at %zu\n", i);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
artifact = amduat_artifact(
|
|
||||||
amduat_octets((const uint8_t *)payload_buf, payload_len));
|
|
||||||
ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
|
||||||
err = amduat_asl_store_put(&store, artifact, &ref);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "put failed at %zu: %d\n", i, (int)err);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
loaded = amduat_artifact(amduat_octets(NULL, 0u));
|
|
||||||
err = amduat_asl_store_get(&store, ref, &loaded);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "get after put failed at %zu: %d\n", i, (int)err);
|
|
||||||
amduat_reference_free(&ref);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
amduat_artifact_free(&loaded);
|
|
||||||
amduat_reference_free(&ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (root != NULL) {
|
|
||||||
if (!remove_tree(root)) {
|
|
||||||
fprintf(stderr, "warning: cleanup failed for %s\n", root);
|
|
||||||
}
|
|
||||||
free(root);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
@ -1,525 +0,0 @@
|
||||||
#include "amduat/asl/log_store.h"
|
|
||||||
#include "amduat/asl/asl_store_index_fs.h"
|
|
||||||
#include "amduat/asl/store.h"
|
|
||||||
#include "amduat/enc/asl1_core.h"
|
|
||||||
#include "amduat/hash/asl1.h"
|
|
||||||
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
static bool join_path(const char *base, const char *segment, char **out_path) {
|
|
||||||
size_t base_len;
|
|
||||||
size_t seg_len;
|
|
||||||
bool needs_sep;
|
|
||||||
size_t total_len;
|
|
||||||
char *buffer;
|
|
||||||
size_t offset;
|
|
||||||
|
|
||||||
if (base == NULL || segment == NULL || out_path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
base_len = strlen(base);
|
|
||||||
seg_len = strlen(segment);
|
|
||||||
if (base_len == 0u || seg_len == 0u) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
needs_sep = base[base_len - 1u] != '/';
|
|
||||||
total_len = base_len + (needs_sep ? 1u : 0u) + seg_len + 1u;
|
|
||||||
buffer = (char *)malloc(total_len);
|
|
||||||
if (buffer == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
offset = 0u;
|
|
||||||
memcpy(buffer + offset, base, base_len);
|
|
||||||
offset += base_len;
|
|
||||||
if (needs_sep) {
|
|
||||||
buffer[offset++] = '/';
|
|
||||||
}
|
|
||||||
memcpy(buffer + offset, segment, seg_len);
|
|
||||||
offset += seg_len;
|
|
||||||
buffer[offset] = '\0';
|
|
||||||
*out_path = buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool remove_tree(const char *path) {
|
|
||||||
struct stat st;
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
|
|
||||||
if (path == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (lstat(path, &st) != 0) {
|
|
||||||
return errno == ENOENT;
|
|
||||||
}
|
|
||||||
if (!S_ISDIR(st.st_mode)) {
|
|
||||||
return unlink(path) == 0;
|
|
||||||
}
|
|
||||||
dir = opendir(path);
|
|
||||||
if (dir == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
|
||||||
char *child = NULL;
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!join_path(path, entry->d_name, &child)) {
|
|
||||||
closedir(dir);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!remove_tree(child)) {
|
|
||||||
free(child);
|
|
||||||
closedir(dir);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
free(child);
|
|
||||||
}
|
|
||||||
if (closedir(dir) != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return rmdir(path) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool refs_equal(amduat_reference_t a, amduat_reference_t b) {
|
|
||||||
if (a.hash_id != b.hash_id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (a.digest.len != b.digest.len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (a.digest.len == 0u) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (a.digest.data == NULL || b.digest.data == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return memcmp(a.digest.data, b.digest.data, a.digest.len) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
amduat_asl_store_t *store;
|
|
||||||
amduat_asl_log_store_t *log_store;
|
|
||||||
const char *log_name;
|
|
||||||
uint16_t kind;
|
|
||||||
size_t iterations;
|
|
||||||
amduat_asl_store_error_t first_err;
|
|
||||||
uint64_t *observed_offsets;
|
|
||||||
} append_worker_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
amduat_asl_store_t *store;
|
|
||||||
uint16_t kind;
|
|
||||||
size_t iterations;
|
|
||||||
amduat_asl_store_error_t first_err;
|
|
||||||
} put_worker_t;
|
|
||||||
|
|
||||||
static void *append_worker_main(void *opaque) {
|
|
||||||
append_worker_t *worker = (append_worker_t *)opaque;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (worker == NULL || worker->store == NULL || worker->log_store == NULL ||
|
|
||||||
worker->log_name == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
worker->first_err = AMDUAT_ASL_STORE_OK;
|
|
||||||
|
|
||||||
for (i = 0u; i < worker->iterations; ++i) {
|
|
||||||
char payload_buf[64];
|
|
||||||
size_t payload_len;
|
|
||||||
amduat_artifact_t payload_artifact;
|
|
||||||
amduat_reference_t payload_ref;
|
|
||||||
amduat_asl_log_entry_t entry;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
uint64_t first_offset = 0u;
|
|
||||||
|
|
||||||
payload_len = (size_t)snprintf(payload_buf, sizeof(payload_buf),
|
|
||||||
"worker-%u-%zu", (unsigned)worker->kind, i);
|
|
||||||
if (payload_len == 0u || payload_len >= sizeof(payload_buf)) {
|
|
||||||
worker->first_err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload_artifact =
|
|
||||||
amduat_artifact(amduat_octets((const uint8_t *)payload_buf, payload_len));
|
|
||||||
payload_ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
|
||||||
err = amduat_asl_store_put(worker->store, payload_artifact, &payload_ref);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
worker->first_err = err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&entry, 0, sizeof(entry));
|
|
||||||
entry.kind = worker->kind;
|
|
||||||
entry.payload_ref = payload_ref;
|
|
||||||
err = amduat_asl_log_append(worker->log_store,
|
|
||||||
worker->log_name,
|
|
||||||
&entry,
|
|
||||||
1u,
|
|
||||||
&first_offset);
|
|
||||||
amduat_reference_free(&payload_ref);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
worker->first_err = err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (worker->observed_offsets != NULL && i < worker->iterations) {
|
|
||||||
worker->observed_offsets[i] = first_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *put_worker_main(void *opaque) {
|
|
||||||
put_worker_t *worker = (put_worker_t *)opaque;
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (worker == NULL || worker->store == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
worker->first_err = AMDUAT_ASL_STORE_OK;
|
|
||||||
|
|
||||||
for (i = 0u; i < worker->iterations; ++i) {
|
|
||||||
char payload_buf[64];
|
|
||||||
size_t payload_len;
|
|
||||||
amduat_artifact_t payload_artifact;
|
|
||||||
amduat_reference_t payload_ref;
|
|
||||||
amduat_asl_store_error_t err;
|
|
||||||
|
|
||||||
payload_len = (size_t)snprintf(payload_buf, sizeof(payload_buf),
|
|
||||||
"put-only-%u-%zu", (unsigned)worker->kind, i);
|
|
||||||
if (payload_len == 0u || payload_len >= sizeof(payload_buf)) {
|
|
||||||
worker->first_err = AMDUAT_ASL_STORE_ERR_IO;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload_artifact =
|
|
||||||
amduat_artifact(amduat_octets((const uint8_t *)payload_buf, payload_len));
|
|
||||||
payload_ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
|
||||||
err = amduat_asl_store_put(worker->store, payload_artifact, &payload_ref);
|
|
||||||
amduat_reference_free(&payload_ref);
|
|
||||||
if (err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
worker->first_err = err;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
amduat_asl_store_config_t config;
|
|
||||||
amduat_asl_store_index_fs_t fs_a;
|
|
||||||
amduat_asl_store_index_fs_t fs_b;
|
|
||||||
amduat_asl_store_t store_a;
|
|
||||||
amduat_asl_store_t store_b;
|
|
||||||
amduat_asl_log_store_t log_a;
|
|
||||||
amduat_asl_log_store_t log_b;
|
|
||||||
amduat_artifact_t payload_artifact_a;
|
|
||||||
amduat_artifact_t payload_artifact_b;
|
|
||||||
amduat_reference_t payload_ref_a;
|
|
||||||
amduat_reference_t payload_ref_b;
|
|
||||||
amduat_asl_log_entry_t entry_a;
|
|
||||||
amduat_asl_log_entry_t entry_b;
|
|
||||||
amduat_asl_log_entry_t *out_entries = NULL;
|
|
||||||
size_t out_len = 0u;
|
|
||||||
uint64_t out_next_offset = 0u;
|
|
||||||
bool out_end = false;
|
|
||||||
uint64_t first_offset = 0u;
|
|
||||||
const char *log_name = "collection/space/app1/daemon/edges/log";
|
|
||||||
enum { WORKER_ITERS = 32 };
|
|
||||||
append_worker_t worker_a;
|
|
||||||
append_worker_t worker_b;
|
|
||||||
append_worker_t mixed_append_worker;
|
|
||||||
put_worker_t mixed_put_worker;
|
|
||||||
pthread_t thread_a;
|
|
||||||
pthread_t thread_b;
|
|
||||||
pthread_t mixed_append_thread;
|
|
||||||
pthread_t mixed_put_thread;
|
|
||||||
bool started_a = false;
|
|
||||||
bool started_b = false;
|
|
||||||
bool started_mixed_append = false;
|
|
||||||
bool started_mixed_put = false;
|
|
||||||
uint64_t worker_a_offsets[WORKER_ITERS];
|
|
||||||
uint64_t worker_b_offsets[WORKER_ITERS];
|
|
||||||
char *root = NULL;
|
|
||||||
int rc = 1;
|
|
||||||
|
|
||||||
root = strdup("/tmp/amduat-log-index-XXXXXX");
|
|
||||||
if (root == NULL) {
|
|
||||||
fprintf(stderr, "alloc root template failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (mkdtemp(root) == NULL) {
|
|
||||||
fprintf(stderr, "mkdtemp failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_a, config, root) ||
|
|
||||||
!amduat_asl_store_index_fs_init(&fs_b, config, root)) {
|
|
||||||
fprintf(stderr, "index fs init failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
amduat_asl_store_init(&store_a, config, amduat_asl_store_index_fs_ops(), &fs_a);
|
|
||||||
amduat_asl_store_init(&store_b, config, amduat_asl_store_index_fs_ops(), &fs_b);
|
|
||||||
|
|
||||||
if (!amduat_asl_log_store_init(&log_a, root, &store_a, NULL) ||
|
|
||||||
!amduat_asl_log_store_init(&log_b, root, &store_b, NULL)) {
|
|
||||||
fprintf(stderr, "log store init failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload_artifact_a = amduat_artifact(amduat_octets((const uint8_t *)"payload-a", 9u));
|
|
||||||
payload_ref_a = amduat_reference(0u, amduat_octets(NULL, 0u));
|
|
||||||
if (amduat_asl_store_put(&store_a, payload_artifact_a, &payload_ref_a) !=
|
|
||||||
AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "put payload a failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&entry_a, 0, sizeof(entry_a));
|
|
||||||
entry_a.kind = 1u;
|
|
||||||
entry_a.payload_ref = payload_ref_a;
|
|
||||||
if (amduat_asl_log_append(&log_a, log_name, &entry_a, 1u, &first_offset) !=
|
|
||||||
AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "first append failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (first_offset != 0u) {
|
|
||||||
fprintf(stderr, "first offset mismatch: %" PRIu64 "\n", first_offset);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload_artifact_b = amduat_artifact(amduat_octets((const uint8_t *)"payload-b", 9u));
|
|
||||||
payload_ref_b = amduat_reference(0u, amduat_octets(NULL, 0u));
|
|
||||||
if (amduat_asl_store_put(&store_b, payload_artifact_b, &payload_ref_b) !=
|
|
||||||
AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "put payload b failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&entry_b, 0, sizeof(entry_b));
|
|
||||||
entry_b.kind = 2u;
|
|
||||||
entry_b.payload_ref = payload_ref_b;
|
|
||||||
if (amduat_asl_log_append(&log_b, log_name, &entry_b, 1u, &first_offset) !=
|
|
||||||
AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "second append failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (first_offset != 1u) {
|
|
||||||
fprintf(stderr, "second first_offset mismatch: %" PRIu64 "\n", first_offset);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amduat_asl_log_read(&log_a,
|
|
||||||
log_name,
|
|
||||||
0u,
|
|
||||||
8u,
|
|
||||||
&out_entries,
|
|
||||||
&out_len,
|
|
||||||
&out_next_offset,
|
|
||||||
&out_end) != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "log read failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out_len != 2u || out_next_offset != 2u || !out_end) {
|
|
||||||
fprintf(stderr, "readback shape mismatch len=%zu next=%" PRIu64 " end=%d\n",
|
|
||||||
out_len, out_next_offset, out_end ? 1 : 0);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (out_entries[0].kind != 1u || !refs_equal(out_entries[0].payload_ref, payload_ref_a)) {
|
|
||||||
fprintf(stderr, "entry0 mismatch\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (out_entries[1].kind != 2u || !refs_equal(out_entries[1].payload_ref, payload_ref_b)) {
|
|
||||||
fprintf(stderr, "entry1 mismatch\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
amduat_asl_log_entries_free(out_entries, out_len);
|
|
||||||
out_entries = NULL;
|
|
||||||
out_len = 0u;
|
|
||||||
|
|
||||||
memset(&worker_a, 0, sizeof(worker_a));
|
|
||||||
worker_a.store = &store_a;
|
|
||||||
worker_a.log_store = &log_a;
|
|
||||||
worker_a.log_name = log_name;
|
|
||||||
worker_a.kind = 10u;
|
|
||||||
worker_a.iterations = WORKER_ITERS;
|
|
||||||
worker_a.observed_offsets = worker_a_offsets;
|
|
||||||
|
|
||||||
memset(&worker_b, 0, sizeof(worker_b));
|
|
||||||
worker_b.store = &store_b;
|
|
||||||
worker_b.log_store = &log_b;
|
|
||||||
worker_b.log_name = log_name;
|
|
||||||
worker_b.kind = 11u;
|
|
||||||
worker_b.iterations = WORKER_ITERS;
|
|
||||||
worker_b.observed_offsets = worker_b_offsets;
|
|
||||||
|
|
||||||
if (pthread_create(&thread_a, NULL, append_worker_main, &worker_a) != 0) {
|
|
||||||
fprintf(stderr, "pthread_create failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
started_a = true;
|
|
||||||
if (pthread_create(&thread_b, NULL, append_worker_main, &worker_b) != 0) {
|
|
||||||
fprintf(stderr, "pthread_create failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
started_b = true;
|
|
||||||
(void)pthread_join(thread_a, NULL);
|
|
||||||
(void)pthread_join(thread_b, NULL);
|
|
||||||
started_a = false;
|
|
||||||
started_b = false;
|
|
||||||
|
|
||||||
if (worker_a.first_err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "worker_a failed err=%d\n", (int)worker_a.first_err);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (worker_b.first_err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "worker_b failed err=%d\n", (int)worker_b.first_err);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
bool seen[2u + 2u * WORKER_ITERS];
|
|
||||||
size_t i;
|
|
||||||
memset(seen, 0, sizeof(seen));
|
|
||||||
for (i = 0u; i < WORKER_ITERS; ++i) {
|
|
||||||
if (worker_a_offsets[i] < 2u ||
|
|
||||||
worker_a_offsets[i] >= (uint64_t)(2u + 2u * WORKER_ITERS)) {
|
|
||||||
fprintf(stderr, "worker_a offset out of range: %" PRIu64 "\n",
|
|
||||||
worker_a_offsets[i]);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (seen[worker_a_offsets[i]]) {
|
|
||||||
fprintf(stderr, "duplicate offset from worker_a: %" PRIu64 "\n",
|
|
||||||
worker_a_offsets[i]);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
seen[worker_a_offsets[i]] = true;
|
|
||||||
}
|
|
||||||
for (i = 0u; i < WORKER_ITERS; ++i) {
|
|
||||||
if (worker_b_offsets[i] < 2u ||
|
|
||||||
worker_b_offsets[i] >= (uint64_t)(2u + 2u * WORKER_ITERS)) {
|
|
||||||
fprintf(stderr, "worker_b offset out of range: %" PRIu64 "\n",
|
|
||||||
worker_b_offsets[i]);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (seen[worker_b_offsets[i]]) {
|
|
||||||
fprintf(stderr, "duplicate offset from worker_b: %" PRIu64 "\n",
|
|
||||||
worker_b_offsets[i]);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
seen[worker_b_offsets[i]] = true;
|
|
||||||
}
|
|
||||||
for (i = 2u; i < (2u + 2u * WORKER_ITERS); ++i) {
|
|
||||||
if (!seen[i]) {
|
|
||||||
fprintf(stderr, "missing worker offset: %zu\n", i);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amduat_asl_log_read(&log_a,
|
|
||||||
log_name,
|
|
||||||
0u,
|
|
||||||
4096u,
|
|
||||||
&out_entries,
|
|
||||||
&out_len,
|
|
||||||
&out_next_offset,
|
|
||||||
&out_end) != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "log read after stress failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (out_len != (2u + 2u * WORKER_ITERS) || out_next_offset != out_len ||
|
|
||||||
!out_end) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"stress read mismatch len=%zu next=%" PRIu64 " expected=%u end=%d\n",
|
|
||||||
out_len, out_next_offset, (unsigned)(2u + 2u * WORKER_ITERS),
|
|
||||||
out_end ? 1 : 0);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
amduat_asl_log_entries_free(out_entries, out_len);
|
|
||||||
out_entries = NULL;
|
|
||||||
out_len = 0u;
|
|
||||||
|
|
||||||
memset(&mixed_append_worker, 0, sizeof(mixed_append_worker));
|
|
||||||
mixed_append_worker.store = &store_a;
|
|
||||||
mixed_append_worker.log_store = &log_a;
|
|
||||||
mixed_append_worker.log_name = log_name;
|
|
||||||
mixed_append_worker.kind = 12u;
|
|
||||||
mixed_append_worker.iterations = WORKER_ITERS;
|
|
||||||
|
|
||||||
memset(&mixed_put_worker, 0, sizeof(mixed_put_worker));
|
|
||||||
mixed_put_worker.store = &store_b;
|
|
||||||
mixed_put_worker.kind = 13u;
|
|
||||||
mixed_put_worker.iterations = WORKER_ITERS * 4u;
|
|
||||||
|
|
||||||
if (pthread_create(&mixed_append_thread, NULL, append_worker_main,
|
|
||||||
&mixed_append_worker) != 0) {
|
|
||||||
fprintf(stderr, "pthread_create mixed append failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
started_mixed_append = true;
|
|
||||||
if (pthread_create(&mixed_put_thread, NULL, put_worker_main,
|
|
||||||
&mixed_put_worker) != 0) {
|
|
||||||
fprintf(stderr, "pthread_create mixed put failed\n");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
started_mixed_put = true;
|
|
||||||
(void)pthread_join(mixed_append_thread, NULL);
|
|
||||||
(void)pthread_join(mixed_put_thread, NULL);
|
|
||||||
started_mixed_append = false;
|
|
||||||
started_mixed_put = false;
|
|
||||||
|
|
||||||
if (mixed_append_worker.first_err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "mixed append worker failed err=%d\n",
|
|
||||||
(int)mixed_append_worker.first_err);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
if (mixed_put_worker.first_err != AMDUAT_ASL_STORE_OK) {
|
|
||||||
fprintf(stderr, "mixed put worker failed err=%d\n",
|
|
||||||
(int)mixed_put_worker.first_err);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
if (started_a) {
|
|
||||||
(void)pthread_join(thread_a, NULL);
|
|
||||||
}
|
|
||||||
if (started_b) {
|
|
||||||
(void)pthread_join(thread_b, NULL);
|
|
||||||
}
|
|
||||||
if (started_mixed_append) {
|
|
||||||
(void)pthread_join(mixed_append_thread, NULL);
|
|
||||||
}
|
|
||||||
if (started_mixed_put) {
|
|
||||||
(void)pthread_join(mixed_put_thread, NULL);
|
|
||||||
}
|
|
||||||
amduat_asl_log_entries_free(out_entries, out_len);
|
|
||||||
amduat_reference_free(&payload_ref_a);
|
|
||||||
amduat_reference_free(&payload_ref_b);
|
|
||||||
if (root != NULL) {
|
|
||||||
if (!remove_tree(root)) {
|
|
||||||
fprintf(stderr, "warning: cleanup failed for %s\n", root);
|
|
||||||
}
|
|
||||||
free(root);
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue