Skip to content
Open
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
24 changes: 24 additions & 0 deletions include/al_utilities.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef AL_UTILITIES_H
#define AL_UTILITIES_H

/**
* General-purpose utility functions for the Access Layer.
*/

#include <vector>
#include <string>

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<std::string>& paths, char*** path_list, int* size);

} // namespace utilities

#endif // AL_UTILITIES_H
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 21 additions & 0 deletions src/al_utilities.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "al_utilities.h"

#include <cstdlib>
#include <cstring>

namespace utilities {

void copy_stringvector_to_c_list(const std::vector<std::string>& paths, char*** path_list, int* size) {
*size = static_cast<int>(paths.size());

if (*size == 0) {
*path_list = nullptr;
return;
}

*path_list = static_cast<char**>(malloc(*size * sizeof(char*)));
for (int i = 0; i < *size; ++i) {
(*path_list)[i] = strdup(paths[i].c_str());
}
}
} // namespace utilities
7 changes: 2 additions & 5 deletions src/hdf5/hdf5_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <stdlib.h>
#include <limits>
#include <boost/algorithm/string.hpp>
#include "al_utilities.h"

#define MAX_LENGTH 200
#define HOMOGENEOUS_TIME_FIELD_NAME "ids_properties&homogeneous_time"
Expand Down Expand Up @@ -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)
Expand Down
113 changes: 112 additions & 1 deletion src/uda/uda_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <string>
#include <random>
#include "al_utilities.h"

using namespace semver::literals;

Expand Down Expand Up @@ -1258,6 +1259,54 @@ std::vector<int> read_occurrences(NodeReader *node) {
return occurrences;
}

std::vector<std::string> read_filled_paths(NodeReader *node) {
std::vector<std::string> paths;

// Read the shape
std::vector<size_t> 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<size_t>());

// 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<char> 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) {
Expand Down Expand Up @@ -1311,5 +1360,67 @@ 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);

*size = 0;
*path_list = nullptr;

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) {
return;
}

const auto tree = uda_capnp_deserialise(data, result_size);
const auto root = uda_capnp_read_root(tree);

auto paths = read_filled_paths(root);
// Allocate and copy paths to C list
utilities::copy_stringvector_to_c_list(paths, path_list, size);

uda_capnp_free_tree_reader(tree);
}
} catch (const uda::UDAException& ex) {
throw ALException(ex.what(), LOG);
}
}
Loading