Skip to content

Commit

Permalink
Merge changes from 'hotfix/5.13.7' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
marcosbento committed Jan 27, 2025
2 parents 464d451 + fef041c commit 324b5bc
Show file tree
Hide file tree
Showing 21 changed files with 399 additions and 55 deletions.
3 changes: 2 additions & 1 deletion Viewer/ecflowUI/src/SuiteFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,9 @@ bool SuiteFilter::loadedSameAs(const std::vector<std::string>& loaded) const {

bool SuiteFilter::setLoaded(const std::vector<std::string>& loaded, bool checkDiff) {
bool same = false;
if (checkDiff)
if (checkDiff) {
same = loadedSameAs(loaded);
}

if (!checkDiff || !same) {
return adjustLoaded(loaded);
Expand Down
32 changes: 25 additions & 7 deletions Viewer/ecflowUI/src/VRepeatAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,44 +269,62 @@ int VRepeatDateAttr::currentPosition() const {

int VRepeatDateTimeAttr::endIndex() const {
if (node_ptr node = parent_->node()) {
return ecf::make_range<RepeatDateTime>(node->repeat()).end();
auto& r = node->repeat();
auto rng = ecf::make_range<RepeatDateTime>(r);
auto idx = rng.end();
idx = std::min(idx, rng.size() - 1); // ensure idx is within range [0, size-1]
return idx;
}
return 0;
}

int VRepeatDateTimeAttr::currentIndex() const {
if (node_ptr node = parent_->node()) {
return ecf::make_range<RepeatDateTime>(node->repeat()).current_index();
auto& r = node->repeat();
auto rng = ecf::make_range<RepeatDateTime>(r);
auto idx = rng.current_index();
return idx;
}
return 0;
}

QString VRepeatDateTimeAttr::startValue() const {
if (node_ptr node = parent_->node()) {
return QString::fromStdString(
ecf::Instant::format(ecf::front(ecf::make_range<RepeatDateTime>(node->repeat()))));
auto& r = node->repeat();
auto rng = ecf::make_range<RepeatDateTime>(r);
auto val = ecf::front(rng); // front(rng) returns the first value in the range;
auto fmt = ecf::Instant::format(val);
return QString::fromStdString(fmt);
}
return {};
}

QString VRepeatDateTimeAttr::endValue() const {
if (node_ptr node = parent_->node()) {
return QString::fromStdString(ecf::Instant::format(ecf::back(ecf::make_range<RepeatDateTime>(node->repeat()))));
auto& r = node->repeat();
auto rng = ecf::make_range<RepeatDateTime>(r);
auto val = ecf::back(rng); // back(rng) returns the last value in the range;
auto fmt = ecf::Instant::format(val);
return QString::fromStdString(fmt);
}
return {};
}

std::string VRepeatDateTimeAttr::value(int index) const {
std::stringstream ss;
if (node_ptr node = parent_->node()) {
ss << ecf::Instant::format(ecf::make_range<RepeatDateTime>(node->repeat()).current_value());
auto& r = node->repeat();
auto rng = ecf::make_range<RepeatDateTime>(r);
auto val = rng.at(index);
auto fmt = ecf::Instant::format(val);
ss << fmt;
}
return ss.str();
}

int VRepeatDateTimeAttr::currentPosition() const {
if (node_ptr node = parent_->node()) {
const Repeat& r = node->repeat();
auto& r = node->repeat();
if (r.start() == r.end()) {
return -1;
}
Expand Down
4 changes: 3 additions & 1 deletion docs/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,9 @@
- Generated variables: These are generated within the :term:`suite definition` node tree during :term:`job creation` and are available for use in the :term:`job file`.
Variables can be referenced in :term:`trigger` and :term:`complete expression`\ s . The value part of the variable should be convertible to an integer otherwise a default value of 0 is used.
Variables can be referenced in :term:`trigger` and :term:`complete expression`\ s . When used as part of a :term:`trigger` or :term:`complete expression`, the value of the
variable should be convertible to an integer (n.b. floating point values are allowed, but will be truncated).
It is important to notice that, when evaluating a :term:`trigger` or :term:`complete expression`, the default value 0 will be used for any variable with a non-numerical value.
See also:
Expand Down
2 changes: 1 addition & 1 deletion docs/release_notes/version_5.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Version 5.10.0
REST API
--------

- **New feature**: a new HTTP server provides access to a running ecFlow server via a REST API. This is still experimental and subject to change, but if you'd like to have a look, the documentation is here: :ref:`rest_api`
- **New feature**: a new HTTP server provides access to a running ecFlow server via a REST API. This is still experimental and subject to change, but if you'd like to have a look, the documentation is :ref:`here <rest_api>`.

ecFlowUI
--------
Expand Down
6 changes: 2 additions & 4 deletions docs/rest_api.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.. _rest_api:

REST API
////////

..
This reStructured Text file uses the following convention:
Expand All @@ -10,10 +12,6 @@
^ for subsubsections
" for paragraphs

REST API
//////////////////////

.. caution::
ecFlow's REST API is experimental, and its details are subject to change. The documentation reflects its current operation.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ cron
A :term:`cron` defines a time dependency for a :term:`node`, similar to :term:`time`,
but one that will be repeated indefinitely.

When a node with a :term:`cron` completes it is :term:`queued` immediately, meaning that the suite
will never complete, and the output will not be not directly accessible through :term:`ecflow_ui`
.. warning::

A suite holding a node with a :term:`cron` attribute will **never** reach status *complete*.

A node with a :term:`cron` attribute is immediately set to :term:`queued` after completion.
In practice, this means that nodes containing a :term:`cron` attribute, and enveloping suites,
do not reach status *complete*, and their output is not be directly accessible through :term:`ecflow_ui`.

It is **highly discouraged** to create completion :term:`triggers <trigger>` on nodes/suites containing :term:`cron` attributes.

If the task aborts, the :term:`ecflow_server` will not schedule it again.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,24 @@ date

This defines a date dependency for a node. There can be multiple date
dependencies. The European format is used for dates, which is:
**dd.mm.yy** as in 31.12.2012. Any of the three number fields can be
expressed with a wildcard \* **to mean any valid value. Thus,
01.*.\*** means the first day of every month of every year.
**dd.mm.yyyy** as in ``31.12.2012``. Any of the three numeric fields can be
expressed with a wildcard \* to mean any valid value. For example,
``01.*.*`` can be used to represent the first day of every month of every year.

Currently, you cannot specify a range of values for any of the three
number fields in a date, See :ref:`text_based_def_day` for a way to specify the first seven
days.
.. warning::

A suite holding a node with a :term:`date` attribute may **never** reach status *complete*.

A node with a :term:`date` attribute is immediately set to :term:`queued` after completion.
In practice, this means that nodes containing a :term:`date` attribute, and enveloping suites,
only reach status *complete* when all specified date values have been exhausted -- which might be **never**.

**Extreme care** is advised when creating completion :term:`triggers <trigger>` on nodes/suites
containing :term:`date` attributes.


Currently, a range of values cannot be used to specify any of the three numeric fields in a date.
See :ref:`text_based_def_day` for a way to specify the first seven days.

.. code-block:: shell
Expand All @@ -28,11 +39,11 @@ There are two kinds of clocks:

- Hybrid clocks: A hybrid clock is a complex notion: the date and time are not connected. The date has a fixed value during the complete execution of the suite. This will be mainly used in cases where the suite does not complete in less than 24 hours. This guarantees that all the tasks of this suite are using the same date. On the other hand, the time follows the time of the machine.

Once a suite is complete, it is repeated automatically, with the next
date. The value of the date is contained in the ecFlow variable
ECF_DATE, and the value of the time is in ECF_TIME. ECF_CLOCK contains
other information such as the day of week. A job should always use the
ecFlow variables, and not directly access the system date.
The value of the date is contained in the ecFlow variable
``ECF_DATE``, and the value of the time is in variable ``ECF_TIME``.
The variable ``ECF_CLOCK`` contains other information such as the day of week.
A well designed job should always use these ecFlow variables, and never directly
access the system date.

If a hybrid clock is defined for a suite, any node held by a date
dependency will be set to complete at the beginning of the suite,
Expand Down
8 changes: 8 additions & 0 deletions libs/attribute/src/ecflow/attribute/RepeatAttr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class RepeatDate final : public RepeatBase {
long last_valid_value_plus(int value) const override;

void delta(int d) { delta_ = d; }
int delta() const { return delta_; }
bool operator==(const RepeatDate& rhs) const;
bool operator<(const RepeatDate& rhs) const { return name() < rhs.name(); }

Expand Down Expand Up @@ -338,6 +339,8 @@ class RepeatDateList final : public RepeatBase {
std::string next_value_as_string() const override;
std::string prev_value_as_string() const override;

const std::vector<int>& values() const { return list_; }

void setToLastValue() override;
void reset() override;
void increment() override;
Expand Down Expand Up @@ -389,6 +392,7 @@ class RepeatInteger final : public RepeatBase {
long value() const override { return value_; }
long index_or_value() const override { return value_; }
long last_valid_value() const override;
int delta() const { return delta_; }

RepeatInteger* clone() const override { return new RepeatInteger(name_, start_, end_, delta_, value_); }
bool compare(RepeatBase*) const override;
Expand Down Expand Up @@ -449,6 +453,8 @@ class RepeatEnumerated final : public RepeatBase {
long index_or_value() const override { return currentIndex_; }
long last_valid_value() const override;

const std::vector<std::string>& values() const { return theEnums_; }

RepeatBase* clone() const override { return new RepeatEnumerated(name_, theEnums_, currentIndex_); }
bool compare(RepeatBase*) const override;
bool valid() const override { return (currentIndex_ >= 0 && currentIndex_ < static_cast<int>(theEnums_.size())); }
Expand Down Expand Up @@ -509,6 +515,8 @@ class RepeatString final : public RepeatBase {
std::string next_value_as_string() const override;
std::string prev_value_as_string() const override;

const std::vector<std::string>& values() const { return theStrings_; }

void setToLastValue() override;
void reset() override;
void increment() override;
Expand Down
8 changes: 8 additions & 0 deletions libs/node/src/ecflow/node/ClientSuiteMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,14 @@ void ClientSuiteMgr::suite_added_in_defs(suite_ptr suite) {
}
}

void ClientSuiteMgr::suite_replaced_in_defs(suite_ptr suite) {
size_t client_suites_size = clientSuites_.size();
for (size_t i = 0; i < client_suites_size; i++) {
clientSuites_[i].suite_replaced_in_defs(suite);
clientSuites_[i].update_suite_order();
}
}

void ClientSuiteMgr::suite_deleted_in_defs(suite_ptr suite) {
size_t client_suites_size = clientSuites_.size();
for (size_t i = 0; i < client_suites_size; i++) {
Expand Down
7 changes: 5 additions & 2 deletions libs/node/src/ecflow/node/ClientSuiteMgr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,15 @@ class ClientSuiteMgr {
/// returns the list of suites associated with a handle, Used by ecFlowview
void suites(unsigned int client_handle, std::vector<std::string>& names) const;

/// A suite is being added in the definition.
/// A suite has been added to the definition.
/// If the suite was previously registered *UPDATE* its suite_ptr
/// Otherwise if any ClientSuites registered for automatic inclusion of new suite, add them in
void suite_added_in_defs(suite_ptr);

/// The suite is being deleted in the definition, reset the suite_ptr
/// A suite has been updated in the definition.
void suite_replaced_in_defs(suite_ptr);

/// The suite has been deleted from the definition, reset the suite_ptr
/// Deleted suites STAY registered, until explicitly dropped.
void suite_deleted_in_defs(suite_ptr);

Expand Down
13 changes: 11 additions & 2 deletions libs/node/src/ecflow/node/ClientSuites.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ void ClientSuites::suite_added_in_defs(suite_ptr suite) {
}
}

void ClientSuites::suite_replaced_in_defs(suite_ptr suite) {
// *IF* and *ONLY IF* the suite was previously registered added, *UPDATE* its suite_ptr
auto i = find_suite(suite->name());
if (i != suites_.end()) {
// previously registered suite, update
add_suite(suite);
}
}

void ClientSuites::suite_deleted_in_defs(suite_ptr suite) {
// Deleted suites are *NOT* automatically removed
// They have to be moved explicitly by the user. Reset to weak ptr
Expand Down Expand Up @@ -136,9 +145,9 @@ defs_ptr ClientSuites::create_defs(defs_ptr server_defs) const {
if (suites_.size() == server_defs->suiteVec().size()) {
size_t real_suite_count = 0;
for (auto i = suites_.begin(); i != suites_end; ++i) {
suite_ptr suite = (*i).weak_suite_ptr_.lock();
if (suite.get())
if (suite_ptr suite = (*i).weak_suite_ptr_.lock(); suite.get()) {
real_suite_count++;
}
}
if (real_suite_count == server_defs->suiteVec().size()) {

Expand Down
7 changes: 5 additions & 2 deletions libs/node/src/ecflow/node/ClientSuites.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ class ClientSuites {
void remove_suite(const std::string&);
bool remove_suite(suite_ptr);

/// A new suite is being added in the definition.
/// A new suite has been added to the definition.
/// If it was already registered update the suite ptr
/// If auto add new suite enabled,register it
void suite_added_in_defs(suite_ptr);

/// The suite is being deleted, update modify_change_no. So we do a full sync
/// A suite has been updated in the definition.
void suite_replaced_in_defs(suite_ptr);

/// The suite has been deleted, update modify_change_no. So we do a full sync
/// RESETs suite ptr. Deleted suites are *NOT* automatically removed
void suite_deleted_in_defs(suite_ptr);

Expand Down
Loading

0 comments on commit 324b5bc

Please sign in to comment.