diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index 463698c3c..daed82a2c 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -51,10 +51,10 @@ jobs:
./build_clean_linux64.sh
shell: bash
- - name: Run coverage (unit tests + signalloadtest)
+ - name: Run coverage (unit tests)
run: |
chmod +x ./coverage_linux.sh
- ./coverage_linux.sh --testdefinition Tests/signalloadtest.xml --build-target libmctest_signalloadtest
+ ./coverage_linux.sh
shell: bash
- name: Upload coverage report
diff --git a/ACT/LibMC.xml b/ACT/LibMC.xml
index 753c7094f..dd83e703b 100644
--- a/ACT/LibMC.xml
+++ b/ACT/LibMC.xml
@@ -722,8 +722,15 @@
+
+
+
+
+
-
+
+
+
diff --git a/ACT/LibMCEnv.xml b/ACT/LibMCEnv.xml
index 4cdd6085e..a16585b7c 100644
--- a/ACT/LibMCEnv.xml
+++ b/ACT/LibMCEnv.xml
@@ -2591,6 +2591,12 @@
+
+
+
+
+
+
@@ -2602,6 +2608,14 @@
+
+
+
+
+
+
+
+
@@ -5040,28 +5054,26 @@
-
-
-
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
+
+
-
+
-
+
-
+
@@ -5098,7 +5110,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -5124,21 +5166,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -5729,6 +5756,10 @@
+
+
+
+
@@ -5900,6 +5931,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ACT/act.linux b/ACT/act.linux
old mode 100644
new mode 100755
diff --git a/ACT/generate.sh b/ACT/generate.sh
new file mode 100755
index 000000000..4137bf15f
--- /dev/null
+++ b/ACT/generate.sh
@@ -0,0 +1,8 @@
+
+./act.linux LibMCEnv.xml -bindings ../Framework/HeadersDev -interfaces ../Framework/InterfacesCore -suppresssubcomponents -suppresslicense -suppressstub -suppressexamples
+./act.linux LibMCPlugin.xml -bindings ../Framework/HeadersCore -interfaces ../Framework/InterfacesDev -suppresssubcomponents -suppresslicense -suppressstub -suppressexamples
+./act.linux LibMCUI.xml -bindings ../Framework/HeadersCore -interfaces ../Framework/InterfacesDev -suppresssubcomponents -suppresslicense -suppressstub -suppressexamples
+./act.linux LibMCDriver.xml -bindings ../Framework/HeadersCore -interfaces ../Framework/InterfacesDev -suppresssubcomponents -suppresslicense -suppressstub -suppressexamples
+./act.linux LibMCData.xml -bindings ../Framework/HeadersCore -interfaces ../Framework/InterfacesCore -suppresssubcomponents -suppresslicense -suppressstub -suppressexamples
+./act.linux LibMC.xml -bindings ../Framework/HeadersCore -interfaces ../Framework/InterfacesCore -suppresssubcomponents -suppresslicense -suppressstub -suppressexamples
+
diff --git a/BuildScripts/createDevPackage.go b/BuildScripts/createDevPackage.go
index fd0adc1da..2a262480e 100644
--- a/BuildScripts/createDevPackage.go
+++ b/BuildScripts/createDevPackage.go
@@ -23,22 +23,28 @@ func addFile (zipWriter * zip.Writer, diskPath string, zipPath string) (error) {
if err != nil {
return err
}
-
-
+
+ // Get file info to preserve permissions
+ fileInfo, err := os.Stat(diskPath)
+ if err != nil {
+ return err
+ }
+
var header zip.FileHeader;
header.Name = zipPath;
header.Method = zip.Deflate;
-
+ header.SetMode(fileInfo.Mode()); // Preserve Unix file permissions
+
filewriter, err := zipWriter.CreateHeader(&header)
if err != nil {
return err
}
-
+
_, err = filewriter.Write(input)
if err != nil {
return err
}
-
+
return nil;
}
diff --git a/Examples/LPBFSystem/Main/mcplugin_main.cpp b/Examples/LPBFSystem/Main/mcplugin_main.cpp
index eefc1eb4a..57302608f 100644
--- a/Examples/LPBFSystem/Main/mcplugin_main.cpp
+++ b/Examples/LPBFSystem/Main/mcplugin_main.cpp
@@ -128,6 +128,10 @@ __DECLARESTATE(idle)
auto dCounterTest = pStateEnvironment->GetDoubleParameter("jobinfo", "countertest");
auto nTimer = pStateEnvironment->GetGlobalTimerInMilliseconds();
+ auto pDummyTrigger = pStateEnvironment->PrepareSignal("plc", "signal_dummy");
+ pDummyTrigger->SetInteger("timer", (int32_t)nTimer);
+ pDummyTrigger->Trigger();
+
pStateEnvironment->SetDoubleParameter ("jobinfo", "countertest", dCounterTest + abs (sin (nTimer * 0.001)));
//pStateEnvironment->LogMessage ("Waiting for user input...");
diff --git a/Examples/LPBFSystem/PLC/mcplugin_plc.cpp b/Examples/LPBFSystem/PLC/mcplugin_plc.cpp
index 4331bee8b..430589e16 100644
--- a/Examples/LPBFSystem/PLC/mcplugin_plc.cpp
+++ b/Examples/LPBFSystem/PLC/mcplugin_plc.cpp
@@ -112,6 +112,12 @@ __DECLARESTATE(idle)
pDriver->QueryParameters();
+ auto pDummySignal = pStateEnvironment->ClaimSignalFromQueue("signal_dummy");
+ if (pDummySignal.get() != nullptr) {
+ pDummySignal->SignalHandled();
+ }
+
+ pStateEnvironment->ClearUnhandledSignalsOfType("signal_dummy");
LibMCEnv::PSignalHandler pHandlerInstance;
if (pStateEnvironment->WaitForSignal("signal_recoatlayer", 0, pHandlerInstance)) {
diff --git a/Examples/LPBFSystem/config.xml b/Examples/LPBFSystem/config.xml
index a2a3e7716..cce8e50d3 100644
--- a/Examples/LPBFSystem/config.xml
+++ b/Examples/LPBFSystem/config.xml
@@ -112,7 +112,7 @@
-
+
@@ -134,7 +134,7 @@
-
+
@@ -263,6 +263,11 @@
+
+
+
+
+
diff --git a/Framework/HeadersCore/CppDynamic/libmc_dynamic.hpp b/Framework/HeadersCore/CppDynamic/libmc_dynamic.hpp
index 7885b4f03..f5278f449 100644
--- a/Framework/HeadersCore/CppDynamic/libmc_dynamic.hpp
+++ b/Framework/HeadersCore/CppDynamic/libmc_dynamic.hpp
@@ -791,6 +791,11 @@ class ELibMCException : public std::exception {
case LIBMC_ERROR_INVALIDTELEMETRYMARKERFINISHTIMESTAMP: return "INVALIDTELEMETRYMARKERFINISHTIMESTAMP";
case LIBMC_ERROR_UNFINISHEDTELEMETRYMARKERSHAVENODURATION: return "UNFINISHEDTELEMETRYMARKERSHAVENODURATION";
case LIBMC_ERROR_TELEMETRYMARKERALREADYREGISTERED: return "TELEMETRYMARKERALREADYREGISTERED";
+ case LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND: return "TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND";
+ case LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE: return "TELEMETRYCHUNKINDEXOUTOFRANGE";
+ case LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH: return "TELEMETRYCHUNKIDMISMATCH";
+ case LIBMC_ERROR_TELEMETRYCHUNKISREADONLY: return "TELEMETRYCHUNKISREADONLY";
+ case LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY: return "TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY";
}
return "UNKNOWN";
}
@@ -1416,6 +1421,11 @@ class ELibMCException : public std::exception {
case LIBMC_ERROR_INVALIDTELEMETRYMARKERFINISHTIMESTAMP: return "Invalid telemetry marker finish timestamp.";
case LIBMC_ERROR_UNFINISHEDTELEMETRYMARKERSHAVENODURATION: return "Unfinished telemetry marker have no duration.";
case LIBMC_ERROR_TELEMETRYMARKERALREADYREGISTERED: return "Telemetry Marker has been already registered.";
+ case LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND: return "Telemetry Chunk Start timestamp is after end timestamp.";
+ case LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE: return "Telemetry Chunk index out of range.";
+ case LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH: return "Telemetry Chunk ID mismatch.";
+ case LIBMC_ERROR_TELEMETRYCHUNKISREADONLY: return "Telemetry Chunk is readonly.";
+ case LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY: return "Telemetry Chunks can only be archived if readonly.";
}
return "unknown error";
}
diff --git a/Framework/HeadersCore/CppDynamic/libmc_types.hpp b/Framework/HeadersCore/CppDynamic/libmc_types.hpp
index 327349718..dad52a6d4 100644
--- a/Framework/HeadersCore/CppDynamic/libmc_types.hpp
+++ b/Framework/HeadersCore/CppDynamic/libmc_types.hpp
@@ -713,6 +713,11 @@ typedef void * LibMC_pvoid;
#define LIBMC_ERROR_INVALIDTELEMETRYMARKERFINISHTIMESTAMP 697 /** Invalid telemetry marker finish timestamp. */
#define LIBMC_ERROR_UNFINISHEDTELEMETRYMARKERSHAVENODURATION 698 /** Unfinished telemetry marker have no duration. */
#define LIBMC_ERROR_TELEMETRYMARKERALREADYREGISTERED 699 /** Telemetry Marker has been already registered. */
+#define LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND 700 /** Telemetry Chunk Start timestamp is after end timestamp. */
+#define LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE 701 /** Telemetry Chunk index out of range. */
+#define LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH 702 /** Telemetry Chunk ID mismatch. */
+#define LIBMC_ERROR_TELEMETRYCHUNKISREADONLY 703 /** Telemetry Chunk is readonly. */
+#define LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY 704 /** Telemetry Chunks can only be archived if readonly. */
/*************************************************************************************************************************
Error strings for LibMC
@@ -1338,6 +1343,11 @@ inline const char * LIBMC_GETERRORSTRING (LibMCResult nErrorCode) {
case LIBMC_ERROR_INVALIDTELEMETRYMARKERFINISHTIMESTAMP: return "Invalid telemetry marker finish timestamp.";
case LIBMC_ERROR_UNFINISHEDTELEMETRYMARKERSHAVENODURATION: return "Unfinished telemetry marker have no duration.";
case LIBMC_ERROR_TELEMETRYMARKERALREADYREGISTERED: return "Telemetry Marker has been already registered.";
+ case LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND: return "Telemetry Chunk Start timestamp is after end timestamp.";
+ case LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE: return "Telemetry Chunk index out of range.";
+ case LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH: return "Telemetry Chunk ID mismatch.";
+ case LIBMC_ERROR_TELEMETRYCHUNKISREADONLY: return "Telemetry Chunk is readonly.";
+ case LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY: return "Telemetry Chunks can only be archived if readonly.";
default: return "unknown error";
}
}
diff --git a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h
index b2b1a1eb5..5f891da6e 100644
--- a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h
+++ b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.h
@@ -4234,6 +4234,19 @@ typedef LibMCEnvResult (*PLibMCEnvBuildExecution_LoadAttachedJournalPtr) (LibMCE
*/
typedef LibMCEnvResult (*PLibMCEnvBuildExecutionIterator_GetCurrentExecutionPtr) (LibMCEnv_BuildExecutionIterator pBuildExecutionIterator, LibMCEnv_BuildExecution * pBuildExecutionInstance);
+/*************************************************************************************************************************
+ Class definition for BuildIterator
+**************************************************************************************************************************/
+
+/**
+* Returns the build the iterator points at.
+*
+* @param[in] pBuildIterator - BuildIterator instance.
+* @param[out] pBuildInstance - returns the Build instance.
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvBuildIterator_GetCurrentBuildPtr) (LibMCEnv_BuildIterator pBuildIterator, LibMCEnv_Build * pBuildInstance);
+
/*************************************************************************************************************************
Class definition for Build
**************************************************************************************************************************/
@@ -4260,6 +4273,28 @@ typedef LibMCEnvResult (*PLibMCEnvBuild_GetNamePtr) (LibMCEnv_Build pBuild, cons
*/
typedef LibMCEnvResult (*PLibMCEnvBuild_GetBuildUUIDPtr) (LibMCEnv_Build pBuild, const LibMCEnv_uint32 nBuildUUIDBufferSize, LibMCEnv_uint32* pBuildUUIDNeededChars, char * pBuildUUIDBuffer);
+/**
+* Returns creation timestamp of the build in ISO-8601 format.
+*
+* @param[in] pBuild - Build instance.
+* @param[in] nTimestampBufferSize - size of the buffer (including trailing 0)
+* @param[out] pTimestampNeededChars - will be filled with the count of the written bytes, or needed buffer size.
+* @param[out] pTimestampBuffer - buffer of Creation timestamp in ISO-8601 format (e.g., 2025-10-23T14:30:00.000Z)., may be NULL
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvBuild_GetCreatedTimestampPtr) (LibMCEnv_Build pBuild, const LibMCEnv_uint32 nTimestampBufferSize, LibMCEnv_uint32* pTimestampNeededChars, char * pTimestampBuffer);
+
+/**
+* Returns the most recent execution timestamp in ISO-8601 format. Returns empty string if build has never been executed.
+*
+* @param[in] pBuild - Build instance.
+* @param[in] nTimestampBufferSize - size of the buffer (including trailing 0)
+* @param[out] pTimestampNeededChars - will be filled with the count of the written bytes, or needed buffer size.
+* @param[out] pTimestampBuffer - buffer of Most recent execution timestamp in ISO-8601 format. Empty string if never executed., may be NULL
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvBuild_GetLastExecutionTimestampPtr) (LibMCEnv_Build pBuild, const LibMCEnv_uint32 nTimestampBufferSize, LibMCEnv_uint32* pTimestampNeededChars, char * pTimestampBuffer);
+
/**
* Returns storage uuid of the build stream.
*
@@ -9218,29 +9253,27 @@ typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_GetPreviousStatePtr) (LibMCEn
typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_PrepareSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pMachineInstance, const char * pSignalName, LibMCEnv_SignalTrigger * pSignalInstance);
/**
-* Waits for a signal for a certain amount of time.
+* Retrieves an InQueue signal by type and changes its phase to InProcess. Recommended to use as it is robust against signal timeouts...
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pSignalName - Name Of Signal
-* @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
-* @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
-* @param[out] pSuccess - Signal has been triggered
+* @param[in] pSignalTypeName - Name Of Signal to be returned
+* @param[out] pHandlerInstance - Signal object. If no signal is InQueue the signal handler object will be null.
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_WaitForSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalName, LibMCEnv_uint32 nTimeOut, LibMCEnv_SignalHandler * pHandlerInstance, bool * pSuccess);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_ClaimSignalFromQueuePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance);
/**
-* Retrieves an unhandled signal By signal type name. Only affects signals with Phase InQueue.
+* Returns if a signal queue is empty for a specific type...
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @param[in] pSignalTypeName - Name Of Signal to be returned
-* @param[out] pHandlerInstance - Signal object. If no signal has been found the signal handler object will be null.
+* @param[out] pIsEmpty - Returns if the signal queue is empty. Please be aware that even a false return value does not guarantee that ClaimSignalFromQueue returns a non-null value.
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_SignalQueueIsEmptyPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, bool * pIsEmpty);
/**
-* Clears all unhandled signals of a certain type and marks them as Cleared. Only affects signals with Phase InQueue.
+* Clears all InQueue or InProcess signals of a certain type and marks them as Cleared. Handled, failed or timedout signals are unaffected
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @param[in] pSignalTypeName - Name Of Signal to be cleared.
@@ -9249,7 +9282,7 @@ typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) (LibMC
typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_ClearUnhandledSignalsOfTypePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName);
/**
-* Clears all unhandled signals and marks them Cleared. Only affects signals in the specific queue (as well as with Phase InQueue.
+* Clears all InQueue or InProcess signals of this state machine and marks them Cleared. Handled, failed or timedout signals are unaffected
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @return error code or 0 (success)
@@ -9257,11 +9290,11 @@ typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_ClearUnhandledSignalsOfTypePt
typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_ClearAllUnhandledSignalsPtr) (LibMCEnv_StateEnvironment pStateEnvironment);
/**
-* retrieves an unhandled signal from the current state machine by UUID.
+* Retrieves an InQueue or InProcess signal from the current state machine by UUID.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @param[in] pUUID - Name
-* @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled already.
+* @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled, failed, cleared or timedout already.
* @param[out] pHandler - Signal handler instance. Returns null, if signal does not exist.
* @return error code or 0 (success)
*/
@@ -9339,87 +9372,109 @@ typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_GetBuildExecutionPtr) (LibMCE
typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_UnloadAllToolpathesPtr) (LibMCEnv_StateEnvironment pStateEnvironment);
/**
-* sets the next state
+* DEPRECIATED: Waits for an InQueue signal to exist for a certain amount of time. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE claim signal instead.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pStateName - Name of next state
+* @param[in] pSignalName - Name Of Signal
+* @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
+* @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
+* @param[out] pSuccess - Signal has been triggered
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_SetNextStatePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pStateName);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_WaitForSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalName, LibMCEnv_uint32 nTimeOut, LibMCEnv_SignalHandler * pHandlerInstance, bool * pSuccess);
/**
-* logs a string as message
+* DEPRECIATED: Retrieves am InQueue signal by type. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE ClaimSignalFromQueue instead.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pLogString - String to Log
+* @param[in] pSignalTypeName - Name Of Signal to be returned
+* @param[out] pHandlerInstance - Signal object. If no signal has been found the signal handler object will be null.
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_LogMessagePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance);
/**
-* logs a string as warning
+* DEPRECIATED: stores a signal handler in the current state machine
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pLogString - String to Log
+* @param[in] pName - Name
+* @param[in] pHandler - Signal handler to store.
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_LogWarningPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_StoreSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler pHandler);
/**
-* logs a string as info
+* DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pLogString - String to Log
+* @param[in] pName - Name
+* @param[out] pHandler - Signal handler instance.
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_LogInfoPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_RetrieveSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler * pHandler);
/**
-* Puts the current instance to sleep for a definite amount of time. MUST be used instead of a blocking sleep call.
+* DEPRECIATED: deletes a value from the data store.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] nDelay - Milliseconds to sleeps
+* @param[in] pName - Name
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_SleepPtr) (LibMCEnv_StateEnvironment pStateEnvironment, LibMCEnv_uint32 nDelay);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_ClearStoredValuePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pName);
/**
-* checks environment for termination signal. MUST be called frequently in longer-running operations.
+* sets the next state
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[out] pShallTerminate - Returns if termination shall appear
+* @param[in] pStateName - Name of next state
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_CheckForTerminationPtr) (LibMCEnv_StateEnvironment pStateEnvironment, bool * pShallTerminate);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_SetNextStatePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pStateName);
/**
-* DEPRECIATED: stores a signal handler in the current state machine
+* logs a string as message
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pName - Name
-* @param[in] pHandler - Signal handler to store.
+* @param[in] pLogString - String to Log
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_StoreSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler pHandler);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_LogMessagePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
/**
-* DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
+* logs a string as warning
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pName - Name
-* @param[out] pHandler - Signal handler instance.
+* @param[in] pLogString - String to Log
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_RetrieveSignalPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler * pHandler);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_LogWarningPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
/**
-* DEPRECIATED: deletes a value from the data store.
+* logs a string as info
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pName - Name
+* @param[in] pLogString - String to Log
* @return error code or 0 (success)
*/
-typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_ClearStoredValuePtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pName);
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_LogInfoPtr) (LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+
+/**
+* Puts the current instance to sleep for a definite amount of time. MUST be used instead of a blocking sleep call.
+*
+* @param[in] pStateEnvironment - StateEnvironment instance.
+* @param[in] nDelay - Milliseconds to sleeps
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_SleepPtr) (LibMCEnv_StateEnvironment pStateEnvironment, LibMCEnv_uint32 nDelay);
+
+/**
+* checks environment for termination signal. MUST be called frequently in longer-running operations.
+*
+* @param[in] pStateEnvironment - StateEnvironment instance.
+* @param[out] pShallTerminate - Returns if termination shall appear
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvStateEnvironment_CheckForTerminationPtr) (LibMCEnv_StateEnvironment pStateEnvironment, bool * pShallTerminate);
/**
* sets a string parameter
@@ -10587,6 +10642,16 @@ typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_HasBuildExecutionPtr) (LibMCEnv_
*/
typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_GetBuildExecutionPtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pExecutionUUID, LibMCEnv_BuildExecution * pExecutionInstance);
+/**
+* Returns an iterator for recent build jobs, ordered by timestamp (newest first).
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] nMaxCount - Maximum number of jobs to return. Must be greater than 0.
+* @param[out] pBuildIterator - Iterator for build jobs, ordered newest first.
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_GetRecentBuildJobsPtr) (LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nMaxCount, LibMCEnv_BuildIterator * pBuildIterator);
+
/**
* Creates an empty discrete field.
*
@@ -10929,6 +10994,46 @@ typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_GetExternalEventParameterPtr) (L
*/
typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_AddExternalEventResultValuePtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, const char * pReturnValue);
+/**
+* Sets a string result value for external event return (typed convenience wrapper).
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] pReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_SetStringResultPtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, const char * pReturnValue);
+
+/**
+* Sets an integer result value for external event return.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] nReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_SetIntegerResultPtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, LibMCEnv_int64 nReturnValue);
+
+/**
+* Sets a boolean result value for external event return.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] bReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_SetBoolResultPtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, bool bReturnValue);
+
+/**
+* Sets a double result value for external event return.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] dReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+typedef LibMCEnvResult (*PLibMCEnvUIEnvironment_SetDoubleResultPtr) (LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, LibMCEnv_double dReturnValue);
+
/**
* Returns the external event parameters. This JSON Object was passed on from the external API.
*
@@ -11404,8 +11509,11 @@ typedef struct {
PLibMCEnvBuildExecution_GetMetaDataStringPtr m_BuildExecution_GetMetaDataString;
PLibMCEnvBuildExecution_LoadAttachedJournalPtr m_BuildExecution_LoadAttachedJournal;
PLibMCEnvBuildExecutionIterator_GetCurrentExecutionPtr m_BuildExecutionIterator_GetCurrentExecution;
+ PLibMCEnvBuildIterator_GetCurrentBuildPtr m_BuildIterator_GetCurrentBuild;
PLibMCEnvBuild_GetNamePtr m_Build_GetName;
PLibMCEnvBuild_GetBuildUUIDPtr m_Build_GetBuildUUID;
+ PLibMCEnvBuild_GetCreatedTimestampPtr m_Build_GetCreatedTimestamp;
+ PLibMCEnvBuild_GetLastExecutionTimestampPtr m_Build_GetLastExecutionTimestamp;
PLibMCEnvBuild_GetStorageUUIDPtr m_Build_GetStorageUUID;
PLibMCEnvBuild_GetStorageSHA256Ptr m_Build_GetStorageSHA256;
PLibMCEnvBuild_EnsureStorageSHA256IsValidPtr m_Build_EnsureStorageSHA256IsValid;
@@ -11867,8 +11975,8 @@ typedef struct {
PLibMCEnvStateEnvironment_GetMachineStatePtr m_StateEnvironment_GetMachineState;
PLibMCEnvStateEnvironment_GetPreviousStatePtr m_StateEnvironment_GetPreviousState;
PLibMCEnvStateEnvironment_PrepareSignalPtr m_StateEnvironment_PrepareSignal;
- PLibMCEnvStateEnvironment_WaitForSignalPtr m_StateEnvironment_WaitForSignal;
- PLibMCEnvStateEnvironment_GetUnhandledSignalPtr m_StateEnvironment_GetUnhandledSignal;
+ PLibMCEnvStateEnvironment_ClaimSignalFromQueuePtr m_StateEnvironment_ClaimSignalFromQueue;
+ PLibMCEnvStateEnvironment_SignalQueueIsEmptyPtr m_StateEnvironment_SignalQueueIsEmpty;
PLibMCEnvStateEnvironment_ClearUnhandledSignalsOfTypePtr m_StateEnvironment_ClearUnhandledSignalsOfType;
PLibMCEnvStateEnvironment_ClearAllUnhandledSignalsPtr m_StateEnvironment_ClearAllUnhandledSignals;
PLibMCEnvStateEnvironment_GetUnhandledSignalByUUIDPtr m_StateEnvironment_GetUnhandledSignalByUUID;
@@ -11879,15 +11987,17 @@ typedef struct {
PLibMCEnvStateEnvironment_HasBuildExecutionPtr m_StateEnvironment_HasBuildExecution;
PLibMCEnvStateEnvironment_GetBuildExecutionPtr m_StateEnvironment_GetBuildExecution;
PLibMCEnvStateEnvironment_UnloadAllToolpathesPtr m_StateEnvironment_UnloadAllToolpathes;
+ PLibMCEnvStateEnvironment_WaitForSignalPtr m_StateEnvironment_WaitForSignal;
+ PLibMCEnvStateEnvironment_GetUnhandledSignalPtr m_StateEnvironment_GetUnhandledSignal;
+ PLibMCEnvStateEnvironment_StoreSignalPtr m_StateEnvironment_StoreSignal;
+ PLibMCEnvStateEnvironment_RetrieveSignalPtr m_StateEnvironment_RetrieveSignal;
+ PLibMCEnvStateEnvironment_ClearStoredValuePtr m_StateEnvironment_ClearStoredValue;
PLibMCEnvStateEnvironment_SetNextStatePtr m_StateEnvironment_SetNextState;
PLibMCEnvStateEnvironment_LogMessagePtr m_StateEnvironment_LogMessage;
PLibMCEnvStateEnvironment_LogWarningPtr m_StateEnvironment_LogWarning;
PLibMCEnvStateEnvironment_LogInfoPtr m_StateEnvironment_LogInfo;
PLibMCEnvStateEnvironment_SleepPtr m_StateEnvironment_Sleep;
PLibMCEnvStateEnvironment_CheckForTerminationPtr m_StateEnvironment_CheckForTermination;
- PLibMCEnvStateEnvironment_StoreSignalPtr m_StateEnvironment_StoreSignal;
- PLibMCEnvStateEnvironment_RetrieveSignalPtr m_StateEnvironment_RetrieveSignal;
- PLibMCEnvStateEnvironment_ClearStoredValuePtr m_StateEnvironment_ClearStoredValue;
PLibMCEnvStateEnvironment_SetStringParameterPtr m_StateEnvironment_SetStringParameter;
PLibMCEnvStateEnvironment_SetUUIDParameterPtr m_StateEnvironment_SetUUIDParameter;
PLibMCEnvStateEnvironment_SetDoubleParameterPtr m_StateEnvironment_SetDoubleParameter;
@@ -11997,6 +12107,7 @@ typedef struct {
PLibMCEnvUIEnvironment_GetBuildJobPtr m_UIEnvironment_GetBuildJob;
PLibMCEnvUIEnvironment_HasBuildExecutionPtr m_UIEnvironment_HasBuildExecution;
PLibMCEnvUIEnvironment_GetBuildExecutionPtr m_UIEnvironment_GetBuildExecution;
+ PLibMCEnvUIEnvironment_GetRecentBuildJobsPtr m_UIEnvironment_GetRecentBuildJobs;
PLibMCEnvUIEnvironment_CreateDiscreteField2DPtr m_UIEnvironment_CreateDiscreteField2D;
PLibMCEnvUIEnvironment_CreateDiscreteField2DFromImagePtr m_UIEnvironment_CreateDiscreteField2DFromImage;
PLibMCEnvUIEnvironment_CheckPermissionPtr m_UIEnvironment_CheckPermission;
@@ -12029,6 +12140,10 @@ typedef struct {
PLibMCEnvUIEnvironment_HasExternalEventParameterPtr m_UIEnvironment_HasExternalEventParameter;
PLibMCEnvUIEnvironment_GetExternalEventParameterPtr m_UIEnvironment_GetExternalEventParameter;
PLibMCEnvUIEnvironment_AddExternalEventResultValuePtr m_UIEnvironment_AddExternalEventResultValue;
+ PLibMCEnvUIEnvironment_SetStringResultPtr m_UIEnvironment_SetStringResult;
+ PLibMCEnvUIEnvironment_SetIntegerResultPtr m_UIEnvironment_SetIntegerResult;
+ PLibMCEnvUIEnvironment_SetBoolResultPtr m_UIEnvironment_SetBoolResult;
+ PLibMCEnvUIEnvironment_SetDoubleResultPtr m_UIEnvironment_SetDoubleResult;
PLibMCEnvUIEnvironment_GetExternalEventParametersPtr m_UIEnvironment_GetExternalEventParameters;
PLibMCEnvUIEnvironment_GetExternalEventResultsPtr m_UIEnvironment_GetExternalEventResults;
PLibMCEnvUIEnvironment_CreateMachineConfigurationHandlerPtr m_UIEnvironment_CreateMachineConfigurationHandler;
diff --git a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp
index c3ae05672..248cd5d60 100644
--- a/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp
+++ b/Framework/HeadersDev/CppDynamic/libmcenv_dynamic.hpp
@@ -97,6 +97,7 @@ class CToolpathLayer;
class CToolpathAccessor;
class CBuildExecution;
class CBuildExecutionIterator;
+class CBuildIterator;
class CBuild;
class CWorkingFileProcess;
class CWorkingFile;
@@ -183,6 +184,7 @@ typedef CToolpathLayer CLibMCEnvToolpathLayer;
typedef CToolpathAccessor CLibMCEnvToolpathAccessor;
typedef CBuildExecution CLibMCEnvBuildExecution;
typedef CBuildExecutionIterator CLibMCEnvBuildExecutionIterator;
+typedef CBuildIterator CLibMCEnvBuildIterator;
typedef CBuild CLibMCEnvBuild;
typedef CWorkingFileProcess CLibMCEnvWorkingFileProcess;
typedef CWorkingFile CLibMCEnvWorkingFile;
@@ -269,6 +271,7 @@ typedef std::shared_ptr PToolpathLayer;
typedef std::shared_ptr PToolpathAccessor;
typedef std::shared_ptr PBuildExecution;
typedef std::shared_ptr PBuildExecutionIterator;
+typedef std::shared_ptr PBuildIterator;
typedef std::shared_ptr PBuild;
typedef std::shared_ptr PWorkingFileProcess;
typedef std::shared_ptr PWorkingFile;
@@ -355,6 +358,7 @@ typedef PToolpathLayer PLibMCEnvToolpathLayer;
typedef PToolpathAccessor PLibMCEnvToolpathAccessor;
typedef PBuildExecution PLibMCEnvBuildExecution;
typedef PBuildExecutionIterator PLibMCEnvBuildExecutionIterator;
+typedef PBuildIterator PLibMCEnvBuildIterator;
typedef PBuild PLibMCEnvBuild;
typedef PWorkingFileProcess PLibMCEnvWorkingFileProcess;
typedef PWorkingFile PLibMCEnvWorkingFile;
@@ -1145,6 +1149,7 @@ class CWrapper {
friend class CToolpathAccessor;
friend class CBuildExecution;
friend class CBuildExecutionIterator;
+ friend class CBuildIterator;
friend class CBuild;
friend class CWorkingFileProcess;
friend class CWorkingFile;
@@ -2232,6 +2237,23 @@ class CBuildExecutionIterator : public CIterator {
inline PBuildExecution GetCurrentExecution();
};
+/*************************************************************************************************************************
+ Class CBuildIterator
+**************************************************************************************************************************/
+class CBuildIterator : public CIterator {
+public:
+
+ /**
+ * CBuildIterator::CBuildIterator - Constructor for BuildIterator class.
+ */
+ CBuildIterator(CWrapper* pWrapper, LibMCEnvHandle pHandle)
+ : CIterator(pWrapper, pHandle)
+ {
+ }
+
+ inline PBuild GetCurrentBuild();
+};
+
/*************************************************************************************************************************
Class CBuild
**************************************************************************************************************************/
@@ -2248,6 +2270,8 @@ class CBuild : public CBase {
inline std::string GetName();
inline std::string GetBuildUUID();
+ inline std::string GetCreatedTimestamp();
+ inline std::string GetLastExecutionTimestamp();
inline std::string GetStorageUUID();
inline std::string GetStorageSHA256();
inline void EnsureStorageSHA256IsValid();
@@ -3349,8 +3373,8 @@ class CStateEnvironment : public CBase {
inline std::string GetMachineState(const std::string & sMachineInstance);
inline std::string GetPreviousState();
inline PSignalTrigger PrepareSignal(const std::string & sMachineInstance, const std::string & sSignalName);
- inline bool WaitForSignal(const std::string & sSignalName, const LibMCEnv_uint32 nTimeOut, PSignalHandler & pHandlerInstance);
- inline PSignalHandler GetUnhandledSignal(const std::string & sSignalTypeName);
+ inline PSignalHandler ClaimSignalFromQueue(const std::string & sSignalTypeName);
+ inline bool SignalQueueIsEmpty(const std::string & sSignalTypeName);
inline void ClearUnhandledSignalsOfType(const std::string & sSignalTypeName);
inline void ClearAllUnhandledSignals();
inline PSignalHandler GetUnhandledSignalByUUID(const std::string & sUUID, const bool bMustExist);
@@ -3361,15 +3385,17 @@ class CStateEnvironment : public CBase {
inline bool HasBuildExecution(const std::string & sExecutionUUID);
inline PBuildExecution GetBuildExecution(const std::string & sExecutionUUID);
inline void UnloadAllToolpathes();
+ inline bool WaitForSignal(const std::string & sSignalName, const LibMCEnv_uint32 nTimeOut, PSignalHandler & pHandlerInstance);
+ inline PSignalHandler GetUnhandledSignal(const std::string & sSignalTypeName);
+ inline void StoreSignal(const std::string & sName, classParam pHandler);
+ inline PSignalHandler RetrieveSignal(const std::string & sName);
+ inline void ClearStoredValue(const std::string & sName);
inline void SetNextState(const std::string & sStateName);
inline void LogMessage(const std::string & sLogString);
inline void LogWarning(const std::string & sLogString);
inline void LogInfo(const std::string & sLogString);
inline void Sleep(const LibMCEnv_uint32 nDelay);
inline bool CheckForTermination();
- inline void StoreSignal(const std::string & sName, classParam pHandler);
- inline PSignalHandler RetrieveSignal(const std::string & sName);
- inline void ClearStoredValue(const std::string & sName);
inline void SetStringParameter(const std::string & sParameterGroup, const std::string & sParameterName, const std::string & sValue);
inline void SetUUIDParameter(const std::string & sParameterGroup, const std::string & sParameterName, const std::string & sValue);
inline void SetDoubleParameter(const std::string & sParameterGroup, const std::string & sParameterName, const LibMCEnv_double dValue);
@@ -3511,6 +3537,7 @@ class CUIEnvironment : public CBase {
inline PBuild GetBuildJob(const std::string & sBuildUUID);
inline bool HasBuildExecution(const std::string & sExecutionUUID);
inline PBuildExecution GetBuildExecution(const std::string & sExecutionUUID);
+ inline PBuildIterator GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount);
inline PDiscreteFieldData2D CreateDiscreteField2D(const LibMCEnv_uint32 nPixelCountX, const LibMCEnv_uint32 nPixelCountY, const LibMCEnv_double dDPIValueX, const LibMCEnv_double dDPIValueY, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY, const LibMCEnv_double dDefaultValue);
inline PDiscreteFieldData2D CreateDiscreteField2DFromImage(classParam pImageDataInstance, const LibMCEnv_double dBlackValue, const LibMCEnv_double dWhiteValue, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY);
inline bool CheckPermission(const std::string & sPermissionIdentifier);
@@ -3543,6 +3570,10 @@ class CUIEnvironment : public CBase {
inline bool HasExternalEventParameter(const std::string & sParameterName);
inline std::string GetExternalEventParameter(const std::string & sParameterName);
inline void AddExternalEventResultValue(const std::string & sReturnValueName, const std::string & sReturnValue);
+ inline void SetStringResult(const std::string & sReturnValueName, const std::string & sReturnValue);
+ inline void SetIntegerResult(const std::string & sReturnValueName, const LibMCEnv_int64 nReturnValue);
+ inline void SetBoolResult(const std::string & sReturnValueName, const bool bReturnValue);
+ inline void SetDoubleResult(const std::string & sReturnValueName, const LibMCEnv_double dReturnValue);
inline PJSONObject GetExternalEventParameters();
inline PJSONObject GetExternalEventResults();
inline PMachineConfigurationHandler CreateMachineConfigurationHandler();
@@ -4021,8 +4052,11 @@ class CUIEnvironment : public CBase {
pWrapperTable->m_BuildExecution_GetMetaDataString = nullptr;
pWrapperTable->m_BuildExecution_LoadAttachedJournal = nullptr;
pWrapperTable->m_BuildExecutionIterator_GetCurrentExecution = nullptr;
+ pWrapperTable->m_BuildIterator_GetCurrentBuild = nullptr;
pWrapperTable->m_Build_GetName = nullptr;
pWrapperTable->m_Build_GetBuildUUID = nullptr;
+ pWrapperTable->m_Build_GetCreatedTimestamp = nullptr;
+ pWrapperTable->m_Build_GetLastExecutionTimestamp = nullptr;
pWrapperTable->m_Build_GetStorageUUID = nullptr;
pWrapperTable->m_Build_GetStorageSHA256 = nullptr;
pWrapperTable->m_Build_EnsureStorageSHA256IsValid = nullptr;
@@ -4484,8 +4518,8 @@ class CUIEnvironment : public CBase {
pWrapperTable->m_StateEnvironment_GetMachineState = nullptr;
pWrapperTable->m_StateEnvironment_GetPreviousState = nullptr;
pWrapperTable->m_StateEnvironment_PrepareSignal = nullptr;
- pWrapperTable->m_StateEnvironment_WaitForSignal = nullptr;
- pWrapperTable->m_StateEnvironment_GetUnhandledSignal = nullptr;
+ pWrapperTable->m_StateEnvironment_ClaimSignalFromQueue = nullptr;
+ pWrapperTable->m_StateEnvironment_SignalQueueIsEmpty = nullptr;
pWrapperTable->m_StateEnvironment_ClearUnhandledSignalsOfType = nullptr;
pWrapperTable->m_StateEnvironment_ClearAllUnhandledSignals = nullptr;
pWrapperTable->m_StateEnvironment_GetUnhandledSignalByUUID = nullptr;
@@ -4496,15 +4530,17 @@ class CUIEnvironment : public CBase {
pWrapperTable->m_StateEnvironment_HasBuildExecution = nullptr;
pWrapperTable->m_StateEnvironment_GetBuildExecution = nullptr;
pWrapperTable->m_StateEnvironment_UnloadAllToolpathes = nullptr;
+ pWrapperTable->m_StateEnvironment_WaitForSignal = nullptr;
+ pWrapperTable->m_StateEnvironment_GetUnhandledSignal = nullptr;
+ pWrapperTable->m_StateEnvironment_StoreSignal = nullptr;
+ pWrapperTable->m_StateEnvironment_RetrieveSignal = nullptr;
+ pWrapperTable->m_StateEnvironment_ClearStoredValue = nullptr;
pWrapperTable->m_StateEnvironment_SetNextState = nullptr;
pWrapperTable->m_StateEnvironment_LogMessage = nullptr;
pWrapperTable->m_StateEnvironment_LogWarning = nullptr;
pWrapperTable->m_StateEnvironment_LogInfo = nullptr;
pWrapperTable->m_StateEnvironment_Sleep = nullptr;
pWrapperTable->m_StateEnvironment_CheckForTermination = nullptr;
- pWrapperTable->m_StateEnvironment_StoreSignal = nullptr;
- pWrapperTable->m_StateEnvironment_RetrieveSignal = nullptr;
- pWrapperTable->m_StateEnvironment_ClearStoredValue = nullptr;
pWrapperTable->m_StateEnvironment_SetStringParameter = nullptr;
pWrapperTable->m_StateEnvironment_SetUUIDParameter = nullptr;
pWrapperTable->m_StateEnvironment_SetDoubleParameter = nullptr;
@@ -4614,6 +4650,7 @@ class CUIEnvironment : public CBase {
pWrapperTable->m_UIEnvironment_GetBuildJob = nullptr;
pWrapperTable->m_UIEnvironment_HasBuildExecution = nullptr;
pWrapperTable->m_UIEnvironment_GetBuildExecution = nullptr;
+ pWrapperTable->m_UIEnvironment_GetRecentBuildJobs = nullptr;
pWrapperTable->m_UIEnvironment_CreateDiscreteField2D = nullptr;
pWrapperTable->m_UIEnvironment_CreateDiscreteField2DFromImage = nullptr;
pWrapperTable->m_UIEnvironment_CheckPermission = nullptr;
@@ -4646,6 +4683,10 @@ class CUIEnvironment : public CBase {
pWrapperTable->m_UIEnvironment_HasExternalEventParameter = nullptr;
pWrapperTable->m_UIEnvironment_GetExternalEventParameter = nullptr;
pWrapperTable->m_UIEnvironment_AddExternalEventResultValue = nullptr;
+ pWrapperTable->m_UIEnvironment_SetStringResult = nullptr;
+ pWrapperTable->m_UIEnvironment_SetIntegerResult = nullptr;
+ pWrapperTable->m_UIEnvironment_SetBoolResult = nullptr;
+ pWrapperTable->m_UIEnvironment_SetDoubleResult = nullptr;
pWrapperTable->m_UIEnvironment_GetExternalEventParameters = nullptr;
pWrapperTable->m_UIEnvironment_GetExternalEventResults = nullptr;
pWrapperTable->m_UIEnvironment_CreateMachineConfigurationHandler = nullptr;
@@ -8232,6 +8273,15 @@ class CUIEnvironment : public CBase {
if (pWrapperTable->m_BuildExecutionIterator_GetCurrentExecution == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ #ifdef _WIN32
+ pWrapperTable->m_BuildIterator_GetCurrentBuild = (PLibMCEnvBuildIterator_GetCurrentBuildPtr) GetProcAddress(hLibrary, "libmcenv_builditerator_getcurrentbuild");
+ #else // _WIN32
+ pWrapperTable->m_BuildIterator_GetCurrentBuild = (PLibMCEnvBuildIterator_GetCurrentBuildPtr) dlsym(hLibrary, "libmcenv_builditerator_getcurrentbuild");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_BuildIterator_GetCurrentBuild == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
#ifdef _WIN32
pWrapperTable->m_Build_GetName = (PLibMCEnvBuild_GetNamePtr) GetProcAddress(hLibrary, "libmcenv_build_getname");
#else // _WIN32
@@ -8250,6 +8300,24 @@ class CUIEnvironment : public CBase {
if (pWrapperTable->m_Build_GetBuildUUID == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ #ifdef _WIN32
+ pWrapperTable->m_Build_GetCreatedTimestamp = (PLibMCEnvBuild_GetCreatedTimestampPtr) GetProcAddress(hLibrary, "libmcenv_build_getcreatedtimestamp");
+ #else // _WIN32
+ pWrapperTable->m_Build_GetCreatedTimestamp = (PLibMCEnvBuild_GetCreatedTimestampPtr) dlsym(hLibrary, "libmcenv_build_getcreatedtimestamp");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_Build_GetCreatedTimestamp == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ #ifdef _WIN32
+ pWrapperTable->m_Build_GetLastExecutionTimestamp = (PLibMCEnvBuild_GetLastExecutionTimestampPtr) GetProcAddress(hLibrary, "libmcenv_build_getlastexecutiontimestamp");
+ #else // _WIN32
+ pWrapperTable->m_Build_GetLastExecutionTimestamp = (PLibMCEnvBuild_GetLastExecutionTimestampPtr) dlsym(hLibrary, "libmcenv_build_getlastexecutiontimestamp");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_Build_GetLastExecutionTimestamp == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
#ifdef _WIN32
pWrapperTable->m_Build_GetStorageUUID = (PLibMCEnvBuild_GetStorageUUIDPtr) GetProcAddress(hLibrary, "libmcenv_build_getstorageuuid");
#else // _WIN32
@@ -12400,21 +12468,21 @@ class CUIEnvironment : public CBase {
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_WaitForSignal = (PLibMCEnvStateEnvironment_WaitForSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_waitforsignal");
+ pWrapperTable->m_StateEnvironment_ClaimSignalFromQueue = (PLibMCEnvStateEnvironment_ClaimSignalFromQueuePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_claimsignalfromqueue");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_WaitForSignal = (PLibMCEnvStateEnvironment_WaitForSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_waitforsignal");
+ pWrapperTable->m_StateEnvironment_ClaimSignalFromQueue = (PLibMCEnvStateEnvironment_ClaimSignalFromQueuePtr) dlsym(hLibrary, "libmcenv_stateenvironment_claimsignalfromqueue");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_WaitForSignal == nullptr)
+ if (pWrapperTable->m_StateEnvironment_ClaimSignalFromQueue == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_GetUnhandledSignal = (PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_getunhandledsignal");
+ pWrapperTable->m_StateEnvironment_SignalQueueIsEmpty = (PLibMCEnvStateEnvironment_SignalQueueIsEmptyPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_signalqueueisempty");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_GetUnhandledSignal = (PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_getunhandledsignal");
+ pWrapperTable->m_StateEnvironment_SignalQueueIsEmpty = (PLibMCEnvStateEnvironment_SignalQueueIsEmptyPtr) dlsym(hLibrary, "libmcenv_stateenvironment_signalqueueisempty");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_GetUnhandledSignal == nullptr)
+ if (pWrapperTable->m_StateEnvironment_SignalQueueIsEmpty == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
@@ -12508,84 +12576,102 @@ class CUIEnvironment : public CBase {
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_SetNextState = (PLibMCEnvStateEnvironment_SetNextStatePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_setnextstate");
+ pWrapperTable->m_StateEnvironment_WaitForSignal = (PLibMCEnvStateEnvironment_WaitForSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_waitforsignal");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_SetNextState = (PLibMCEnvStateEnvironment_SetNextStatePtr) dlsym(hLibrary, "libmcenv_stateenvironment_setnextstate");
+ pWrapperTable->m_StateEnvironment_WaitForSignal = (PLibMCEnvStateEnvironment_WaitForSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_waitforsignal");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_SetNextState == nullptr)
+ if (pWrapperTable->m_StateEnvironment_WaitForSignal == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_LogMessage = (PLibMCEnvStateEnvironment_LogMessagePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_logmessage");
+ pWrapperTable->m_StateEnvironment_GetUnhandledSignal = (PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_getunhandledsignal");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_LogMessage = (PLibMCEnvStateEnvironment_LogMessagePtr) dlsym(hLibrary, "libmcenv_stateenvironment_logmessage");
+ pWrapperTable->m_StateEnvironment_GetUnhandledSignal = (PLibMCEnvStateEnvironment_GetUnhandledSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_getunhandledsignal");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_LogMessage == nullptr)
+ if (pWrapperTable->m_StateEnvironment_GetUnhandledSignal == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_LogWarning = (PLibMCEnvStateEnvironment_LogWarningPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_logwarning");
+ pWrapperTable->m_StateEnvironment_StoreSignal = (PLibMCEnvStateEnvironment_StoreSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_storesignal");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_LogWarning = (PLibMCEnvStateEnvironment_LogWarningPtr) dlsym(hLibrary, "libmcenv_stateenvironment_logwarning");
+ pWrapperTable->m_StateEnvironment_StoreSignal = (PLibMCEnvStateEnvironment_StoreSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_storesignal");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_LogWarning == nullptr)
+ if (pWrapperTable->m_StateEnvironment_StoreSignal == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_LogInfo = (PLibMCEnvStateEnvironment_LogInfoPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_loginfo");
+ pWrapperTable->m_StateEnvironment_RetrieveSignal = (PLibMCEnvStateEnvironment_RetrieveSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_retrievesignal");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_LogInfo = (PLibMCEnvStateEnvironment_LogInfoPtr) dlsym(hLibrary, "libmcenv_stateenvironment_loginfo");
+ pWrapperTable->m_StateEnvironment_RetrieveSignal = (PLibMCEnvStateEnvironment_RetrieveSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_retrievesignal");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_LogInfo == nullptr)
+ if (pWrapperTable->m_StateEnvironment_RetrieveSignal == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_Sleep = (PLibMCEnvStateEnvironment_SleepPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_sleep");
+ pWrapperTable->m_StateEnvironment_ClearStoredValue = (PLibMCEnvStateEnvironment_ClearStoredValuePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_clearstoredvalue");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_Sleep = (PLibMCEnvStateEnvironment_SleepPtr) dlsym(hLibrary, "libmcenv_stateenvironment_sleep");
+ pWrapperTable->m_StateEnvironment_ClearStoredValue = (PLibMCEnvStateEnvironment_ClearStoredValuePtr) dlsym(hLibrary, "libmcenv_stateenvironment_clearstoredvalue");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_Sleep == nullptr)
+ if (pWrapperTable->m_StateEnvironment_ClearStoredValue == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_CheckForTermination = (PLibMCEnvStateEnvironment_CheckForTerminationPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_checkfortermination");
+ pWrapperTable->m_StateEnvironment_SetNextState = (PLibMCEnvStateEnvironment_SetNextStatePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_setnextstate");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_CheckForTermination = (PLibMCEnvStateEnvironment_CheckForTerminationPtr) dlsym(hLibrary, "libmcenv_stateenvironment_checkfortermination");
+ pWrapperTable->m_StateEnvironment_SetNextState = (PLibMCEnvStateEnvironment_SetNextStatePtr) dlsym(hLibrary, "libmcenv_stateenvironment_setnextstate");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_CheckForTermination == nullptr)
+ if (pWrapperTable->m_StateEnvironment_SetNextState == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_StoreSignal = (PLibMCEnvStateEnvironment_StoreSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_storesignal");
+ pWrapperTable->m_StateEnvironment_LogMessage = (PLibMCEnvStateEnvironment_LogMessagePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_logmessage");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_StoreSignal = (PLibMCEnvStateEnvironment_StoreSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_storesignal");
+ pWrapperTable->m_StateEnvironment_LogMessage = (PLibMCEnvStateEnvironment_LogMessagePtr) dlsym(hLibrary, "libmcenv_stateenvironment_logmessage");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_StoreSignal == nullptr)
+ if (pWrapperTable->m_StateEnvironment_LogMessage == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_RetrieveSignal = (PLibMCEnvStateEnvironment_RetrieveSignalPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_retrievesignal");
+ pWrapperTable->m_StateEnvironment_LogWarning = (PLibMCEnvStateEnvironment_LogWarningPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_logwarning");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_RetrieveSignal = (PLibMCEnvStateEnvironment_RetrieveSignalPtr) dlsym(hLibrary, "libmcenv_stateenvironment_retrievesignal");
+ pWrapperTable->m_StateEnvironment_LogWarning = (PLibMCEnvStateEnvironment_LogWarningPtr) dlsym(hLibrary, "libmcenv_stateenvironment_logwarning");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_RetrieveSignal == nullptr)
+ if (pWrapperTable->m_StateEnvironment_LogWarning == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
- pWrapperTable->m_StateEnvironment_ClearStoredValue = (PLibMCEnvStateEnvironment_ClearStoredValuePtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_clearstoredvalue");
+ pWrapperTable->m_StateEnvironment_LogInfo = (PLibMCEnvStateEnvironment_LogInfoPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_loginfo");
#else // _WIN32
- pWrapperTable->m_StateEnvironment_ClearStoredValue = (PLibMCEnvStateEnvironment_ClearStoredValuePtr) dlsym(hLibrary, "libmcenv_stateenvironment_clearstoredvalue");
+ pWrapperTable->m_StateEnvironment_LogInfo = (PLibMCEnvStateEnvironment_LogInfoPtr) dlsym(hLibrary, "libmcenv_stateenvironment_loginfo");
dlerror();
#endif // _WIN32
- if (pWrapperTable->m_StateEnvironment_ClearStoredValue == nullptr)
+ if (pWrapperTable->m_StateEnvironment_LogInfo == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ #ifdef _WIN32
+ pWrapperTable->m_StateEnvironment_Sleep = (PLibMCEnvStateEnvironment_SleepPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_sleep");
+ #else // _WIN32
+ pWrapperTable->m_StateEnvironment_Sleep = (PLibMCEnvStateEnvironment_SleepPtr) dlsym(hLibrary, "libmcenv_stateenvironment_sleep");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_StateEnvironment_Sleep == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ #ifdef _WIN32
+ pWrapperTable->m_StateEnvironment_CheckForTermination = (PLibMCEnvStateEnvironment_CheckForTerminationPtr) GetProcAddress(hLibrary, "libmcenv_stateenvironment_checkfortermination");
+ #else // _WIN32
+ pWrapperTable->m_StateEnvironment_CheckForTermination = (PLibMCEnvStateEnvironment_CheckForTerminationPtr) dlsym(hLibrary, "libmcenv_stateenvironment_checkfortermination");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_StateEnvironment_CheckForTermination == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
#ifdef _WIN32
@@ -13569,6 +13655,15 @@ class CUIEnvironment : public CBase {
if (pWrapperTable->m_UIEnvironment_GetBuildExecution == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ #ifdef _WIN32
+ pWrapperTable->m_UIEnvironment_GetRecentBuildJobs = (PLibMCEnvUIEnvironment_GetRecentBuildJobsPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_getrecentbuildjobs");
+ #else // _WIN32
+ pWrapperTable->m_UIEnvironment_GetRecentBuildJobs = (PLibMCEnvUIEnvironment_GetRecentBuildJobsPtr) dlsym(hLibrary, "libmcenv_uienvironment_getrecentbuildjobs");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_UIEnvironment_GetRecentBuildJobs == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
#ifdef _WIN32
pWrapperTable->m_UIEnvironment_CreateDiscreteField2D = (PLibMCEnvUIEnvironment_CreateDiscreteField2DPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_creatediscretefield2d");
#else // _WIN32
@@ -13857,6 +13952,42 @@ class CUIEnvironment : public CBase {
if (pWrapperTable->m_UIEnvironment_AddExternalEventResultValue == nullptr)
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ #ifdef _WIN32
+ pWrapperTable->m_UIEnvironment_SetStringResult = (PLibMCEnvUIEnvironment_SetStringResultPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_setstringresult");
+ #else // _WIN32
+ pWrapperTable->m_UIEnvironment_SetStringResult = (PLibMCEnvUIEnvironment_SetStringResultPtr) dlsym(hLibrary, "libmcenv_uienvironment_setstringresult");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_UIEnvironment_SetStringResult == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ #ifdef _WIN32
+ pWrapperTable->m_UIEnvironment_SetIntegerResult = (PLibMCEnvUIEnvironment_SetIntegerResultPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_setintegerresult");
+ #else // _WIN32
+ pWrapperTable->m_UIEnvironment_SetIntegerResult = (PLibMCEnvUIEnvironment_SetIntegerResultPtr) dlsym(hLibrary, "libmcenv_uienvironment_setintegerresult");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_UIEnvironment_SetIntegerResult == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ #ifdef _WIN32
+ pWrapperTable->m_UIEnvironment_SetBoolResult = (PLibMCEnvUIEnvironment_SetBoolResultPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_setboolresult");
+ #else // _WIN32
+ pWrapperTable->m_UIEnvironment_SetBoolResult = (PLibMCEnvUIEnvironment_SetBoolResultPtr) dlsym(hLibrary, "libmcenv_uienvironment_setboolresult");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_UIEnvironment_SetBoolResult == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ #ifdef _WIN32
+ pWrapperTable->m_UIEnvironment_SetDoubleResult = (PLibMCEnvUIEnvironment_SetDoubleResultPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_setdoubleresult");
+ #else // _WIN32
+ pWrapperTable->m_UIEnvironment_SetDoubleResult = (PLibMCEnvUIEnvironment_SetDoubleResultPtr) dlsym(hLibrary, "libmcenv_uienvironment_setdoubleresult");
+ dlerror();
+ #endif // _WIN32
+ if (pWrapperTable->m_UIEnvironment_SetDoubleResult == nullptr)
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
#ifdef _WIN32
pWrapperTable->m_UIEnvironment_GetExternalEventParameters = (PLibMCEnvUIEnvironment_GetExternalEventParametersPtr) GetProcAddress(hLibrary, "libmcenv_uienvironment_getexternaleventparameters");
#else // _WIN32
@@ -15513,6 +15644,10 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_BuildExecutionIterator_GetCurrentExecution == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ eLookupError = (*pLookup)("libmcenv_builditerator_getcurrentbuild", (void**)&(pWrapperTable->m_BuildIterator_GetCurrentBuild));
+ if ( (eLookupError != 0) || (pWrapperTable->m_BuildIterator_GetCurrentBuild == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
eLookupError = (*pLookup)("libmcenv_build_getname", (void**)&(pWrapperTable->m_Build_GetName));
if ( (eLookupError != 0) || (pWrapperTable->m_Build_GetName == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -15521,6 +15656,14 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_Build_GetBuildUUID == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ eLookupError = (*pLookup)("libmcenv_build_getcreatedtimestamp", (void**)&(pWrapperTable->m_Build_GetCreatedTimestamp));
+ if ( (eLookupError != 0) || (pWrapperTable->m_Build_GetCreatedTimestamp == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_build_getlastexecutiontimestamp", (void**)&(pWrapperTable->m_Build_GetLastExecutionTimestamp));
+ if ( (eLookupError != 0) || (pWrapperTable->m_Build_GetLastExecutionTimestamp == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
eLookupError = (*pLookup)("libmcenv_build_getstorageuuid", (void**)&(pWrapperTable->m_Build_GetStorageUUID));
if ( (eLookupError != 0) || (pWrapperTable->m_Build_GetStorageUUID == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -17365,12 +17508,12 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_PrepareSignal == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
- eLookupError = (*pLookup)("libmcenv_stateenvironment_waitforsignal", (void**)&(pWrapperTable->m_StateEnvironment_WaitForSignal));
- if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_WaitForSignal == nullptr) )
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_claimsignalfromqueue", (void**)&(pWrapperTable->m_StateEnvironment_ClaimSignalFromQueue));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_ClaimSignalFromQueue == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
- eLookupError = (*pLookup)("libmcenv_stateenvironment_getunhandledsignal", (void**)&(pWrapperTable->m_StateEnvironment_GetUnhandledSignal));
- if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_GetUnhandledSignal == nullptr) )
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_signalqueueisempty", (void**)&(pWrapperTable->m_StateEnvironment_SignalQueueIsEmpty));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_SignalQueueIsEmpty == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
eLookupError = (*pLookup)("libmcenv_stateenvironment_clearunhandledsignalsoftype", (void**)&(pWrapperTable->m_StateEnvironment_ClearUnhandledSignalsOfType));
@@ -17413,6 +17556,26 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_UnloadAllToolpathes == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_waitforsignal", (void**)&(pWrapperTable->m_StateEnvironment_WaitForSignal));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_WaitForSignal == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_getunhandledsignal", (void**)&(pWrapperTable->m_StateEnvironment_GetUnhandledSignal));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_GetUnhandledSignal == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_storesignal", (void**)&(pWrapperTable->m_StateEnvironment_StoreSignal));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_StoreSignal == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_retrievesignal", (void**)&(pWrapperTable->m_StateEnvironment_RetrieveSignal));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_RetrieveSignal == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_stateenvironment_clearstoredvalue", (void**)&(pWrapperTable->m_StateEnvironment_ClearStoredValue));
+ if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_ClearStoredValue == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
eLookupError = (*pLookup)("libmcenv_stateenvironment_setnextstate", (void**)&(pWrapperTable->m_StateEnvironment_SetNextState));
if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_SetNextState == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -17437,18 +17600,6 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_CheckForTermination == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
- eLookupError = (*pLookup)("libmcenv_stateenvironment_storesignal", (void**)&(pWrapperTable->m_StateEnvironment_StoreSignal));
- if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_StoreSignal == nullptr) )
- return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
-
- eLookupError = (*pLookup)("libmcenv_stateenvironment_retrievesignal", (void**)&(pWrapperTable->m_StateEnvironment_RetrieveSignal));
- if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_RetrieveSignal == nullptr) )
- return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
-
- eLookupError = (*pLookup)("libmcenv_stateenvironment_clearstoredvalue", (void**)&(pWrapperTable->m_StateEnvironment_ClearStoredValue));
- if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_ClearStoredValue == nullptr) )
- return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
-
eLookupError = (*pLookup)("libmcenv_stateenvironment_setstringparameter", (void**)&(pWrapperTable->m_StateEnvironment_SetStringParameter));
if ( (eLookupError != 0) || (pWrapperTable->m_StateEnvironment_SetStringParameter == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -17885,6 +18036,10 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_GetBuildExecution == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ eLookupError = (*pLookup)("libmcenv_uienvironment_getrecentbuildjobs", (void**)&(pWrapperTable->m_UIEnvironment_GetRecentBuildJobs));
+ if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_GetRecentBuildJobs == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
eLookupError = (*pLookup)("libmcenv_uienvironment_creatediscretefield2d", (void**)&(pWrapperTable->m_UIEnvironment_CreateDiscreteField2D));
if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_CreateDiscreteField2D == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -18013,6 +18168,22 @@ class CUIEnvironment : public CBase {
if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_AddExternalEventResultValue == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+ eLookupError = (*pLookup)("libmcenv_uienvironment_setstringresult", (void**)&(pWrapperTable->m_UIEnvironment_SetStringResult));
+ if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_SetStringResult == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_uienvironment_setintegerresult", (void**)&(pWrapperTable->m_UIEnvironment_SetIntegerResult));
+ if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_SetIntegerResult == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_uienvironment_setboolresult", (void**)&(pWrapperTable->m_UIEnvironment_SetBoolResult));
+ if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_SetBoolResult == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
+ eLookupError = (*pLookup)("libmcenv_uienvironment_setdoubleresult", (void**)&(pWrapperTable->m_UIEnvironment_SetDoubleResult));
+ if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_SetDoubleResult == nullptr) )
+ return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
+
eLookupError = (*pLookup)("libmcenv_uienvironment_getexternaleventparameters", (void**)&(pWrapperTable->m_UIEnvironment_GetExternalEventParameters));
if ( (eLookupError != 0) || (pWrapperTable->m_UIEnvironment_GetExternalEventParameters == nullptr) )
return LIBMCENV_ERROR_COULDNOTFINDLIBRARYEXPORT;
@@ -23313,6 +23484,25 @@ class CUIEnvironment : public CBase {
return std::make_shared(m_pWrapper, hBuildExecutionInstance);
}
+ /**
+ * Method definitions for class CBuildIterator
+ */
+
+ /**
+ * CBuildIterator::GetCurrentBuild - Returns the build the iterator points at.
+ * @return returns the Build instance.
+ */
+ PBuild CBuildIterator::GetCurrentBuild()
+ {
+ LibMCEnvHandle hBuildInstance = nullptr;
+ CheckError(m_pWrapper->m_WrapperTable.m_BuildIterator_GetCurrentBuild(m_pHandle, &hBuildInstance));
+
+ if (!hBuildInstance) {
+ CheckError(LIBMCENV_ERROR_INVALIDPARAM);
+ }
+ return std::make_shared(m_pWrapper, hBuildInstance);
+ }
+
/**
* Method definitions for class CBuild
*/
@@ -23347,6 +23537,36 @@ class CUIEnvironment : public CBase {
return std::string(&bufferBuildUUID[0]);
}
+ /**
+ * CBuild::GetCreatedTimestamp - Returns creation timestamp of the build in ISO-8601 format.
+ * @return Creation timestamp in ISO-8601 format (e.g., 2025-10-23T14:30:00.000Z).
+ */
+ std::string CBuild::GetCreatedTimestamp()
+ {
+ LibMCEnv_uint32 bytesNeededTimestamp = 0;
+ LibMCEnv_uint32 bytesWrittenTimestamp = 0;
+ CheckError(m_pWrapper->m_WrapperTable.m_Build_GetCreatedTimestamp(m_pHandle, 0, &bytesNeededTimestamp, nullptr));
+ std::vector bufferTimestamp(bytesNeededTimestamp);
+ CheckError(m_pWrapper->m_WrapperTable.m_Build_GetCreatedTimestamp(m_pHandle, bytesNeededTimestamp, &bytesWrittenTimestamp, &bufferTimestamp[0]));
+
+ return std::string(&bufferTimestamp[0]);
+ }
+
+ /**
+ * CBuild::GetLastExecutionTimestamp - Returns the most recent execution timestamp in ISO-8601 format. Returns empty string if build has never been executed.
+ * @return Most recent execution timestamp in ISO-8601 format. Empty string if never executed.
+ */
+ std::string CBuild::GetLastExecutionTimestamp()
+ {
+ LibMCEnv_uint32 bytesNeededTimestamp = 0;
+ LibMCEnv_uint32 bytesWrittenTimestamp = 0;
+ CheckError(m_pWrapper->m_WrapperTable.m_Build_GetLastExecutionTimestamp(m_pHandle, 0, &bytesNeededTimestamp, nullptr));
+ std::vector bufferTimestamp(bytesNeededTimestamp);
+ CheckError(m_pWrapper->m_WrapperTable.m_Build_GetLastExecutionTimestamp(m_pHandle, bytesNeededTimestamp, &bytesWrittenTimestamp, &bufferTimestamp[0]));
+
+ return std::string(&bufferTimestamp[0]);
+ }
+
/**
* CBuild::GetStorageUUID - Returns storage uuid of the build stream.
* @return Storage UUID of the build.
@@ -29813,45 +30033,37 @@ class CUIEnvironment : public CBase {
}
/**
- * CStateEnvironment::WaitForSignal - Waits for a signal for a certain amount of time.
- * @param[in] sSignalName - Name Of Signal
- * @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
- * @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
- * @return Signal has been triggered
+ * CStateEnvironment::ClaimSignalFromQueue - Retrieves an InQueue signal by type and changes its phase to InProcess. Recommended to use as it is robust against signal timeouts...
+ * @param[in] sSignalTypeName - Name Of Signal to be returned
+ * @return Signal object. If no signal is InQueue the signal handler object will be null.
*/
- bool CStateEnvironment::WaitForSignal(const std::string & sSignalName, const LibMCEnv_uint32 nTimeOut, PSignalHandler & pHandlerInstance)
+ PSignalHandler CStateEnvironment::ClaimSignalFromQueue(const std::string & sSignalTypeName)
{
LibMCEnvHandle hHandlerInstance = nullptr;
- bool resultSuccess = 0;
- CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_WaitForSignal(m_pHandle, sSignalName.c_str(), nTimeOut, &hHandlerInstance, &resultSuccess));
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_ClaimSignalFromQueue(m_pHandle, sSignalTypeName.c_str(), &hHandlerInstance));
+
if (hHandlerInstance) {
- pHandlerInstance = std::make_shared(m_pWrapper, hHandlerInstance);
+ return std::make_shared(m_pWrapper, hHandlerInstance);
} else {
- pHandlerInstance = nullptr;
+ return nullptr;
}
-
- return resultSuccess;
}
/**
- * CStateEnvironment::GetUnhandledSignal - Retrieves an unhandled signal By signal type name. Only affects signals with Phase InQueue.
+ * CStateEnvironment::SignalQueueIsEmpty - Returns if a signal queue is empty for a specific type...
* @param[in] sSignalTypeName - Name Of Signal to be returned
- * @return Signal object. If no signal has been found the signal handler object will be null.
+ * @return Returns if the signal queue is empty. Please be aware that even a false return value does not guarantee that ClaimSignalFromQueue returns a non-null value.
*/
- PSignalHandler CStateEnvironment::GetUnhandledSignal(const std::string & sSignalTypeName)
+ bool CStateEnvironment::SignalQueueIsEmpty(const std::string & sSignalTypeName)
{
- LibMCEnvHandle hHandlerInstance = nullptr;
- CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_GetUnhandledSignal(m_pHandle, sSignalTypeName.c_str(), &hHandlerInstance));
+ bool resultIsEmpty = 0;
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_SignalQueueIsEmpty(m_pHandle, sSignalTypeName.c_str(), &resultIsEmpty));
- if (hHandlerInstance) {
- return std::make_shared(m_pWrapper, hHandlerInstance);
- } else {
- return nullptr;
- }
+ return resultIsEmpty;
}
/**
- * CStateEnvironment::ClearUnhandledSignalsOfType - Clears all unhandled signals of a certain type and marks them as Cleared. Only affects signals with Phase InQueue.
+ * CStateEnvironment::ClearUnhandledSignalsOfType - Clears all InQueue or InProcess signals of a certain type and marks them as Cleared. Handled, failed or timedout signals are unaffected
* @param[in] sSignalTypeName - Name Of Signal to be cleared.
*/
void CStateEnvironment::ClearUnhandledSignalsOfType(const std::string & sSignalTypeName)
@@ -29860,7 +30072,7 @@ class CUIEnvironment : public CBase {
}
/**
- * CStateEnvironment::ClearAllUnhandledSignals - Clears all unhandled signals and marks them Cleared. Only affects signals in the specific queue (as well as with Phase InQueue.
+ * CStateEnvironment::ClearAllUnhandledSignals - Clears all InQueue or InProcess signals of this state machine and marks them Cleared. Handled, failed or timedout signals are unaffected
*/
void CStateEnvironment::ClearAllUnhandledSignals()
{
@@ -29868,9 +30080,9 @@ class CUIEnvironment : public CBase {
}
/**
- * CStateEnvironment::GetUnhandledSignalByUUID - retrieves an unhandled signal from the current state machine by UUID.
+ * CStateEnvironment::GetUnhandledSignalByUUID - Retrieves an InQueue or InProcess signal from the current state machine by UUID.
* @param[in] sUUID - Name
- * @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled already.
+ * @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled, failed, cleared or timedout already.
* @return Signal handler instance. Returns null, if signal does not exist.
*/
PSignalHandler CStateEnvironment::GetUnhandledSignalByUUID(const std::string & sUUID, const bool bMustExist)
@@ -29977,6 +30189,80 @@ class CUIEnvironment : public CBase {
CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_UnloadAllToolpathes(m_pHandle));
}
+ /**
+ * CStateEnvironment::WaitForSignal - DEPRECIATED: Waits for an InQueue signal to exist for a certain amount of time. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE claim signal instead.
+ * @param[in] sSignalName - Name Of Signal
+ * @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
+ * @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
+ * @return Signal has been triggered
+ */
+ bool CStateEnvironment::WaitForSignal(const std::string & sSignalName, const LibMCEnv_uint32 nTimeOut, PSignalHandler & pHandlerInstance)
+ {
+ LibMCEnvHandle hHandlerInstance = nullptr;
+ bool resultSuccess = 0;
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_WaitForSignal(m_pHandle, sSignalName.c_str(), nTimeOut, &hHandlerInstance, &resultSuccess));
+ if (hHandlerInstance) {
+ pHandlerInstance = std::make_shared(m_pWrapper, hHandlerInstance);
+ } else {
+ pHandlerInstance = nullptr;
+ }
+
+ return resultSuccess;
+ }
+
+ /**
+ * CStateEnvironment::GetUnhandledSignal - DEPRECIATED: Retrieves am InQueue signal by type. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE ClaimSignalFromQueue instead.
+ * @param[in] sSignalTypeName - Name Of Signal to be returned
+ * @return Signal object. If no signal has been found the signal handler object will be null.
+ */
+ PSignalHandler CStateEnvironment::GetUnhandledSignal(const std::string & sSignalTypeName)
+ {
+ LibMCEnvHandle hHandlerInstance = nullptr;
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_GetUnhandledSignal(m_pHandle, sSignalTypeName.c_str(), &hHandlerInstance));
+
+ if (hHandlerInstance) {
+ return std::make_shared(m_pWrapper, hHandlerInstance);
+ } else {
+ return nullptr;
+ }
+ }
+
+ /**
+ * CStateEnvironment::StoreSignal - DEPRECIATED: stores a signal handler in the current state machine
+ * @param[in] sName - Name
+ * @param[in] pHandler - Signal handler to store.
+ */
+ void CStateEnvironment::StoreSignal(const std::string & sName, classParam pHandler)
+ {
+ LibMCEnvHandle hHandler = pHandler.GetHandle();
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_StoreSignal(m_pHandle, sName.c_str(), hHandler));
+ }
+
+ /**
+ * CStateEnvironment::RetrieveSignal - DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
+ * @param[in] sName - Name
+ * @return Signal handler instance.
+ */
+ PSignalHandler CStateEnvironment::RetrieveSignal(const std::string & sName)
+ {
+ LibMCEnvHandle hHandler = nullptr;
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_RetrieveSignal(m_pHandle, sName.c_str(), &hHandler));
+
+ if (!hHandler) {
+ CheckError(LIBMCENV_ERROR_INVALIDPARAM);
+ }
+ return std::make_shared(m_pWrapper, hHandler);
+ }
+
+ /**
+ * CStateEnvironment::ClearStoredValue - DEPRECIATED: deletes a value from the data store.
+ * @param[in] sName - Name
+ */
+ void CStateEnvironment::ClearStoredValue(const std::string & sName)
+ {
+ CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_ClearStoredValue(m_pHandle, sName.c_str()));
+ }
+
/**
* CStateEnvironment::SetNextState - sets the next state
* @param[in] sStateName - Name of next state
@@ -30034,42 +30320,6 @@ class CUIEnvironment : public CBase {
return resultShallTerminate;
}
- /**
- * CStateEnvironment::StoreSignal - DEPRECIATED: stores a signal handler in the current state machine
- * @param[in] sName - Name
- * @param[in] pHandler - Signal handler to store.
- */
- void CStateEnvironment::StoreSignal(const std::string & sName, classParam pHandler)
- {
- LibMCEnvHandle hHandler = pHandler.GetHandle();
- CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_StoreSignal(m_pHandle, sName.c_str(), hHandler));
- }
-
- /**
- * CStateEnvironment::RetrieveSignal - DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
- * @param[in] sName - Name
- * @return Signal handler instance.
- */
- PSignalHandler CStateEnvironment::RetrieveSignal(const std::string & sName)
- {
- LibMCEnvHandle hHandler = nullptr;
- CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_RetrieveSignal(m_pHandle, sName.c_str(), &hHandler));
-
- if (!hHandler) {
- CheckError(LIBMCENV_ERROR_INVALIDPARAM);
- }
- return std::make_shared(m_pWrapper, hHandler);
- }
-
- /**
- * CStateEnvironment::ClearStoredValue - DEPRECIATED: deletes a value from the data store.
- * @param[in] sName - Name
- */
- void CStateEnvironment::ClearStoredValue(const std::string & sName)
- {
- CheckError(m_pWrapper->m_WrapperTable.m_StateEnvironment_ClearStoredValue(m_pHandle, sName.c_str()));
- }
-
/**
* CStateEnvironment::SetStringParameter - sets a string parameter
* @param[in] sParameterGroup - Parameter Group
@@ -31635,6 +31885,22 @@ class CUIEnvironment : public CBase {
return std::make_shared(m_pWrapper, hExecutionInstance);
}
+ /**
+ * CUIEnvironment::GetRecentBuildJobs - Returns an iterator for recent build jobs, ordered by timestamp (newest first).
+ * @param[in] nMaxCount - Maximum number of jobs to return. Must be greater than 0.
+ * @return Iterator for build jobs, ordered newest first.
+ */
+ PBuildIterator CUIEnvironment::GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount)
+ {
+ LibMCEnvHandle hBuildIterator = nullptr;
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_GetRecentBuildJobs(m_pHandle, nMaxCount, &hBuildIterator));
+
+ if (!hBuildIterator) {
+ CheckError(LIBMCENV_ERROR_INVALIDPARAM);
+ }
+ return std::make_shared(m_pWrapper, hBuildIterator);
+ }
+
/**
* CUIEnvironment::CreateDiscreteField2D - Creates an empty discrete field.
* @param[in] nPixelCountX - Pixel count in X. MUST be positive.
@@ -32126,6 +32392,46 @@ class CUIEnvironment : public CBase {
CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_AddExternalEventResultValue(m_pHandle, sReturnValueName.c_str(), sReturnValue.c_str()));
}
+ /**
+ * CUIEnvironment::SetStringResult - Sets a string result value for external event return (typed convenience wrapper).
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] sReturnValue - Return value.
+ */
+ void CUIEnvironment::SetStringResult(const std::string & sReturnValueName, const std::string & sReturnValue)
+ {
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_SetStringResult(m_pHandle, sReturnValueName.c_str(), sReturnValue.c_str()));
+ }
+
+ /**
+ * CUIEnvironment::SetIntegerResult - Sets an integer result value for external event return.
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] nReturnValue - Return value.
+ */
+ void CUIEnvironment::SetIntegerResult(const std::string & sReturnValueName, const LibMCEnv_int64 nReturnValue)
+ {
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_SetIntegerResult(m_pHandle, sReturnValueName.c_str(), nReturnValue));
+ }
+
+ /**
+ * CUIEnvironment::SetBoolResult - Sets a boolean result value for external event return.
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] bReturnValue - Return value.
+ */
+ void CUIEnvironment::SetBoolResult(const std::string & sReturnValueName, const bool bReturnValue)
+ {
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_SetBoolResult(m_pHandle, sReturnValueName.c_str(), bReturnValue));
+ }
+
+ /**
+ * CUIEnvironment::SetDoubleResult - Sets a double result value for external event return.
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] dReturnValue - Return value.
+ */
+ void CUIEnvironment::SetDoubleResult(const std::string & sReturnValueName, const LibMCEnv_double dReturnValue)
+ {
+ CheckError(m_pWrapper->m_WrapperTable.m_UIEnvironment_SetDoubleResult(m_pHandle, sReturnValueName.c_str(), dReturnValue));
+ }
+
/**
* CUIEnvironment::GetExternalEventParameters - Returns the external event parameters. This JSON Object was passed on from the external API.
* @return Parameter value.
diff --git a/Framework/HeadersDev/CppDynamic/libmcenv_types.hpp b/Framework/HeadersDev/CppDynamic/libmcenv_types.hpp
index 42e8f6a15..35641291e 100644
--- a/Framework/HeadersDev/CppDynamic/libmcenv_types.hpp
+++ b/Framework/HeadersDev/CppDynamic/libmcenv_types.hpp
@@ -656,6 +656,7 @@ typedef LibMCEnvHandle LibMCEnv_ToolpathLayer;
typedef LibMCEnvHandle LibMCEnv_ToolpathAccessor;
typedef LibMCEnvHandle LibMCEnv_BuildExecution;
typedef LibMCEnvHandle LibMCEnv_BuildExecutionIterator;
+typedef LibMCEnvHandle LibMCEnv_BuildIterator;
typedef LibMCEnvHandle LibMCEnv_Build;
typedef LibMCEnvHandle LibMCEnv_WorkingFileProcess;
typedef LibMCEnvHandle LibMCEnv_WorkingFile;
diff --git a/Framework/InterfacesCore/libmc_types.hpp b/Framework/InterfacesCore/libmc_types.hpp
index 327349718..dad52a6d4 100644
--- a/Framework/InterfacesCore/libmc_types.hpp
+++ b/Framework/InterfacesCore/libmc_types.hpp
@@ -713,6 +713,11 @@ typedef void * LibMC_pvoid;
#define LIBMC_ERROR_INVALIDTELEMETRYMARKERFINISHTIMESTAMP 697 /** Invalid telemetry marker finish timestamp. */
#define LIBMC_ERROR_UNFINISHEDTELEMETRYMARKERSHAVENODURATION 698 /** Unfinished telemetry marker have no duration. */
#define LIBMC_ERROR_TELEMETRYMARKERALREADYREGISTERED 699 /** Telemetry Marker has been already registered. */
+#define LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND 700 /** Telemetry Chunk Start timestamp is after end timestamp. */
+#define LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE 701 /** Telemetry Chunk index out of range. */
+#define LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH 702 /** Telemetry Chunk ID mismatch. */
+#define LIBMC_ERROR_TELEMETRYCHUNKISREADONLY 703 /** Telemetry Chunk is readonly. */
+#define LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY 704 /** Telemetry Chunks can only be archived if readonly. */
/*************************************************************************************************************************
Error strings for LibMC
@@ -1338,6 +1343,11 @@ inline const char * LIBMC_GETERRORSTRING (LibMCResult nErrorCode) {
case LIBMC_ERROR_INVALIDTELEMETRYMARKERFINISHTIMESTAMP: return "Invalid telemetry marker finish timestamp.";
case LIBMC_ERROR_UNFINISHEDTELEMETRYMARKERSHAVENODURATION: return "Unfinished telemetry marker have no duration.";
case LIBMC_ERROR_TELEMETRYMARKERALREADYREGISTERED: return "Telemetry Marker has been already registered.";
+ case LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND: return "Telemetry Chunk Start timestamp is after end timestamp.";
+ case LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE: return "Telemetry Chunk index out of range.";
+ case LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH: return "Telemetry Chunk ID mismatch.";
+ case LIBMC_ERROR_TELEMETRYCHUNKISREADONLY: return "Telemetry Chunk is readonly.";
+ case LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY: return "Telemetry Chunks can only be archived if readonly.";
default: return "unknown error";
}
}
diff --git a/Framework/InterfacesCore/libmcenv_abi.hpp b/Framework/InterfacesCore/libmcenv_abi.hpp
index 6cbced6eb..a5e36da0c 100644
--- a/Framework/InterfacesCore/libmcenv_abi.hpp
+++ b/Framework/InterfacesCore/libmcenv_abi.hpp
@@ -4247,6 +4247,19 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_buildexecution_loadattachedjournal(Lib
*/
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_buildexecutioniterator_getcurrentexecution(LibMCEnv_BuildExecutionIterator pBuildExecutionIterator, LibMCEnv_BuildExecution * pBuildExecutionInstance);
+/*************************************************************************************************************************
+ Class definition for BuildIterator
+**************************************************************************************************************************/
+
+/**
+* Returns the build the iterator points at.
+*
+* @param[in] pBuildIterator - BuildIterator instance.
+* @param[out] pBuildInstance - returns the Build instance.
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_builditerator_getcurrentbuild(LibMCEnv_BuildIterator pBuildIterator, LibMCEnv_Build * pBuildInstance);
+
/*************************************************************************************************************************
Class definition for Build
**************************************************************************************************************************/
@@ -4273,6 +4286,28 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_build_getname(LibMCEnv_Build pBuild, c
*/
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_build_getbuilduuid(LibMCEnv_Build pBuild, const LibMCEnv_uint32 nBuildUUIDBufferSize, LibMCEnv_uint32* pBuildUUIDNeededChars, char * pBuildUUIDBuffer);
+/**
+* Returns creation timestamp of the build in ISO-8601 format.
+*
+* @param[in] pBuild - Build instance.
+* @param[in] nTimestampBufferSize - size of the buffer (including trailing 0)
+* @param[out] pTimestampNeededChars - will be filled with the count of the written bytes, or needed buffer size.
+* @param[out] pTimestampBuffer - buffer of Creation timestamp in ISO-8601 format (e.g., 2025-10-23T14:30:00.000Z)., may be NULL
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_build_getcreatedtimestamp(LibMCEnv_Build pBuild, const LibMCEnv_uint32 nTimestampBufferSize, LibMCEnv_uint32* pTimestampNeededChars, char * pTimestampBuffer);
+
+/**
+* Returns the most recent execution timestamp in ISO-8601 format. Returns empty string if build has never been executed.
+*
+* @param[in] pBuild - Build instance.
+* @param[in] nTimestampBufferSize - size of the buffer (including trailing 0)
+* @param[out] pTimestampNeededChars - will be filled with the count of the written bytes, or needed buffer size.
+* @param[out] pTimestampBuffer - buffer of Most recent execution timestamp in ISO-8601 format. Empty string if never executed., may be NULL
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_build_getlastexecutiontimestamp(LibMCEnv_Build pBuild, const LibMCEnv_uint32 nTimestampBufferSize, LibMCEnv_uint32* pTimestampNeededChars, char * pTimestampBuffer);
+
/**
* Returns storage uuid of the build stream.
*
@@ -9231,29 +9266,27 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_getpreviousstate(LibM
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_preparesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pMachineInstance, const char * pSignalName, LibMCEnv_SignalTrigger * pSignalInstance);
/**
-* Waits for a signal for a certain amount of time.
+* Retrieves an InQueue signal by type and changes its phase to InProcess. Recommended to use as it is robust against signal timeouts...
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pSignalName - Name Of Signal
-* @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
-* @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
-* @param[out] pSuccess - Signal has been triggered
+* @param[in] pSignalTypeName - Name Of Signal to be returned
+* @param[out] pHandlerInstance - Signal object. If no signal is InQueue the signal handler object will be null.
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_waitforsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalName, LibMCEnv_uint32 nTimeOut, LibMCEnv_SignalHandler * pHandlerInstance, bool * pSuccess);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_claimsignalfromqueue(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance);
/**
-* Retrieves an unhandled signal By signal type name. Only affects signals with Phase InQueue.
+* Returns if a signal queue is empty for a specific type...
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @param[in] pSignalTypeName - Name Of Signal to be returned
-* @param[out] pHandlerInstance - Signal object. If no signal has been found the signal handler object will be null.
+* @param[out] pIsEmpty - Returns if the signal queue is empty. Please be aware that even a false return value does not guarantee that ClaimSignalFromQueue returns a non-null value.
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_getunhandledsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_signalqueueisempty(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, bool * pIsEmpty);
/**
-* Clears all unhandled signals of a certain type and marks them as Cleared. Only affects signals with Phase InQueue.
+* Clears all InQueue or InProcess signals of a certain type and marks them as Cleared. Handled, failed or timedout signals are unaffected
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @param[in] pSignalTypeName - Name Of Signal to be cleared.
@@ -9262,7 +9295,7 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_getunhandledsignal(Li
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_clearunhandledsignalsoftype(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName);
/**
-* Clears all unhandled signals and marks them Cleared. Only affects signals in the specific queue (as well as with Phase InQueue.
+* Clears all InQueue or InProcess signals of this state machine and marks them Cleared. Handled, failed or timedout signals are unaffected
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @return error code or 0 (success)
@@ -9270,11 +9303,11 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_clearunhandledsignals
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_clearallunhandledsignals(LibMCEnv_StateEnvironment pStateEnvironment);
/**
-* retrieves an unhandled signal from the current state machine by UUID.
+* Retrieves an InQueue or InProcess signal from the current state machine by UUID.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
* @param[in] pUUID - Name
-* @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled already.
+* @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled, failed, cleared or timedout already.
* @param[out] pHandler - Signal handler instance. Returns null, if signal does not exist.
* @return error code or 0 (success)
*/
@@ -9352,87 +9385,109 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_getbuildexecution(Lib
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_unloadalltoolpathes(LibMCEnv_StateEnvironment pStateEnvironment);
/**
-* sets the next state
+* DEPRECIATED: Waits for an InQueue signal to exist for a certain amount of time. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE claim signal instead.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pStateName - Name of next state
+* @param[in] pSignalName - Name Of Signal
+* @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
+* @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
+* @param[out] pSuccess - Signal has been triggered
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_setnextstate(LibMCEnv_StateEnvironment pStateEnvironment, const char * pStateName);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_waitforsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalName, LibMCEnv_uint32 nTimeOut, LibMCEnv_SignalHandler * pHandlerInstance, bool * pSuccess);
/**
-* logs a string as message
+* DEPRECIATED: Retrieves am InQueue signal by type. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE ClaimSignalFromQueue instead.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pLogString - String to Log
+* @param[in] pSignalTypeName - Name Of Signal to be returned
+* @param[out] pHandlerInstance - Signal object. If no signal has been found the signal handler object will be null.
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_logmessage(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_getunhandledsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance);
/**
-* logs a string as warning
+* DEPRECIATED: stores a signal handler in the current state machine
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pLogString - String to Log
+* @param[in] pName - Name
+* @param[in] pHandler - Signal handler to store.
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_logwarning(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_storesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler pHandler);
/**
-* logs a string as info
+* DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pLogString - String to Log
+* @param[in] pName - Name
+* @param[out] pHandler - Signal handler instance.
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_loginfo(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_retrievesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler * pHandler);
/**
-* Puts the current instance to sleep for a definite amount of time. MUST be used instead of a blocking sleep call.
+* DEPRECIATED: deletes a value from the data store.
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] nDelay - Milliseconds to sleeps
+* @param[in] pName - Name
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_sleep(LibMCEnv_StateEnvironment pStateEnvironment, LibMCEnv_uint32 nDelay);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_clearstoredvalue(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName);
/**
-* checks environment for termination signal. MUST be called frequently in longer-running operations.
+* sets the next state
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[out] pShallTerminate - Returns if termination shall appear
+* @param[in] pStateName - Name of next state
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_checkfortermination(LibMCEnv_StateEnvironment pStateEnvironment, bool * pShallTerminate);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_setnextstate(LibMCEnv_StateEnvironment pStateEnvironment, const char * pStateName);
/**
-* DEPRECIATED: stores a signal handler in the current state machine
+* logs a string as message
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pName - Name
-* @param[in] pHandler - Signal handler to store.
+* @param[in] pLogString - String to Log
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_storesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler pHandler);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_logmessage(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
/**
-* DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
+* logs a string as warning
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pName - Name
-* @param[out] pHandler - Signal handler instance.
+* @param[in] pLogString - String to Log
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_retrievesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler * pHandler);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_logwarning(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
/**
-* DEPRECIATED: deletes a value from the data store.
+* logs a string as info
*
* @param[in] pStateEnvironment - StateEnvironment instance.
-* @param[in] pName - Name
+* @param[in] pLogString - String to Log
* @return error code or 0 (success)
*/
-LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_clearstoredvalue(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName);
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_loginfo(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString);
+
+/**
+* Puts the current instance to sleep for a definite amount of time. MUST be used instead of a blocking sleep call.
+*
+* @param[in] pStateEnvironment - StateEnvironment instance.
+* @param[in] nDelay - Milliseconds to sleeps
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_sleep(LibMCEnv_StateEnvironment pStateEnvironment, LibMCEnv_uint32 nDelay);
+
+/**
+* checks environment for termination signal. MUST be called frequently in longer-running operations.
+*
+* @param[in] pStateEnvironment - StateEnvironment instance.
+* @param[out] pShallTerminate - Returns if termination shall appear
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_stateenvironment_checkfortermination(LibMCEnv_StateEnvironment pStateEnvironment, bool * pShallTerminate);
/**
* sets a string parameter
@@ -10600,6 +10655,16 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_hasbuildexecution(LibMCE
*/
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_getbuildexecution(LibMCEnv_UIEnvironment pUIEnvironment, const char * pExecutionUUID, LibMCEnv_BuildExecution * pExecutionInstance);
+/**
+* Returns an iterator for recent build jobs, ordered by timestamp (newest first).
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] nMaxCount - Maximum number of jobs to return. Must be greater than 0.
+* @param[out] pBuildIterator - Iterator for build jobs, ordered newest first.
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_getrecentbuildjobs(LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nMaxCount, LibMCEnv_BuildIterator * pBuildIterator);
+
/**
* Creates an empty discrete field.
*
@@ -10942,6 +11007,46 @@ LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_getexternaleventparamete
*/
LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_addexternaleventresultvalue(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, const char * pReturnValue);
+/**
+* Sets a string result value for external event return (typed convenience wrapper).
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] pReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_setstringresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, const char * pReturnValue);
+
+/**
+* Sets an integer result value for external event return.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] nReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_setintegerresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, LibMCEnv_int64 nReturnValue);
+
+/**
+* Sets a boolean result value for external event return.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] bReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_setboolresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, bool bReturnValue);
+
+/**
+* Sets a double result value for external event return.
+*
+* @param[in] pUIEnvironment - UIEnvironment instance.
+* @param[in] pReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+* @param[in] dReturnValue - Return value.
+* @return error code or 0 (success)
+*/
+LIBMCENV_DECLSPEC LibMCEnvResult libmcenv_uienvironment_setdoubleresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, LibMCEnv_double dReturnValue);
+
/**
* Returns the external event parameters. This JSON Object was passed on from the external API.
*
diff --git a/Framework/InterfacesCore/libmcenv_interfaces.hpp b/Framework/InterfacesCore/libmcenv_interfaces.hpp
index c655dd7ac..71734574b 100644
--- a/Framework/InterfacesCore/libmcenv_interfaces.hpp
+++ b/Framework/InterfacesCore/libmcenv_interfaces.hpp
@@ -92,6 +92,7 @@ class IToolpathLayer;
class IToolpathAccessor;
class IBuildExecution;
class IBuildExecutionIterator;
+class IBuildIterator;
class IBuild;
class IWorkingFileProcess;
class IWorkingFile;
@@ -3517,6 +3518,23 @@ class IBuildExecutionIterator : public virtual IIterator {
typedef IBaseSharedPtr PIBuildExecutionIterator;
+/*************************************************************************************************************************
+ Class interface for BuildIterator
+**************************************************************************************************************************/
+
+class IBuildIterator : public virtual IIterator {
+public:
+ /**
+ * IBuildIterator::GetCurrentBuild - Returns the build the iterator points at.
+ * @return returns the Build instance.
+ */
+ virtual IBuild * GetCurrentBuild() = 0;
+
+};
+
+typedef IBaseSharedPtr PIBuildIterator;
+
+
/*************************************************************************************************************************
Class interface for Build
**************************************************************************************************************************/
@@ -3535,6 +3553,18 @@ class IBuild : public virtual IBase {
*/
virtual std::string GetBuildUUID() = 0;
+ /**
+ * IBuild::GetCreatedTimestamp - Returns creation timestamp of the build in ISO-8601 format.
+ * @return Creation timestamp in ISO-8601 format (e.g., 2025-10-23T14:30:00.000Z).
+ */
+ virtual std::string GetCreatedTimestamp() = 0;
+
+ /**
+ * IBuild::GetLastExecutionTimestamp - Returns the most recent execution timestamp in ISO-8601 format. Returns empty string if build has never been executed.
+ * @return Most recent execution timestamp in ISO-8601 format. Empty string if never executed.
+ */
+ virtual std::string GetLastExecutionTimestamp() = 0;
+
/**
* IBuild::GetStorageUUID - Returns storage uuid of the build stream.
* @return Storage UUID of the build.
@@ -7168,36 +7198,34 @@ class IStateEnvironment : public virtual IBase {
virtual ISignalTrigger * PrepareSignal(const std::string & sMachineInstance, const std::string & sSignalName) = 0;
/**
- * IStateEnvironment::WaitForSignal - Waits for a signal for a certain amount of time.
- * @param[in] sSignalName - Name Of Signal
- * @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
- * @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
- * @return Signal has been triggered
+ * IStateEnvironment::ClaimSignalFromQueue - Retrieves an InQueue signal by type and changes its phase to InProcess. Recommended to use as it is robust against signal timeouts...
+ * @param[in] sSignalTypeName - Name Of Signal to be returned
+ * @return Signal object. If no signal is InQueue the signal handler object will be null.
*/
- virtual bool WaitForSignal(const std::string & sSignalName, const LibMCEnv_uint32 nTimeOut, ISignalHandler*& pHandlerInstance) = 0;
+ virtual ISignalHandler * ClaimSignalFromQueue(const std::string & sSignalTypeName) = 0;
/**
- * IStateEnvironment::GetUnhandledSignal - Retrieves an unhandled signal By signal type name. Only affects signals with Phase InQueue.
+ * IStateEnvironment::SignalQueueIsEmpty - Returns if a signal queue is empty for a specific type...
* @param[in] sSignalTypeName - Name Of Signal to be returned
- * @return Signal object. If no signal has been found the signal handler object will be null.
+ * @return Returns if the signal queue is empty. Please be aware that even a false return value does not guarantee that ClaimSignalFromQueue returns a non-null value.
*/
- virtual ISignalHandler * GetUnhandledSignal(const std::string & sSignalTypeName) = 0;
+ virtual bool SignalQueueIsEmpty(const std::string & sSignalTypeName) = 0;
/**
- * IStateEnvironment::ClearUnhandledSignalsOfType - Clears all unhandled signals of a certain type and marks them as Cleared. Only affects signals with Phase InQueue.
+ * IStateEnvironment::ClearUnhandledSignalsOfType - Clears all InQueue or InProcess signals of a certain type and marks them as Cleared. Handled, failed or timedout signals are unaffected
* @param[in] sSignalTypeName - Name Of Signal to be cleared.
*/
virtual void ClearUnhandledSignalsOfType(const std::string & sSignalTypeName) = 0;
/**
- * IStateEnvironment::ClearAllUnhandledSignals - Clears all unhandled signals and marks them Cleared. Only affects signals in the specific queue (as well as with Phase InQueue.
+ * IStateEnvironment::ClearAllUnhandledSignals - Clears all InQueue or InProcess signals of this state machine and marks them Cleared. Handled, failed or timedout signals are unaffected
*/
virtual void ClearAllUnhandledSignals() = 0;
/**
- * IStateEnvironment::GetUnhandledSignalByUUID - retrieves an unhandled signal from the current state machine by UUID.
+ * IStateEnvironment::GetUnhandledSignalByUUID - Retrieves an InQueue or InProcess signal from the current state machine by UUID.
* @param[in] sUUID - Name
- * @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled already.
+ * @param[in] bMustExist - The call fails if MustExist is true and not signal with UUID does exist or a signal with UUID has been handled, failed, cleared or timedout already.
* @return Signal handler instance. Returns null, if signal does not exist.
*/
virtual ISignalHandler * GetUnhandledSignalByUUID(const std::string & sUUID, const bool bMustExist) = 0;
@@ -7250,6 +7278,42 @@ class IStateEnvironment : public virtual IBase {
*/
virtual void UnloadAllToolpathes() = 0;
+ /**
+ * IStateEnvironment::WaitForSignal - DEPRECIATED: Waits for an InQueue signal to exist for a certain amount of time. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE claim signal instead.
+ * @param[in] sSignalName - Name Of Signal
+ * @param[in] nTimeOut - Timeout in Milliseconds. 0 for Immediate return.
+ * @param[out] pHandlerInstance - Signal object. If Success is false, the Signal Handler Object will be null.
+ * @return Signal has been triggered
+ */
+ virtual bool WaitForSignal(const std::string & sSignalName, const LibMCEnv_uint32 nTimeOut, ISignalHandler*& pHandlerInstance) = 0;
+
+ /**
+ * IStateEnvironment::GetUnhandledSignal - DEPRECIATED: Retrieves am InQueue signal by type. DOES NOT change signal phase to InProcess, and is not atomic. And so NOT robust against signal timeouts. USE ClaimSignalFromQueue instead.
+ * @param[in] sSignalTypeName - Name Of Signal to be returned
+ * @return Signal object. If no signal has been found the signal handler object will be null.
+ */
+ virtual ISignalHandler * GetUnhandledSignal(const std::string & sSignalTypeName) = 0;
+
+ /**
+ * IStateEnvironment::StoreSignal - DEPRECIATED: stores a signal handler in the current state machine
+ * @param[in] sName - Name
+ * @param[in] pHandler - Signal handler to store.
+ */
+ virtual void StoreSignal(const std::string & sName, ISignalHandler* pHandler) = 0;
+
+ /**
+ * IStateEnvironment::RetrieveSignal - DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
+ * @param[in] sName - Name
+ * @return Signal handler instance.
+ */
+ virtual ISignalHandler * RetrieveSignal(const std::string & sName) = 0;
+
+ /**
+ * IStateEnvironment::ClearStoredValue - DEPRECIATED: deletes a value from the data store.
+ * @param[in] sName - Name
+ */
+ virtual void ClearStoredValue(const std::string & sName) = 0;
+
/**
* IStateEnvironment::SetNextState - sets the next state
* @param[in] sStateName - Name of next state
@@ -7286,26 +7350,6 @@ class IStateEnvironment : public virtual IBase {
*/
virtual bool CheckForTermination() = 0;
- /**
- * IStateEnvironment::StoreSignal - DEPRECIATED: stores a signal handler in the current state machine
- * @param[in] sName - Name
- * @param[in] pHandler - Signal handler to store.
- */
- virtual void StoreSignal(const std::string & sName, ISignalHandler* pHandler) = 0;
-
- /**
- * IStateEnvironment::RetrieveSignal - DEPRECIATED: retrieves a signal handler from the current state machine. Fails if value has not been stored before or signal has been already handled.
- * @param[in] sName - Name
- * @return Signal handler instance.
- */
- virtual ISignalHandler * RetrieveSignal(const std::string & sName) = 0;
-
- /**
- * IStateEnvironment::ClearStoredValue - DEPRECIATED: deletes a value from the data store.
- * @param[in] sName - Name
- */
- virtual void ClearStoredValue(const std::string & sName) = 0;
-
/**
* IStateEnvironment::SetStringParameter - sets a string parameter
* @param[in] sParameterGroup - Parameter Group
@@ -8127,6 +8171,13 @@ class IUIEnvironment : public virtual IBase {
*/
virtual IBuildExecution * GetBuildExecution(const std::string & sExecutionUUID) = 0;
+ /**
+ * IUIEnvironment::GetRecentBuildJobs - Returns an iterator for recent build jobs, ordered by timestamp (newest first).
+ * @param[in] nMaxCount - Maximum number of jobs to return. Must be greater than 0.
+ * @return Iterator for build jobs, ordered newest first.
+ */
+ virtual IBuildIterator * GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount) = 0;
+
/**
* IUIEnvironment::CreateDiscreteField2D - Creates an empty discrete field.
* @param[in] nPixelCountX - Pixel count in X. MUST be positive.
@@ -8361,6 +8412,34 @@ class IUIEnvironment : public virtual IBase {
*/
virtual void AddExternalEventResultValue(const std::string & sReturnValueName, const std::string & sReturnValue) = 0;
+ /**
+ * IUIEnvironment::SetStringResult - Sets a string result value for external event return (typed convenience wrapper).
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] sReturnValue - Return value.
+ */
+ virtual void SetStringResult(const std::string & sReturnValueName, const std::string & sReturnValue) = 0;
+
+ /**
+ * IUIEnvironment::SetIntegerResult - Sets an integer result value for external event return.
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] nReturnValue - Return value.
+ */
+ virtual void SetIntegerResult(const std::string & sReturnValueName, const LibMCEnv_int64 nReturnValue) = 0;
+
+ /**
+ * IUIEnvironment::SetBoolResult - Sets a boolean result value for external event return.
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] bReturnValue - Return value.
+ */
+ virtual void SetBoolResult(const std::string & sReturnValueName, const bool bReturnValue) = 0;
+
+ /**
+ * IUIEnvironment::SetDoubleResult - Sets a double result value for external event return.
+ * @param[in] sReturnValueName - The name of the return parameter. MUST be an alphanumeric ASCII string (with optional _ and -)
+ * @param[in] dReturnValue - Return value.
+ */
+ virtual void SetDoubleResult(const std::string & sReturnValueName, const LibMCEnv_double dReturnValue) = 0;
+
/**
* IUIEnvironment::GetExternalEventParameters - Returns the external event parameters. This JSON Object was passed on from the external API.
* @return Parameter value.
diff --git a/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp b/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp
index 2dcd60431..209caba70 100644
--- a/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp
+++ b/Framework/InterfacesCore/libmcenv_interfacewrapper.cpp
@@ -12187,6 +12187,38 @@ LibMCEnvResult libmcenv_buildexecutioniterator_getcurrentexecution(LibMCEnv_Buil
}
+/*************************************************************************************************************************
+ Class implementation for BuildIterator
+**************************************************************************************************************************/
+LibMCEnvResult libmcenv_builditerator_getcurrentbuild(LibMCEnv_BuildIterator pBuildIterator, LibMCEnv_Build * pBuildInstance)
+{
+ IBase* pIBaseClass = (IBase *)pBuildIterator;
+
+ try {
+ if (pBuildInstance == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ IBase* pBaseBuildInstance(nullptr);
+ IBuildIterator* pIBuildIterator = dynamic_cast(pIBaseClass);
+ if (!pIBuildIterator)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pBaseBuildInstance = pIBuildIterator->GetCurrentBuild();
+
+ *pBuildInstance = (IBase*)(pBaseBuildInstance);
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+
/*************************************************************************************************************************
Class implementation for Build
**************************************************************************************************************************/
@@ -12286,6 +12318,102 @@ LibMCEnvResult libmcenv_build_getbuilduuid(LibMCEnv_Build pBuild, const LibMCEnv
}
}
+LibMCEnvResult libmcenv_build_getcreatedtimestamp(LibMCEnv_Build pBuild, const LibMCEnv_uint32 nTimestampBufferSize, LibMCEnv_uint32* pTimestampNeededChars, char * pTimestampBuffer)
+{
+ IBase* pIBaseClass = (IBase *)pBuild;
+
+ try {
+ if ( (!pTimestampBuffer) && !(pTimestampNeededChars) )
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sTimestamp("");
+ IBuild* pIBuild = dynamic_cast(pIBaseClass);
+ if (!pIBuild)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ bool isCacheCall = (pTimestampBuffer == nullptr);
+ if (isCacheCall) {
+ sTimestamp = pIBuild->GetCreatedTimestamp();
+
+ pIBuild->_setCache (new ParameterCache_1 (sTimestamp));
+ }
+ else {
+ auto cache = dynamic_cast*> (pIBuild->_getCache ());
+ if (cache == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+ cache->retrieveData (sTimestamp);
+ pIBuild->_setCache (nullptr);
+ }
+
+ if (pTimestampNeededChars)
+ *pTimestampNeededChars = (LibMCEnv_uint32) (sTimestamp.size()+1);
+ if (pTimestampBuffer) {
+ if (sTimestamp.size() >= nTimestampBufferSize)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_BUFFERTOOSMALL);
+ for (size_t iTimestamp = 0; iTimestamp < sTimestamp.size(); iTimestamp++)
+ pTimestampBuffer[iTimestamp] = sTimestamp[iTimestamp];
+ pTimestampBuffer[sTimestamp.size()] = 0;
+ }
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+LibMCEnvResult libmcenv_build_getlastexecutiontimestamp(LibMCEnv_Build pBuild, const LibMCEnv_uint32 nTimestampBufferSize, LibMCEnv_uint32* pTimestampNeededChars, char * pTimestampBuffer)
+{
+ IBase* pIBaseClass = (IBase *)pBuild;
+
+ try {
+ if ( (!pTimestampBuffer) && !(pTimestampNeededChars) )
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sTimestamp("");
+ IBuild* pIBuild = dynamic_cast(pIBaseClass);
+ if (!pIBuild)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ bool isCacheCall = (pTimestampBuffer == nullptr);
+ if (isCacheCall) {
+ sTimestamp = pIBuild->GetLastExecutionTimestamp();
+
+ pIBuild->_setCache (new ParameterCache_1 (sTimestamp));
+ }
+ else {
+ auto cache = dynamic_cast*> (pIBuild->_getCache ());
+ if (cache == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+ cache->retrieveData (sTimestamp);
+ pIBuild->_setCache (nullptr);
+ }
+
+ if (pTimestampNeededChars)
+ *pTimestampNeededChars = (LibMCEnv_uint32) (sTimestamp.size()+1);
+ if (pTimestampBuffer) {
+ if (sTimestamp.size() >= nTimestampBufferSize)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_BUFFERTOOSMALL);
+ for (size_t iTimestamp = 0; iTimestamp < sTimestamp.size(); iTimestamp++)
+ pTimestampBuffer[iTimestamp] = sTimestamp[iTimestamp];
+ pTimestampBuffer[sTimestamp.size()] = 0;
+ }
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
LibMCEnvResult libmcenv_build_getstorageuuid(LibMCEnv_Build pBuild, const LibMCEnv_uint32 nStorageUUIDBufferSize, LibMCEnv_uint32* pStorageUUIDNeededChars, char * pStorageUUIDBuffer)
{
IBase* pIBaseClass = (IBase *)pBuild;
@@ -27731,24 +27859,22 @@ LibMCEnvResult libmcenv_stateenvironment_preparesignal(LibMCEnv_StateEnvironment
}
}
-LibMCEnvResult libmcenv_stateenvironment_waitforsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalName, LibMCEnv_uint32 nTimeOut, LibMCEnv_SignalHandler * pHandlerInstance, bool * pSuccess)
+LibMCEnvResult libmcenv_stateenvironment_claimsignalfromqueue(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pSignalName == nullptr)
+ if (pSignalTypeName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
if (pHandlerInstance == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- if (pSuccess == nullptr)
- throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sSignalName(pSignalName);
- ISignalHandler* pBaseHandlerInstance(nullptr);
+ std::string sSignalTypeName(pSignalTypeName);
+ IBase* pBaseHandlerInstance(nullptr);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- *pSuccess = pIStateEnvironment->WaitForSignal(sSignalName, nTimeOut, pBaseHandlerInstance);
+ pBaseHandlerInstance = pIStateEnvironment->ClaimSignalFromQueue(sSignalTypeName);
*pHandlerInstance = (IBase*)(pBaseHandlerInstance);
return LIBMCENV_SUCCESS;
@@ -27764,24 +27890,22 @@ LibMCEnvResult libmcenv_stateenvironment_waitforsignal(LibMCEnv_StateEnvironment
}
}
-LibMCEnvResult libmcenv_stateenvironment_getunhandledsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance)
+LibMCEnvResult libmcenv_stateenvironment_signalqueueisempty(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, bool * pIsEmpty)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
if (pSignalTypeName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- if (pHandlerInstance == nullptr)
+ if (pIsEmpty == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
std::string sSignalTypeName(pSignalTypeName);
- IBase* pBaseHandlerInstance(nullptr);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pBaseHandlerInstance = pIStateEnvironment->GetUnhandledSignal(sSignalTypeName);
+ *pIsEmpty = pIStateEnvironment->SignalQueueIsEmpty(sSignalTypeName);
- *pHandlerInstance = (IBase*)(pBaseHandlerInstance);
return LIBMCENV_SUCCESS;
}
catch (ELibMCEnvInterfaceException & Exception) {
@@ -28103,20 +28227,26 @@ LibMCEnvResult libmcenv_stateenvironment_unloadalltoolpathes(LibMCEnv_StateEnvir
}
}
-LibMCEnvResult libmcenv_stateenvironment_setnextstate(LibMCEnv_StateEnvironment pStateEnvironment, const char * pStateName)
+LibMCEnvResult libmcenv_stateenvironment_waitforsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalName, LibMCEnv_uint32 nTimeOut, LibMCEnv_SignalHandler * pHandlerInstance, bool * pSuccess)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pStateName == nullptr)
+ if (pSignalName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sStateName(pStateName);
+ if (pHandlerInstance == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ if (pSuccess == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sSignalName(pSignalName);
+ ISignalHandler* pBaseHandlerInstance(nullptr);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->SetNextState(sStateName);
+ *pSuccess = pIStateEnvironment->WaitForSignal(sSignalName, nTimeOut, pBaseHandlerInstance);
+ *pHandlerInstance = (IBase*)(pBaseHandlerInstance);
return LIBMCENV_SUCCESS;
}
catch (ELibMCEnvInterfaceException & Exception) {
@@ -28130,20 +28260,24 @@ LibMCEnvResult libmcenv_stateenvironment_setnextstate(LibMCEnv_StateEnvironment
}
}
-LibMCEnvResult libmcenv_stateenvironment_logmessage(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString)
+LibMCEnvResult libmcenv_stateenvironment_getunhandledsignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pSignalTypeName, LibMCEnv_SignalHandler * pHandlerInstance)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pLogString == nullptr)
+ if (pSignalTypeName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sLogString(pLogString);
+ if (pHandlerInstance == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sSignalTypeName(pSignalTypeName);
+ IBase* pBaseHandlerInstance(nullptr);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->LogMessage(sLogString);
+ pBaseHandlerInstance = pIStateEnvironment->GetUnhandledSignal(sSignalTypeName);
+ *pHandlerInstance = (IBase*)(pBaseHandlerInstance);
return LIBMCENV_SUCCESS;
}
catch (ELibMCEnvInterfaceException & Exception) {
@@ -28157,19 +28291,24 @@ LibMCEnvResult libmcenv_stateenvironment_logmessage(LibMCEnv_StateEnvironment pS
}
}
-LibMCEnvResult libmcenv_stateenvironment_logwarning(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString)
+LibMCEnvResult libmcenv_stateenvironment_storesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler pHandler)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pLogString == nullptr)
+ if (pName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sLogString(pLogString);
+ std::string sName(pName);
+ IBase* pIBaseClassHandler = (IBase *)pHandler;
+ ISignalHandler* pIHandler = dynamic_cast(pIBaseClassHandler);
+ if (!pIHandler)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDCAST);
+
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->LogWarning(sLogString);
+ pIStateEnvironment->StoreSignal(sName, pIHandler);
return LIBMCENV_SUCCESS;
}
@@ -28184,20 +28323,24 @@ LibMCEnvResult libmcenv_stateenvironment_logwarning(LibMCEnv_StateEnvironment pS
}
}
-LibMCEnvResult libmcenv_stateenvironment_loginfo(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString)
+LibMCEnvResult libmcenv_stateenvironment_retrievesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler * pHandler)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pLogString == nullptr)
+ if (pName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sLogString(pLogString);
+ if (pHandler == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sName(pName);
+ IBase* pBaseHandler(nullptr);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->LogInfo(sLogString);
+ pBaseHandler = pIStateEnvironment->RetrieveSignal(sName);
+ *pHandler = (IBase*)(pBaseHandler);
return LIBMCENV_SUCCESS;
}
catch (ELibMCEnvInterfaceException & Exception) {
@@ -28211,16 +28354,19 @@ LibMCEnvResult libmcenv_stateenvironment_loginfo(LibMCEnv_StateEnvironment pStat
}
}
-LibMCEnvResult libmcenv_stateenvironment_sleep(LibMCEnv_StateEnvironment pStateEnvironment, LibMCEnv_uint32 nDelay)
+LibMCEnvResult libmcenv_stateenvironment_clearstoredvalue(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
+ if (pName == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sName(pName);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->Sleep(nDelay);
+ pIStateEnvironment->ClearStoredValue(sName);
return LIBMCENV_SUCCESS;
}
@@ -28235,18 +28381,19 @@ LibMCEnvResult libmcenv_stateenvironment_sleep(LibMCEnv_StateEnvironment pStateE
}
}
-LibMCEnvResult libmcenv_stateenvironment_checkfortermination(LibMCEnv_StateEnvironment pStateEnvironment, bool * pShallTerminate)
+LibMCEnvResult libmcenv_stateenvironment_setnextstate(LibMCEnv_StateEnvironment pStateEnvironment, const char * pStateName)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pShallTerminate == nullptr)
+ if (pStateName == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sStateName(pStateName);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- *pShallTerminate = pIStateEnvironment->CheckForTermination();
+ pIStateEnvironment->SetNextState(sStateName);
return LIBMCENV_SUCCESS;
}
@@ -28261,24 +28408,19 @@ LibMCEnvResult libmcenv_stateenvironment_checkfortermination(LibMCEnv_StateEnvir
}
}
-LibMCEnvResult libmcenv_stateenvironment_storesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler pHandler)
+LibMCEnvResult libmcenv_stateenvironment_logmessage(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pName == nullptr)
+ if (pLogString == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sName(pName);
- IBase* pIBaseClassHandler = (IBase *)pHandler;
- ISignalHandler* pIHandler = dynamic_cast(pIBaseClassHandler);
- if (!pIHandler)
- throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDCAST);
-
+ std::string sLogString(pLogString);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->StoreSignal(sName, pIHandler);
+ pIStateEnvironment->LogMessage(sLogString);
return LIBMCENV_SUCCESS;
}
@@ -28293,24 +28435,47 @@ LibMCEnvResult libmcenv_stateenvironment_storesignal(LibMCEnv_StateEnvironment p
}
}
-LibMCEnvResult libmcenv_stateenvironment_retrievesignal(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName, LibMCEnv_SignalHandler * pHandler)
+LibMCEnvResult libmcenv_stateenvironment_logwarning(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pName == nullptr)
+ if (pLogString == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- if (pHandler == nullptr)
+ std::string sLogString(pLogString);
+ IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIStateEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pIStateEnvironment->LogWarning(sLogString);
+
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+LibMCEnvResult libmcenv_stateenvironment_loginfo(LibMCEnv_StateEnvironment pStateEnvironment, const char * pLogString)
+{
+ IBase* pIBaseClass = (IBase *)pStateEnvironment;
+
+ try {
+ if (pLogString == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sName(pName);
- IBase* pBaseHandler(nullptr);
+ std::string sLogString(pLogString);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pBaseHandler = pIStateEnvironment->RetrieveSignal(sName);
+ pIStateEnvironment->LogInfo(sLogString);
- *pHandler = (IBase*)(pBaseHandler);
return LIBMCENV_SUCCESS;
}
catch (ELibMCEnvInterfaceException & Exception) {
@@ -28324,19 +28489,42 @@ LibMCEnvResult libmcenv_stateenvironment_retrievesignal(LibMCEnv_StateEnvironmen
}
}
-LibMCEnvResult libmcenv_stateenvironment_clearstoredvalue(LibMCEnv_StateEnvironment pStateEnvironment, const char * pName)
+LibMCEnvResult libmcenv_stateenvironment_sleep(LibMCEnv_StateEnvironment pStateEnvironment, LibMCEnv_uint32 nDelay)
{
IBase* pIBaseClass = (IBase *)pStateEnvironment;
try {
- if (pName == nullptr)
+ IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIStateEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pIStateEnvironment->Sleep(nDelay);
+
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+LibMCEnvResult libmcenv_stateenvironment_checkfortermination(LibMCEnv_StateEnvironment pStateEnvironment, bool * pShallTerminate)
+{
+ IBase* pIBaseClass = (IBase *)pStateEnvironment;
+
+ try {
+ if (pShallTerminate == nullptr)
throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
- std::string sName(pName);
IStateEnvironment* pIStateEnvironment = dynamic_cast(pIBaseClass);
if (!pIStateEnvironment)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
- pIStateEnvironment->ClearStoredValue(sName);
+ *pShallTerminate = pIStateEnvironment->CheckForTermination();
return LIBMCENV_SUCCESS;
}
@@ -31928,6 +32116,34 @@ LibMCEnvResult libmcenv_uienvironment_getbuildexecution(LibMCEnv_UIEnvironment p
}
}
+LibMCEnvResult libmcenv_uienvironment_getrecentbuildjobs(LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nMaxCount, LibMCEnv_BuildIterator * pBuildIterator)
+{
+ IBase* pIBaseClass = (IBase *)pUIEnvironment;
+
+ try {
+ if (pBuildIterator == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ IBase* pBaseBuildIterator(nullptr);
+ IUIEnvironment* pIUIEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIUIEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pBaseBuildIterator = pIUIEnvironment->GetRecentBuildJobs(nMaxCount);
+
+ *pBuildIterator = (IBase*)(pBaseBuildIterator);
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
LibMCEnvResult libmcenv_uienvironment_creatediscretefield2d(LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_uint32 nPixelCountX, LibMCEnv_uint32 nPixelCountY, LibMCEnv_double dDPIValueX, LibMCEnv_double dDPIValueY, LibMCEnv_double dOriginX, LibMCEnv_double dOriginY, LibMCEnv_double dDefaultValue, LibMCEnv_DiscreteFieldData2D * pFieldDataInstance)
{
IBase* pIBaseClass = (IBase *)pUIEnvironment;
@@ -32984,6 +33200,117 @@ LibMCEnvResult libmcenv_uienvironment_addexternaleventresultvalue(LibMCEnv_UIEnv
}
}
+LibMCEnvResult libmcenv_uienvironment_setstringresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, const char * pReturnValue)
+{
+ IBase* pIBaseClass = (IBase *)pUIEnvironment;
+
+ try {
+ if (pReturnValueName == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ if (pReturnValue == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sReturnValueName(pReturnValueName);
+ std::string sReturnValue(pReturnValue);
+ IUIEnvironment* pIUIEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIUIEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pIUIEnvironment->SetStringResult(sReturnValueName, sReturnValue);
+
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+LibMCEnvResult libmcenv_uienvironment_setintegerresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, LibMCEnv_int64 nReturnValue)
+{
+ IBase* pIBaseClass = (IBase *)pUIEnvironment;
+
+ try {
+ if (pReturnValueName == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sReturnValueName(pReturnValueName);
+ IUIEnvironment* pIUIEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIUIEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pIUIEnvironment->SetIntegerResult(sReturnValueName, nReturnValue);
+
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+LibMCEnvResult libmcenv_uienvironment_setboolresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, bool bReturnValue)
+{
+ IBase* pIBaseClass = (IBase *)pUIEnvironment;
+
+ try {
+ if (pReturnValueName == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sReturnValueName(pReturnValueName);
+ IUIEnvironment* pIUIEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIUIEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pIUIEnvironment->SetBoolResult(sReturnValueName, bReturnValue);
+
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
+LibMCEnvResult libmcenv_uienvironment_setdoubleresult(LibMCEnv_UIEnvironment pUIEnvironment, const char * pReturnValueName, LibMCEnv_double dReturnValue)
+{
+ IBase* pIBaseClass = (IBase *)pUIEnvironment;
+
+ try {
+ if (pReturnValueName == nullptr)
+ throw ELibMCEnvInterfaceException (LIBMCENV_ERROR_INVALIDPARAM);
+ std::string sReturnValueName(pReturnValueName);
+ IUIEnvironment* pIUIEnvironment = dynamic_cast(pIBaseClass);
+ if (!pIUIEnvironment)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ pIUIEnvironment->SetDoubleResult(sReturnValueName, dReturnValue);
+
+ return LIBMCENV_SUCCESS;
+ }
+ catch (ELibMCEnvInterfaceException & Exception) {
+ return handleLibMCEnvException(pIBaseClass, Exception);
+ }
+ catch (std::exception & StdException) {
+ return handleStdException(pIBaseClass, StdException);
+ }
+ catch (...) {
+ return handleUnhandledException(pIBaseClass);
+ }
+}
+
LibMCEnvResult libmcenv_uienvironment_getexternaleventparameters(LibMCEnv_UIEnvironment pUIEnvironment, LibMCEnv_JSONObject * pParameterValue)
{
IBase* pIBaseClass = (IBase *)pUIEnvironment;
@@ -33867,10 +34194,16 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_buildexecution_loadattachedjournal;
if (sProcName == "libmcenv_buildexecutioniterator_getcurrentexecution")
*ppProcAddress = (void*) &libmcenv_buildexecutioniterator_getcurrentexecution;
+ if (sProcName == "libmcenv_builditerator_getcurrentbuild")
+ *ppProcAddress = (void*) &libmcenv_builditerator_getcurrentbuild;
if (sProcName == "libmcenv_build_getname")
*ppProcAddress = (void*) &libmcenv_build_getname;
if (sProcName == "libmcenv_build_getbuilduuid")
*ppProcAddress = (void*) &libmcenv_build_getbuilduuid;
+ if (sProcName == "libmcenv_build_getcreatedtimestamp")
+ *ppProcAddress = (void*) &libmcenv_build_getcreatedtimestamp;
+ if (sProcName == "libmcenv_build_getlastexecutiontimestamp")
+ *ppProcAddress = (void*) &libmcenv_build_getlastexecutiontimestamp;
if (sProcName == "libmcenv_build_getstorageuuid")
*ppProcAddress = (void*) &libmcenv_build_getstorageuuid;
if (sProcName == "libmcenv_build_getstoragesha256")
@@ -34793,10 +35126,10 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_stateenvironment_getpreviousstate;
if (sProcName == "libmcenv_stateenvironment_preparesignal")
*ppProcAddress = (void*) &libmcenv_stateenvironment_preparesignal;
- if (sProcName == "libmcenv_stateenvironment_waitforsignal")
- *ppProcAddress = (void*) &libmcenv_stateenvironment_waitforsignal;
- if (sProcName == "libmcenv_stateenvironment_getunhandledsignal")
- *ppProcAddress = (void*) &libmcenv_stateenvironment_getunhandledsignal;
+ if (sProcName == "libmcenv_stateenvironment_claimsignalfromqueue")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_claimsignalfromqueue;
+ if (sProcName == "libmcenv_stateenvironment_signalqueueisempty")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_signalqueueisempty;
if (sProcName == "libmcenv_stateenvironment_clearunhandledsignalsoftype")
*ppProcAddress = (void*) &libmcenv_stateenvironment_clearunhandledsignalsoftype;
if (sProcName == "libmcenv_stateenvironment_clearallunhandledsignals")
@@ -34817,6 +35150,16 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_stateenvironment_getbuildexecution;
if (sProcName == "libmcenv_stateenvironment_unloadalltoolpathes")
*ppProcAddress = (void*) &libmcenv_stateenvironment_unloadalltoolpathes;
+ if (sProcName == "libmcenv_stateenvironment_waitforsignal")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_waitforsignal;
+ if (sProcName == "libmcenv_stateenvironment_getunhandledsignal")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_getunhandledsignal;
+ if (sProcName == "libmcenv_stateenvironment_storesignal")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_storesignal;
+ if (sProcName == "libmcenv_stateenvironment_retrievesignal")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_retrievesignal;
+ if (sProcName == "libmcenv_stateenvironment_clearstoredvalue")
+ *ppProcAddress = (void*) &libmcenv_stateenvironment_clearstoredvalue;
if (sProcName == "libmcenv_stateenvironment_setnextstate")
*ppProcAddress = (void*) &libmcenv_stateenvironment_setnextstate;
if (sProcName == "libmcenv_stateenvironment_logmessage")
@@ -34829,12 +35172,6 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_stateenvironment_sleep;
if (sProcName == "libmcenv_stateenvironment_checkfortermination")
*ppProcAddress = (void*) &libmcenv_stateenvironment_checkfortermination;
- if (sProcName == "libmcenv_stateenvironment_storesignal")
- *ppProcAddress = (void*) &libmcenv_stateenvironment_storesignal;
- if (sProcName == "libmcenv_stateenvironment_retrievesignal")
- *ppProcAddress = (void*) &libmcenv_stateenvironment_retrievesignal;
- if (sProcName == "libmcenv_stateenvironment_clearstoredvalue")
- *ppProcAddress = (void*) &libmcenv_stateenvironment_clearstoredvalue;
if (sProcName == "libmcenv_stateenvironment_setstringparameter")
*ppProcAddress = (void*) &libmcenv_stateenvironment_setstringparameter;
if (sProcName == "libmcenv_stateenvironment_setuuidparameter")
@@ -35053,6 +35390,8 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_uienvironment_hasbuildexecution;
if (sProcName == "libmcenv_uienvironment_getbuildexecution")
*ppProcAddress = (void*) &libmcenv_uienvironment_getbuildexecution;
+ if (sProcName == "libmcenv_uienvironment_getrecentbuildjobs")
+ *ppProcAddress = (void*) &libmcenv_uienvironment_getrecentbuildjobs;
if (sProcName == "libmcenv_uienvironment_creatediscretefield2d")
*ppProcAddress = (void*) &libmcenv_uienvironment_creatediscretefield2d;
if (sProcName == "libmcenv_uienvironment_creatediscretefield2dfromimage")
@@ -35117,6 +35456,14 @@ LibMCEnvResult LibMCEnv::Impl::LibMCEnv_GetProcAddress (const char * pProcName,
*ppProcAddress = (void*) &libmcenv_uienvironment_getexternaleventparameter;
if (sProcName == "libmcenv_uienvironment_addexternaleventresultvalue")
*ppProcAddress = (void*) &libmcenv_uienvironment_addexternaleventresultvalue;
+ if (sProcName == "libmcenv_uienvironment_setstringresult")
+ *ppProcAddress = (void*) &libmcenv_uienvironment_setstringresult;
+ if (sProcName == "libmcenv_uienvironment_setintegerresult")
+ *ppProcAddress = (void*) &libmcenv_uienvironment_setintegerresult;
+ if (sProcName == "libmcenv_uienvironment_setboolresult")
+ *ppProcAddress = (void*) &libmcenv_uienvironment_setboolresult;
+ if (sProcName == "libmcenv_uienvironment_setdoubleresult")
+ *ppProcAddress = (void*) &libmcenv_uienvironment_setdoubleresult;
if (sProcName == "libmcenv_uienvironment_getexternaleventparameters")
*ppProcAddress = (void*) &libmcenv_uienvironment_getexternaleventparameters;
if (sProcName == "libmcenv_uienvironment_getexternaleventresults")
diff --git a/Framework/InterfacesCore/libmcenv_types.hpp b/Framework/InterfacesCore/libmcenv_types.hpp
index 42e8f6a15..35641291e 100644
--- a/Framework/InterfacesCore/libmcenv_types.hpp
+++ b/Framework/InterfacesCore/libmcenv_types.hpp
@@ -656,6 +656,7 @@ typedef LibMCEnvHandle LibMCEnv_ToolpathLayer;
typedef LibMCEnvHandle LibMCEnv_ToolpathAccessor;
typedef LibMCEnvHandle LibMCEnv_BuildExecution;
typedef LibMCEnvHandle LibMCEnv_BuildExecutionIterator;
+typedef LibMCEnvHandle LibMCEnv_BuildIterator;
typedef LibMCEnvHandle LibMCEnv_Build;
typedef LibMCEnvHandle LibMCEnv_WorkingFileProcess;
typedef LibMCEnvHandle LibMCEnv_WorkingFile;
diff --git a/Implementation/API/amc_api_handler_external.cpp b/Implementation/API/amc_api_handler_external.cpp
index 962040f7f..a0e59d96a 100644
--- a/Implementation/API/amc_api_handler_external.cpp
+++ b/Implementation/API/amc_api_handler_external.cpp
@@ -147,6 +147,11 @@ uint32_t CAPIHandler_External::handleEventRequest(CJSONWriter& writer, const std
newObject.copyFromObject (iIter->value);
writer.addObject(sValueName, newObject);
}
+ if (iIter->value.IsArray()) {
+ AMC::CJSONWriterArray newArray (writer);
+ newArray.copyFromArray (iIter->value);
+ writer.addArray(sValueName, newArray);
+ }
}
diff --git a/Implementation/Core/amc_discretefielddata2d.cpp b/Implementation/Core/amc_discretefielddata2d.cpp
index de741c048..7cfc2553f 100644
--- a/Implementation/Core/amc_discretefielddata2d.cpp
+++ b/Implementation/Core/amc_discretefielddata2d.cpp
@@ -133,9 +133,9 @@ CDiscreteFieldData2DInstance::CDiscreteFieldData2DInstance(size_t nPixelCountX,
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDDPIVALUE);
if (dDPIY <= 0.0)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDDPIVALUE);
- if (abs (dOriginX) > DISCRETEFIELD_MAXORIGINCOORDINATE)
+ if (std::abs(dOriginX) > DISCRETEFIELD_MAXORIGINCOORDINATE)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_ORIGINOUTOFRANGE);
- if (abs(dOriginY) > DISCRETEFIELD_MAXORIGINCOORDINATE)
+ if (std::abs(dOriginY) > DISCRETEFIELD_MAXORIGINCOORDINATE)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_ORIGINOUTOFRANGE);
m_Data = std::make_unique> ();
@@ -400,7 +400,7 @@ PDiscreteFieldData2DInstance CDiscreteFieldData2DInstance::ScaleFieldUp(const ui
pSource++;
for (uint32_t dY = 0; dY < nFactorY; dY++) {
- double* pTarget = &pNewField->m_Data->at(((size_t)nY * nFactorY + dY) * nNewPixelCountX);
+ double* pTarget = &pNewField->m_Data->at(((size_t)nY * nFactorY + dY) * nNewPixelCountX + (size_t)nX * nFactorX);
for (uint32_t dX = 0; dX < nFactorX; dX++) {
*pTarget = dValue;
pTarget++;
diff --git a/Implementation/Core/amc_jsonwriter.cpp b/Implementation/Core/amc_jsonwriter.cpp
index 290c5015d..53809501d 100644
--- a/Implementation/Core/amc_jsonwriter.cpp
+++ b/Implementation/Core/amc_jsonwriter.cpp
@@ -152,6 +152,11 @@ void CJSONWriterArray::addArray(CJSONWriterArray& array)
m_Value.PushBack(array.m_Value, m_allocator);
}
+void CJSONWriterArray::copyFromArray(const rapidjson::Value& arrayValue)
+{
+ m_Value.CopyFrom(arrayValue, m_allocator);
+}
+
CJSONWriter::CJSONWriter()
diff --git a/Implementation/Core/amc_jsonwriter.hpp b/Implementation/Core/amc_jsonwriter.hpp
index 490232a88..a8ef30bd8 100644
--- a/Implementation/Core/amc_jsonwriter.hpp
+++ b/Implementation/Core/amc_jsonwriter.hpp
@@ -98,6 +98,8 @@ namespace AMC {
void addArray(CJSONWriterArray& array);
+ void copyFromArray(const rapidjson::Value& arrayValue);
+
bool isEmpty();
};
diff --git a/Implementation/Core/amc_statesignal.cpp b/Implementation/Core/amc_statesignal.cpp
index 554cb4709..3a8522652 100644
--- a/Implementation/Core/amc_statesignal.cpp
+++ b/Implementation/Core/amc_statesignal.cpp
@@ -41,9 +41,11 @@ namespace AMC {
CStateSignalMessage::CStateSignalMessage(const std::string& sUUID, uint32_t nReactionTimeoutInMS, PTelemetryChannel pQueueTelemetryChannel, PTelemetryChannel pInProcessTelemetryChannel, PTelemetryChannel pAcknowledgeTelemetryChannel)
: m_sUUID(AMCCommon::CUtils::normalizeUUIDString(sUUID)),
m_nReactionTimeoutInMS(nReactionTimeoutInMS),
- m_MessagePhase (eAMCSignalPhase::InQueue),
- m_pInProcessTelemetryChannel (pInProcessTelemetryChannel),
- m_pAcknowledgeTelemetryChannel (pAcknowledgeTelemetryChannel)
+ m_MessagePhase(eAMCSignalPhase::InQueue),
+ m_pInProcessTelemetryChannel(pInProcessTelemetryChannel),
+ m_pAcknowledgeTelemetryChannel(pAcknowledgeTelemetryChannel),
+ m_nCreationTimestamp(0),
+ m_nTerminalTimestamp(0)
{
if (pQueueTelemetryChannel.get () == nullptr)
@@ -54,6 +56,7 @@ namespace AMC {
throw ELibMCInterfaceException(LIBMC_ERROR_INVALIDPARAM);
m_pTelemetryInQueueMarker = pQueueTelemetryChannel->startIntervalMarker(0);
+ m_nCreationTimestamp = m_pTelemetryInQueueMarker->getStartTimestamp();
}
CStateSignalMessage::~CStateSignalMessage()
@@ -71,17 +74,12 @@ namespace AMC {
uint64_t CStateSignalMessage::getCreationTimestamp() const
{
- return m_pTelemetryInQueueMarker->getStartTimestamp ();
+ return m_nCreationTimestamp;
}
uint64_t CStateSignalMessage::getTerminalTimestamp() const
- {
- if (m_pTelemetryInProcessMarker.get() != nullptr) {
- if (m_pTelemetryInProcessMarker->isFinished())
- return m_pTelemetryInProcessMarker->getFinishTimestamp();
- }
-
- return 0;
+ {
+ return m_nTerminalTimestamp;
}
bool CStateSignalMessage::setPhase(AMC::eAMCSignalPhase messagePhase)
@@ -93,6 +91,7 @@ namespace AMC {
if (m_pTelemetryInProcessMarker.get () != nullptr) {
m_pTelemetryInProcessMarker->finishMarker();
+ m_nTerminalTimestamp = m_pTelemetryInProcessMarker->getFinishTimestamp();
m_pTelemetryInProcessMarker = nullptr;
}
@@ -141,9 +140,7 @@ namespace AMC {
bool CStateSignalMessage::hadReactionTimeout(uint64_t nGlobalTimestamp)
{
- uint64_t nInQueueTimestamp = m_pTelemetryInQueueMarker->getStartTimestamp();
-
- uint64_t nTimeoutTimestamp = nInQueueTimestamp + (uint64_t)m_nReactionTimeoutInMS * 1000;
+ uint64_t nTimeoutTimestamp = m_nCreationTimestamp + (uint64_t)m_nReactionTimeoutInMS * 1000;
return (nGlobalTimestamp >= nTimeoutTimestamp);
}
@@ -192,6 +189,7 @@ namespace AMC {
m_nHandledCount (0),
m_nFailedCount (0),
m_nTimedOutCount (0),
+ m_nArchivedCount (0),
m_nMaxReactionTime (0),
m_pRegistry (pRegistry)
@@ -205,6 +203,7 @@ namespace AMC {
pSignalInformationGroup->addNewIntParameter("handled_" + m_sName, m_sName + " was handled", 0);
pSignalInformationGroup->addNewIntParameter("failed_" + m_sName, m_sName + " has failed", 0);
pSignalInformationGroup->addNewIntParameter("timeout_" + m_sName, m_sName + " timed out", 0);
+ pSignalInformationGroup->addNewIntParameter("archived_" + m_sName, m_sName + " archived", 0);
pSignalInformationGroup->addNewIntParameter("reactiontime_" + m_sName, m_sName + " max reaction time (microseconds)", 0);
pSignalInformationGroup->addNewIntParameter("finishtime_" + m_sName, m_sName + " max finish time (microseconds)", 0);
pSignalInformationGroup->addNewIntParameter("acknowledgetime_" + m_sName, m_sName + " max acknowledge time (microseconds)", 0);
@@ -307,6 +306,15 @@ namespace AMC {
updateTimingStatistics();
}
+ void CStateSignalSlot::increaseArchivedCount()
+ {
+ m_nArchivedCount++;
+ if (m_pSignalInformationGroup.get() != nullptr) {
+ m_pSignalInformationGroup->setIntParameterValueByName("archived_" + m_sName, (int64_t)m_nArchivedCount);
+ }
+
+ }
+
bool CStateSignalSlot::queueIsFullNoMutex()
{
@@ -319,6 +327,12 @@ namespace AMC {
return queueIsFullNoMutex();
}
+ bool CStateSignalSlot::queueIsEmpty()
+ {
+ std::lock_guard lockGuard(m_Mutex);
+ return m_Queue.size() == 0;
+ }
+
uint32_t CStateSignalSlot::getAvailableSignalQueueEntriesInternal()
{
std::lock_guard lockGuard(m_Mutex);
@@ -405,23 +419,26 @@ namespace AMC {
}
pMessage = std::make_shared(sNormalizedUUID, nReactionTimeoutInMS, m_pQueueTelemetryChannel, m_pProcessingTelemetryChannel, m_pAcknowledgementTelemetryChannel);
- m_Queue.push_back(pMessage);
- m_QueueMap.insert(std::make_pair(sNormalizedUUID, std::prev(m_Queue.end())));
- m_MessageMap.insert(std::make_pair(sNormalizedUUID, pMessage));
+ pMessage->setParameterDataJSON(sParameterData);
+
+ // should be outside the lock, but we need to make sure that registration and addition are atomic
+ try {
+ m_pRegistry->registerMessage(sNormalizedUUID, this);
+ }
+ catch (...) {
+ eraseMessage(sNormalizedUUID);
+ throw;
+ };
increaseTriggerCount();
+ m_MessageMap.insert(std::make_pair(sNormalizedUUID, pMessage));
- pMessage->setParameterDataJSON(sParameterData);
- }
+ // Adding to queue will start the signal processing
+ m_Queue.push_back(pMessage);
+ m_QueueMap.insert(std::make_pair(sNormalizedUUID, std::prev(m_Queue.end())));
- // needs to be outside lock
- try {
- m_pRegistry->registerMessage(sNormalizedUUID, this);
+
}
- catch (...) {
- eraseMessage(sNormalizedUUID);
- throw;
- };
return pMessage;
}
@@ -542,6 +559,9 @@ namespace AMC {
}
if (bToArchive) {
+
+ increaseArchivedCount();
+
pMessage->setPhase(eAMCSignalPhase::Archived);
m_MessagesToArchive.push_back(pMessage);
m_MessageMap.erase(iMessageIter);
@@ -684,6 +704,7 @@ namespace AMC {
}
if (nGlobalTimestamp >= nArchiveTimestamp) {
+ increaseArchivedCount();
messagesToArchive.push_back(it.first);
}
}
@@ -697,8 +718,6 @@ namespace AMC {
void CStateSignalSlot::writeMessagesToArchive(CStateSignalArchiveWriter* pArchiveWriter)
{
- if (pArchiveWriter == nullptr)
- throw ELibMCCustomException(LIBMC_ERROR_INVALIDPARAM, "writeMessagesToArchive: Archive writer is null");
std::deque messagesToArchive;
{
@@ -706,14 +725,19 @@ namespace AMC {
messagesToArchive.swap (m_MessagesToArchive);
}
- for (auto pMessage : messagesToArchive) {
- pArchiveWriter->writeSignalMessageToArchive (m_sInstanceName, m_sName, pMessage.get ());
+ if (pArchiveWriter != nullptr) {
+ // If Archive Writer is null, we just clear the archive queue
+
+ for (auto pMessage : messagesToArchive) {
+ pArchiveWriter->writeSignalMessageToArchive(m_sInstanceName, m_sName, pMessage.get());
+ }
+
}
}
- PStateSignalMessage CStateSignalSlot::claimMessageFromQueueInternal(bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp)
+ PStateSignalMessage CStateSignalSlot::claimMessageFromQueueInternal(bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp, bool bChangePhaseToInprocess)
{
(void)nTimeStamp;
std::lock_guard lockGuard(m_Mutex);
@@ -728,13 +752,18 @@ namespace AMC {
auto pMessage = m_Queue.front();
std::string sUUID = pMessage->getUUID();
- m_Queue.pop_front();
- m_QueueMap.erase(sUUID);
+ if (bChangePhaseToInprocess) {
- pMessage->setPhase(eAMCSignalPhase::InProcess);
- m_InProcess.insert(sUUID);
+ // Change the phase to Inprocess in an atomic way
+ m_Queue.pop_front();
+ m_QueueMap.erase(sUUID);
- updateTimingStatistics();
+ pMessage->setPhase(eAMCSignalPhase::InProcess);
+ m_InProcess.insert(sUUID);
+
+ updateTimingStatistics();
+
+ }
return pMessage;
}
diff --git a/Implementation/Core/amc_statesignal.hpp b/Implementation/Core/amc_statesignal.hpp
index 836ea4cfa..5900269b8 100644
--- a/Implementation/Core/amc_statesignal.hpp
+++ b/Implementation/Core/amc_statesignal.hpp
@@ -91,6 +91,9 @@ namespace AMC {
std::string m_sErrorMessage;
+ uint64_t m_nCreationTimestamp;
+ uint64_t m_nTerminalTimestamp;
+
AMC::PTelemetryMarker m_pTelemetryInQueueMarker;
AMC::PTelemetryMarker m_pTelemetryInProcessMarker;
AMC::PTelemetryMarker m_pTelemetryAcknowledgedMarker;
@@ -164,6 +167,7 @@ namespace AMC {
uint64_t m_nHandledCount;
uint64_t m_nFailedCount;
uint64_t m_nTimedOutCount;
+ uint64_t m_nArchivedCount;
uint64_t m_nMaxReactionTime;
PTelemetryChannel m_pQueueTelemetryChannel;
@@ -174,6 +178,7 @@ namespace AMC {
void increaseHandledCount();
void increaseFailedCount();
void increaseTimeoutCount();
+ void increaseArchivedCount();
void updateTimingStatistics();
PParameterGroup m_pSignalInformationGroup;
@@ -199,6 +204,7 @@ namespace AMC {
std::string getSignalTelemetryAcknowledgementIdentifier() const;
bool queueIsFull();
+ bool queueIsEmpty();
size_t clearQueueInternal();
bool eraseMessage(const std::string& sUUID);
@@ -223,7 +229,7 @@ namespace AMC {
void writeMessagesToArchive (CStateSignalArchiveWriter * pArchiveWriter);
- PStateSignalMessage claimMessageFromQueueInternal(bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp);
+ PStateSignalMessage claimMessageFromQueueInternal(bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp, bool bChangePhaseToInprocess);
std::string getResultDataJSONInternal(const std::string& sMessageUUID);
std::string getParameterDataJSONInternal(const std::string& sMessageUUID);
diff --git a/Implementation/Core/amc_statesignalhandler.cpp b/Implementation/Core/amc_statesignalhandler.cpp
index 1620b9e6d..685958a9d 100644
--- a/Implementation/Core/amc_statesignalhandler.cpp
+++ b/Implementation/Core/amc_statesignalhandler.cpp
@@ -166,12 +166,19 @@ namespace AMC {
return !pSlot->queueIsFull();
}
+ bool CStateSignalInstance::queueIsEmpty(const std::string& sSignalName)
+ {
+ AMC::PStateSignalSlot pSlot = getSignalSlot(sSignalName);
+ return pSlot->queueIsEmpty();
+ }
+
+
- bool CStateSignalInstance::claimSignalMessage(const std::string& sSignalName, bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp, std::string& sSignalUUID, std::string& sParameterDataJSON)
+ bool CStateSignalInstance::claimSignalMessage(const std::string& sSignalName, bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp, std::string& sSignalUUID, std::string& sParameterDataJSON, bool bChangePhaseToInprocess)
{
AMC::PStateSignalSlot pSlot = getSignalSlot(sSignalName);
- auto pMessage = pSlot->claimMessageFromQueueInternal(bCheckForReactionTimeout, nGlobalTimestamp, nTimeStamp);
+ auto pMessage = pSlot->claimMessageFromQueueInternal(bCheckForReactionTimeout, nGlobalTimestamp, nTimeStamp, bChangePhaseToInprocess);
if (pMessage.get() == nullptr)
return false;
diff --git a/Implementation/Core/amc_statesignalhandler.hpp b/Implementation/Core/amc_statesignalhandler.hpp
index 863730419..6c50ad460 100644
--- a/Implementation/Core/amc_statesignalhandler.hpp
+++ b/Implementation/Core/amc_statesignalhandler.hpp
@@ -89,9 +89,11 @@ namespace AMC {
bool canTrigger(const std::string& sSignalName);
+ bool queueIsEmpty(const std::string& sSignalName);
+
bool hasSignalDefinition(const std::string& sSignalName);
- bool claimSignalMessage(const std::string& sSignalName, bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp, std::string& sSignalUUID, std::string& sParameterDataJSON);
+ bool claimSignalMessage(const std::string& sSignalName, bool bCheckForReactionTimeout, uint64_t nGlobalTimestamp, uint64_t nTimeStamp, std::string& sSignalUUID, std::string& sParameterDataJSON, bool bChangePhaseToInprocess);
bool addNewInQueueSignal(const std::string& sSignalName, const std::string& sSignalUUID, const std::string& sParameterData, uint32_t nResponseTimeOutInMS, uint64_t nTimestamp);
diff --git a/Implementation/Core/amc_telemetry.cpp b/Implementation/Core/amc_telemetry.cpp
index fd4ebc2f6..0f40daaf0 100644
--- a/Implementation/Core/amc_telemetry.cpp
+++ b/Implementation/Core/amc_telemetry.cpp
@@ -36,15 +36,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "libmcdata_dynamic.hpp"
+#define TELEMETRY_DEFAULT_CHUNKINTERVAL_MICROSECONDS 60000000 // 60 seconds
+#define TELEMETRY_ONEHOURINMICROSECONDS 3600000000ULL
+
namespace AMC {
- CTelemetryDataChunk::CTelemetryDataChunk(CTelemetryWriter* pWriter, uint32_t nChunkID)
+ CTelemetryDataChunk::CTelemetryDataChunk(CTelemetryWriter* pWriter, uint64_t nChunkID, uint64_t nChunkStartTimestamp, uint64_t nChunkEndTimestamp)
: m_nTelemetryChunkID(nChunkID), m_nMinTimestamp(0), m_nMaxTimestamp(0), m_nMinMarkerID(0), m_nMaxMarkerID(0),
- m_pWriter(pWriter)
+ m_pWriter(pWriter), m_nChunkStartTimestamp(nChunkStartTimestamp), m_nChunkEndTimestamp(nChunkEndTimestamp), m_bChunkIsReadonly (false), m_bChunkHasBeenArchived (false)
{
if (pWriter == nullptr)
throw ELibMCInterfaceException(LIBMC_ERROR_INVALIDPARAM);
+ if (nChunkStartTimestamp >= nChunkEndTimestamp)
+ throw ELibMCInterfaceException(LIBMC_ERROR_TELEMETRYCHUNKSTARTTIMESTAMPAFTEREND);
+
}
CTelemetryDataChunk::~CTelemetryDataChunk()
@@ -52,6 +58,11 @@ namespace AMC {
}
+ uint64_t CTelemetryDataChunk::getChunkID() const
+ {
+ return m_nTelemetryChunkID;
+ }
+
bool CTelemetryDataChunk::isEmpty() const
{
std::lock_guard lock(m_ChunkMutex);
@@ -59,58 +70,120 @@ namespace AMC {
return m_Entries.empty();
}
- void CTelemetryDataChunk::writeEntry(const sTelemetryChunkEntry& entry)
+ void CTelemetryDataChunk::writeEntry(const LibMCData::sTelemetryChunkEntry& entry)
{
uint32_t nEntryIndex;
{
std::lock_guard lock(m_ChunkMutex);
+ if (m_bChunkIsReadonly)
+ throw ELibMCCustomException(LIBMC_ERROR_TELEMETRYCHUNKISREADONLY, std::to_string(m_nTelemetryChunkID));
+
m_Entries.emplace_back(entry);
// entry index shall be one-based
nEntryIndex = static_cast (m_Entries.size());
if (nEntryIndex == 1) {
- m_nMinMarkerID = entry.m_nMarkerID;
- m_nMaxMarkerID = entry.m_nMarkerID;
- m_nMinTimestamp = entry.m_nTimestamp;
- m_nMaxTimestamp = entry.m_nTimestamp;
+ m_nMinMarkerID = entry.m_MarkerID;
+ m_nMaxMarkerID = entry.m_MarkerID;
+ m_nMinTimestamp = entry.m_TimeStamp;
+ m_nMaxTimestamp = entry.m_TimeStamp;
}
else {
- if (entry.m_nMarkerID < m_nMinMarkerID)
- m_nMinMarkerID = entry.m_nMarkerID;
- if (entry.m_nMarkerID > m_nMaxMarkerID)
- m_nMaxMarkerID = entry.m_nMarkerID;
- if (entry.m_nTimestamp < m_nMinTimestamp)
- m_nMinTimestamp = entry.m_nTimestamp;
- if (entry.m_nTimestamp > m_nMaxTimestamp)
- m_nMaxTimestamp = entry.m_nTimestamp;
+ if (entry.m_MarkerID < m_nMinMarkerID)
+ m_nMinMarkerID = entry.m_MarkerID;
+ if (entry.m_MarkerID > m_nMaxMarkerID)
+ m_nMaxMarkerID = entry.m_MarkerID;
+ if (entry.m_TimeStamp < m_nMinTimestamp)
+ m_nMinTimestamp = entry.m_TimeStamp;
+ if (entry.m_TimeStamp > m_nMaxTimestamp)
+ m_nMaxTimestamp = entry.m_TimeStamp;
}
}
- if (entry.m_EntryType == eTelemetryChunkEntryType::IntervalStartMarker) {
- m_pWriter->registerOpenInterval (entry.m_nMarkerID, m_nTelemetryChunkID, nEntryIndex);
+ if (entry.m_EntryType == LibMCData::eTelemetryChunkEntryType::IntervalStartMarker) {
+ m_pWriter->registerOpenInterval (entry.m_MarkerID, m_nTelemetryChunkID, nEntryIndex);
}
- else if (entry.m_EntryType == eTelemetryChunkEntryType::IntervalEndMarker) {
- m_pWriter->eraseOpenInterval(entry.m_nMarkerID);
+ else if (entry.m_EntryType == LibMCData::eTelemetryChunkEntryType::IntervalEndMarker) {
+ m_pWriter->eraseOpenInterval(entry.m_MarkerID);
}
}
+ void CTelemetryDataChunk::makeReadOnly()
+ {
+ std::lock_guard lock(m_ChunkMutex);
+ m_bChunkIsReadonly = true;
+ }
+
+ bool CTelemetryDataChunk::isReadOnly() const
+ {
+ std::lock_guard lock(m_ChunkMutex);
+ return m_bChunkIsReadonly;
+ }
+
+ bool CTelemetryDataChunk::hasBeenArchived() const
+ {
+ std::lock_guard lock(m_ChunkMutex);
+ return m_bChunkHasBeenArchived;
+ }
+
+ void CTelemetryDataChunk::writeToArchive(LibMCData::PTelemetrySession pTelemetrySession)
+ {
+ if (pTelemetrySession.get() == nullptr)
+ throw ELibMCInterfaceException(LIBMC_ERROR_INVALIDPARAM);
+
+ std::vector chunkEntries;
+ uint64_t nChunkStartTimestamp;
+ uint64_t nChunkEndTimestamp;
+
+ {
+ std::lock_guard lock(m_ChunkMutex);
+ if (!m_bChunkIsReadonly)
+ throw ELibMCCustomException(LIBMC_ERROR_TELEMETRYCHUNKSCANONLYBEARCHIVEDIFREADONLY, std::to_string(m_nTelemetryChunkID));
+
+ if (m_bChunkHasBeenArchived)
+ return;
+
+ chunkEntries.swap(m_Entries);
+
+ nChunkStartTimestamp = m_nChunkStartTimestamp;
+ nChunkEndTimestamp = m_nChunkEndTimestamp;
+ m_bChunkHasBeenArchived = true;
+ }
+
+ try {
+ pTelemetrySession->WriteTelemetryChunk(nChunkStartTimestamp, nChunkEndTimestamp, chunkEntries);
+ }
+ catch (...) {
+ // Restore entries on failure
+ std::lock_guard lock(m_ChunkMutex);
+ chunkEntries.swap(m_Entries);
+ m_bChunkHasBeenArchived = false;
+
+ // Propagate exception to archiving routine
+ throw;
+ }
+
+
+
+ }
CTelemetryWriter::CTelemetryWriter(LibMCData::PTelemetrySession pTelemetrySession, AMCCommon::PChrono pGlobalChrono)
- : m_nNextChunkIndex(1), m_pTelemetrySession(pTelemetrySession), m_nNextMarkerID(1), m_pGlobalChrono (pGlobalChrono)
+ : m_pTelemetrySession(pTelemetrySession), m_nNextMarkerID(1), m_pGlobalChrono (pGlobalChrono),
+ m_nChunkIntervalInMicroseconds (TELEMETRY_DEFAULT_CHUNKINTERVAL_MICROSECONDS)
{
if (pGlobalChrono.get () == nullptr)
throw ELibMCInterfaceException(LIBMC_ERROR_INVALIDPARAM);
if (pTelemetrySession.get() == nullptr)
throw ELibMCInterfaceException(LIBMC_ERROR_INVALIDPARAM);
- createNewChunk();
+ extendChunksUntil(1);
}
CTelemetryWriter::~CTelemetryWriter()
@@ -118,26 +191,61 @@ namespace AMC {
}
- PTelemetryDataChunk CTelemetryWriter::getCurrentChunk()
+ PTelemetryDataChunk CTelemetryWriter::getOrCreateChunkByTimestamp(uint64_t nTimestamp)
{
+
+ uint64_t nChunkIndexZeroBased = nTimestamp / m_nChunkIntervalInMicroseconds;
+ uint64_t nChunkIndexOneBased = nChunkIndexZeroBased + 1;
+
+ // Telemetry chunk IDs are one-based
+ // telemetry session is per-process-lifetime, and
+ // the DB schema expects chunk ranges per session
+ extendChunksUntil(nChunkIndexOneBased);
+
std::lock_guard lock(m_ChunkMutex);
- return m_pCurrentChunk;
+
+ // Telemetry array is zero-based
+ auto pChunk = m_Chunks.at (nChunkIndexZeroBased);
+
+ if (pChunk->getChunkID() != nChunkIndexOneBased)
+ throw ELibMCCustomException(LIBMC_ERROR_TELEMETRYCHUNKIDMISMATCH, std::to_string (pChunk->getChunkID()) + " != " + std::to_string (nChunkIndexOneBased));
+
+ return pChunk;
+
}
- PTelemetryDataChunk CTelemetryWriter::createNewChunk()
+ void CTelemetryWriter::extendChunksUntil(uint64_t nMaxChunkIndexOneBased)
{
- std::lock_guard lock(m_ChunkMutex);
- auto pChunk = std::make_shared (this, m_nNextChunkIndex);
- m_nNextChunkIndex++;
- m_Chunks.emplace_back(pChunk);
- m_pCurrentChunk = pChunk;
+ // Reasonable max chunk index based on current time is maximum an hour in the future!
+ uint64_t nReasonableMaxChunkIndex = ((m_pGlobalChrono->getElapsedMicroseconds() + TELEMETRY_ONEHOURINMICROSECONDS) / m_nChunkIntervalInMicroseconds) + 1;
+ if (nMaxChunkIndexOneBased > nReasonableMaxChunkIndex)
+ throw ELibMCCustomException(LIBMC_ERROR_TELEMETRYCHUNKINDEXOUTOFRANGE, std::to_string(nMaxChunkIndexOneBased));
- return pChunk;
+ std::lock_guard lock(m_ChunkMutex);
+ for (uint64_t nZeroBasedIndexToAdd = m_Chunks.size(); nZeroBasedIndexToAdd < nMaxChunkIndexOneBased; nZeroBasedIndexToAdd++) {
+ uint64_t nChunkStartTimestamp = nZeroBasedIndexToAdd * m_nChunkIntervalInMicroseconds;
+ uint64_t nChunkEndTimestamp = nChunkStartTimestamp + m_nChunkIntervalInMicroseconds - 1;
+
+ uint64_t nOneBasedChunkIndex = nZeroBasedIndexToAdd + 1;
+
+ auto pChunk = std::make_shared(this, nOneBasedChunkIndex, nChunkStartTimestamp, nChunkEndTimestamp);
+ m_Chunks.emplace_back(pChunk);
+
+ // We make all chunks read-only except for the last two chunks (which might get some writing due to timing race conditions)
+ if (nZeroBasedIndexToAdd >= 2) {
+ uint64_t nZeroBasedMakeReadonly = nZeroBasedIndexToAdd - 2;
+ auto pChunkToMakeReadonly = m_Chunks.at(nZeroBasedMakeReadonly);
+ pChunkToMakeReadonly->makeReadOnly();
+
+ std::lock_guard archiveLock(m_ArchiveQueueMutex);
+ m_ArchiveQueue.push (pChunkToMakeReadonly);
+ }
+ }
}
- void CTelemetryWriter::writeEntry(const sTelemetryChunkEntry& entry)
+ void CTelemetryWriter::writeEntry(const LibMCData::sTelemetryChunkEntry& entry)
{
- auto pChunk = getCurrentChunk();
+ auto pChunk = getOrCreateChunkByTimestamp(entry.m_TimeStamp);
pChunk->writeEntry(entry);
}
@@ -166,6 +274,32 @@ namespace AMC {
m_pTelemetrySession->CreateChannelInDB (sUUID, channelType, nChannelIndex, sChannelIdentifier, sChannelDescription);
}
+ void CTelemetryWriter::archiveOldChunksToDB()
+ {
+
+ bool bIsEmpty = false;
+ while (!bIsEmpty) {
+
+ PTelemetryDataChunk pChunkToArchive;
+ {
+ std::lock_guard archiveLock(m_ArchiveQueueMutex);
+ bIsEmpty = m_ArchiveQueue.empty ();
+ if (bIsEmpty)
+ break;
+
+ pChunkToArchive = m_ArchiveQueue.front();
+ m_ArchiveQueue.pop();
+ }
+
+ {
+ std::lock_guard lock(m_DataMutex);
+ pChunkToArchive->writeToArchive(m_pTelemetrySession);
+ }
+ }
+
+ }
+
+
uint64_t CTelemetryWriter::createMarkerID()
{
return m_nNextMarkerID.fetch_add(1, std::memory_order_relaxed);
@@ -191,10 +325,10 @@ namespace AMC {
if (bMarkInstant) {
m_nFinishTimestamp = m_nStartTimestamp;
- pWriter->writeEntry({ eTelemetryChunkEntryType::InstantMarker, nChannelIndex, m_nMarkerID, m_nStartTimestamp, m_nContextData });
+ pWriter->writeEntry({ LibMCData::eTelemetryChunkEntryType::InstantMarker, nChannelIndex, m_nMarkerID, m_nStartTimestamp, m_nContextData });
}
else {
- pWriter->writeEntry({ eTelemetryChunkEntryType::IntervalStartMarker, nChannelIndex, m_nMarkerID, m_nStartTimestamp, m_nContextData });
+ pWriter->writeEntry({ LibMCData::eTelemetryChunkEntryType::IntervalStartMarker, nChannelIndex, m_nMarkerID, m_nStartTimestamp, m_nContextData });
}
@@ -235,7 +369,7 @@ namespace AMC {
pLockedChannel->getChannelIdentifier() + " / " + std::to_string(m_nMarkerID));
}
- pWriter->writeEntry({ eTelemetryChunkEntryType::IntervalEndMarker, nChannelIndex, m_nMarkerID, nTimestamp, m_nContextData });
+ pWriter->writeEntry({ LibMCData::eTelemetryChunkEntryType::IntervalEndMarker, nChannelIndex, m_nMarkerID, nTimestamp, m_nContextData });
uint64_t nDuration = nTimestamp - m_nStartTimestamp;
pLockedChannel->unregisterMarker(m_nMarkerID, nDuration);
@@ -509,6 +643,10 @@ namespace AMC {
}
+ void CTelemetryHandler::archiveOldChunksToDB()
+ {
+ m_pTelemetryWriter->archiveOldChunksToDB();
+ }
}
diff --git a/Implementation/Core/amc_telemetry.hpp b/Implementation/Core/amc_telemetry.hpp
index 017ddaf1d..a1df48113 100644
--- a/Implementation/Core/amc_telemetry.hpp
+++ b/Implementation/Core/amc_telemetry.hpp
@@ -55,20 +55,6 @@ namespace AMC {
class CTelemetryWriter;
- enum class eTelemetryChunkEntryType : uint32_t {
- InstantMarker = 1,
- IntervalStartMarker = 2,
- IntervalEndMarker = 3
- };
-
- struct sTelemetryChunkEntry {
- eTelemetryChunkEntryType m_EntryType;
- uint32_t m_nChannelIndex;
- uint64_t m_nMarkerID;
- uint64_t m_nTimestamp;
- uint64_t m_nContextData;
- };
-
struct sTelemetryOpenIntervalMarker {
uint32_t m_nChunkID;
uint32_t m_nEntryIndex;
@@ -78,26 +64,43 @@ namespace AMC {
private:
CTelemetryWriter* m_pWriter;
- uint64_t m_nMinTimestamp;
- uint64_t m_nMaxTimestamp;
+ uint64_t m_nChunkStartTimestamp;
+ uint64_t m_nChunkEndTimestamp;
+
+ uint64_t m_nMinTimestamp; // Should be within chunk time interval
+ uint64_t m_nMaxTimestamp; // Should be within chunk time interval
uint64_t m_nMinMarkerID;
uint64_t m_nMaxMarkerID;
- uint32_t m_nTelemetryChunkID;
+ uint64_t m_nTelemetryChunkID;
+
+ std::vector m_Entries;
+
+ bool m_bChunkIsReadonly;
- std::vector m_Entries;
+ bool m_bChunkHasBeenArchived;
mutable std::mutex m_ChunkMutex;
public:
- CTelemetryDataChunk (CTelemetryWriter* pWriter, uint32_t nChunkID);
+ CTelemetryDataChunk (CTelemetryWriter* pWriter, uint64_t nTelemetryChunkID, uint64_t nChunkStartTimestamp, uint64_t nChunkEndTimestamp);
virtual ~CTelemetryDataChunk();
+ uint64_t getChunkID() const;
+
bool isEmpty() const;
- void writeEntry(const sTelemetryChunkEntry& entry);
+ void writeEntry(const LibMCData::sTelemetryChunkEntry& entry);
+
+ void makeReadOnly();
+
+ bool isReadOnly() const;
+
+ bool hasBeenArchived() const;
+
+ void writeToArchive(LibMCData::PTelemetrySession pTelemetrySession);
};
@@ -107,9 +110,12 @@ namespace AMC {
{
private:
std::mutex m_ChunkMutex;
- std::deque m_Chunks;
- uint32_t m_nNextChunkIndex;
- PTelemetryDataChunk m_pCurrentChunk;
+ std::vector m_Chunks;
+
+ std::mutex m_ArchiveQueueMutex;
+ std::queue m_ArchiveQueue;
+
+ uint64_t m_nChunkIntervalInMicroseconds;
std::mutex m_OpenIntervalMutex;
std::unordered_map m_OpenIntervalMarkers;
@@ -121,17 +127,17 @@ namespace AMC {
std::atomic m_nNextMarkerID;
+ void extendChunksUntil(uint64_t nMaxChunkIndexOneBased);
+
public:
CTelemetryWriter(LibMCData::PTelemetrySession pTelemetrySession, AMCCommon::PChrono pGlobalChrono);
virtual ~CTelemetryWriter();
- PTelemetryDataChunk getCurrentChunk();
-
- PTelemetryDataChunk createNewChunk();
+ PTelemetryDataChunk getOrCreateChunkByTimestamp(uint64_t nTimestamp);
- void writeEntry(const sTelemetryChunkEntry& entry);
+ void writeEntry(const LibMCData::sTelemetryChunkEntry& entry);
void registerOpenInterval (uint64_t nMarkerID, uint32_t nChunkID, uint32_t nChunkEntryIndex);
@@ -139,6 +145,8 @@ namespace AMC {
void createChannelInDB(const std::string & sUUID, LibMCData::eTelemetryChannelType channelType, uint32_t nChannelIndex, const std::string & sChannelIdentifier, const std::string & sChannelDescription);
+ void archiveOldChunksToDB();
+
uint64_t createMarkerID();
uint64_t getCurrentTimestamp();
@@ -287,6 +295,8 @@ namespace AMC {
PTelemetryChannel findChannelByIdentifier(const std::string& sChannelIdentifier, bool bFailIfNotExisting);
+ void archiveOldChunksToDB();
+
};
diff --git a/Implementation/DataModel/amcdata_journal.cpp b/Implementation/DataModel/amcdata_journal.cpp
index f5a975273..e00a9b7cd 100644
--- a/Implementation/DataModel/amcdata_journal.cpp
+++ b/Implementation/DataModel/amcdata_journal.cpp
@@ -151,10 +151,25 @@ namespace AMCData {
return m_nTotalSize;
}
- CJournal::CJournal(const std::string& sJournalBasePath, const std::string& sJournalName, const std::string& sJournalChunkBaseName, const std::string& sSessionUUID)
+ CJournal::CJournal(const std::string& sJournalBasePath, const std::string& sJournalName, const std::string& sJournalChunkBaseName, const std::string& sTelemetryChunkBaseName, const std::string& sSessionUUID)
: m_LogID(1), m_AlertID(1), m_sSessionUUID(AMCCommon::CUtils::normalizeUUIDString(sSessionUUID)),
- m_sJournalBasePath(sJournalBasePath), m_sChunkBaseName (sJournalChunkBaseName)
+ m_sJournalBasePath(sJournalBasePath), m_sChunkBaseName (sJournalChunkBaseName),
+ m_TelemetryChunkID (1)
{
+ if (!sTelemetryChunkBaseName.empty()) {
+ m_sTelemetryChunkBaseName = sTelemetryChunkBaseName;
+ }
+ else {
+ m_sTelemetryChunkBaseName = m_sChunkBaseName;
+ const std::string sJournalPrefix = "journal_";
+ const std::string sTelemetryPrefix = "telemetry_";
+ if (m_sTelemetryChunkBaseName.rfind(sJournalPrefix, 0) == 0) {
+ m_sTelemetryChunkBaseName.replace(0, sJournalPrefix.size(), sTelemetryPrefix);
+ }
+ else {
+ m_sTelemetryChunkBaseName = sTelemetryPrefix + m_sTelemetryChunkBaseName;
+ }
+ }
m_pSQLHandler = std::make_shared(m_sJournalBasePath + sJournalName);
@@ -268,6 +283,7 @@ namespace AMCData {
pTelemetryChunkStatement = nullptr;
m_pCurrentJournalFile = createJournalFile();
+ m_pCurrentTelemetryFile = createTelemetryFile();
}
@@ -300,6 +316,30 @@ namespace AMCData {
return pJournalFile;
}
+ PActiveJournalFile CJournal::createTelemetryFile()
+ {
+ uint32_t nFileIndex = (uint32_t)m_TelemetryFiles.size();
+ if (nFileIndex > JOURNAL_MAXFILESPERSESSION)
+ throw ELibMCDataInterfaceException(LIBMCDATA_ERROR_JOURNALEXCEEDSMAXIMUMFILES);
+
+ std::stringstream sFileNameStream;
+ sFileNameStream << m_sTelemetryChunkBaseName << std::setw(JOURNAL_MAXFILEDIGITS) << std::setfill('0') << nFileIndex << ".data";
+
+ std::string sFileName = sFileNameStream.str();
+
+ std::string sQuery = "INSERT INTO telemetry_datafiles (fileindex, filename) VALUES (?, ?)";
+ auto pStatement = m_pSQLHandler->prepareStatement(sQuery);
+ pStatement->setInt(1, nFileIndex);
+ pStatement->setString(2, sFileName);
+ pStatement->execute();
+ pStatement = nullptr;
+
+ auto pTelemetryFile = std::make_shared(m_sJournalBasePath + sFileName, nFileIndex);
+ m_TelemetryFiles.push_back(pTelemetryFile);
+
+ return pTelemetryFile;
+ }
+
std::string CJournal::getSessionUUID()
{
return m_sSessionUUID;
@@ -926,26 +966,36 @@ namespace AMCData {
{
std::lock_guard lockGuard(m_JournalMutex);
- uint32_t nChunkIndex = 0;
- uint32_t nFileIndex = 0;
- uint32_t nDataOffset = 0;
- uint32_t nDataLength = 0;
+ if (nTelemetryEntriesBufferSize == 0)
+ return;
+ if (pTelemetryEntriesBuffer == nullptr)
+ throw ELibMCDataInterfaceException(LIBMCDATA_ERROR_INVALIDPARAM);
+ if (nStartTimeStamp > nEndTimeStamp)
+ throw ELibMCDataInterfaceException(LIBMCDATA_ERROR_INVALIDPARAM);
+
+ if (m_pCurrentTelemetryFile->getTotalSize() > getMaxChunkFileSizeQuotaInBytes())
+ m_pCurrentTelemetryFile = createTelemetryFile();
+
+ uint64_t nDataLength = nTelemetryEntriesBufferSize * sizeof(LibMCData::sTelemetryChunkEntry);
+ uint64_t nDataOffset = m_pCurrentTelemetryFile->retrieveWritePosition();
+ m_pCurrentTelemetryFile->writeBuffer(pTelemetryEntriesBuffer, nDataLength);
+ m_pCurrentTelemetryFile->flushBuffers();
+
+ uint32_t nChunkIndex = m_TelemetryChunkID.fetch_add(1, std::memory_order_relaxed);
- std::string sQuery = "INSERT INTO telemetry_chunks (chunkindex, fileindex, starttimestamp, endtimestamp, entrycount, dataoffset, datalength) VALUES (?, ?, ?, ?, ?)";
+ std::string sQuery = "INSERT INTO telemetry_chunks (chunkindex, fileindex, starttimestamp, endtimestamp, entrycount, dataoffset, datalength) VALUES (?, ?, ?, ?, ?, ?, ?)";
auto pStatement = m_pSQLHandler->prepareStatement(sQuery);
pStatement->setInt64(1, nChunkIndex);
- pStatement->setInt64(2, nFileIndex);
+ pStatement->setInt64(2, m_pCurrentTelemetryFile->getFileIndex());
pStatement->setInt64(3, (int64_t)nStartTimeStamp);
pStatement->setInt64(4, (int64_t)nEndTimeStamp);
- pStatement->setInt64(5, (int64_t) nTelemetryEntriesBufferSize);
+ pStatement->setInt64(5, (int64_t)nTelemetryEntriesBufferSize);
pStatement->setInt64(6, (int64_t)nDataOffset);
pStatement->setInt64(7, (int64_t)nDataLength);
pStatement->execute();
- pStatement = nullptr;
+ pStatement = nullptr;
}
}
-
-
diff --git a/Implementation/DataModel/amcdata_journal.hpp b/Implementation/DataModel/amcdata_journal.hpp
index 04d9997df..c42393ce7 100644
--- a/Implementation/DataModel/amcdata_journal.hpp
+++ b/Implementation/DataModel/amcdata_journal.hpp
@@ -91,6 +91,7 @@ namespace AMCData {
std::string m_sJournalBasePath;
std::string m_sChunkBaseName;
+ std::string m_sTelemetryChunkBaseName;
std::vector m_JournalFiles;
@@ -98,13 +99,21 @@ namespace AMCData {
PActiveJournalFile createJournalFile();
+ std::vector m_TelemetryFiles;
+
+ PActiveJournalFile m_pCurrentTelemetryFile;
+
+ std::atomic m_TelemetryChunkID;
+
+ PActiveJournalFile createTelemetryFile();
+
public:
static std::string convertAlertLevelToString(const LibMCData::eAlertLevel eLevel);
static LibMCData::eAlertLevel convertStringToAlertLevel(const std::string & sValue, bool bFailIfUnknown);
- CJournal(const std::string& sJournalBasePath, const std::string& sJournalName, const std::string& sJournalChunkBaseName, const std::string & sSessionUUID);
+ CJournal(const std::string& sJournalBasePath, const std::string& sJournalName, const std::string& sJournalChunkBaseName, const std::string& sTelemetryChunkBaseName, const std::string & sSessionUUID);
virtual ~CJournal();
@@ -175,4 +184,3 @@ namespace AMCData {
#endif //__AMCDATA_JOURNAL
-
diff --git a/Implementation/LibMC/libmc_mccontext.cpp b/Implementation/LibMC/libmc_mccontext.cpp
index f123b345a..4a9b657c1 100644
--- a/Implementation/LibMC/libmc_mccontext.cpp
+++ b/Implementation/LibMC/libmc_mccontext.cpp
@@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "amc_statemachineinstance.hpp"
#include "amc_logger.hpp"
#include "amc_alerthandler.hpp"
+#include "amc_telemetry.hpp"
#include "amc_parameterhandler.hpp"
#include "amc_statemachinedata.hpp"
#include "amc_logger_multi.hpp"
@@ -951,10 +952,19 @@ void CMCContext::executeSystemThread()
while (!systemThreadShallTerminate()) {
- uint64_t nGlobalTimestamp = m_pSystemState->globalChrono()->getElapsedMicroseconds();
- m_pSystemState->stateSignalHandler()->checkForReactionTimeouts(nGlobalTimestamp);
+
+ auto pSignalHandler = m_pSystemState->getStateSignalHandlerInstance();
+ pSignalHandler->checkForReactionTimeouts(m_pSystemState->globalChrono()->getElapsedMicroseconds());
+ pSignalHandler->autoArchiveMessages(m_pSystemState->globalChrono()->getElapsedMicroseconds());
+ pSignalHandler->writeMessagesToArchive(nullptr);
+
+ auto pTelemetryHandler = m_pSystemState->getTelemetryHandlerInstance();
+ pTelemetryHandler->archiveOldChunksToDB();
+
m_pSystemState->updateMemoryUsageParameters();
+
+
}
}
catch (std::exception & E)
diff --git a/Implementation/LibMCData/libmcdata_datamodel.cpp b/Implementation/LibMCData/libmcdata_datamodel.cpp
index 860c75caf..76febedcb 100644
--- a/Implementation/LibMCData/libmcdata_datamodel.cpp
+++ b/Implementation/LibMCData/libmcdata_datamodel.cpp
@@ -144,8 +144,9 @@ void CDataModel::InitialiseDatabase(const std::string & sDataDirectory, const Li
auto sJournalBasePath = m_pStorageState->getJournalBasePath(m_sTimeFileName);
auto sJournalName = m_pStorageState->getJournalFileName(m_sTimeFileName);
auto sJournalChunkBaseName = m_pStorageState->getJournalChunkBaseName(m_sTimeFileName);
+ auto sTelemetryChunkBaseName = "telemetry_" + m_sTimeFileName + "_chunk";
- m_pJournal = std::make_shared (sJournalBasePath, sJournalName, sJournalChunkBaseName, m_sSessionUUID);
+ m_pJournal = std::make_shared (sJournalBasePath, sJournalName, sJournalChunkBaseName, sTelemetryChunkBaseName, m_sSessionUUID);
auto pStatement = m_pSQLHandler->prepareStatement("INSERT INTO journals (uuid, starttime, logfilename, journalfilename, logfilepath, journalfilepath, schemaversion, githash) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
pStatement->setString(1, m_sSessionUUID);
diff --git a/Implementation/LibMCData/libmcdata_telemetrysession.cpp b/Implementation/LibMCData/libmcdata_telemetrysession.cpp
index f5eb28d85..6edc63736 100644
--- a/Implementation/LibMCData/libmcdata_telemetrysession.cpp
+++ b/Implementation/LibMCData/libmcdata_telemetrysession.cpp
@@ -67,5 +67,5 @@ void CTelemetrySession::CreateChannelInDB(const std::string & sUUID, const LibMC
void CTelemetrySession::WriteTelemetryChunk(const LibMCData_uint64 nStartTimeStamp, const LibMCData_uint64 nEndTimeStamp, const LibMCData_uint64 nTelemetryEntriesBufferSize, const LibMCData::sTelemetryChunkEntry* pTelemetryEntriesBuffer)
{
-
+ m_pJournal->writeTelemetryChunk(nStartTimeStamp, nEndTimeStamp, nTelemetryEntriesBufferSize, pTelemetryEntriesBuffer);
}
diff --git a/Implementation/LibMCEnv/libmcenv_build.cpp b/Implementation/LibMCEnv/libmcenv_build.cpp
index d7b3dd6dd..2cdab0a6f 100644
--- a/Implementation/LibMCEnv/libmcenv_build.cpp
+++ b/Implementation/LibMCEnv/libmcenv_build.cpp
@@ -81,6 +81,19 @@ CBuild::~CBuild()
{
}
+CBuild* CBuild::makeFrom(CBuild* pBuild)
+{
+ if (pBuild == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM);
+
+ return new CBuild(pBuild->m_pDataModel, pBuild->m_sBuildJobUUID, pBuild->m_pToolpathHandler, pBuild->m_pMeshHandler, pBuild->m_pGlobalChrono, pBuild->m_pStateJournal);
+}
+
+std::shared_ptr CBuild::makeSharedFrom(CBuild* pBuild)
+{
+ return std::shared_ptr(makeFrom(pBuild));
+}
+
std::string CBuild::GetName()
{
auto pBuildJobHandler = m_pDataModel->CreateBuildJobHandler();
@@ -95,6 +108,39 @@ std::string CBuild::GetBuildUUID()
return pBuildJob->GetUUID();
}
+std::string CBuild::GetCreatedTimestamp()
+{
+ auto pBuildJobHandler = m_pDataModel->CreateBuildJobHandler();
+ auto pBuildJob = pBuildJobHandler->RetrieveJob(m_sBuildJobUUID);
+ return pBuildJob->GetTimeStamp();
+}
+
+std::string CBuild::GetLastExecutionTimestamp()
+{
+ auto pBuildJobHandler = m_pDataModel->CreateBuildJobHandler();
+ auto pBuildJob = pBuildJobHandler->RetrieveJob(m_sBuildJobUUID);
+
+ // Find the latest execution timestamp
+ std::string sLatestExecutionTime = "";
+ uint64_t nLatestExecutionMicroseconds = 0;
+
+ auto pJobExecutionIterator = pBuildJob->RetrieveBuildJobExecutions("");
+ while (pJobExecutionIterator->MoveNext()) {
+ auto pJobExecution = pJobExecutionIterator->GetCurrentJobExecution();
+ uint64_t nExecutionTime = pJobExecution->GetStartTimeStampInMicroseconds();
+ if (nExecutionTime > nLatestExecutionMicroseconds) {
+ nLatestExecutionMicroseconds = nExecutionTime;
+ }
+ }
+
+ // Convert to ISO 8601 format if we found any executions
+ if (nLatestExecutionMicroseconds > 0) {
+ sLatestExecutionTime = AMCCommon::CChrono::convertToISO8601TimeUTC(nLatestExecutionMicroseconds);
+ }
+
+ return sLatestExecutionTime;
+}
+
std::string CBuild::GetStorageUUID()
{
auto pBuildJobHandler = m_pDataModel->CreateBuildJobHandler();
diff --git a/Implementation/LibMCEnv/libmcenv_build.hpp b/Implementation/LibMCEnv/libmcenv_build.hpp
index de140f2fb..f793b02d1 100644
--- a/Implementation/LibMCEnv/libmcenv_build.hpp
+++ b/Implementation/LibMCEnv/libmcenv_build.hpp
@@ -73,10 +73,18 @@ class CBuild : public virtual IBuild, public virtual CBase {
virtual ~CBuild();
+ static CBuild* makeFrom (CBuild * pBuild);
+
+ static std::shared_ptr makeSharedFrom(CBuild* pBuild);
+
std::string GetName() override;
std::string GetBuildUUID() override;
+ std::string GetCreatedTimestamp() override;
+
+ std::string GetLastExecutionTimestamp() override;
+
std::string GetStorageUUID() override;
std::string GetStorageSHA256() override;
diff --git a/Implementation/LibMCEnv/libmcenv_builditerator.cpp b/Implementation/LibMCEnv/libmcenv_builditerator.cpp
new file mode 100644
index 000000000..0250eaf70
--- /dev/null
+++ b/Implementation/LibMCEnv/libmcenv_builditerator.cpp
@@ -0,0 +1,97 @@
+/*++
+
+Copyright (C) 2020 Autodesk Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Autodesk Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Abstract: This is a stub class definition of CBuildIterator
+
+*/
+
+#include "libmcenv_builditerator.hpp"
+#include "libmcenv_interfaceexception.hpp"
+
+// Include custom headers here.
+
+
+using namespace LibMCEnv::Impl;
+
+/*************************************************************************************************************************
+ Class definition of CBuildIterator
+**************************************************************************************************************************/
+
+CBuildIterator::CBuildIterator()
+{
+
+}
+
+CBuildIterator::~CBuildIterator()
+{
+
+}
+
+
+IBase* CBuildIterator::GetCurrent()
+{
+ return GetCurrentBuild();
+}
+
+IBuild* CBuildIterator::GetCurrentBuild()
+{
+ if ((m_nCurrentIndex < 0) || (m_nCurrentIndex >= m_List.size()))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDITERATOR);
+
+ auto pBuild = std::dynamic_pointer_cast (m_List[m_nCurrentIndex]);
+ if (pBuild.get() == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+
+ return CBuild::makeFrom(pBuild.get());
+}
+
+
+IIterator* CBuildIterator::Clone()
+{
+ std::unique_ptr pNewIterator(new CBuildIterator());
+
+ for (auto pBase : m_List) {
+ auto pBuild = std::dynamic_pointer_cast (pBase);
+ if (pBuild.get() == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDCAST);
+ pNewIterator->AddBuild(CBuild::makeSharedFrom(pBuild.get()));
+ }
+
+ return pNewIterator.release();
+}
+
+void CBuildIterator::AddBuild(std::shared_ptr pBuild)
+{
+ if (pBuild.get() == nullptr)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM);
+
+ m_List.push_back(pBuild);
+}
+
+
diff --git a/Implementation/LibMCEnv/libmcenv_builditerator.hpp b/Implementation/LibMCEnv/libmcenv_builditerator.hpp
new file mode 100644
index 000000000..a2d8aa903
--- /dev/null
+++ b/Implementation/LibMCEnv/libmcenv_builditerator.hpp
@@ -0,0 +1,82 @@
+/*++
+
+Copyright (C) 2020 Autodesk Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Autodesk Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Abstract: This is the class declaration of CBuildIterator
+
+*/
+
+
+#ifndef __LIBMCENV_BUILDITERATOR
+#define __LIBMCENV_BUILDITERATOR
+
+#include "libmcenv_interfaces.hpp"
+
+// Parent classes
+#include "libmcenv_iterator.hpp"
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4250)
+#endif
+
+// Include custom headers here.
+#include "libmcenv_build.hpp"
+
+
+namespace LibMCEnv {
+namespace Impl {
+
+
+/*************************************************************************************************************************
+ Class declaration of CBuildIterator
+**************************************************************************************************************************/
+
+class CBuildIterator : public virtual IBuildIterator, public virtual CIterator {
+
+public:
+ CBuildIterator();
+
+ virtual ~CBuildIterator();
+
+ IIterator* Clone() override;
+
+ IBase* GetCurrent() override;
+
+ IBuild* GetCurrentBuild() override;
+
+ void AddBuild(std::shared_ptr pBuild);
+
+};
+
+} // namespace Impl
+} // namespace LibMCEnv
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#endif // __LIBMCENV_BUILDITERATOR
diff --git a/Implementation/LibMCEnv/libmcenv_imagedata.cpp b/Implementation/LibMCEnv/libmcenv_imagedata.cpp
index aff0afa2d..fb9c843bf 100644
--- a/Implementation/LibMCEnv/libmcenv_imagedata.cpp
+++ b/Implementation/LibMCEnv/libmcenv_imagedata.cpp
@@ -888,18 +888,10 @@ void CImageData::GetPixels(const LibMCEnv_uint32 nStartX, const LibMCEnv_uint32
{
if (m_PixelData.get() == nullptr)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDIMAGEBUFFER);
-
- if (pValueBuffer == nullptr)
- throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM);
-
- if (m_PixelData.get() == nullptr)
- throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDIMAGEBUFFER);
-
if (nCountX <= 0)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPIXELCOUNT);
if (nCountY <= 0)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPIXELCOUNT);
-
if (nStartX >= m_nPixelCountX)
throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDXCOORDINATE);
if (nStartY >= m_nPixelCountY)
diff --git a/Implementation/LibMCEnv/libmcenv_jsonarray.cpp b/Implementation/LibMCEnv/libmcenv_jsonarray.cpp
index abc5f84b8..0ef813c0d 100644
--- a/Implementation/LibMCEnv/libmcenv_jsonarray.cpp
+++ b/Implementation/LibMCEnv/libmcenv_jsonarray.cpp
@@ -260,7 +260,10 @@ IJSONObject * CJSONArray::AddObjectValue()
jsonValue.SetObject();
- auto pMember = &m_pInstance->PushBack(jsonValue, m_pDocument->GetAllocator());
+ m_pInstance->PushBack(jsonValue, m_pDocument->GetAllocator());
+
+ // Get pointer to the newly added element (last element in array)
+ auto pMember = &(*m_pInstance)[m_pInstance->Size() - 1];
return new CJSONObject(m_pDocument, pMember);
}
@@ -271,7 +274,10 @@ IJSONArray * CJSONArray::AddArrayValue()
jsonValue.SetArray();
- auto pMember = &m_pInstance->PushBack(jsonValue, m_pDocument->GetAllocator());
+ m_pInstance->PushBack(jsonValue, m_pDocument->GetAllocator());
+
+ // Get pointer to the newly added element (last element in array)
+ auto pMember = &(*m_pInstance)[m_pInstance->Size() - 1];
return new CJSONArray(m_pDocument, pMember);
}
diff --git a/Implementation/LibMCEnv/libmcenv_jsonobject.cpp b/Implementation/LibMCEnv/libmcenv_jsonobject.cpp
index 06ba7ffcf..f1034e7ac 100644
--- a/Implementation/LibMCEnv/libmcenv_jsonobject.cpp
+++ b/Implementation/LibMCEnv/libmcenv_jsonobject.cpp
@@ -347,10 +347,13 @@ IJSONObject * CJSONObject::AddObjectValue(const std::string & sName)
jsonName.SetString(sName.c_str(), m_pDocument->GetAllocator());
jsonValue.SetObject ();
- auto pMember = &m_pInstance->AddMember(jsonName, jsonValue, m_pDocument->GetAllocator());
+ m_pInstance->AddMember(jsonName, jsonValue, m_pDocument->GetAllocator());
+
+ // Get pointer to the newly added member value (not the parent object)
+ auto pMember = &(*m_pInstance)[sName.c_str()];
return new CJSONObject (m_pDocument, pMember);
-
+
}
IJSONArray * CJSONObject::AddArrayValue(const std::string & sName)
@@ -361,7 +364,10 @@ IJSONArray * CJSONObject::AddArrayValue(const std::string & sName)
jsonName.SetString(sName.c_str(), m_pDocument->GetAllocator());
jsonValue.SetArray();
- auto pMember = &m_pInstance->AddMember(jsonName, jsonValue, m_pDocument->GetAllocator());
+ m_pInstance->AddMember(jsonName, jsonValue, m_pDocument->GetAllocator());
+
+ // Get pointer to the newly added member value (not the parent object)
+ auto pMember = &(*m_pInstance)[sName.c_str()];
return new CJSONArray(m_pDocument, pMember);
}
diff --git a/Implementation/LibMCEnv/libmcenv_stateenvironment.cpp b/Implementation/LibMCEnv/libmcenv_stateenvironment.cpp
index 4c13fe74b..5c49f0dfb 100644
--- a/Implementation/LibMCEnv/libmcenv_stateenvironment.cpp
+++ b/Implementation/LibMCEnv/libmcenv_stateenvironment.cpp
@@ -134,7 +134,7 @@ bool CStateEnvironment::WaitForSignal(const std::string& sSignalName, const LibM
std::string sUnhandledSignalUUID;
std::string sParameterDataJSON;
- bool bHasSignal = pSignalInstance->claimSignalMessage(sSignalName, true, nCurrentTime, nCurrentTime, sUnhandledSignalUUID, sParameterDataJSON);
+ bool bHasSignal = pSignalInstance->claimSignalMessage(sSignalName, true, nCurrentTime, nCurrentTime, sUnhandledSignalUUID, sParameterDataJSON, false);
if (bHasSignal) {
pHandlerInstance = new CSignalHandler(m_pSystemState->getStateSignalHandlerInstance(), m_sInstanceName, sSignalName, sUnhandledSignalUUID, sParameterDataJSON, m_pSystemState->getGlobalChronoInstance());
@@ -164,7 +164,7 @@ ISignalHandler* CStateEnvironment::GetUnhandledSignal(const std::string& sSignal
std::string sUnhandledSignalUUID;
std::string sParameterDataJSON;
uint64_t nCurrentTime = pChronoInstance->getElapsedMicroseconds();
- bool bHasSignal = pSignalInstance->claimSignalMessage(sSignalTypeName, true, nCurrentTime, nCurrentTime, sUnhandledSignalUUID, sParameterDataJSON);
+ bool bHasSignal = pSignalInstance->claimSignalMessage(sSignalTypeName, true, nCurrentTime, nCurrentTime, sUnhandledSignalUUID, sParameterDataJSON, false);
if (bHasSignal) {
return new CSignalHandler(m_pSystemState->getStateSignalHandlerInstance(), m_sInstanceName, sSignalTypeName, sUnhandledSignalUUID, sParameterDataJSON, pChronoInstance);
}
@@ -172,6 +172,29 @@ ISignalHandler* CStateEnvironment::GetUnhandledSignal(const std::string& sSignal
return nullptr;
}
+ISignalHandler* CStateEnvironment::ClaimSignalFromQueue(const std::string& sSignalTypeName)
+{
+ auto pChronoInstance = m_pSystemState->getGlobalChronoInstance();
+ auto pSignalInstance = m_pSystemState->stateSignalHandler()->getInstance(m_sInstanceName);
+
+ std::string sUnhandledSignalUUID;
+ std::string sParameterDataJSON;
+ uint64_t nCurrentTime = pChronoInstance->getElapsedMicroseconds();
+ bool bHasSignal = pSignalInstance->claimSignalMessage(sSignalTypeName, true, nCurrentTime, nCurrentTime, sUnhandledSignalUUID, sParameterDataJSON, true);
+ if (bHasSignal) {
+ return new CSignalHandler(m_pSystemState->getStateSignalHandlerInstance(), m_sInstanceName, sSignalTypeName, sUnhandledSignalUUID, sParameterDataJSON, pChronoInstance);
+ }
+
+ return nullptr;
+}
+
+bool CStateEnvironment::SignalQueueIsEmpty(const std::string& sSignalTypeName)
+{
+ auto pSignalInstance = m_pSystemState->stateSignalHandler()->getInstance(m_sInstanceName);
+ return pSignalInstance->queueIsEmpty(sSignalTypeName);
+}
+
+
void CStateEnvironment::ClearAllUnhandledSignals()
{
auto pChrono = m_pSystemState->globalChrono();
diff --git a/Implementation/LibMCEnv/libmcenv_stateenvironment.hpp b/Implementation/LibMCEnv/libmcenv_stateenvironment.hpp
index 1f6237405..718edaa55 100644
--- a/Implementation/LibMCEnv/libmcenv_stateenvironment.hpp
+++ b/Implementation/LibMCEnv/libmcenv_stateenvironment.hpp
@@ -85,6 +85,10 @@ class CStateEnvironment : public virtual IStateEnvironment, public virtual CBase
ISignalHandler* GetUnhandledSignal(const std::string& sSignalTypeName) override;
+ ISignalHandler* ClaimSignalFromQueue(const std::string& sSignalTypeName) override;
+
+ bool SignalQueueIsEmpty(const std::string& sSignalTypeName) override;
+
ISignalHandler* GetUnhandledSignalByUUID(const std::string& sUUID, const bool bMustExist) override;
void ClearUnhandledSignalsOfType(const std::string& sSignalTypeName) override;
diff --git a/Implementation/LibMCEnv/libmcenv_uienvironment.cpp b/Implementation/LibMCEnv/libmcenv_uienvironment.cpp
index afc93668d..739d16261 100644
--- a/Implementation/LibMCEnv/libmcenv_uienvironment.cpp
+++ b/Implementation/LibMCEnv/libmcenv_uienvironment.cpp
@@ -60,6 +60,7 @@ Abstract: This is a stub class definition of CUIEnvironment
#include "libmcenv_imagedata.hpp"
#include "libmcenv_testenvironment.hpp"
#include "libmcenv_build.hpp"
+#include "libmcenv_builditerator.hpp"
#include "libmcenv_buildexecution.hpp"
#include "libmcenv_streamreader.hpp"
#include "libmcenv_datatable.hpp"
@@ -617,6 +618,32 @@ IBuildExecution* CUIEnvironment::GetBuildExecution(const std::string& sExecution
}
+IBuildIterator* CUIEnvironment::GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount)
+{
+ if (nMaxCount == 0)
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDPARAM, "MaxCount must be greater than 0");
+
+ auto pDataModel = m_pUISystemState->getDataModel();
+ auto pBuildJobHandler = pDataModel->CreateBuildJobHandler();
+ auto pBuildJobIterator = pBuildJobHandler->ListJobsByStatus(LibMCData::eBuildJobStatus::Validated);
+
+ std::unique_ptr pResultIterator(new CBuildIterator());
+
+ uint32_t nCount = 0;
+ while (pBuildJobIterator->MoveNext() && (nCount < nMaxCount)) {
+ auto pBuildJob = pBuildJobIterator->GetCurrentJob();
+ auto pBuild = std::make_shared(pDataModel, pBuildJob->GetUUID(),
+ m_pUISystemState->getToolpathHandler(),
+ m_pUISystemState->getMeshHandler(),
+ m_pUISystemState->getGlobalChronoInstance(),
+ m_pUISystemState->getStateJournal());
+ pResultIterator->AddBuild(pBuild);
+ nCount++;
+ }
+
+ return pResultIterator.release();
+}
+
IDiscreteFieldData2D* CUIEnvironment::CreateDiscreteField2D(const LibMCEnv_uint32 nPixelSizeX, const LibMCEnv_uint32 nPixelSizeY, const LibMCEnv_double dDPIValueX, const LibMCEnv_double dDPIValueY, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY, const LibMCEnv_double dDefaultValue)
{
@@ -1024,6 +1051,69 @@ void CUIEnvironment::AddExternalEventResultValue(const std::string& sReturnValue
m_ExternalEventReturnValues->AddMember(jsonName, jsonValue, m_ExternalEventReturnValues->GetAllocator ());
}
+void CUIEnvironment::SetStringResult(const std::string& sReturnValueName, const std::string& sReturnValue)
+{
+ // Convenience wrapper for AddExternalEventResultValue
+ AddExternalEventResultValue(sReturnValueName, sReturnValue);
+}
+
+void CUIEnvironment::SetIntegerResult(const std::string& sReturnValueName, const LibMCEnv_int64 nReturnValue)
+{
+ if (!AMCCommon::CUtils::stringIsValidAlphanumericNameString(sReturnValueName))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDEXTERNALEVENTRETURNVALUEKEY, "invalid external return value key: " + sReturnValueName);
+
+ if (AMC::CUIHandleEventResponse::externalValueNameIsReserved(sReturnValueName))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_EXTERNALEVENTRETURNVALUEKEYISRESERVED, "external return value key is reserved: " + sReturnValueName);
+
+ if (m_ExternalEventReturnValues->HasMember(sReturnValueName.c_str()))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_DUPLICATEEXTERNALEVENTRETURNKEY, "duplicate external event return key: " + sReturnValueName);
+
+ rapidjson::Value jsonName;
+ rapidjson::Value jsonValue;
+
+ jsonName.SetString(sReturnValueName.c_str(), m_ExternalEventReturnValues->GetAllocator());
+ jsonValue.SetInt64(nReturnValue);
+ m_ExternalEventReturnValues->AddMember(jsonName, jsonValue, m_ExternalEventReturnValues->GetAllocator());
+}
+
+void CUIEnvironment::SetBoolResult(const std::string& sReturnValueName, const bool bReturnValue)
+{
+ if (!AMCCommon::CUtils::stringIsValidAlphanumericNameString(sReturnValueName))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDEXTERNALEVENTRETURNVALUEKEY, "invalid external return value key: " + sReturnValueName);
+
+ if (AMC::CUIHandleEventResponse::externalValueNameIsReserved(sReturnValueName))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_EXTERNALEVENTRETURNVALUEKEYISRESERVED, "external return value key is reserved: " + sReturnValueName);
+
+ if (m_ExternalEventReturnValues->HasMember(sReturnValueName.c_str()))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_DUPLICATEEXTERNALEVENTRETURNKEY, "duplicate external event return key: " + sReturnValueName);
+
+ rapidjson::Value jsonName;
+ rapidjson::Value jsonValue;
+
+ jsonName.SetString(sReturnValueName.c_str(), m_ExternalEventReturnValues->GetAllocator());
+ jsonValue.SetBool(bReturnValue);
+ m_ExternalEventReturnValues->AddMember(jsonName, jsonValue, m_ExternalEventReturnValues->GetAllocator());
+}
+
+void CUIEnvironment::SetDoubleResult(const std::string& sReturnValueName, const LibMCEnv_double dReturnValue)
+{
+ if (!AMCCommon::CUtils::stringIsValidAlphanumericNameString(sReturnValueName))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_INVALIDEXTERNALEVENTRETURNVALUEKEY, "invalid external return value key: " + sReturnValueName);
+
+ if (AMC::CUIHandleEventResponse::externalValueNameIsReserved(sReturnValueName))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_EXTERNALEVENTRETURNVALUEKEYISRESERVED, "external return value key is reserved: " + sReturnValueName);
+
+ if (m_ExternalEventReturnValues->HasMember(sReturnValueName.c_str()))
+ throw ELibMCEnvInterfaceException(LIBMCENV_ERROR_DUPLICATEEXTERNALEVENTRETURNKEY, "duplicate external event return key: " + sReturnValueName);
+
+ rapidjson::Value jsonName;
+ rapidjson::Value jsonValue;
+
+ jsonName.SetString(sReturnValueName.c_str(), m_ExternalEventReturnValues->GetAllocator());
+ jsonValue.SetDouble(dReturnValue);
+ m_ExternalEventReturnValues->AddMember(jsonName, jsonValue, m_ExternalEventReturnValues->GetAllocator());
+}
+
IJSONObject* CUIEnvironment::GetExternalEventParameters()
{
return new CJSONObject(m_ExternalEventParameters, m_ExternalEventParameters.get());
diff --git a/Implementation/LibMCEnv/libmcenv_uienvironment.hpp b/Implementation/LibMCEnv/libmcenv_uienvironment.hpp
index 10f409de7..9ba33b23d 100644
--- a/Implementation/LibMCEnv/libmcenv_uienvironment.hpp
+++ b/Implementation/LibMCEnv/libmcenv_uienvironment.hpp
@@ -198,6 +198,8 @@ class CUIEnvironment : public virtual IUIEnvironment, public virtual CBase {
IBuildExecution* GetBuildExecution(const std::string& sExecutionUUID) override;
+ IBuildIterator* GetRecentBuildJobs(const LibMCEnv_uint32 nMaxCount) override;
+
IDiscreteFieldData2D* CreateDiscreteField2D(const LibMCEnv_uint32 nPixelSizeX, const LibMCEnv_uint32 nPixelSizeY, const LibMCEnv_double dDPIValueX, const LibMCEnv_double dDPIValueY, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY, const LibMCEnv_double dDefaultValue) override;
IDiscreteFieldData2D* CreateDiscreteField2DFromImage(IImageData* pImageDataInstance, const LibMCEnv_double dBlackValue, const LibMCEnv_double dWhiteValue, const LibMCEnv_double dOriginX, const LibMCEnv_double dOriginY) override;
@@ -268,6 +270,15 @@ class CUIEnvironment : public virtual IUIEnvironment, public virtual CBase {
void AddExternalEventResultValue(const std::string& sReturnValueName, const std::string& sReturnValue) override;
+ // Typed result setters for /api/ext event handlers
+ void SetStringResult(const std::string& sReturnValueName, const std::string& sReturnValue) override;
+
+ void SetIntegerResult(const std::string& sReturnValueName, const LibMCEnv_int64 nReturnValue) override;
+
+ void SetBoolResult(const std::string& sReturnValueName, const bool bReturnValue) override;
+
+ void SetDoubleResult(const std::string& sReturnValueName, const LibMCEnv_double dReturnValue) override;
+
IJSONObject* GetExternalEventParameters() override;
IJSONObject* GetExternalEventResults() override;
diff --git a/Implementation/UnitTest/amc_unittests.cpp b/Implementation/UnitTest/amc_unittests.cpp
index 45f771084..a84a1af2f 100644
--- a/Implementation/UnitTest/amc_unittests.cpp
+++ b/Implementation/UnitTest/amc_unittests.cpp
@@ -45,6 +45,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "amc_unittests_statejournal.hpp"
#include "amc_unittests_common_utils.hpp"
#include "amc_unittests_resourcepackage.hpp"
+#include "amc_unittests_jpeg.hpp"
+#include "amc_unittests_streams.hpp"
+#include "amc_unittests_alerts.hpp"
+#include "amc_unittests_dataseries.hpp"
+#include "amc_unittests_discretefielddata2d.hpp"
using namespace AMCUnitTest;
@@ -68,4 +73,9 @@ CUnitTests::CUnitTests (PUnitTestIO pIO)
registerTestGroup(std::make_shared ());
registerTestGroup(std::make_shared ());
registerTestGroup(std::make_shared ());
+ registerTestGroup(std::make_shared ());
+ registerTestGroup(std::make_shared ());
+ registerTestGroup(std::make_shared ());
+ registerTestGroup(std::make_shared ());
+ registerTestGroup(std::make_shared ());
}
diff --git a/Implementation/UnitTest/amc_unittests_alerts.hpp b/Implementation/UnitTest/amc_unittests_alerts.hpp
new file mode 100644
index 000000000..74a04e68a
--- /dev/null
+++ b/Implementation/UnitTest/amc_unittests_alerts.hpp
@@ -0,0 +1,182 @@
+/*++
+
+Copyright (C) 2025 Autodesk Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Autodesk Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef __AMCTEST_UNITTEST_ALERTS
+#define __AMCTEST_UNITTEST_ALERTS
+
+
+#include "amc_unittests.hpp"
+#include "amc_alerthandler.hpp"
+#include "amc_languagedefinition.hpp"
+
+
+namespace AMCUnitTest {
+
+ class CUnitTestGroup_Alerts : public CUnitTestGroup {
+ public:
+
+ std::string getTestGroupName() override {
+ return "Alerts";
+ }
+
+ void registerTests() override {
+ registerTest("AlertDefinitionBasics", "Alert definition properties and translations", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_Alerts::testAlertDefinitionBasics, this));
+ registerTest("AlertLevelConversions", "Alert level string conversions", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_Alerts::testAlertLevelConversions, this));
+ registerTest("AlertHandlerDefinitions", "Alert handler add/find/validate definitions", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_Alerts::testAlertHandlerDefinitions, this));
+ }
+
+ void initializeTests() override {
+ }
+
+ private:
+
+ void testAlertDefinitionBasics()
+ {
+ AMC::CLanguageString description("test_desc", "Custom");
+ AMC::CAlertDefinition definition("AlertOne", LibMCData::eAlertLevel::Warning, description, true);
+ assertTrue(definition.getIdentifier() == "AlertOne");
+ assertTrue(definition.getAlertLevel() == LibMCData::eAlertLevel::Warning);
+ assertTrue(definition.needsAcknowledgement());
+ assertTrue(definition.getDescription().getStringIdentifier() == "test_desc");
+ assertTrue(definition.getDescription().getCustomValue() == "Custom");
+
+ auto pLanguage = std::make_shared("en", nullptr);
+ pLanguage->addTranslation("test_desc", "Translated");
+ assertTrue(definition.getTranslatedDescription(pLanguage.get()) == "Translated");
+
+ AMC::CLanguageString customOnly("", "Fallback");
+ AMC::CAlertDefinition customDefinition("AlertTwo", LibMCData::eAlertLevel::Message, customOnly, false);
+ assertFalse(customDefinition.needsAcknowledgement());
+ assertTrue(customDefinition.getTranslatedDescription(pLanguage.get()) == "Fallback");
+
+ definition.setAckPermissionIdentifier("ack_permission");
+ assertTrue(definition.getAckPermissionIdentifier() == "ack_permission");
+ }
+
+ void testAlertLevelConversions()
+ {
+ assertTrue(AMC::CAlertDefinition::stringToAlertLevel("fatalerror", true) == LibMCData::eAlertLevel::FatalError);
+ assertTrue(AMC::CAlertDefinition::stringToAlertLevel("criticalerror", true) == LibMCData::eAlertLevel::CriticalError);
+ assertTrue(AMC::CAlertDefinition::stringToAlertLevel("warning", true) == LibMCData::eAlertLevel::Warning);
+ assertTrue(AMC::CAlertDefinition::stringToAlertLevel("message", true) == LibMCData::eAlertLevel::Message);
+ assertTrue(AMC::CAlertDefinition::stringToAlertLevel("unknown", false) == LibMCData::eAlertLevel::Unknown);
+
+ bool thrown = false;
+ try {
+ AMC::CAlertDefinition::stringToAlertLevel("unknown", true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected stringToAlertLevel to throw on unknown input");
+
+ assertTrue(AMC::CAlertDefinition::alertLevelToString(LibMCData::eAlertLevel::FatalError) == "fatalerror");
+ assertTrue(AMC::CAlertDefinition::alertLevelToString(LibMCData::eAlertLevel::CriticalError) == "criticalerror");
+ assertTrue(AMC::CAlertDefinition::alertLevelToString(LibMCData::eAlertLevel::Warning) == "warning");
+ assertTrue(AMC::CAlertDefinition::alertLevelToString(LibMCData::eAlertLevel::Message) == "message");
+ assertTrue(AMC::CAlertDefinition::alertLevelToString(LibMCData::eAlertLevel::Unknown) == "unknown");
+ }
+
+ void testAlertHandlerDefinitions()
+ {
+ AMC::CAlertHandler handler;
+ AMC::CLanguageString description("desc", "Desc");
+
+ assertFalse(handler.hasDefinition("AlertOne"));
+ auto pDefinition = handler.addDefinition("AlertOne", LibMCData::eAlertLevel::Warning, description, true);
+ assertTrue(handler.hasDefinition("AlertOne"));
+ assertTrue(pDefinition.get() != nullptr);
+
+ auto pFound = handler.findDefinition("AlertOne", true);
+ assertTrue(pFound.get() == pDefinition.get());
+ assertTrue(pFound->needsAcknowledgement());
+
+ auto pMissing = handler.findDefinition("Missing", false);
+ assertTrue(pMissing.get() == nullptr);
+
+ bool thrown = false;
+ try {
+ handler.findDefinition("Missing", true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected findDefinition to throw on missing definition");
+
+ thrown = false;
+ try {
+ handler.addDefinition("AlertOne", LibMCData::eAlertLevel::Warning, description, false);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected addDefinition to throw on duplicate identifier");
+
+ thrown = false;
+ try {
+ handler.addDefinition("", LibMCData::eAlertLevel::Warning, description, false);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected addDefinition to throw on empty identifier");
+
+ thrown = false;
+ try {
+ handler.addDefinition("bad-char", LibMCData::eAlertLevel::Warning, description, false);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected addDefinition to throw on invalid identifier");
+
+ thrown = false;
+ try {
+ handler.hasDefinition("");
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected hasDefinition to throw on empty identifier");
+
+ thrown = false;
+ try {
+ handler.hasDefinition("bad-char");
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected hasDefinition to throw on invalid identifier");
+ }
+ };
+
+}
+
+#endif // __AMCTEST_UNITTEST_ALERTS
diff --git a/Implementation/UnitTest/amc_unittests_common_utils.hpp b/Implementation/UnitTest/amc_unittests_common_utils.hpp
index d5db9057b..d2604d1f7 100644
--- a/Implementation/UnitTest/amc_unittests_common_utils.hpp
+++ b/Implementation/UnitTest/amc_unittests_common_utils.hpp
@@ -56,6 +56,7 @@ namespace AMCUnitTest {
registerTest("FilePathFunctions", "Path handling and file/directory helpers", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_CommonUtils::testFilePathFunctions, this));
registerTest("TempAndDirectoryFunctions", "Temporary paths, directory content, and OS helpers", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_CommonUtils::testTempAndDirectoryFunctions, this));
registerTest("AlphanumericValidation", "Alphanumeric name and path validation", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_CommonUtils::testAlphanumericValidation, this));
+ registerTest("FileNameValidation", "Filename validation for invalid characters and dot-dot", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_CommonUtils::testFileNameValidation, this));
}
void initializeTests() override {
@@ -116,6 +117,14 @@ namespace AMCUnitTest {
assertTrue(AMCCommon::CUtils::stringIsUUIDString(uuid));
assertTrue(AMCCommon::CUtils::stringIsNonEmptyUUIDString(uuid));
assertTrue(AMCCommon::CUtils::normalizeUUIDString(uuid) == uuid);
+ assertTrue(AMCCommon::CUtils::stringIsUUIDString(" " + uuid + " "));
+
+ std::string uuidV4 = AMCCommon::CUtils::createUUIDV4();
+ assertTrue(AMCCommon::CUtils::stringIsUUIDString(uuidV4));
+ assertTrue(AMCCommon::CUtils::stringIsNonEmptyUUIDString(uuidV4));
+ assertTrue(AMCCommon::CUtils::normalizeUUIDString(uuidV4) == uuidV4);
+ assertTrue(uuidV4.at(14) == '4');
+ assertTrue((uuidV4.at(19) == '8') || (uuidV4.at(19) == '9') || (uuidV4.at(19) == 'a') || (uuidV4.at(19) == 'b'));
std::string emptyUUID = AMCCommon::CUtils::createEmptyUUID();
assertTrue(AMCCommon::CUtils::stringIsUUIDString(emptyUUID));
@@ -126,6 +135,13 @@ namespace AMCUnitTest {
assertTrue(normalizedUUID == "a1b2c3d4-1111-2222-3333-444455556666");
assertFalse(AMCCommon::CUtils::stringIsUUIDString("not-a-uuid"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("a1b2c3d4-1111-2222-3333-44445555666"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("a1b2c3d4-1111-2222-3333-4444555566667"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("a1b2c3d4-1111-2222-3333444455556666"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("a1b2c3d4-1111-2222-3333-44445555666x"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("a1b2c3d4-1111-2222-3333_444455556666"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("A1B2C3D4-1111-2222-3333-44445555666G"));
+ assertFalse(AMCCommon::CUtils::stringIsUUIDString("a1b2c3d4111122223333444455556666"));
bool thrown = false;
try {
@@ -135,6 +151,15 @@ namespace AMCUnitTest {
thrown = true;
}
assertTrue(thrown, "Expected normalizeUUIDString to throw on invalid input");
+
+ thrown = false;
+ try {
+ AMCCommon::CUtils::normalizeUUIDString("a1b2c3d4111122223333444455556666ff");
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected normalizeUUIDString to throw on oversized input");
}
void testUTF8Conversions()
@@ -290,6 +315,24 @@ namespace AMCUnitTest {
std::string normalizedSHA = AMCCommon::CUtils::normalizeSHA256String(rawSHA);
assertTrue(normalizedSHA == expectedHash);
+ thrown = false;
+ try {
+ AMCCommon::CUtils::normalizeSHA256String("abc");
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected normalizeSHA256String to throw on invalid length");
+
+ thrown = false;
+ try {
+ AMCCommon::CUtils::normalizeSHA256String(expectedHash + "0");
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected normalizeSHA256String to throw on oversized input");
+
thrown = false;
try {
AMCCommon::CUtils::calculateRandomSHA256String(0);
@@ -396,6 +439,7 @@ namespace AMCUnitTest {
std::string fullPath = AMCCommon::CUtils::getFullPathName(nonExistingPath, false);
assertTrue(!fullPath.empty());
assertFalse(AMCCommon::CUtils::fileOrPathExistsOnDisk(nonExistingPath));
+ assertFalse(AMCCommon::CUtils::pathIsDirectory(nonExistingPath));
char delimiter = AMCCommon::CUtils::getPathDelimiter();
#ifdef _WIN32
@@ -406,6 +450,9 @@ namespace AMCUnitTest {
std::string withDelimiter = AMCCommon::CUtils::includeTrailingPathDelimiter("path");
assertTrue(withDelimiter.back() == '/' || withDelimiter.back() == '\\');
assertTrue(AMCCommon::CUtils::includeTrailingPathDelimiter(withDelimiter) == withDelimiter);
+ std::string emptyWithDelimiter = AMCCommon::CUtils::includeTrailingPathDelimiter("");
+ assertTrue(emptyWithDelimiter.size() == 1);
+ assertTrue(emptyWithDelimiter.at(0) == delimiter);
assertTrue(AMCCommon::CUtils::removeLeadingPathDelimiter("///path") == "path");
}
@@ -473,6 +520,25 @@ namespace AMCUnitTest {
assertFalse(AMCCommon::CUtils::stringIsValidAlphanumericPathString(".abc"));
assertFalse(AMCCommon::CUtils::stringIsValidAlphanumericPathString("abc."));
}
+
+ void testFileNameValidation()
+ {
+ assertFalse(AMCCommon::CUtils::stringIsValidFileName(""));
+ assertFalse(AMCCommon::CUtils::stringIsValidFileName("file:name.txt"));
+ assertFalse(AMCCommon::CUtils::stringIsValidFileName("file>name.txt"));
+ assertFalse(AMCCommon::CUtils::stringIsValidFileName("file= series.getEntryCount() * sizeof(AMC::sDataSeriesEntry));
+
+ series.increaseVersion();
+ assertTrue(series.getVersion() == 2);
+
+ series.clearData();
+ assertTrue(series.isEmpty());
+ assertTrue(series.getEntryCount() == 0);
+ }
+
+ void testDataSeriesHandlerBasics()
+ {
+ AMC::CDataSeriesHandler handler;
+ std::string missingUUID = AMCCommon::CUtils::createUUID();
+
+ assertFalse(handler.hasDataSeries(missingUUID));
+ assertTrue(handler.findDataSeries(missingUUID, false).get() == nullptr);
+
+ bool thrown = false;
+ try {
+ handler.findDataSeries(missingUUID, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected findDataSeries to throw on missing entry");
+
+ auto pSeries = handler.createDataSeries("SeriesTwo");
+ assertTrue(pSeries.get() != nullptr);
+
+ std::string seriesUUID = pSeries->getUUID();
+ assertTrue(handler.hasDataSeries(seriesUUID));
+ assertTrue(handler.findDataSeries(seriesUUID, true).get() == pSeries.get());
+
+ pSeries->getEntries().push_back({ 100, 1.0 });
+ uint64_t usage = handler.getMemoryUsageInBytes();
+ assertTrue(usage >= pSeries->getMemoryUsageInBytes());
+
+ handler.unloadDataSeries(seriesUUID);
+ handler.unloadAllEntities();
+ }
+ };
+
+}
+
+#endif // __AMCTEST_UNITTEST_DATASERIES
diff --git a/Implementation/UnitTest/amc_unittests_discretefielddata2d.hpp b/Implementation/UnitTest/amc_unittests_discretefielddata2d.hpp
new file mode 100644
index 000000000..b2ea94d19
--- /dev/null
+++ b/Implementation/UnitTest/amc_unittests_discretefielddata2d.hpp
@@ -0,0 +1,480 @@
+/*++
+
+Copyright (C) 2025 Autodesk Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Autodesk Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef __AMCTEST_UNITTEST_DISCRETEFIELDDATA2D
+#define __AMCTEST_UNITTEST_DISCRETEFIELDDATA2D
+
+
+#include "amc_unittests.hpp"
+#include "amc_discretefielddata2d.hpp"
+
+#include
+
+
+namespace AMCUnitTest {
+
+ class CUnitTestGroup_DiscreteFieldData2D : public CUnitTestGroup {
+ public:
+
+ std::string getTestGroupName() override {
+ return "DiscreteFieldData2D";
+ }
+
+ void registerTests() override {
+ registerTest("ConstructionAndBasics", "Discrete field construction and basic properties", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testConstructionAndBasics, this));
+ registerTest("ResizeClampAndPixels", "Discrete field resizing, clamping, and pixel access", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testResizeClampAndPixels, this));
+ registerTest("ScalingAndTransform", "Discrete field scaling and transform operations", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testScalingAndTransform, this));
+ registerTest("DuplicateAndAdd", "Discrete field duplication and add operations", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testDuplicateAndAdd, this));
+ registerTest("RenderAndSampling", "Discrete field rendering and sampling operations", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testRenderAndSampling, this));
+ registerTest("SerializationAndLoad", "Discrete field serialization and raw pixel loading", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testSerializationAndLoad, this));
+ registerTest("NotImplementedPaths", "Discrete field not implemented paths throw", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_DiscreteFieldData2D::testNotImplementedPaths, this));
+ }
+
+ void initializeTests() override {
+ }
+
+ private:
+
+ bool nearlyEqual(const double a, const double b, const double epsilon = 1.0e-9)
+ {
+ return std::abs(a - b) < epsilon;
+ }
+
+ void testConstructionAndBasics()
+ {
+ bool thrown = false;
+ try {
+ AMC::CDiscreteFieldData2DInstance invalidField(0, 1, 1.0, 1.0, 0.0, 0.0, 0.0, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected constructor to reject zero pixel count");
+
+ thrown = false;
+ try {
+ AMC::CDiscreteFieldData2DInstance invalidField(1, 1, 0.0, 1.0, 0.0, 0.0, 0.0, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected constructor to reject invalid DPI");
+
+ thrown = false;
+ try {
+ AMC::CDiscreteFieldData2DInstance invalidField(1, 1, 1.0, 1.0, 1.0e10, 0.0, 0.0, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected constructor to reject origin out of range");
+
+ AMC::CDiscreteFieldData2DInstance field(2, 3, 25.4, 25.4, 1.0, 2.0, 7.0, true);
+ double dpiX = 0.0, dpiY = 0.0;
+ field.GetDPI(dpiX, dpiY);
+ assertTrue(nearlyEqual(dpiX, 25.4));
+ assertTrue(nearlyEqual(dpiY, 25.4));
+
+ double originX = 0.0, originY = 0.0;
+ field.GetOriginInMM(originX, originY);
+ assertTrue(nearlyEqual(originX, 1.0));
+ assertTrue(nearlyEqual(originY, 2.0));
+
+ double sizeX = 0.0, sizeY = 0.0;
+ field.GetSizeInMM(sizeX, sizeY);
+ assertTrue(nearlyEqual(sizeX, 2.0));
+ assertTrue(nearlyEqual(sizeY, 3.0));
+
+ uint32_t sizeXPix = 0, sizeYPix = 0;
+ field.GetSizeInPixels(sizeXPix, sizeYPix);
+ assertTrue(sizeXPix == 2);
+ assertTrue(sizeYPix == 3);
+
+ assertTrue(nearlyEqual(field.GetPixel(0, 0), 7.0));
+
+ field.SetDPI(50.0, 100.0);
+ field.GetDPI(dpiX, dpiY);
+ assertTrue(nearlyEqual(dpiX, 50.0));
+ assertTrue(nearlyEqual(dpiY, 100.0));
+
+ field.SetOriginInMM(-1.0, -2.0);
+ field.GetOriginInMM(originX, originY);
+ assertTrue(nearlyEqual(originX, -1.0));
+ assertTrue(nearlyEqual(originY, -2.0));
+
+ thrown = false;
+ try {
+ field.SetDPI(0.0, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected SetDPI to reject invalid values");
+ }
+
+ void testResizeClampAndPixels()
+ {
+ AMC::CDiscreteFieldData2DInstance field(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ field.SetPixel(0, 0, 1.0);
+ field.SetPixel(1, 0, 2.0);
+ field.SetPixel(0, 1, 3.0);
+ field.SetPixel(1, 1, 4.0);
+
+ assertTrue(nearlyEqual(field.GetPixel(1, 1), 4.0));
+
+ bool thrown = false;
+ try {
+ field.GetPixel(2, 0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected GetPixel to reject invalid X coordinate");
+
+ thrown = false;
+ try {
+ field.SetPixel(0, 3, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected SetPixel to reject invalid Y coordinate");
+
+ thrown = false;
+ try {
+ field.Clamp(1.0, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected Clamp to reject invalid range");
+
+ field.Clamp(0.0, 3.0);
+ assertTrue(nearlyEqual(field.GetPixel(1, 1), 3.0));
+
+ uint32_t newX = 3;
+ uint32_t newY = 1;
+ field.ResizeField(newX, newY, 5.0);
+ uint32_t sizeX = 0, sizeY = 0;
+ field.GetSizeInPixels(sizeX, sizeY);
+ assertTrue(sizeX == 3);
+ assertTrue(sizeY == 1);
+ assertTrue(nearlyEqual(field.GetPixel(0, 0), 1.0));
+ assertTrue(nearlyEqual(field.GetPixel(1, 0), 2.0));
+ assertTrue(nearlyEqual(field.GetPixel(2, 0), 5.0));
+ }
+
+ void testScalingAndTransform()
+ {
+ AMC::CDiscreteFieldData2DInstance field(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ field.SetPixel(0, 0, 1.0);
+ field.SetPixel(1, 0, 2.0);
+ field.SetPixel(0, 1, 3.0);
+ field.SetPixel(1, 1, 4.0);
+
+ bool thrown = false;
+ try {
+ field.ScaleFieldDown(0, 1);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected ScaleFieldDown to reject invalid factors");
+
+ auto scaledDown = field.ScaleFieldDown(2, 2);
+ uint32_t sizeX = 0, sizeY = 0;
+ scaledDown->GetSizeInPixels(sizeX, sizeY);
+ assertTrue(sizeX == 1);
+ assertTrue(sizeY == 1);
+ assertTrue(nearlyEqual(scaledDown->GetPixel(0, 0), 2.5));
+
+ thrown = false;
+ try {
+ field.ScaleFieldUp(0, 1);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected ScaleFieldUp to reject invalid factors");
+
+ auto scaledUp = field.ScaleFieldUp(2, 2);
+ scaledUp->GetSizeInPixels(sizeX, sizeY);
+ assertTrue(sizeX == 4);
+ assertTrue(sizeY == 4);
+ assertTrue(nearlyEqual(scaledUp->GetPixel(0, 0), 1.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(1, 0), 1.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(2, 0), 2.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(3, 0), 2.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(0, 1), 1.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(2, 1), 2.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(0, 2), 3.0));
+ assertTrue(nearlyEqual(scaledUp->GetPixel(2, 2), 4.0));
+
+ field.TransformField(2.0, 1.0);
+ assertTrue(nearlyEqual(field.GetPixel(0, 0), 3.0));
+ assertTrue(nearlyEqual(field.GetPixel(1, 1), 9.0));
+ }
+
+ void testDuplicateAndAdd()
+ {
+ AMC::CDiscreteFieldData2DInstance field(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ field.SetPixel(0, 0, 1.0);
+ field.SetPixel(1, 0, 2.0);
+ field.SetPixel(0, 1, 3.0);
+ field.SetPixel(1, 1, 4.0);
+
+ auto duplicate = field.Duplicate();
+ assertTrue(duplicate.get() != nullptr);
+ assertTrue(duplicate.get() != &field);
+ assertTrue(nearlyEqual(duplicate->GetPixel(1, 1), 4.0));
+
+ bool thrown = false;
+ try {
+ field.AddField(nullptr, 1.0, 0.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected AddField to reject null input");
+
+ AMC::CDiscreteFieldData2DInstance other(3, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ thrown = false;
+ try {
+ field.AddField(&other, 1.0, 0.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected AddField to reject mismatched sizes");
+
+ AMC::CDiscreteFieldData2DInstance same(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ same.SetPixel(0, 0, 10.0);
+ field.AddField(&same, 0.5, 1.0);
+ assertTrue(nearlyEqual(field.GetPixel(0, 0), 1.0 + 10.0 * 0.5 + 1.0));
+ }
+
+ void testRenderAndSampling()
+ {
+ AMC::CDiscreteFieldData2DInstance field(3, 1, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ field.SetPixel(0, 0, 0.0);
+ field.SetPixel(1, 0, 0.5);
+ field.SetPixel(2, 0, 1.0);
+
+ bool thrown = false;
+ try {
+ field.renderRGBImage(nullptr, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected renderRGBImage to reject null output buffer");
+
+ std::vector pixels;
+ field.renderRGBImage(&pixels, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0);
+ assertTrue(pixels.size() == 9);
+ assertTrue(pixels.at(0) == 0);
+ assertTrue(pixels.at(1) == 0);
+ assertTrue(pixels.at(2) == 0);
+ assertTrue(pixels.at(3) == 128);
+ assertTrue(pixels.at(4) == 128);
+ assertTrue(pixels.at(5) == 128);
+ assertTrue(pixels.at(6) == 255);
+ assertTrue(pixels.at(7) == 255);
+ assertTrue(pixels.at(8) == 255);
+
+ thrown = false;
+ try {
+ field.renderRGBImage(&pixels, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 1.0, 1.0, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected renderRGBImage to reject invalid color range");
+
+ AMC::CDiscreteFieldData2DInstance samplingField(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ LibMCEnv::sFieldData2DPoint points[3];
+ points[0].m_Coordinates[0] = 0.2;
+ points[0].m_Coordinates[1] = 0.2;
+ points[0].m_Value = 2.0;
+ points[1].m_Coordinates[0] = 0.8;
+ points[1].m_Coordinates[1] = 0.8;
+ points[1].m_Value = 4.0;
+ points[2].m_Coordinates[0] = 1.2;
+ points[2].m_Coordinates[1] = 0.2;
+ points[2].m_Value = 6.0;
+ samplingField.renderAveragePointValues_FloorSampling(-1.0, 3, points);
+ assertTrue(nearlyEqual(samplingField.GetPixel(0, 0), 3.0));
+ assertTrue(nearlyEqual(samplingField.GetPixel(1, 0), 6.0));
+ assertTrue(nearlyEqual(samplingField.GetPixel(0, 1), -1.0));
+ assertTrue(nearlyEqual(samplingField.GetPixel(1, 1), -1.0));
+
+ samplingField.SetPixel(0, 0, 9.0);
+ samplingField.renderAveragePointValues_FloorSampling(7.0, 0, nullptr);
+ assertTrue(nearlyEqual(samplingField.GetPixel(0, 0), 7.0));
+
+ thrown = false;
+ try {
+ samplingField.renderAveragePointValues_FloorSampling(0.0, 1, nullptr);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected renderAveragePointValues_FloorSampling to reject null input");
+ }
+
+ void testSerializationAndLoad()
+ {
+ AMC::CDiscreteFieldData2DInstance field(2, 2, 10.0, 20.0, 1.0, 2.0, 0.0, true);
+ field.SetPixel(0, 0, 1.0);
+ field.SetPixel(1, 0, 2.0);
+ field.SetPixel(0, 1, 3.0);
+ field.SetPixel(1, 1, 4.0);
+
+ std::vector buffer;
+ field.saveToBuffer(buffer);
+ auto loaded = AMC::CDiscreteFieldData2DInstance::createFromBuffer(buffer);
+ uint32_t sizeX = 0, sizeY = 0;
+ loaded->GetSizeInPixels(sizeX, sizeY);
+ assertTrue(sizeX == 2);
+ assertTrue(sizeY == 2);
+
+ double dpiX = 0.0, dpiY = 0.0;
+ loaded->GetDPI(dpiX, dpiY);
+ assertTrue(nearlyEqual(dpiX, 10.0));
+ assertTrue(nearlyEqual(dpiY, 20.0));
+
+ double originX = 0.0, originY = 0.0;
+ loaded->GetOriginInMM(originX, originY);
+ assertTrue(nearlyEqual(originX, 1.0));
+ assertTrue(nearlyEqual(originY, 2.0));
+ assertTrue(nearlyEqual(loaded->GetPixel(1, 1), 4.0));
+
+ bool thrown = false;
+ try {
+ std::vector tiny;
+ AMC::CDiscreteFieldData2DInstance::createFromBuffer(tiny);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected createFromBuffer to reject empty buffer");
+
+ thrown = false;
+ try {
+ std::vector corrupted = buffer;
+ if (corrupted.size() > 0)
+ corrupted[0] = 0;
+ AMC::CDiscreteFieldData2DInstance::createFromBuffer(corrupted);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected createFromBuffer to reject invalid signature");
+
+ AMC::CDiscreteFieldData2DInstance pixelField(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ std::vector grayData = { 0, 255, 128, 64 };
+ pixelField.loadFromRawPixelData(grayData, LibMCEnv::eImagePixelFormat::GreyScale8bit, 0.0, 1.0);
+ assertTrue(nearlyEqual(pixelField.GetPixel(0, 0), 0.0));
+ assertTrue(nearlyEqual(pixelField.GetPixel(1, 0), 1.0));
+
+ std::vector rgbData = {
+ 0, 0, 0,
+ 255, 255, 255,
+ 255, 0, 0,
+ 0, 255, 0
+ };
+ pixelField.loadFromRawPixelData(rgbData, LibMCEnv::eImagePixelFormat::RGB24bit, 0.0, 1.0);
+ assertTrue(nearlyEqual(pixelField.GetPixel(0, 0), 0.0));
+ assertTrue(nearlyEqual(pixelField.GetPixel(1, 0), 1.0));
+
+ std::vector rgbaData = {
+ 0, 0, 0, 255,
+ 255, 255, 255, 255,
+ 255, 0, 0, 255,
+ 0, 255, 0, 255
+ };
+ pixelField.loadFromRawPixelData(rgbaData, LibMCEnv::eImagePixelFormat::RGBA32bit, 0.0, 1.0);
+ assertTrue(nearlyEqual(pixelField.GetPixel(0, 0), 0.0));
+ assertTrue(nearlyEqual(pixelField.GetPixel(1, 0), 1.0));
+
+ thrown = false;
+ try {
+ pixelField.loadFromRawPixelData(grayData, LibMCEnv::eImagePixelFormat::RGB24bit, 0.0, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected loadFromRawPixelData to reject mismatched buffer size");
+
+ thrown = false;
+ try {
+ pixelField.loadFromRawPixelData(grayData, LibMCEnv::eImagePixelFormat::Unknown, 0.0, 1.0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected loadFromRawPixelData to reject unknown pixel format");
+ }
+
+ void testNotImplementedPaths()
+ {
+ AMC::CDiscreteFieldData2DInstance field(2, 2, 25.4, 25.4, 0.0, 0.0, 0.0, true);
+ bool thrown = false;
+ try {
+ field.GetPixelRange(0, 0, 1, 1, 0, nullptr, nullptr);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected GetPixelRange to throw not implemented");
+
+ thrown = false;
+ try {
+ field.SetPixelRange(0, 0, 1, 1, 0, nullptr);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected SetPixelRange to throw not implemented");
+
+ thrown = false;
+ try {
+ field.DiscretizeWithMapping(0, nullptr, 0, nullptr);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected DiscretizeWithMapping to throw not implemented");
+ }
+ };
+
+}
+
+#endif // __AMCTEST_UNITTEST_DISCRETEFIELDDATA2D
diff --git a/Implementation/UnitTest/amc_unittests_jpeg.hpp b/Implementation/UnitTest/amc_unittests_jpeg.hpp
new file mode 100644
index 000000000..093ba47f0
--- /dev/null
+++ b/Implementation/UnitTest/amc_unittests_jpeg.hpp
@@ -0,0 +1,177 @@
+/*++
+
+Copyright (C) 2025 Autodesk Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Autodesk Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef __AMCTEST_UNITTEST_JPEG
+#define __AMCTEST_UNITTEST_JPEG
+
+
+#include "amc_unittests.hpp"
+#include "common_jpeg.hpp"
+
+
+namespace AMCUnitTest {
+
+ class CUnitTestGroup_JPEG : public CUnitTestGroup {
+ public:
+
+ std::string getTestGroupName() override {
+ return "JPEG";
+ }
+
+ void registerTests() override {
+ registerTest("EncodeDecodeRGB", "Encode RGB data to JPEG and decode metadata and buffers", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_JPEG::testEncodeDecodeRGB, this));
+ registerTest("EncodeGrayUnsupported", "Grayscale encode should fail for unsupported channel count", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_JPEG::testEncodeGrayUnsupported, this));
+ registerTest("DecoderInvalidInput", "Decoder rejects invalid buffers", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_JPEG::testDecoderInvalidInput, this));
+ registerTest("EncoderInvalidInput", "Encoder rejects invalid image input", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_JPEG::testEncoderInvalidInput, this));
+ }
+
+ void initializeTests() override {
+ }
+
+ private:
+
+ void testEncodeDecodeRGB()
+ {
+ const uint32_t nWidth = 2;
+ const uint32_t nHeight = 2;
+ std::vector imageData = {
+ 255, 0, 0,
+ 0, 255, 0,
+ 0, 0, 255,
+ 255, 255, 0
+ };
+
+ std::vector jpegData;
+ AMCCommon::CJPEGImageEncoder encoder(nWidth, nHeight, AMCCommon::eJPEGChannelCount::ccRGB, imageData.data(), jpegData, true);
+ assertTrue(encoder.getWidth() == nWidth);
+ assertTrue(encoder.getHeight() == nHeight);
+ assertTrue(encoder.getChannelCount() == AMCCommon::eJPEGChannelCount::ccRGB);
+ assertTrue(!jpegData.empty());
+
+ AMCCommon::CJPEGImageDecoder decoder(jpegData.data(), jpegData.size());
+ assertTrue(decoder.getWidth() == nWidth);
+ assertTrue(decoder.getHeight() == nHeight);
+ assertTrue(decoder.getChannelCount() == AMCCommon::eJPEGChannelCount::ccRGB);
+
+ std::vector rgbBuffer;
+ decoder.writeToBufferRGB24bit(rgbBuffer);
+ assertTrue(rgbBuffer.size() == (size_t)nWidth * (size_t)nHeight * 3);
+
+ std::vector grayBuffer;
+ decoder.writeToBufferGreyScale8bit(grayBuffer);
+ assertTrue(grayBuffer.size() == (size_t)nWidth * (size_t)nHeight);
+
+ std::vector rgbaBuffer;
+ decoder.writeToBufferRGBA32bit(rgbaBuffer);
+ assertTrue(rgbaBuffer.size() == (size_t)nWidth * (size_t)nHeight * 4);
+ }
+
+ void testEncodeGrayUnsupported()
+ {
+ const uint32_t nWidth = 2;
+ const uint32_t nHeight = 2;
+ std::vector imageData = {
+ 0,
+ 64,
+ 128,
+ 255
+ };
+
+ bool thrown = false;
+ try {
+ std::vector jpegData;
+ AMCCommon::CJPEGImageEncoder encoder(nWidth, nHeight, AMCCommon::eJPEGChannelCount::ccGray, imageData.data(), jpegData, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected grayscale JPEG encode to throw on unsupported channel count");
+ }
+
+ void testDecoderInvalidInput()
+ {
+ bool thrown = false;
+ try {
+ uint8_t data = 0;
+ AMCCommon::CJPEGImageDecoder decoder(&data, 0);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected decoder to throw on empty buffer size");
+
+ thrown = false;
+ try {
+ AMCCommon::CJPEGImageDecoder decoder(nullptr, 1);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected decoder to throw on null buffer");
+
+ thrown = false;
+ try {
+ std::vector invalidData = { 0x00, 0x01, 0x02, 0x03 };
+ AMCCommon::CJPEGImageDecoder decoder(invalidData.data(), invalidData.size());
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected decoder to throw on invalid JPEG data");
+ }
+
+ void testEncoderInvalidInput()
+ {
+ bool thrown = false;
+ try {
+ std::vector jpegData;
+ AMCCommon::CJPEGImageEncoder encoder(1, 1, AMCCommon::eJPEGChannelCount::ccRGB, nullptr, jpegData, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected encoder to throw on null image data");
+
+ thrown = false;
+ try {
+ std::vector imageData = { 0, 0, 0 };
+ std::vector jpegData;
+ AMCCommon::CJPEGImageEncoder encoder(0, 1, AMCCommon::eJPEGChannelCount::ccRGB, imageData.data(), jpegData, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected encoder to throw on invalid image size");
+ }
+ };
+
+}
+
+#endif // __AMCTEST_UNITTEST_JPEG
diff --git a/Implementation/UnitTest/amc_unittests_streams.hpp b/Implementation/UnitTest/amc_unittests_streams.hpp
new file mode 100644
index 000000000..d5370f7e9
--- /dev/null
+++ b/Implementation/UnitTest/amc_unittests_streams.hpp
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (C) 2025 Autodesk Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of the Autodesk Inc. nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef __AMCTEST_UNITTEST_STREAMS
+#define __AMCTEST_UNITTEST_STREAMS
+
+
+#include "amc_unittests.hpp"
+#include "common_exportstream_native.hpp"
+#include "common_importstream_native.hpp"
+#include "common_portablezipwriter.hpp"
+#include "common_utils.hpp"
+
+
+namespace AMCUnitTest {
+
+ class CUnitTestGroup_Streams : public CUnitTestGroup {
+ public:
+
+ std::string getTestGroupName() override {
+ return "Streams";
+ }
+
+ void registerTests() override {
+ registerTest("NativeRoundTrip", "Export/import stream roundtrip including seek operations", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_Streams::testNativeRoundTrip, this));
+ registerTest("ZIPRoundTrip", "ZIP export stream writes expected ZIP structures", eUnitTestCategory::utMandatoryPass, std::bind(&CUnitTestGroup_Streams::testZIPRoundTrip, this));
+ }
+
+ void initializeTests() override {
+ }
+
+ private:
+
+ struct CScopedTempDir {
+ std::string m_sPath;
+ CScopedTempDir()
+ {
+ m_sPath = std::string("amc_unittest_streams_") + AMCCommon::CUtils::createUUID();
+ AMCCommon::CUtils::createDirectoryOnDisk(m_sPath);
+ }
+ ~CScopedTempDir()
+ {
+ try {
+ AMCCommon::CUtils::deleteDirectoryFromDisk(m_sPath, false);
+ }
+ catch (...) {
+ }
+ }
+ };
+
+ std::string joinPath(const std::string& sBase, const std::string& sEntry)
+ {
+ std::string baseWithDelimiter = AMCCommon::CUtils::includeTrailingPathDelimiter(sBase);
+ return baseWithDelimiter + sEntry;
+ }
+
+ bool bufferContainsSequence(const std::vector& buffer, const std::vector& sequence)
+ {
+ if (sequence.empty() || (buffer.size() < sequence.size()))
+ return false;
+
+ for (size_t offset = 0; offset <= buffer.size() - sequence.size(); offset++) {
+ bool matches = true;
+ for (size_t index = 0; index < sequence.size(); index++) {
+ if (buffer[offset + index] != sequence[index]) {
+ matches = false;
+ break;
+ }
+ }
+ if (matches)
+ return true;
+ }
+
+ return false;
+ }
+
+ void testNativeRoundTrip()
+ {
+ CScopedTempDir tempDir;
+ std::string filePath = joinPath(tempDir.m_sPath, "stream.bin");
+
+ {
+ AMCCommon::CExportStream_Native exportStream(filePath);
+ const char* initialData = "abcdef";
+ exportStream.writeBuffer(initialData, 6);
+ assertTrue(exportStream.getPosition() == 6);
+
+ exportStream.seekPosition(2, true);
+ exportStream.writeBuffer("ZZ", 2);
+ assertTrue(exportStream.getPosition() == 4);
+
+ exportStream.seekForward(1, true);
+ exportStream.writeBuffer("X", 1);
+
+ exportStream.seekFromEnd(0, true);
+ exportStream.writeZeros(2);
+ exportStream.flushStream();
+ }
+
+ AMCCommon::CImportStream_Native importStream(filePath);
+ uint64_t size = importStream.retrieveSize();
+ assertTrue(size == 8);
+
+ std::vector buffer;
+ buffer.resize(size);
+ importStream.seekPosition(0, true);
+ importStream.readBuffer(buffer.data(), size, true);
+ assertTrue(buffer.at(0) == 'a');
+ assertTrue(buffer.at(1) == 'b');
+ assertTrue(buffer.at(2) == 'Z');
+ assertTrue(buffer.at(3) == 'Z');
+ assertTrue(buffer.at(4) == 'e');
+ assertTrue(buffer.at(5) == 'X');
+ assertTrue(buffer.at(6) == 0);
+ assertTrue(buffer.at(7) == 0);
+
+ importStream.seekPosition(2, true);
+ uint8_t zz[2] = { 0, 0 };
+ importStream.readBuffer(zz, 2, true);
+ assertTrue((zz[0] == 'Z') && (zz[1] == 'Z'));
+
+ importStream.seekPosition(0, true);
+ importStream.seekForward(1, true);
+ uint8_t bChar = 0;
+ importStream.readBuffer(&bChar, 1, true);
+ assertTrue(bChar == 'b');
+
+ importStream.seekFromEnd(2, true);
+ uint8_t tail[2] = { 1, 1 };
+ importStream.readBuffer(tail, 2, true);
+ assertTrue((tail[0] == 0) && (tail[1] == 0));
+ }
+
+ void testZIPRoundTrip()
+ {
+ CScopedTempDir tempDir;
+ std::string filePath = joinPath(tempDir.m_sPath, "stream.zip");
+
+ const std::string entryName = "test.txt";
+ const std::string entryData = "hello zip";
+
+ {
+ auto pExportStream = std::make_shared(filePath);
+ AMCCommon::CPortableZIPWriter zipWriter(pExportStream, true);
+ auto pEntryStream = zipWriter.createEntry(entryName, 0);
+
+ bool thrown = false;
+ try {
+ pEntryStream->seekPosition(0, true);
+ }
+ catch (...) {
+ thrown = true;
+ }
+ assertTrue(thrown, "Expected ZIP export stream to reject seeking");
+
+ pEntryStream->writeBuffer(entryData.data(), entryData.size());
+ zipWriter.closeEntry();
+ zipWriter.writeDirectory();
+ }
+
+ AMCCommon::CImportStream_Native importStream(filePath);
+ std::vector buffer;
+ importStream.readIntoMemory(buffer);
+ assertTrue(buffer.size() > 0);
+
+ const std::vector localHeader = { 'P', 'K', 0x03, 0x04 };
+ const std::vector centralHeader = { 'P', 'K', 0x01, 0x02 };
+ const std::vector endHeader = { 'P', 'K', 0x05, 0x06 };
+ const std::vector nameBytes(entryName.begin(), entryName.end());
+
+ assertTrue(bufferContainsSequence(buffer, localHeader));
+ assertTrue(bufferContainsSequence(buffer, centralHeader));
+ assertTrue(bufferContainsSequence(buffer, endHeader));
+ assertTrue(bufferContainsSequence(buffer, nameBytes));
+ }
+
+ };
+
+}
+
+#endif // __AMCTEST_UNITTEST_STREAMS
diff --git a/build_clean_linux64.sh b/build_clean_linux64.sh
index acf85a643..d1dca4c5a 100755
--- a/build_clean_linux64.sh
+++ b/build_clean_linux64.sh
@@ -7,18 +7,21 @@ export GO111MODULE="off"
basepath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
PLATFORMNAME="linux64"
+CMAKE_OPTIONS=""
for var in "$@"
do
-echo "command line parameter: $var"
-if test $var = "--buildrpi"
-then
- PLATFORMNAME="rpi"
-fi
-if test $var = "--buildwin64"
-then
- PLATFORMNAME="win64"
-fi
+ echo "command line parameter: $var"
+ if test "$var" = "--buildrpi"
+ then
+ PLATFORMNAME="rpi"
+ elif test "$var" = "--buildwin64"
+ then
+ PLATFORMNAME="win64"
+ elif [[ "$var" == -D* ]]
+ then
+ CMAKE_OPTIONS="$CMAKE_OPTIONS $var"
+ fi
done
builddir="$basepath/build_${PLATFORMNAME}"
@@ -136,9 +139,9 @@ cd "$builddir"
echo "Building Core Modules"
if test $PLATFORMNAME = "win64"
then
-cmake -DOVERRIDE_PLATFORM=linux64 -DCMAKE_TOOLCHAIN_FILE=$basepath/BuildScripts/CrossCompile_Win32FromDebian.txt ..
+cmake -DOVERRIDE_PLATFORM=linux64 -DCMAKE_TOOLCHAIN_FILE=$basepath/BuildScripts/CrossCompile_Win32FromDebian.txt $CMAKE_OPTIONS ..
else
-cmake -DOVERRIDE_PLATFORM=$PLATFORMNAME ..
+cmake -DOVERRIDE_PLATFORM=$PLATFORMNAME $CMAKE_OPTIONS ..
fi
cmake --build . --config Release
@@ -167,7 +170,7 @@ cp ../Output/${GITHASH}_core_libmcdata.${DLLEXT} Framework/Dist/
cp ../Output/${GITHASH}_*.data Framework/Dist/
cp ../Output/${GITHASH}_core.client Framework/Dist/
cp ../Output/${GITHASH}_package.xml Framework/Dist/
-cp ../Output/${GITHASH}_driver_*.${DLLEXT} Framework/Dist/
+cp ../Output/${GITHASH}_driver_*.${DLLEXT} Framework/Dist/ 2>/dev/null || echo "No driver libraries found"
cp ../../Framework/HeadersDev/CppDynamic/*.* Framework/HeadersDev/CppDynamic
cp ../../Framework/InterfacesDev/*.* Framework/InterfacesDev
cp ../../Framework/PluginCpp/*.* Framework/PluginCpp