Skip to content

Commit

Permalink
22408: Add ExecuteEntityJsonPtrLogged API call (#326)
Browse files Browse the repository at this point in the history
Returns both the JSON data, as in ExecuteEntityJsonPtr, and also a
transaction-log entry that can be sent back via the EvalOnEntity API.
  • Loading branch information
dmaze authored Dec 17, 2024
1 parent 645471b commit e837c79
Show file tree
Hide file tree
Showing 10 changed files with 366 additions and 21 deletions.
5 changes: 2 additions & 3 deletions build/cmake/create_tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ foreach(TEST_TARGET ${ALL_SHAREDLIB_TARGETS})

# Create test exe:
set(TEST_EXE_NAME "${TEST_TARGET}-tester")
set(TEST_SOURCES "test/lib_smoke_test/main.cpp" "test/lib_smoke_test/test.amlg")
set(TEST_SOURCES "test/lib_smoke_test/main.cpp" "test/lib_smoke_test/test.amlg" "test/lib_smoke_test/counter.amlg")
source_group(TREE ${CMAKE_SOURCE_DIR} FILES ${TEST_SOURCES})
add_executable(${TEST_EXE_NAME} ${TEST_SOURCES})
set_target_properties(${TEST_EXE_NAME} PROPERTIES FOLDER "Testing")
Expand All @@ -78,10 +78,9 @@ foreach(TEST_TARGET ${ALL_SHAREDLIB_TARGETS})
# Test for test exe:
set(TEST_NAME "Lib.SmokeTest.${TEST_EXE_NAME}")
add_test(NAME ${TEST_NAME}
COMMAND ${TEST_RUNNER} "$<TARGET_FILE:${TEST_EXE_NAME}>" test.amlg
COMMAND ${TEST_RUNNER} "$<TARGET_FILE:${TEST_EXE_NAME}>"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/test/lib_smoke_test
)
set_tests_properties(${TEST_NAME} PROPERTIES PASS_REGULAR_EXPRESSION "${AMALGAM_VERSION_FULL_ESCAPED}")
list(APPEND ALL_TEST_TARGETS ${TEST_NAME})

endforeach()
Expand Down
8 changes: 8 additions & 0 deletions src/Amalgam/Amalgam.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ extern "C"
char *version;
};

//output from ExecuteEntityJsonPtrLogged
struct ResultWithLog
{
char *json;
char *log;
};

//loads the entity specified into handle
AMALGAM_EXPORT LoadEntityStatus LoadEntity(char *handle, char *path, char *file_type,
bool persistent, char *json_file_params, char *write_log_filename, char *print_log_filename);
Expand Down Expand Up @@ -59,6 +66,7 @@ extern "C"

AMALGAM_EXPORT wchar_t *ExecuteEntityJsonPtrWide(char *handle, char *label, char *json);
AMALGAM_EXPORT char *ExecuteEntityJsonPtr(char *handle, char *label, char *json);
AMALGAM_EXPORT ResultWithLog ExecuteEntityJsonPtrLogged(char *handle, char *label, char *json);

AMALGAM_EXPORT char *EvalOnEntity(char *handle, char *amlg);

Expand Down
12 changes: 12 additions & 0 deletions src/Amalgam/AmalgamAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@ extern "C"
return StringToCharPtr(ret);
}

ResultWithLog ExecuteEntityJsonPtrLogged(char *handle, char *label, char *json)
{
std::string h(handle);
std::string l(label);
std::string_view j(json);
std::pair<std::string, std::string> ret = entint.ExecuteEntityJSONLogged(h, l, j);
ResultWithLog rwl;
rwl.json = StringToCharPtr(ret.first);
rwl.log = StringToCharPtr(ret.second);
return rwl;
}

void ExecuteEntity(char *handle, char *label)
{
std::string h(handle);
Expand Down
8 changes: 8 additions & 0 deletions src/Amalgam/AmalgamTrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ int32_t RunAmalgamTrace(std::istream *in_stream, std::ostream *out_stream, std::
json_payload = input; // json data
response = entint.ExecuteEntityJSON(handle, label, json_payload);
}
else if(command == "EXECUTE_ENTITY_JSON_LOGGED")
{
handle = StringManipulation::RemoveFirstToken(input);
label = StringManipulation::RemoveFirstToken(input);
json_payload = input; // json data
auto [json_response, log] = entint.ExecuteEntityJSONLogged(handle, label, json_payload);
response = json_response + "\n# " + log;
}
else if(command == "EVAL_ON_ENTITY")
{
handle = StringManipulation::RemoveFirstToken(input);
Expand Down
2 changes: 1 addition & 1 deletion src/Amalgam/entity/Entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ class Entity
}

//same as Execute but accepts a string for label name
inline EvaluableNodeReference Execute(std::string &label_name,
inline EvaluableNodeReference Execute(const std::string &label_name,
EvaluableNode *call_stack, bool on_self = false, Interpreter *calling_interpreter = nullptr,
std::vector<EntityWriteListener *> *write_listeners = nullptr, PrintListener *print_listener = nullptr,
PerformanceConstraints *performance_constraints = nullptr
Expand Down
37 changes: 37 additions & 0 deletions src/Amalgam/entity/EntityExternalInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,43 @@ std::string EntityExternalInterface::ExecuteEntityJSON(std::string &handle, std:
return (converted ? result : string_intern_pool.GetStringFromID(string_intern_pool.NOT_A_STRING_ID));
}

std::pair<std::string, std::string> EntityExternalInterface::ExecuteEntityJSONLogged(const std::string &handle, const std::string &label, std::string_view json)
{
auto bundle = FindEntityBundle(handle);
if(bundle == nullptr)
return std::pair("", "");

EntityWriteListener logger(bundle->entity, true);
std::vector<EntityWriteListener *> listeners(bundle->writeListeners);
listeners.push_back(&logger);

EvaluableNodeManager &enm = bundle->entity->evaluableNodeManager;
#ifdef MULTITHREAD_SUPPORT
//lock memory before allocating call stack
Concurrency::ReadLock enm_lock(enm.memoryModificationMutex);
#endif
EvaluableNodeReference args = EvaluableNodeReference(EvaluableNodeJSONTranslation::JsonToEvaluableNode(&enm, json), true);

auto call_stack = Interpreter::ConvertArgsToCallStack(args, enm);

EvaluableNodeReference returned_value = bundle->entity->Execute(label, call_stack, false, nullptr,
&listeners, bundle->printListener, nullptr
#ifdef MULTITHREAD_SUPPORT
, &enm_lock
#endif
);
enm.FreeNode(call_stack->GetOrderedChildNodesReference()[0]);
enm.FreeNode(call_stack);

auto [result, converted] = EvaluableNodeJSONTranslation::EvaluableNodeToJson(returned_value);
enm.FreeNodeTreeIfPossible(returned_value);
std::string json_out = converted ? result : string_intern_pool.GetStringFromID(string_intern_pool.NOT_A_STRING_ID);

std::string log = Parser::Unparse(logger.GetWrites(), false, false);

return std::pair(json_out, log);
}

std::string EntityExternalInterface::EvalOnEntity(const std::string &handle, const std::string &amlg)
{
auto bundle = FindEntityBundle(handle);
Expand Down
1 change: 1 addition & 0 deletions src/Amalgam/entity/EntityExternalInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class EntityExternalInterface
bool SetJSONToLabel(std::string &handle, std::string &label, std::string_view json);
std::string GetJSONFromLabel(std::string &handle, std::string &label);
std::string ExecuteEntityJSON(std::string &handle, std::string &label, std::string_view json);
std::pair<std::string, std::string> ExecuteEntityJSONLogged(const std::string &handle, const std::string &label, std::string_view json);
std::string EvalOnEntity(const std::string &handle, const std::string &amlg);

protected:
Expand Down
2 changes: 1 addition & 1 deletion src/Amalgam/interpreter/InterpreterOpcodesEntityAccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ EvaluableNodeReference Interpreter::InterpretNode_ENT_CALL_ENTITY_and_CALL_ENTIT
memoryModificationLock.unlock();
#endif

EvaluableNodeReference result = called_entity->Execute(entity_label_sid,
EvaluableNodeReference result = called_entity->Execute(StringInternPool::StringID(entity_label_sid),
call_stack, called_entity == curEntity, this, cur_write_listeners, printListener, perf_constraints_ptr
#ifdef MULTITHREAD_SUPPORT
, &enm_lock
Expand Down
24 changes: 24 additions & 0 deletions test/lib_smoke_test/counter.amlg
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
; An entity that's a trivial counter.
(null
#!value
0

#initialize
(assign_to_entities (assoc !value 0))

#get_value
(retrieve_from_entity "!value")

#increment
(seq
(accum_to_entities (assoc !value 1))
(call get_value)
)

#add
(declare
(assoc count 1)
(accum_to_entities (assoc !value count))
(call get_value)
)
)
Loading

0 comments on commit e837c79

Please sign in to comment.