Skip to content

Snapshots feature refactor#292

Open
AnnaPaolaMusio wants to merge 12 commits into
eclipse-score:mainfrom
etas-contrib:snapshots-feature-refactor
Open

Snapshots feature refactor#292
AnnaPaolaMusio wants to merge 12 commits into
eclipse-score:mainfrom
etas-contrib:snapshots-feature-refactor

Conversation

@AnnaPaolaMusio

Copy link
Copy Markdown
Contributor

The C++ implementation of the KVS module has been modified in terms of snapshot behavior.

  1. Removal of snapshot_rotate
    The snapshot_rotate function has been completely removed from the C++ implementation. Snapshot management is no longer automatic and requires an explicit call to the snapshot_create() function.

  2. The flush() function no longer automatically creates snapshots.
    In the previous behavior (still valid for RUST) flush() persisted the data and called snapshot_rotate() to automatically create a new snapshot. Now flush() now only persists the current state of the KVS to disk.

  3. Implementation of snapshot_create API
    The new snapshot_create() function has been implemented, allowing for the explicit creation of snapshots in the first available slot.

  4. Implementation of snapshot_delete API
    The snapshot_delete() function has been implemented to explicitly remove a specific snapshots by ID.

  5. Update to snapshot_count and snapshot_restore.

  6. A new component requirement has been introduced, according to the new behaviour of the snapshot_create.

@github-actions

github-actions Bot commented May 26, 2026

Copy link
Copy Markdown

License Check Results

🚀 The license check job ran with the Bazel command:

bazel run --lockfile_mode=error //:license-check

Status: ⚠️ Needs Review

Click to expand output
[License Check Output]
Extracting Bazel installation...
Starting local Bazel server (8.6.0) and connecting to it...
INFO: Invocation ID: 0660ef43-a66e-4091-b028-d4ef98e98455
Computing main repo mapping: 
Computing main repo mapping: 
Computing main repo mapping: 
WARNING: For repository 'rules_python', the root module requires module version rules_python@1.8.3, but got rules_python@1.8.5 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'buildifier_prebuilt', the root module requires module version buildifier_prebuilt@8.2.0.2, but got buildifier_prebuilt@8.5.1 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
WARNING: For repository 'aspect_rules_lint', the root module requires module version aspect_rules_lint@2.0.0, but got aspect_rules_lint@2.5.0 in the resolved dependency graph. Please update the version in your MODULE.bazel or set --check_direct_dependencies=off
Computing main repo mapping: 
Loading: 
Loading: 3 packages loaded
Loading: 3 packages loaded
    currently loading: 
Loading: 3 packages loaded
    currently loading: 
Loading: 3 packages loaded
    currently loading: 
Loading: 3 packages loaded
    currently loading: 
Analyzing: target //:license-check (4 packages loaded, 0 targets configured)
Analyzing: target //:license-check (4 packages loaded, 0 targets configured)

Analyzing: target //:license-check (76 packages loaded, 10 targets configured)

Analyzing: target //:license-check (147 packages loaded, 4023 targets configured)

Analyzing: target //:license-check (154 packages loaded, 8078 targets configured)

Analyzing: target //:license-check (159 packages loaded, 8127 targets configured)

Analyzing: target //:license-check (159 packages loaded, 8127 targets configured)

Analyzing: target //:license-check (162 packages loaded, 10015 targets configured)

Analyzing: target //:license-check (162 packages loaded, 10015 targets configured)

INFO: Analyzed target //:license-check (164 packages loaded, 10265 targets configured).
INFO: From Generating Dash formatted dependency file ...:
INFO: Successfully converted 66 packages from Cargo.lock to bazel-out/k8-fastbuild/bin/formatted.txt
[15 / 17] [Prepa] JavaToolchainCompileBootClasspath external/rules_java+/toolchains/platformclasspath.jar
INFO: Found 1 target...
Target //:license.check.license_check up-to-date:
  bazel-bin/license.check.license_check
  bazel-bin/license.check.license_check.jar
INFO: Elapsed time: 22.181s, Critical Path: 2.16s
INFO: 17 processes: 12 internal, 4 processwrapper-sandbox, 1 worker.
INFO: Build completed successfully, 17 total actions
INFO: Running command line: bazel-bin/license.check.license_check ./formatted.txt <args omitted>
usage: org.eclipse.dash.licenses.cli.Main [-batch <int>] [-cd <url>]
       [-confidence <int>] [-ef <url>] [-excludeSources <sources>] [-help] [-lic
       <url>] [-project <shortname>] [-repo <url>] [-review] [-summary <file>]
       [-timeout <seconds>] [-token <token>]

@github-actions

Copy link
Copy Markdown

The created documentation from the pull request is available at: docu-html

@AnnaPaolaMusio AnnaPaolaMusio marked this pull request as ready for review May 27, 2026 11:43
Comment thread tests/test_cases/tests/test_cit_snapshots.py Outdated
Comment thread src/cpp/src/kvs.cpp
Comment thread src/cpp/src/kvs.cpp Outdated
result = write_json_data(buf);
}
{
/* Write JSON Data */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here that it writes to a file with snapshot ID 0.
Add this information to flush method docs.

Comment thread src/cpp/src/kvs.cpp
size_t count = 0;
bool error = false;
for (size_t idx = 0; idx < KVS_MAX_SNAPSHOTS; ++idx)
for (size_t idx = 1; idx <= KVS_MAX_SNAPSHOTS; ++idx)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so snapshot ID==0 is not considered snapshot? This might be fine, but consider documenting the approach to snapshot ID in score/kvs/docs/requirements/index.rst. It should be written somewhere that 0 is reserved for current storage, and snapshots are in <1; max snapshot> range.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot IDs and files index are two different things.
Snapshot IDs start from 0 to 2, while files index start from 0 to 3.
'kvs_0' is the current kvs while 'kvs_1', 'kvs_2' and 'kvs_3' are the snapshot files.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But Your requirements state that snapshot IDs start at 1?

Comment thread src/cpp/src/kvs.cpp Outdated
const score::filesystem::Path dst_json{filename_prefix.Native() + "_" + to_string(new_snapshot_id) + ".json"};
const score::filesystem::Path dst_hash{filename_prefix.Native() + "_" + to_string(new_snapshot_id) + ".hash"};

const auto copy_json_res = filesystem->standard->CopyFile(src_json, dst_json);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach stores new snapshot based on snapshot 0 file. This can lead to surprising behavior if flush was not done prior to snapshot creation.
I'd consider storing current memory state as less surprising variant, but nonetheless this should be clearly stated.

Comment thread src/cpp/src/kvs.cpp
return count;
}

score::Result<std::size_t> Kvs::snapshot_create()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rework the function to return quickly on error. This will reduce if-else pyramids occurring in the code, with easier tracking on what's the method result.

Comment thread src/cpp/src/kvs.cpp Outdated
}
else
{
if (snapshot_count_res.value() == 0 || snapshot_id.id >= snapshot_max_count())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From previous methods I inferred that range is <1; max snapshot>, but this condition indicates that restoring for max snapshot is disallowed. Similar issue is observed in other methods.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Snapshot IDs start from 0 to 2. Therefore, it is not possible to restore the snapshot ID == 3 . Same check in snapshot_delete function

Comment thread src/cpp/src/kvs.cpp Outdated
else if (snapshot_count_res.value() < snapshot_id.id)
else if (!json_exists_res.value())
{
logger->LogError() << "Snapshot JSON file does not exist: '" << json_path << "'";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if it prints correctly, without added whitespaces surrouding path. If so, consider reworking those logs to logger->LogError() << "Snapshot JSON file does not exist:" << json_path;

Comment thread src/cpp/tests/test_kvs.cpp Outdated
/* Check if files were created correctly */
EXPECT_TRUE(std::filesystem::exists(kvs_prefix + ".json"));
EXPECT_TRUE(std::filesystem::exists(kvs_prefix + ".hash"));
EXPECT_FALSE(std::filesystem::exists(filename_prefix + "_1.json"));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment that having a rotated snapshot was previous expected behavior, or remove check for snapshot ID 1.

Comment thread src/cpp/tests/test_kvs.cpp Outdated
}


/* Crea snapshot non contigui e verifica che il conteggio sia corretto */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace non-english comments.

AnnaPaolaMusio and others added 3 commits June 30, 2026 12:58
Signed-off-by: Anna Paola  <103565983+AnnaPaolaMusio@users.noreply.github.com>
@AnnaPaolaMusio AnnaPaolaMusio requested a review from arkjedrz June 30, 2026 14:39

@arkjedrz arkjedrz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might require comments from other people.

The component shall maintain a configurable maximum number of snapshots.
The component shall create a snapshot in the first available slot when the snapshot_create function is explicitly called.
In the C++ implementation, slot 0 always holds the latest current the KVS (written on flush),
while slots 1 through 3 are available for explicitly created snapshots.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true, when number of snapshots is configurable.

:tags: inspected

The component shall maintain a configurable maximum number of snapshots.
The component shall create a snapshot in the first available slot when the snapshot_create function is explicitly called.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true, when comp_req__kvs__snapshot_id define ID=1 as latest and ID=2,3,4... as older.
Maybe add clear explanation how creation and removal operations affect snapshot IDs available in the system.


The component shall maintain a configurable maximum number of snapshots.
The component shall create a snapshot in the first available slot when the snapshot_create function is explicitly called.
In the C++ implementation, slot 0 always holds the latest current the KVS (written on flush),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requirements should not discuss implementation details for one of the implementations.

Comment thread src/cpp/src/kvs.cpp
else
{
logger->LogError() << "Failed to create directory for KVS file '" << json_path << "'";
logger->LogError() << "Failed to create directory for KVS file : " << json_path;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary whitespaces will occur.

Comment thread src/cpp/src/kvs.cpp
size_t count = 0;
bool error = false;
for (size_t idx = 0; idx < KVS_MAX_SNAPSHOTS; ++idx)
for (size_t idx = 1; idx <= KVS_MAX_SNAPSHOTS; ++idx)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But Your requirements state that snapshot IDs start at 1?

:tags: inspected

The component shall rotate and delete the oldest snapshot when the maximum number is reached.
The component shall assign the ID 1 to the newest snapshot and shall increment the IDs of older snapshots accordingly.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd help to have a clear range of IDs available.

application to implement versioning, including upgrade and downgrade paths,
as needed.

.. comp_req:: Snapshot Creation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This requirement is no longer true with comp_req__kvs__snapshot_explicit_creation in effect. Current storage is something else than snapshots, right?

     * This function creates a snapshot by copying the current KVS file (`*_0.json` and its corresponding `*_0.hash`)
     * into the first available snapshot file (file index : `*_1` .. `*_3`).

Comment thread src/cpp/src/kvs.hpp
* @brief Creates a new snapshot of the current kvs saved on the physical storage.
*
* This function attempts to restore the key-value store to the state
* This function creates a snapshot by copying the current KVS file (`*_0.json` and its corresponding `*_0.hash`)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clear to me, but raising this topic as a point for discussion if snapshot_create should dump current file state or current memory state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants