Skip to content

ECKIT-635 FAM Mock and data structures on FAM via OpenFAM lib#209

Open
mcakircali wants to merge 240 commits intodevelopfrom
feature/ECKIT-635_fam-backend-map
Open

ECKIT-635 FAM Mock and data structures on FAM via OpenFAM lib#209
mcakircali wants to merge 240 commits intodevelopfrom
feature/ECKIT-635_fam-backend-map

Conversation

@mcakircali
Copy link
Copy Markdown
Contributor

@mcakircali mcakircali commented Jul 2, 2025

Description

Adds a FAM-backed unordered map (plus supporting list/session/URI infrastructure) and an OpenFAM mock implementation to enable development/testing without a real OpenFAM deployment.

Introduces:

  • FAM data structures (FamList, FamMap, iterators, entries) and associated naming/URI/session utilities.
  • OpenFAM mock (shared-memory based), wired into the cmake configuration.
  • suite of OpenFAM/FAM unit tests
  • CMake options for OpenFAM/OpenFAM-mock builds

Contributor Declaration

By opening this pull request, I affirm the following:

  • All authors agree to the Contributor License Agreement.
  • The code follows the project's coding standards.
  • I have performed self-review and added comments where needed.
  • I have added or updated tests to verify that my changes are effective and functional.
  • I have run all existing tests and confirmed they pass.

🌦️ >> Documentation << 🌦️
https://sites.ecmwf.int/docs/dev-section/eckit/pull-requests/PR-209

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 57 out of 58 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mcakircali mcakircali changed the title ECKIT-635 FAM data structures ECKIT-635 FAM Mock and data structures on FAM via OpenFAM lib Mar 23, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 57 out of 58 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mcakircali mcakircali force-pushed the feature/ECKIT-635_fam-backend-map branch from ca84fec to 682537f Compare March 24, 2026 09:33

ecbuild_add_option( FEATURE OPENFAM
DEFAULT OFF
REQUIRED_PACKAGES "LibUUID REQUIRED" "OpenFAM 3.2.0 REQUIRED"
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.

You definitely do not need to repeat "REQUIRED" within the REQUIRED_PACKAGES.

Also, for something truly optional, I don't know that we want to pollute the output with error messages for optional packages.

Typically something like:

find_package(LibUUID QUIET)
find_package(OpenFAM 3.2 QUIET)

ecbuild_add_option(
FEATURE OPENFAM_MOCK
DEFAULT NOT OpenFAM_FOUND
CONDITION LibUUID_FOUND
DESCRITION "Use dummy implementation of FAM for testing"
)

ecbuild_add_option(
FEATURE OPENFAM
DEFAULT ON
CONDITION (OpenFAM_FOUND OR HAVE_OPENFAM_MOCK) AND LibUUID_FOUND)
DESCRIPTION "OPENFAM suuport"
)

(Code not tested, apologies for any typos/errors)

REQUIRED_PACKAGES "LibUUID REQUIRED"
DESCRIPTION "Enables OpenFAM Mock for testing and development." )

if( eckit_HAVE_OPENFAM_MOCK )
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.

The logic here is not quite right. See suggestion for previous comment.

namespace mock {

//----------------------------------------------------------------------------------------------------------------------
/// Capacity (@note: don't just change values)
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.

Can you explain what these values are, where they come from, and why they should not just be changed. That is not obvious at all.


// Build time check that State fits into the shared-memory segment.
// Leave at least 16 MiB for the data area.
static_assert(sizeof(State) + 16 * 1024 * 1024 <= g_shm_total_size,
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.

Why 16MiB? That is a bit of a magic number here?

void reset();

/// Same as reset() but must be called while the mutex is held (e.g., during initialization).
void resetUnlocked();
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.

Is this something we want to have as a public method?

new_object.put(length, offsetof(FamListNode, length));
new_object.put(data, sizeof(FamListNode), length);

// 2. Link into list: use CAS-loop to atomically update head.next
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.

Be explicit. CAS === Compare-And-Swap.

///
/// Supports multiple readers and writers operating concurrently without locks.
/// Implements wait-free insertion and logical deletion, with version-based ABA detection.
class FamList {
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 class really is great.


/// Check if key already exists
/// @note: This check-then-insert sequence is not atomic.
/// concurrent inserts of the same key may both insert resulting duplicates.
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 come and discuss. I want to understand what needs to be done to make this 'right'.

Can we write a test case that fails due to the non-atomicity.


/// Encode a key-value pair into a flat buffer for storage in FamList nodes.
/// Layout: [key (KeySize bytes)] [value data (length bytes)]
static Buffer encode(const key_type& key, const void* data, size_type length) {
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.

Do we need to construct a contiguous buffer, and write that to FAM. IS that more efficient than writing the data to FAM directly in two chunks, only doing the assembly in-situ?

}
++bucket_;
}
// we reached the end
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.

some of these comments are pretty uninformative.

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.

4 participants