From 9f311c4d0c4d8775f9da168a42e6f4f967f50611 Mon Sep 17 00:00:00 2001 From: Deepak <56668629+deepakmaroo@users.noreply.github.com> Date: Thu, 5 Mar 2026 10:03:03 +0100 Subject: [PATCH 1/4] Integrated UDA-Plugins api listFilledPaths - API listFilledPaths returns the list of filled paths of given IDS --- src/uda/uda_backend.cpp | 124 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/src/uda/uda_backend.cpp b/src/uda/uda_backend.cpp index 74a538b3..a0c55fb9 100644 --- a/src/uda/uda_backend.cpp +++ b/src/uda/uda_backend.cpp @@ -1258,6 +1258,54 @@ std::vector read_occurrences(NodeReader *node) { return occurrences; } +std::vector read_filled_paths(NodeReader *node) { + std::vector paths; + + // Read the shape + std::vector shape_vec(1); + uda_capnp_read_shape(node, shape_vec.data()); + const size_t total_bytes = std::accumulate(shape_vec.begin(), shape_vec.end(), 1, std::multiplies()); + + // For empty buffers, return empty list + if (total_bytes == 0) { + return paths; + } + + const char *name = uda_capnp_read_name(node); + if (name != nullptr && std::string(name) != "filled_paths") { + throw imas::uda::CacheException("Invalid node: " + std::string(name)); + } + + bool eos = uda_capnp_read_is_eos(node); + if (!eos) { + throw imas::uda::CacheException("UDA backend does not currently handle streamed data"); + } + + size_t num_slices = uda_capnp_read_num_slices(node); + if (num_slices != 1) { + throw imas::uda::CacheException("Incorrect number of slices for filled_paths node"); + } + + // Read the data slice + size_t slice_size = uda_capnp_read_slice_size(node, 0); + if (slice_size != total_bytes) { + throw imas::uda::CacheException("Slice size does not match total bytes for filled_paths"); + } + + std::vector buffer(total_bytes); + uda_capnp_read_data(node, 0, buffer.data()); + + const char* ptr = buffer.data(); + const char* end = ptr + total_bytes; + + while (ptr < end && *ptr != '\0') { + std::string path(ptr); + paths.push_back(path); + ptr += strlen(ptr) + 1; + } + + return paths; +} } // anon namespace void UDABackend::get_occurrences(Context* ctx, const char* ids_name, int** occurrences_list, int* size) { @@ -1311,5 +1359,79 @@ void UDABackend::get_occurrences(Context* ctx, const char* ids_name, int** occur } void UDABackend::list_filled_paths(Context* ctx, const char* dataobjectname, char*** path_list, int* size) { - throw ALBackendException("list_filled_paths is not implemented in the UDA Backend", LOG); + if (access_local_) { + return local_backend_->list_filled_paths(ctx, dataobjectname, path_list, size); + } + + if (verbose_) { + std::cout << "UDABackend list_filled_paths\n"; + } + + auto query = ctx->getURI().query; + std::string backend = get_backend(query); + if (backend != "hdf5") { + throw ALException("UDABackend only supports HDF5 backend for list_filled_paths API", LOG); + } + + query.remove("backend"); + query.remove("cache_mode"); + query.remove("verbose"); + std::string dd_version = query.get("dd_version").value_or(dd_version_); + query.set("dd_version", dd_version); + std::string uri = "imas:" + backend + "?" + query.to_string(); + + std::stringstream ss; + + ss << plugin_ + << "::listFilledPaths(" + << "uri='" << uri << "'" + << ", ids='" << dataobjectname << "'" + << ")"; + + const std::string directive = ss.str(); + + if (verbose_) { + std::cout << "UDABackend request: " << directive << "\n"; + } + + try { + const uda::Result& result = uda_client_.get(directive, ""); + + if (result.errorCode() == 0 && result.uda_type() == UDA_TYPE_CAPNP) { + const char* data = result.raw_data(); + const size_t result_size = result.size(); + + // If buffer is empty, return empty path list + if (result_size == 0) { + *size = 0; + *path_list = nullptr; + return; + } + + const auto tree = uda_capnp_deserialise(data, result_size); + const auto root = uda_capnp_read_root(tree); + + auto paths = read_filled_paths(root); + *size = static_cast(paths.size()); + + if (*size > 0) { + *path_list = static_cast(malloc(sizeof(char*) * (*size))); + for (int i = 0; i < *size; ++i) { + (*path_list)[i] = static_cast(malloc(paths[i].length() + 1)); + strcpy((*path_list)[i], paths[i].c_str()); + } + } else { + *path_list = nullptr; + } + + uda_capnp_free_tree_reader(tree); + } else { + *size = 0; + *path_list = nullptr; + } + } catch (const uda::UDAException& ex) { + throw ALException(ex.what(), LOG); + } catch (const std::exception& ex) { + throw; + } } From a1fece2949375838b49698d09c40315bb17930f4 Mon Sep 17 00:00:00 2001 From: marood Date: Thu, 5 Mar 2026 17:55:50 +0100 Subject: [PATCH 2/4] Added al_utilities and function to convert vector of strings into a C-style array of strings --- src/CMakeLists.txt | 1 + src/hdf5/hdf5_reader.cpp | 7 ++----- src/uda/uda_backend.cpp | 23 +++++++---------------- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2800528e..3aa7a997 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources( al PRIVATE al_context.cpp al_const.cpp al_exception.cpp + al_utilities.cpp no_backend.cpp memory_backend.cpp ascii_backend.cpp diff --git a/src/hdf5/hdf5_reader.cpp b/src/hdf5/hdf5_reader.cpp index 04dcd7e0..a4a553b9 100644 --- a/src/hdf5/hdf5_reader.cpp +++ b/src/hdf5/hdf5_reader.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "al_utilities.h" #define MAX_LENGTH 200 #define HOMOGENEOUS_TIME_FIELD_NAME "ids_properties&homogeneous_time" @@ -1604,11 +1605,7 @@ void HDF5Reader::list_filled_paths(const char* dataobjectname, char*** path_list } // Create the C-style array: - *size = variables.size(); - *path_list = (char**) malloc(*size * sizeof(char*)); - for (int i=0; i < *size; ++i) { - (*path_list)[i] = strdup(variables[i].c_str()); - } + utilities::copy_stringvector_to_c_list(variables, path_list, size); } herr_t HDF5Reader::iterate_callback(hid_t loc_id, const char *name, const H5L_info_t *info, void *callback_data) diff --git a/src/uda/uda_backend.cpp b/src/uda/uda_backend.cpp index a0c55fb9..b8bf1b6f 100644 --- a/src/uda/uda_backend.cpp +++ b/src/uda/uda_backend.cpp @@ -17,6 +17,7 @@ #include #include +#include "al_utilities.h" using namespace semver::literals; @@ -1359,6 +1360,10 @@ void UDABackend::get_occurrences(Context* ctx, const char* ids_name, int** occur } void UDABackend::list_filled_paths(Context* ctx, const char* dataobjectname, char*** path_list, int* size) { + + *size = 0; + *path_list = nullptr; + if (access_local_) { return local_backend_->list_filled_paths(ctx, dataobjectname, path_list, size); } @@ -1403,8 +1408,6 @@ void UDABackend::list_filled_paths(Context* ctx, const char* dataobjectname, cha // If buffer is empty, return empty path list if (result_size == 0) { - *size = 0; - *path_list = nullptr; return; } @@ -1412,22 +1415,10 @@ void UDABackend::list_filled_paths(Context* ctx, const char* dataobjectname, cha const auto root = uda_capnp_read_root(tree); auto paths = read_filled_paths(root); - *size = static_cast(paths.size()); - - if (*size > 0) { - *path_list = static_cast(malloc(sizeof(char*) * (*size))); - for (int i = 0; i < *size; ++i) { - (*path_list)[i] = static_cast(malloc(paths[i].length() + 1)); - strcpy((*path_list)[i], paths[i].c_str()); - } - } else { - *path_list = nullptr; - } + // Allocate and copy paths to C list + utilities::copy_stringvector_to_c_list(paths, path_list, size); uda_capnp_free_tree_reader(tree); - } else { - *size = 0; - *path_list = nullptr; } } catch (const uda::UDAException& ex) { throw ALException(ex.what(), LOG); From 1f557dd436645822a7575a854caa0431f93e0595 Mon Sep 17 00:00:00 2001 From: marood Date: Thu, 5 Mar 2026 18:01:29 +0100 Subject: [PATCH 3/4] Added al_utilities and function to convert vector of strings into a C-style array of strings --- include/al_utilities.h | 24 ++++++++++++++++++++++++ src/al_utilities.cpp | 21 +++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 include/al_utilities.h create mode 100644 src/al_utilities.cpp diff --git a/include/al_utilities.h b/include/al_utilities.h new file mode 100644 index 00000000..ed17a4f5 --- /dev/null +++ b/include/al_utilities.h @@ -0,0 +1,24 @@ +#ifndef AL_UTILITIES_H +#define AL_UTILITIES_H + +/** + * General-purpose utility functions for the Access Layer. +*/ + +#include +#include + +namespace utilities { + +/** + * Convert a vector of strings into a C-style array of strings. + * + * @param paths the vector of strings to convert + * @param path_list a pointer to the C-style array to create + * @param size a pointer to an integer to store the size of the created array + */ +void copy_stringvector_to_c_list(const std::vector& paths, char*** path_list, int* size); + +} // namespace utilities + +#endif // AL_UTILITIES_H diff --git a/src/al_utilities.cpp b/src/al_utilities.cpp new file mode 100644 index 00000000..f2faa4c7 --- /dev/null +++ b/src/al_utilities.cpp @@ -0,0 +1,21 @@ +#include "al_utilities.h" + +#include +#include + +namespace utilities { + +void copy_stringvector_to_c_list(const std::vector& paths, char*** path_list, int* size) { + *size = static_cast(paths.size()); + + if (*size == 0) { + *path_list = nullptr; + return; + } + + *path_list = static_cast(malloc(*size * sizeof(char*))); + for (int i = 0; i < *size; ++i) { + (*path_list)[i] = strdup(paths[i].c_str()); + } +} +} // namespace utilities \ No newline at end of file From 31d5a795fb15f6209c52fe2173596d470b6e540c Mon Sep 17 00:00:00 2001 From: Deepak <56668629+deepakmaroo@users.noreply.github.com> Date: Fri, 6 Mar 2026 09:57:38 +0100 Subject: [PATCH 4/4] Apply suggestion from @maarten-ic Co-authored-by: Maarten Sebregts <110895564+maarten-ic@users.noreply.github.com> --- src/uda/uda_backend.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/uda/uda_backend.cpp b/src/uda/uda_backend.cpp index b8bf1b6f..d380251e 100644 --- a/src/uda/uda_backend.cpp +++ b/src/uda/uda_backend.cpp @@ -1422,7 +1422,5 @@ void UDABackend::list_filled_paths(Context* ctx, const char* dataobjectname, cha } } catch (const uda::UDAException& ex) { throw ALException(ex.what(), LOG); - } catch (const std::exception& ex) { - throw; } }