Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #438, atomic pdi_deactivate.h, allows disabling PDI's operation while maintaining valid syntax #504

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
Expand Down
2 changes: 2 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -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 ([email protected])
* Maintainer (Nov. 2024 - ...)

Julien Bigot - CEA ([email protected])
* Maintainer (Dec. 2014 - ...)
Expand Down
1 change: 1 addition & 0 deletions pdi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<const Scalar_datatype>& 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
Expand Down
1 change: 1 addition & 0 deletions pdi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Copy link
Member

Choose a reason for hiding this comment

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

as we discussed, put the file under no-pdi/include/pdi.h

DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT Development
)
Expand Down
1 change: 1 addition & 0 deletions pdi/docs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion pdi/docs/Using_PDI.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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.
304 changes: 304 additions & 0 deletions pdi/include/pdi_deactivation.h
Original file line number Diff line number Diff line change
@@ -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 <paraconf.h>
Copy link
Member

Choose a reason for hiding this comment

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

Could we remove this paraconf dependency?


#include <pdi/export.h>
#include <pdi/version.h>

#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
4 changes: 3 additions & 1 deletion tests/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -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 ([email protected])
* Maintainer (Nov. 2024 - ...)

Julien Bigot - CEA ([email protected])
* Initial buildsystem
Expand All @@ -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 ([email protected])
* Maintainer (Sept. 2023 - ...)
* Maintainer (Sept. 2023 - ...)
4 changes: 4 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 "$<TARGET_FILE:test_04_C>" "${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 "$<TARGET_FILE:test_06_C>" "${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}")

Expand Down
Loading
Loading