diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index eb10fa34..2d3ed566 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,7 +6,8 @@ Before merging your code, please check the following: * [ ] you have added a line describing your changes to the Changelog; * [ ] you have added unit tests for any new or improved feature; -* [ ] In case you updated dependencies, you have checked pdi/docs/CheckList.md +* [ ] in case you updated dependencies, you have checked pdi/docs/CheckList.md; +* [ ] in case you added a new member to pdi.h, add the equivalent empty member to pdi_deactivation.h * you have checked your code format: - [ ] you have checked that you respect all conventions specified in CONTRIBUTING.md; - [ ] you have checked that the indentation and formatting conforms to the `.clang-format`; diff --git a/AUTHORS b/AUTHORS index 9af99cd4..a597553d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,6 +6,8 @@ Please note this is the list for the distribution mechanism of PDI. The list for each sub-project (including PDI itself) is located in the dedicated sub-project AUTHORS file. +Julian Auriac - CEA (julian.auriac@cea.fr) +* Maintainer (Nov. 2024 - ...) Julien Bigot - CEA (julien.bigot@cea.fr) * Maintainer (Dec. 2014 - ...) diff --git a/pdi/CHANGELOG.md b/pdi/CHANGELOG.md index 19686e99..aeffecdf 100644 --- a/pdi/CHANGELOG.md +++ b/pdi/CHANGELOG.md @@ -51,6 +51,7 @@ and this project adheres to * Add the `Context::find()` method. [#445](https://gitlab.maisondelasimulation.fr/pdidev/pdi/-/issues/445) * Add the `pybind11::dtype to_python(const std::shared_ptr& scalar_type)` helper function. +* Add the header pdi_deactivation.h which allows to disable PDI effects while keeping code syntax unchanged. #### Changed * Update the version of dependencies according to our policy: oldest supported diff --git a/pdi/CMakeLists.txt b/pdi/CMakeLists.txt index 17917f22..ea62ddde 100644 --- a/pdi/CMakeLists.txt +++ b/pdi/CMakeLists.txt @@ -199,6 +199,7 @@ install(TARGETS PDI_C EXPORT PDI_C_EXPORT ) install(FILES "${PDI_SOURCE_DIR}/include/pdi.h" + "${PDI_SOURCE_DIR}/include/pdi_deactivation.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" COMPONENT Development ) diff --git a/pdi/docs/CMakeLists.txt b/pdi/docs/CMakeLists.txt index b1ea2da9..57d8e762 100644 --- a/pdi/docs/CMakeLists.txt +++ b/pdi/docs/CMakeLists.txt @@ -90,6 +90,7 @@ doxygen_add_docs(doxygen_doc "${PDI_BINARY_DIR}/pdi/version.h" "${PDI_BINARY_DIR}/fmoddir/pdif.h" "${PDI_SOURCE_DIR}/include/pdi.h" + "${PDI_SOURCE_DIR}/include/pdi_deactivation.h" "${PDI_SOURCE_DIR}/include/pdi/" "${PDI_SOURCE_DIR}/../example/README.md" "${PDI_SOURCE_DIR}/../tutorial/README.md" diff --git a/pdi/docs/Using_PDI.md b/pdi/docs/Using_PDI.md index 000fc386..f3124eb5 100644 --- a/pdi/docs/Using_PDI.md +++ b/pdi/docs/Using_PDI.md @@ -36,6 +36,7 @@ variables set up. If source files (of application that uses %PDI) and specification tree file are ready, the compilation step can be made. For C make sure that source files that use %PDI API are including `pdi.h` header file. +%PDI can be disabled by using `pdi_deactivation.h` instead of `pdi.h`, and re-enabled by doing the opposite. For Fortran make sure that source files that use %PDI API are using `%PDI` module file (`USE %PDI`). ### Compiling by hand {#compiling_by_hand} @@ -92,4 +93,4 @@ plugins in 4 steps (it will use the first plugin found): 1. `PDI_PLUGIN_PATH` environment variable that is colon separated list with paths, 2. `plugin_path` subtree in specification tree: \ref plugin_path_map_node, 3. Relative path of used %PDI shared object `libpdi.so`, -4. `LD_LIBRARY_PATH` environment variable that is colon separated list. +4. `LD_LIBRARY_PATH` environment variable that is colon separated list. \ No newline at end of file diff --git a/pdi/include/pdi_deactivation.h b/pdi/include/pdi_deactivation.h new file mode 100644 index 00000000..2378614e --- /dev/null +++ b/pdi/include/pdi_deactivation.h @@ -0,0 +1,304 @@ +/******************************************************************************* +* Copyright (C) 2015-2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of CEA nor the names of its contributors may be used to +* endorse or promote products derived from this software without specific +* prior written permission. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +******************************************************************************/ + +/** \file pdi_deactivation.h + * + * C user API + * + * The user facing API is the interface offered by PDI to C application + * developers. + * + * \defgroup init_final Initialization and finalization + * + * The initialization and finalization part of the API is used to setup PDI, + * release its resources and check version information. + * + * \defgroup annotation Code annotation + * + * The code annotation API is the main interface to use in the code. + * + * It offers functions that can be called from code with no side effect by + * default and that can therefore be considered as annotations. + * + * \defgroup error Error handling + * + * The error handling API supports checking the error status of PDI. + * + * By default, errors in PDI C API are signaled by a return code of type + * PDI_status_t and an error message can be retrieved with the PDI_errmsg + * function. This default behavior can be changed by replacing the error handler + * with the PDI_errhandler function. + * + */ + +#define PDI_H_ + +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup error + * \{ + */ + +/** Error codes of PDI + */ +typedef enum PDI_status_e { + /// everything went well + PDI_OK = 0, + /// on an input call, no such data is available + PDI_UNAVAILABLE, + /// The configuration file is invalid + PDI_ERR_CONFIG, + /// A value expression is invalid + PDI_ERR_VALUE, + /// Tried to load a non-existing plugin + PDI_ERR_PLUGIN, + /// Implementation limitation (typically an unimplemented feature) + PDI_ERR_IMPL, + /// A system error occured (OS, etc.) + PDI_ERR_SYSTEM, + /** A call to a function has been made at a wrong time (e.g. closing an + * unopened transaction) + */ + PDI_ERR_STATE, + /// A conflict of onwership over a content has been raised + PDI_ERR_RIGHT, + /// Invalid type error + PDI_ERR_TYPE + +} PDI_status_t; + +/** Type of a callback function used when an error occurs + * \param status the error code + * \param message the human-readable error message + * \param context a user-provided context + */ +typedef void (*PDI_errfunc_f)(PDI_status_t status, const char* message, void* context); + +/** Definition of an error handler + */ +typedef struct PDI_errhandler_s { + /// The function to handle the error (none if NULL) + PDI_errfunc_f func; + + /// the context that will be provided to the function + void* context; + +} PDI_errhandler_t; + +/** Prints the error message and aborts if the status is invalid + */ +extern const PDI_errhandler_t PDI_EXPORT PDI_ASSERT_HANDLER; + +/** Prints the error message and continue if the status is invalid + */ +extern const PDI_errhandler_t PDI_EXPORT PDI_WARN_HANDLER; + +/** Does nothing + */ +extern const PDI_errhandler_t PDI_EXPORT PDI_NULL_HANDLER; + + +/** Return a human-readabe message describing the last error that occured in PDI + */ +const char PDI_EXPORT * PDI_errmsg(void){}; + +/** Sets the error handler to use + * + * PDI_asserthandler is the default handler before this function is called + * + * \param handler the new handler to set + * \return the previous handler + */ +PDI_errhandler_t PDI_EXPORT PDI_errhandler(PDI_errhandler_t handler){}; + +/// \} + +/** \addtogroup init_final Initialization and finalization + * + * The initialization and finalization part of the API is used to setup PDI, + * release its resources and check version information. + * \{ + */ + +/** Initializes PDI + * \param[in] conf the configuration + * \return an error status + */ +PDI_status_t PDI_EXPORT PDI_init(PC_tree_t conf){}; + +/** Finalizes PDI + * \return an error status + */ +PDI_status_t PDI_EXPORT PDI_finalize(void){}; + +/** Checks PDI API version + * + * \param[out] provided version if non-null it is filled with the provided API version + * \param[in] expected if non-zero the expected API version + * \return an error status if the expected version is incompatible with the + * provided one + */ +PDI_status_t PDI_EXPORT PDI_version(unsigned long* provided, unsigned long expected){}; + +/// \} + +/** \addtogroup annotation + * \{ + */ + +/** + * Access directions + */ +typedef enum PDI_inout_e { + /// No data transfert + PDI_NONE = 0, + /// data tranfer from PDI to the main code + PDI_IN = 1, + /// data transfer from the main code to PDI + PDI_OUT = 2, + /// data transfer in both direction + PDI_INOUT = 3 + +} PDI_inout_t; + +/** Shares some data with PDI. The user code should not modify it before + * a call to either PDI_release or PDI_reclaim. + * \param[in] name the data name + * \param[in,out] data the accessed data + * \param[in] access whether the data can be accessed for read or write + * by PDI + * \return an error status + * \pre the user code owns the data buffer + * \post ownership of the data buffer is shared between PDI and the user code + * + * the access parameter is a binary OR of PDI_IN & PDI_OUT. + * * PDI_IN means PDI can set the buffer content + * * PDI_OUT means the buffer contains data that can be accessed by PDI + */ +PDI_status_t PDI_EXPORT PDI_share(const char* name, void* data, PDI_inout_t access){}; + +/** Requests for PDI to access a data buffer. + * \param[in] name the data name + * \param[in,out] buffer a pointer to the accessed data buffer + * \param[in] inout the access properties (PDI_IN, PDI_OUT, PDI_INOUT) + * \return an error status + * \pre PDI owns the data buffer + * \post ownership of the data buffer is shared between PDI and the user code + */ +PDI_status_t PDI_EXPORT PDI_access(const char* name, void** buffer, PDI_inout_t inout){}; + +/** Releases ownership of a data shared with PDI. PDI is then responsible to + * free the associated memory whenever necessary. + * \param[in] name name of the data to release + * \return an error status + * \pre ownership of the data buffer is shared between PDI and the user code + * \pre PDI owns the data buffer + */ +PDI_status_t PDI_EXPORT PDI_release(const char* name){}; + +/** Reclaims ownership of a data buffer shared with PDI. PDI does not manage + * the buffer memory anymore. + * \param[in] name name of the data to reclaim + * \return an error status + * \pre ownership of the data buffer is shared between PDI and the user code + * \post the user code owns the data buffer + */ +PDI_status_t PDI_EXPORT PDI_reclaim(const char* name){}; + +/** Triggers a PDI "event" + * \param[in] event the event name + * \return an error status + */ +PDI_status_t PDI_EXPORT PDI_event(const char* event){}; + +/** Shortly exposes some data to PDI. Equivalent to PDI_share + PDI_reclaim. + * \param[in] name the data name + * \param[in] data the exposed data + * \param[in] access whether the data can be accessed for read or write + * by PDI + * \return an error status + */ +PDI_status_t PDI_EXPORT PDI_expose(const char* name, void* data, PDI_inout_t access){}; + +/** Performs multiple exposes at once. All the data is shared in order they were specified + * and reclaimed in reversed order after an event is triggered. + * + * NULL argument indicates an end of the list. + * + * \param[in] event_name the name of the event that will be triggered when + * all data become available + * \param[in] name the data name + * \param[in] data the exposed data + * \param[in] access whether the data can be accessed for read or write by PDI + * \param[in] ... (additional arguments) additional list of data to expose, + * each should contain name, data and access, NULL argument + * inidactes an end of the list. + * \return an error status + */ +PDI_status_t PDI_EXPORT PDI_multi_expose(const char* event_name, const char* name, void* data, PDI_inout_t access, ...){}; + +#ifdef PDI_WITH_DEPRECATED + +/** Begin a transaction in which all PDI_expose calls are grouped. + * + * This requires a call to PDI_transaction_end to close the transaction. + * + * \deprecated the transaction part of the API is deprecated, the + * PDI_multi_expose function should be used instead. + * + * \see PDI_expose the function used to expose data inside the transaction + * \see PDI_transaction_end the function used to end the transaction + * + * \param[in] name the name of the transaction (an event thus named will be + * triggered when all data become available) + * \return an error status + */ +PDI_status_t PDI_DEPRECATED_EXPORT PDI_transaction_begin(const char* name){}; + +/** Ends the previously opened transaction. + * + * \deprecated the transaction part of the API is deprecated, the + * PDI_multi_expose function should be used instead. + * + * \see PDI_transaction_begin the function used to start the transaction + * \see PDI_expose the function used to expose data inside the transaction + * + * \return an error status + */ +PDI_status_t PDI_DEPRECATED_EXPORT PDI_transaction_end(void){}; + +#endif // PDI_WITH_DEPRECATED + +/// \} + +#ifdef __cplusplus +} // extern C +#endif diff --git a/tests/AUTHORS b/tests/AUTHORS index 9c4b3f55..ec69e7b2 100644 --- a/tests/AUTHORS +++ b/tests/AUTHORS @@ -2,6 +2,8 @@ Multiple people have contributed to the PDI tests. To show our appreciation for their public spirit, we list here in alphabetical order a condensed list of their contributions. +Julian Auriac - CEA (julian.auriac@cea.fr) +* Maintainer (Nov. 2024 - ...) Julien Bigot - CEA (julien.bigot@cea.fr) * Initial buildsystem @@ -15,4 +17,4 @@ project co-financed by Polish Ministry of Science and Higher Education. * Tests inspired by Parflow that combine Serialize & Decl'HDF5 Yushan Wang - CEA (yushan.wang@cea.fr) -* Maintainer (Sept. 2023 - ...) +* Maintainer (Sept. 2023 - ...) \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1706d200..8386477f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,6 +56,10 @@ add_executable(test_04_C test_04.c) target_link_libraries(test_04_C PDI::PDI_C) add_test(NAME test_04_C COMMAND "$" "${CMAKE_CURRENT_SOURCE_DIR}/test_04.yml") +add_executable(test_06_C test_06.c) +target_link_libraries(test_06_C PDI::PDI_C) +add_test(NAME test_06_C COMMAND "$" "${CMAKE_CURRENT_SOURCE_DIR}/test_06.yml") + endif("${BUILD_DECL_HDF5_PLUGIN}" AND "${BUILD_SERIALIZE_PLUGIN}") if("${BUILD_DECL_NETCDF_PLUGIN}" AND "${BUILD_SERIALIZE_PLUGIN}") diff --git a/tests/test_06.c b/tests/test_06.c new file mode 100644 index 00000000..f84359a6 --- /dev/null +++ b/tests/test_06.c @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (C) 2024 Commissariat a l'energie atomique et aux energies alternatives (CEA) + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of CEA nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#include +// #include +#include +#include + +int main(int argc, char* argv[]) +{ + PC_tree_t conf = PC_parse_path(argv[1]); + + PDI_init(PC_get(conf, ".pdi")); + printf("%s", argv[1]); + + long longval; + + int global_size[2]; + PC_int(PC_get(conf, ".global_size.height"), &longval); + global_size[0] = longval; + PC_int(PC_get(conf, ".global_size.width"), &longval); + global_size[1] = longval; + + // # As the value is shared with pdi.h, it can be reclaimed in a second time. + // # In the case of pdi_deactivation.h, the value is never shared, hence the reclaim operation fails. + // PDI_share("global_size", global_size, PDI_OUT) == NULL; + PDI_reclaim("global_size"); + + PDI_finalize(); + return 0; +} diff --git a/tests/test_06.yml b/tests/test_06.yml new file mode 100644 index 00000000..3003893f --- /dev/null +++ b/tests/test_06.yml @@ -0,0 +1,6 @@ +global_size: { height: 60, width: 12 } + +pdi: + plugins: + trace: + logging: { pattern: '[PDI][%n-plugin] *** %l: %v' } \ No newline at end of file