Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support of transient federates #2213

Open
wants to merge 71 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
272da11
Add isTransient member to a federated instance and parse the transien…
ChadliaJerad Jan 11, 2024
ab8b5d3
Set the transient indicator
ChadliaJerad Jan 11, 2024
4daef37
Make federates bin directory visible
ChadliaJerad Feb 20, 2024
dffabc4
Add support of transient attribute
ChadliaJerad Jan 11, 2024
eb5eb21
Transient annotation is only allowed for federates + Leave fixmes abo…
ChadliaJerad Jan 11, 2024
dc95f45
Align reactor-c
ChadliaJerad Feb 14, 2024
612d057
Add the number of transients option to the fderation launcher script
ChadliaJerad Feb 19, 2024
ee48c1d
Fix script identation
ChadliaJerad Feb 19, 2024
0766e03
Add transients tests
ChadliaJerad Feb 20, 2024
4925182
Apply spotless
ChadliaJerad Feb 20, 2024
94a10c2
Apply spotless
ChadliaJerad Feb 20, 2024
bbca7ac
Fix accidentally removed line from FederateInstance.java
ChadliaJerad Feb 21, 2024
6bfa7c8
Update core/src/main/java/org/lflang/federated/launcher/FedLauncherGe…
ChadliaJerad Feb 22, 2024
51eb135
Update test/C/src/federated/transient/TransientHotSwap.lf
ChadliaJerad Feb 22, 2024
e7b9505
Address review by removing FIXMEs and open an issue instead
ChadliaJerad Feb 22, 2024
3624e6b
Address review by removing period from TransientExec in transients te…
ChadliaJerad Feb 22, 2024
740e006
Reduce the probability of flaky failiures due to indeterminate amount…
ChadliaJerad Feb 22, 2024
de3c0ba
Fix TransientHotSwap documentation based on review
ChadliaJerad Feb 22, 2024
ad48c81
Apply spotless
ChadliaJerad Feb 22, 2024
1671246
Fix TransientDownstreamWithTwoUpstreams error condition to account do…
ChadliaJerad Feb 22, 2024
c99fe39
Add TransientStatePersistence test and align reactor-c
ChadliaJerad Feb 29, 2024
2f0be1c
Apply Spotless
ChadliaJerad Feb 29, 2024
b1a7436
Typo + Adjust message
ChadliaJerad Mar 18, 2024
5c1d050
Use lf_tag_effective_start() instead of lf_get_effective_start_tag()
ChadliaJerad Mar 18, 2024
35903ab
Fix comment
ChadliaJerad Mar 18, 2024
ff93cd7
Minor updates to transient tests
ChadliaJerad Mar 18, 2024
4d8849f
Add authentication to TransientDownstreamWithTimer.lf test
ChadliaJerad Apr 24, 2024
9167a31
TransientHotSwap test uses authentication + Align reactorC
ChadliaJerad May 18, 2024
6267fcb
Fix the usage of authentication is transient tests
ChadliaJerad Jun 19, 2024
d518b37
Include LF_FEDERATES_BIN_DIRECTORY in cmake for federaes + Align reac…
ChadliaJerad Jun 20, 2024
3c5a634
Align reactor-c
ChadliaJerad Dec 30, 2024
428fd00
Make federates bin directory visible
ChadliaJerad Feb 20, 2024
7d8638e
Include LF_FEDERATES_BIN_DIRECTORY is cmake for federaes + Align reac…
ChadliaJerad Jun 20, 2024
7dca421
Support zero-delay cycles
edwardalee Jul 15, 2024
07fd0cf
Fixed compile and Docker errors
edwardalee Jul 15, 2024
1ce4da7
Format
edwardalee Jul 15, 2024
8390155
Fix code printing of eroDelayCycleNetworkUpstreamFeds
ChadliaJerad Jul 17, 2024
1e6a1b1
Corrected upstream settings
edwardalee Jul 17, 2024
9cf954d
Fix merge of maybeQuote in CCmpiler + Align reactor-c
ChadliaJerad Jul 24, 2024
d1ac2e7
Revert quotes specification in cmakeOptions()
ChadliaJerad Aug 7, 2024
ec3b190
Remove no more needed import
ChadliaJerad Aug 7, 2024
2e349d2
Update the preamble in transients tests
ChadliaJerad Aug 7, 2024
ce66d8b
Remove compile definition of the federate bin path + Align reactor-c
ChadliaJerad Aug 7, 2024
aa8a2ee
Run spotles
ChadliaJerad Aug 7, 2024
2b8cb9b
Apply formatter
ChadliaJerad Aug 14, 2024
060c7e9
Apply spotless
ChadliaJerad Dec 2, 2024
34b6cb6
Attempt to pass tests by manually adding prototypes to lf code
ChadliaJerad Dec 2, 2024
9705333
Attempt to fix redundant declaration error
ChadliaJerad Dec 2, 2024
b08a78a
Removed lf_get_federates_bin_directory. Use LF_FED_PACKAGE_DIRECTORY
edwardalee Dec 2, 2024
58ca5b1
Debugging state persistence in CI
ChadliaJerad Dec 4, 2024
7d68906
More output in State Persistence test + Apply Spotless
ChadliaJerad Dec 4, 2024
84a96c3
Fix error in TransientStatePersistence
ChadliaJerad Dec 5, 2024
9212264
Avoid name tangling when running CCPP tests
ChadliaJerad Dec 5, 2024
418afdb
Try refactoring TransientStatePersistence test
ChadliaJerad Dec 5, 2024
6a943a5
Cleaned up lf_get_federation_id
edwardalee Dec 8, 2024
8da5c8a
Fix messages order in TransientStatePersistence test + format + align…
ChadliaJerad Dec 9, 2024
961f0a4
Better logical ordering of the reactions in transients tests + align …
ChadliaJerad Dec 11, 2024
ff68011
Cleanup after rebase
ChadliaJerad Jan 3, 2025
93b5719
Aligne reactor-c
ChadliaJerad Jan 3, 2025
322bc2b
Align reactr-c
ChadliaJerad Jan 4, 2025
a382d29
Merge branch 'master' into transient-fed
ChadliaJerad Jan 4, 2025
4e33e86
Align reactor-c
ChadliaJerad Jan 4, 2025
141a420
Align reactor-c
ChadliaJerad Jan 4, 2025
ea39b50
Align reactor-c
ChadliaJerad Jan 4, 2025
779df68
Align reactor-c
ChadliaJerad Jan 5, 2025
00e2492
Merge branch 'master' into transient-fed
ChadliaJerad Jan 13, 2025
b19c602
Fix adding LF_SOURCE_GEN_DIRECTORY flag to cmake
ChadliaJerad Jan 13, 2025
17413f7
Merge branch 'master' into transient-fed
ChadliaJerad Jan 23, 2025
b567efe
Align reactor-cpp
ChadliaJerad Jan 23, 2025
f304a44
Merge branch 'update-github-actions' into transient-fed
ChadliaJerad Jan 23, 2025
935b2e5
Merge branch 'master' into transient-fed
ChadliaJerad Jan 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/src/main/java/org/lflang/AttributeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ public static boolean isSparse(EObject node) {
return findAttributeByName(node, "sparse") != null;
}

/** Return true if the node has an {@code @transient} attribute. */
public static boolean isTransient(Instantiation node) {
return findAttributeByName(node, "transient") != null;
}

/** Return true if the reactor is marked to be a federate. */
public static boolean isFederate(Reactor reactor) {
return findAttributeByName(reactor, "_fed_config") != null;
Expand Down
28 changes: 24 additions & 4 deletions core/src/main/java/org/lflang/federated/extensions/CExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ public String generatePortAbsentReactionBody(
+ receivingPortID
+ ", "
+ connection.getDstFederate().id
+ ", (long long) lf_time_logical_elapsed());",
+ ", lf_time_logical_elapsed());",
"if (" + sendRef + " == NULL || !" + sendRef + "->is_present) {",
"LF_PRINT_LOG(\"The output port is NULL or it is not present.\");",
" lf_send_port_absent_to_federate("
Expand Down Expand Up @@ -553,15 +553,33 @@ protected String makePreamble(
// that handles incoming network messages destined to the specified
// port. This will only be used if there are federates.
int numOfNetworkActions = federate.networkMessageActions.size();
int numZDCNetworkActions = federate.zeroDelayCycleNetworkMessageActions.size();
code.pr(
"""
interval_t _lf_action_delay_table[%1$s];
lf_action_base_t* _lf_action_table[%1$s];
size_t _lf_action_table_size = %1$s;
lf_action_base_t* _lf_zero_delay_cycle_action_table[%2$s];
size_t _lf_zero_delay_cycle_action_table_size = %2$s;
"""
.formatted(numOfNetworkActions, federate.zeroDelayCycleNetworkMessageActions.size()));
.formatted(numOfNetworkActions));
if (numZDCNetworkActions > 0) {
code.pr(
"""
lf_action_base_t* _lf_zero_delay_cycle_action_table[%1$s];
size_t _lf_zero_delay_cycle_action_table_size = %1$s;
uint16_t _lf_zero_delay_cycle_upstream_ids[%1$s];
bool _lf_zero_delay_cycle_upstream_disconnected[%1$s] = { false };
"""
.formatted(numZDCNetworkActions));
} else {
// Make sure these symbols are defined, even though only size will be used.
code.pr(
"""
lf_action_base_t** _lf_zero_delay_cycle_action_table = NULL;
size_t _lf_zero_delay_cycle_action_table_size = 0;
uint16_t* _lf_zero_delay_cycle_upstream_ids = NULL;
bool* _lf_zero_delay_cycle_upstream_disconnected = NULL;
""");
}

int numOfNetworkReactions = federate.networkReceiverReactions.size();
code.pr(
Expand Down Expand Up @@ -723,6 +741,8 @@ else if (globalSTP instanceof CodeExprImpl)
}
// Set global variable identifying the federate.
code.pr("_lf_my_fed_id = " + federate.id + ";");
// Set indicator variable that specifies whether the federate is transient or not.
code.pr("_fed.is_transient = " + federate.isTransient + ";");

// We keep separate record for incoming and outgoing p2p connections to allow incoming traffic
// to be processed in a separate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ public static String initializeTriggersForNetworkActions(
CodeBuilder code = new CodeBuilder();
if (!federate.networkMessageActions.isEmpty()) {
var actionTableCount = 0;
var zeroDelayActionTableCount = 0;
for (int i = 0; i < federate.networkMessageActions.size(); ++i) {
// Find the corresponding ActionInstance.
Action action = federate.networkMessageActions.get(i);
Expand All @@ -76,10 +75,17 @@ public static String initializeTriggersForNetworkActions(
// Set the ID of the source federate.
code.pr(
trigger + ".source_id = " + federate.networkMessageSourceFederate.get(i).id + "; \\");
if (federate.zeroDelayCycleNetworkMessageActions.contains(action)) {
int j = federate.zeroDelayCycleNetworkMessageActions.indexOf(action);
if (j >= 0) {
var upstream = federate.zeroDelayCycleNetworkUpstreamFeds.get(j);
code.pr("_lf_zero_delay_cycle_upstream_ids[" + j + "] = " + upstream.id + "; \\");
if (upstream.isTransient) {
// Transient federates are assumed to be initially disconnected.
code.pr("_lf_zero_delay_cycle_upstream_disconnected[" + j + "] = true; \\");
}
code.pr(
"_lf_zero_delay_cycle_action_table["
+ zeroDelayActionTableCount++
+ j
+ "] = (lf_action_base_t*)&"
+ trigger
+ "; \\");
Expand Down Expand Up @@ -151,7 +157,8 @@ public static String stpStructs(FederateInstance federate) {
*/
public static String createPortStatusFieldForInput(Input input) {
StringBuilder builder = new StringBuilder();
// If it is not a multiport, then we could re-use the port trigger, and nothing needs to be done
// If it is not a multiport, then we could re-use the port trigger, and nothing
// needs to be done
if (ASTUtils.isMultiport(input)) {
// If it is a multiport, then create an auxiliary list of port
// triggers for each channel of
Expand Down Expand Up @@ -236,12 +243,13 @@ static boolean clockSyncIsOn(FederateInstance federate, RtiConfig rtiConfig) {
*
* <p>Clock synchronization can be enabled using the clock-sync target property.
*
* @see <a
* href="https://github.com/icyphy/lingua-franca/wiki/Distributed-Execution#clock-synchronization">Documentation</a>
* @see <a href=
* "https://github.com/icyphy/lingua-franca/wiki/Distributed-Execution#clock-synchronization">Documentation</a>
*/
public static void initializeClockSynchronization(
FederateInstance federate, RtiConfig rtiConfig, MessageReporter messageReporter) {
// Check if clock synchronization should be enabled for this federate in the first place
// Check if clock synchronization should be enabled for this federate in the
// first place
if (clockSyncIsOn(federate, rtiConfig)) {
messageReporter
.nowhere()
Expand All @@ -267,8 +275,8 @@ public static void initializeClockSynchronization(
*
* <p>Clock synchronization can be enabled using the clock-sync target property.
*
* @see <a
* href="https://github.com/icyphy/lingua-franca/wiki/Distributed-Execution#clock-synchronization">Documentation</a>
* @see <a href=
* "https://github.com/icyphy/lingua-franca/wiki/Distributed-Execution#clock-synchronization">Documentation</a>
*/
public static void addClockSyncCompileDefinitions(FederateInstance federate) {

Expand Down Expand Up @@ -311,8 +319,15 @@ public static void generateCMakeInclude(
"add_compile_definitions(LF_SOURCE_DIRECTORY=\"" + fileConfig.srcPath + "\")");
cmakeIncludeCode.pr(
"add_compile_definitions(LF_PACKAGE_DIRECTORY=\"" + fileConfig.srcPkgPath + "\")");
// After federates have been divided, their root package directory is different.
cmakeIncludeCode.pr(
"add_compile_definitions(LF_SOURCE_GEN_DIRECTORY=\"" + fileConfig.getSrcGenPath() + "\")");
"add_compile_definitions(LF_FED_PACKAGE_DIRECTORY=\""
+ fileConfig.srcPkgPath
+ File.separator
+ "fed-gen"
+ File.separator
+ fileConfig.name
+ "\")");
cmakeIncludeCode.pr("add_compile_definitions(LF_FILE_SEPARATOR=\"" + File.separator + "\")");
try (var srcWriter = Files.newBufferedWriter(cmakeIncludePath)) {
srcWriter.write(cmakeIncludeCode.getCode());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,10 @@ private static void addNetworkReceiverReactor(
connection.dstFederate.networkMessageSourceFederate.add(connection.srcFederate);
connection.dstFederate.networkMessageActionDelays.add(connection.getDefinition().getDelay());
if (connection.srcFederate.isInZeroDelayCycle()
&& connection.getDefinition().getDelay() == null)
&& connection.getDefinition().getDelay() == null) {
connection.dstFederate.zeroDelayCycleNetworkMessageActions.add(networkAction);

connection.dstFederate.zeroDelayCycleNetworkUpstreamFeds.add(connection.srcFederate);
}
// Get the largest STAA for any reaction triggered by the destination port.
TimeValue maxSTAA = findMaxSTAA(connection, coordination);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.lflang.AttributeUtils;
import org.lflang.MessageReporter;
import org.lflang.TimeValue;
import org.lflang.ast.ASTUtils;
Expand Down Expand Up @@ -96,6 +97,7 @@ public FederateInstance(
this.bankWidth = bankWidth;
this.messageReporter = messageReporter;
this.targetConfig = targetConfig;
this.isTransient = AttributeUtils.isTransient(instantiation);

// If the instantiation is in a bank, then we have to append
// the bank index to the name.
Expand Down Expand Up @@ -157,6 +159,9 @@ public Instantiation getInstantiation() {
/** The integer ID of this federate. */
public int id;

/** Type of the federate: transient if true, and peristent if false . */
public boolean isTransient = false;

/**
* The name of this federate instance. This will be the instantiation name, possibly appended with
* "__n", where n is the bank position of this instance if the instantiation is of a bank of
Expand Down Expand Up @@ -188,6 +193,12 @@ public Instantiation getInstantiation() {
*/
public List<Action> zeroDelayCycleNetworkMessageActions = new ArrayList<>();

/**
* List of upstream federates corresponding to actions in the zeroDelayCycleNetworkMessageActions
* list.
*/
public List<FederateInstance> zeroDelayCycleNetworkUpstreamFeds = new ArrayList<>();

/**
* A set of federates with which this federate has an inbound connection There will only be one
* physical connection even if federate A has defined multiple physical connections to federate B.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,17 @@ private String getRtiCommand(List<FederateInstance> federates, boolean isRemote)
if (targetConfig.getOrDefault(TracingProperty.INSTANCE).isEnabled()) {
commands.add(" -t \\");
}
// Identify the number of transient federates.
int transientFederatesNumber = 0;
for (FederateInstance federate : federates) {
if (federate.isTransient) {
transientFederatesNumber++;
}
}
commands.addAll(
List.of(
" -n " + federates.size() + " \\",
" -nt " + transientFederatesNumber + " \\",
" -c "
+ targetConfig.getOrDefault(ClockSyncModeProperty.INSTANCE).toString()
+ " \\"));
Expand Down
13 changes: 7 additions & 6 deletions core/src/main/java/org/lflang/generator/c/CCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ public boolean runCCompiler(GeneratorBase generator, LFGeneratorContext context)
// avoid any error residue that can occur in CMake from
// a previous build.
// FIXME: This is slow and only needed if an error
// has previously occurred. Deleting the build directory
// if no prior errors have occurred can prolong the compilation
// substantially. See #1416 for discussion.
// has previously occurred. Deleting the build directory
// if no prior errors have occurred can prolong the compilation
// substantially. See #1416 for discussion.
FileUtil.deleteDirectory(buildPath);
// Make sure the build directory exists
Files.createDirectories(buildPath);
Expand Down Expand Up @@ -240,14 +240,15 @@ private static List<String> cmakeOptions(TargetConfig targetConfig, FileConfig f
+ FileUtil.toUnixString(fileConfig.getOutPath().relativize(fileConfig.binPath)),
"-DLF_FILE_SEPARATOR='" + quote + separator + quote + "'"));
// Add #define for source file directory.
// Do not do this for federated programs because for those, the definition is put
// into the cmake file (and fileConfig.srcPath is the wrong directory anyway).
// Do not do this for federated programs because for those, the definition is
// put into the cmake file (and fileConfig.srcPath is the wrong directory
// anyway).
if (!fileConfig.srcPath.toString().contains("fed-gen")) {
// Do not convert to Unix path
arguments.add("-DLF_SOURCE_DIRECTORY='" + quote + srcPath + quote + "'");
arguments.add("-DLF_PACKAGE_DIRECTORY='" + quote + rootPath + quote + "'");
arguments.add("-DLF_SOURCE_GEN_DIRECTORY='" + quote + srcGenPath + quote + "'");
}
arguments.add("-DLF_SOURCE_GEN_DIRECTORY='" + quote + srcGenPath + quote + "'");
arguments.add(FileUtil.toUnixString(fileConfig.getSrcGenPath()));

if (GeneratorUtils.isHostWindows()) {
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/lflang/validation/AttributeSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ enum AttrParamType {
new AttributeSpec(List.of(new AttrParamSpec(VALUE_ATTR, AttrParamType.STRING, false))));
// @sparse
ATTRIBUTE_SPECS_BY_NAME.put("sparse", new AttributeSpec(null));
// @transient
ATTRIBUTE_SPECS_BY_NAME.put("transient", new AttributeSpec(null));
// @icon("value")
ATTRIBUTE_SPECS_BY_NAME.put(
"icon",
Expand Down
13 changes: 13 additions & 0 deletions core/src/main/java/org/lflang/validation/LFValidator.java
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,19 @@ public void checkInstantiation(Instantiation instantiation) {
error("Variable-width banks are not supported.", Literals.INSTANTIATION__WIDTH_SPEC);
}
}

// If the Instantiation is annotated as '@transient', then:
// - The container has to be a federated reactor,
// - The coordination is centralized,
// - And the target is C.
if (AttributeUtils.isTransient(instantiation)) {
Reactor container = (Reactor) instantiation.eContainer();
if (!container.isFederated()) {
error(
"Only federates can be transients: " + instantiation.getReactorClass().getName(),
Literals.INSTANTIATION__REACTOR_CLASS);
}
}
}

@Check(CheckType.FAST)
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/resources/lib/cpp/reactor-cpp
Submodule reactor-cpp updated 1 files
+2 −2 CONTRIBUTING.md
Loading