Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 37 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Refresh compile_commands.json",
"type": "shell",
"isBackground": true,
"command": "bazel run @hedron_compile_commands//:refresh_all",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": false
},
"presentation": {
"reveal": "always",
"panel": "shared"
}
},
{
"label": "Refresh IntelliSense",
"dependsOn": [
"Refresh compile_commands.json"
],
"command": "${command:clangd.restart}",
"isBackground": true,
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "silent",
"panel": "shared"
}
}
]
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ This section contains information on how to build and use Lifecycle feature.
* Build System: Bazel
* Operating System: Linux (Ubuntu 22.04+)
* Dependencies: S-Core Baselibs, Google Flatbuffers, libacl1-dev
* Dependencies of demo applications: Docker, Python (3.12)
* Dependencies of example applications: Docker, Python (3.12)

## Building the project

Expand Down Expand Up @@ -122,7 +122,7 @@ TODO: Currently rust binaries are not compiling for QNX.

## Running Lifecycle feature and example applications

The ``demo`` folder contains a demo setup running in a docker container, consisting of a set of example applications and corresponding configuration. As per configuration, Launch Manager will start Health Monitor and a set of configured applications. For more information see [demo/README.md](demo/README.md) file.
The ``examples`` folder contains a demo setup running in a docker container, consisting of a set of example applications and corresponding configuration. As per configuration, Launch Manager will start Health Monitor and a set of configured applications. For more information see [examples/README.md](examples/README.md) file.

## Configuration

Expand Down Expand Up @@ -444,7 +444,7 @@ Sample configuration of Health Monitor daemon:
}
```

Full configuration for example applications can be found in ``demo/config`` folder.
Full configuration for example applications can be found in ``examples/config`` folder.

# Architecture

Expand Down
2 changes: 1 addition & 1 deletion examples/control_application/control_daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ int main(int argc, char** argv) {
}

score::lcm::ControlClient client([](const score::lcm::ExecutionErrorEvent& event) {
std::cerr << "Undefined state callback invoked for process group id: " << event.processGroup.data() << std::endl;
std::cerr << "Undefined state callback invoked for process group id: " << event.processGroup << std::endl;
});

score::safecpp::Scope<> scope{};
Expand Down
2 changes: 2 additions & 0 deletions src/launch_manager_daemon/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# *******************************************************************************
load("//config:common_cc.bzl", "cc_binary_with_common_opts", "cc_library_with_common_opts")

package(default_visibility = ["//tests:__subpackages__"])

cc_library(
name = "config",
hdrs = ["config/lm_flatcfg_generated.h"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/


#ifndef IDENTIFIER_HASH_H_
#define IDENTIFIER_HASH_H_

#include <cstddef>

#include <optional>
#include <ostream>
#include <string>
#include <string_view>
#include <unordered_map>

namespace score {
namespace score
{

namespace lcm {
namespace lcm
{

/// @file identifier_hash.hpp
/// @brief This file contains the declaration of the IdentifierHash class,
Expand All @@ -36,8 +39,9 @@ namespace lcm {
/// @details The class is designed to be used in contexts where IDs needs to be managed,
/// compared, and manipulated. It ensures that IDs are handled efficiently and provides
/// necessary operators and functions for common operations.
class IdentifierHash final {
public:
class IdentifierHash final
{
public:
/// @brief Constructs an IdentifierHash object from the given ID.
/// @param id A const reference to std::string representing an ID.
explicit IdentifierHash(const std::string& id);
Expand Down Expand Up @@ -85,8 +89,8 @@ class IdentifierHash final {
bool operator<(const IdentifierHash& other) const; // Overloaded operator for comparison

///@brief Default constructor for the IdentifierHash class.
///This constructor initializes the IdentifierHash object with a default ID value.
///The ID value is calculated by hashing an empty string using std::hash<std::string>.
/// This constructor initializes the IdentifierHash object with a default ID value.
/// The ID value is calculated by hashing an empty string using std::hash<std::string>.

// this constructor is used in the code that is not part of the POC
// not sure if we should have this constructor or not, but there is code like this:
Expand Down Expand Up @@ -116,11 +120,46 @@ class IdentifierHash final {
/// @return A constant reference to the data stored in the IdentifierHash object.
std::size_t data() const;

private:
/// @brief Returns the registry mapping hash values to their corresponding string representations.
///
/// Static registry, which gets initialized per process.
///
/// @return A reference to the static unordered_map that serves as the registry.
static std::unordered_map<std::size_t, std::string>& get_registry();

private:
/// internal representation of the ID, that was passed in constructor
std::size_t hash_id_ = 0;
};

/// @brief Overloaded stream insertion operator for IdentifierHash.
///
/// This operator allows IdentifierHash objects to be output to an ostream.
/// It uses the the static registry to find the string representation of the hash ID.
///
/// If there is no value stored in the registry for the given hash
/// (i.e. the IdentifierHash is not constructed in this process,
/// instead it has been transferred from another process via e.g. shared memory),
/// it outputs an error message.
///
/// @param os The output stream.
/// @param id The IdentifierHash object to output.
/// @return A reference to the output stream.
inline std::ostream& operator<<(std::ostream& os, const IdentifierHash& id)
{
const auto& reg = IdentifierHash::get_registry();
const auto it = reg.find(id.data());
if (it != reg.end())
{
os << it->second;
}
else
{
os << "<Unknown IdentifierHash: " << id.data() << ">";
}
return os;
}

} // namespace lcm

} // namespace score
Expand Down
52 changes: 38 additions & 14 deletions src/launch_manager_daemon/common/src/identifier_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@

#include <score/lcm/identifier_hash.hpp>
#include <functional>
#include <unordered_map>

namespace score {
namespace score
{

namespace lcm {
namespace lcm
{

// Please note that a lot of the following info, would normally belong to identifier_hash.hpp file.
// However, decision was made to publish identifier_hash.hpp alongside other headers.
Expand Down Expand Up @@ -55,47 +58,68 @@ namespace lcm {
// One thing to note: hashing function is implementation specific.
// So if this should work between different compilers, we may need to go for our own hash function.

IdentifierHash::IdentifierHash(const std::string& id) {
IdentifierHash::IdentifierHash(const std::string& id)
{
hash_id_ = std::hash<std::string>{}(id);
get_registry()[hash_id_] = id;
}

IdentifierHash::IdentifierHash(std::string_view id) {
IdentifierHash::IdentifierHash(std::string_view id)
{
hash_id_ = std::hash<std::string_view>{}(id);
get_registry()[hash_id_] = id;
}

IdentifierHash::IdentifierHash(const char* id) {
hash_id_ =
std::hash<std::string_view>{}(id != nullptr ? std::string_view(id) : std::string_view(""));
IdentifierHash::IdentifierHash(const char* id)
{
const std::string_view sv = (id != nullptr) ? std::string_view(id) : std::string_view("");
hash_id_ = std::hash<std::string_view>{}(sv);
get_registry()[hash_id_] = sv;
}

bool IdentifierHash::operator==(const IdentifierHash& other) const {
bool IdentifierHash::operator==(const IdentifierHash& other) const
{
return hash_id_ == other.hash_id_;
}

bool IdentifierHash::operator!=(const IdentifierHash& other) const {
bool IdentifierHash::operator!=(const IdentifierHash& other) const
{
return !operator==(other);
}

bool IdentifierHash::operator==(const std::string_view& other) const {
bool IdentifierHash::operator==(const std::string_view& other) const
{
return hash_id_ == (IdentifierHash{other}).hash_id_;
}

bool IdentifierHash::operator!=(const std::string_view& other) const {
bool IdentifierHash::operator!=(const std::string_view& other) const
{
return !operator==(IdentifierHash{other});
}

bool IdentifierHash::operator<(const IdentifierHash& other) const {
bool IdentifierHash::operator<(const IdentifierHash& other) const
{
return hash_id_ < other.hash_id_;
}

IdentifierHash::IdentifierHash() {
IdentifierHash::IdentifierHash()
{
hash_id_ = std::hash<std::string_view>{}(std::string_view(""));
get_registry()[hash_id_] = "";
}

std::size_t IdentifierHash::data() const {
std::size_t IdentifierHash::data() const
{
return hash_id_;
}

std::unordered_map<std::size_t, std::string>& IdentifierHash::get_registry()
{
/// Static registry, which gets initialized per process.
static std::unordered_map<std::size_t, std::string> registry;
return registry;
}

} // namespace lcm

} // namespace score
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ bool ProcessStateReader::distributeChanges(const timers::NanoSecondType f_syncTi
const auto changedPosixProcess{resultChangedProcess.value()};
if (changedPosixProcess)
{
logger_r.LogDebug() << "Process with Id" << changedPosixProcess->id.data() << "changed state PG"
<< changedPosixProcess->processGroupStateId.data() << "PS"
logger_r.LogDebug() << "Process with Id" << changedPosixProcess->id << "changed state PG"
<< changedPosixProcess->processGroupStateId << "PS"
<< static_cast<int>(changedPosixProcess->processStateId);
isPushPending = pushUpdateTill(*changedPosixProcess, f_syncTimestamp);
flagContinue = (!isPushPending);
Expand Down
Loading
Loading