Skip to content

Commit

Permalink
[ 7104] Add replica_truncate API
Browse files Browse the repository at this point in the history
The replica_truncate API is meant to act as a replacement for
rcDataObjTruncate. The interface is very similar to rcDataObjTruncate,
but the result is different. The API only targets one replica to be
truncated, and will trigger fileModified as if the file had been
modified via an open/write/close.
  • Loading branch information
alanking committed Mar 13, 2024
1 parent fbb67ad commit 99218ca
Show file tree
Hide file tree
Showing 12 changed files with 514 additions and 1 deletion.
2 changes: 2 additions & 0 deletions lib/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ foreach(variant IN ITEMS client server)
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_register_physical_path.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_replica_close.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_replica_open.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_replica_truncate.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_set_delay_server_migration_info.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_set_grid_configuration_value.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rc_switch_user.cpp"
Expand Down Expand Up @@ -314,6 +315,7 @@ install(
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/register_physical_path.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/replica_close.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/replica_open.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/replica_truncate.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rmColl.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/ruleExecDel.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/ruleExecMod.h"
Expand Down
1 change: 1 addition & 0 deletions lib/api/include/irods/apiNumberData.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ API_NUMBER(GET_LIMITED_PASSWORD_AN, 726)

API_NUMBER(CHECK_AUTH_CREDENTIALS_AN, 800)
API_NUMBER(GET_LIBRARY_FEATURES_AN, 801)
API_NUMBER(REPLICA_TRUNCATE_AN, 802)

/* 1100 - 1200 - SSL API calls */
API_NUMBER(SSL_START_AN, 1100)
Expand Down
8 changes: 8 additions & 0 deletions lib/api/include/irods/apiTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
# include "irods/rs_check_auth_credentials.hpp"
# include "irods/rs_get_library_features.hpp"
# include "irods/rs_get_resource_info_for_operation.hpp"
# include "irods/rs_replica_truncate.hpp"
# define NULLPTR_FOR_CLIENT_TABLE(x) x
#elif !defined(CREATE_API_TABLE_FOR_SERVER) && defined(CREATE_API_TABLE_FOR_CLIENT)
# define NULLPTR_FOR_CLIENT_TABLE(x) nullptr
Expand Down Expand Up @@ -264,6 +265,7 @@
#define RS_REG_COLL NULLPTR_FOR_CLIENT_TABLE(rsRegColl)
#define RS_REG_DATA_OBJ NULLPTR_FOR_CLIENT_TABLE(rsRegDataObj)
#define RS_REG_REPLICA NULLPTR_FOR_CLIENT_TABLE(rsRegReplica)
#define RS_REPLICA_TRUNCATE NULLPTR_FOR_CLIENT_TABLE(rs_replica_truncate)
#define RS_RM_COLL NULLPTR_FOR_CLIENT_TABLE(rsRmColl)
#define RS_RULE_EXEC_DEL NULLPTR_FOR_CLIENT_TABLE(rsRuleExecDel)
#define RS_RULE_EXEC_MOD NULLPTR_FOR_CLIENT_TABLE(rsRuleExecMod)
Expand Down Expand Up @@ -1279,6 +1281,12 @@ static irods::apidef_t client_api_table_inp[] = {
boost::any(std::function<int(rsComm_t*,dataObjInp_t*,char**)>(RS_GET_RESOURCE_INFO_FOR_OPERATION)),
"api_get_resource_info_for_operation", clearDataObjInp, irods::clearOutStruct_noop,
(funcPtr)CALL_GET_RESOURCE_INFO_FOR_OPERATION
},
{ REPLICA_TRUNCATE_AN, RODS_API_VERSION, REMOTE_USER_AUTH, REMOTE_USER_AUTH,
"DataObjInp_PI", 0, "STR_PI", 0,
boost::any(std::function<int(rsComm_t*, dataObjInp_t*, char**)>(RS_REPLICA_TRUNCATE)),
"api_replica_truncate", clearDataObjInp, irods::clearOutStruct_noop,
(funcPtr)CALL_REPLICA_TRUNCATE
}
// clang-format on
}; // _api_table_inp
Expand Down
82 changes: 82 additions & 0 deletions lib/api/include/irods/replica_truncate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef IRODS_REPLICA_TRUNCATE_H
#define IRODS_REPLICA_TRUNCATE_H

struct RcComm;
struct DataObjInp;

#ifdef __cplusplus
extern "C" {
#endif

/// Truncate a replica for the specified data object to the specified size.
///
/// \parblock
/// This API selects a replica to truncate according to the rules of POSIX truncate(2). The caller may provide keywords
/// via condInput in order to influence the hierarchy resolution for selecting a replica to truncate.
/// \endparblock
///
/// \param[in] _comm A pointer to a RcComm.
/// \param[in] _inp \parblock
/// DataObjInp structure which requires the following inputs:
/// objPath - The full logical path to the target data object.
/// dataSize - The desired size of the replica after truncating.
///
/// The condInput supports the following keywords for hierarchy resolution for a "write" operation:
/// replNum - The replica number of the replica to truncate.
/// rescName - The name of the resource with the replica to truncate. Must be a root resource.
/// defRescName - The default resource to target in the absence of any other inputs or policy.
/// resc_hier - Full resource hierarchy to the replica to truncate. Use with caution.
/// irodsAdmin - Flag indicating that the operation is to be performed with elevated privileges. No value required.
/// \endparblock
/// \param[out] _out \parblock
/// Character string representing a JSON structure with the following form:
/// \code{.js}
/// {
/// // Resource hierarchy of the selected replica for truncate.
/// "resource_hierarchy": <string>,
/// // Replica number of the selected replica for truncate.
/// "replica_number": <integer>,
/// // A string containing any relevant message the client may wish to send to the user (including error messages).
/// "message": <string>
/// }
/// \endcode
/// \endparblock
///
/// \usage \parblock
/// \code{c}
/// RcComm* comm = NULL;
/// // Establish connection with iRODS server, authenticate, etc.
///
/// // Don't forget to call clearKeyVal on truncate_doi.condInput before exiting to prevent leaks.
/// DataObjInp truncate_doi;
/// memset(&truncate_doi, 0, sizeof(DataObjInp));
///
/// // Set the path and the desired size.
/// strncpy(truncate_doi.objPath, "/tempZone/home/alice/foo", MAX_NAME_LEN);
/// truncate_doi.size = 0;
///
/// // Target a specific replica, if desired.
/// addKeyVal(&truncate_doi.condInput, "replNum", "3");
///
/// // Need a character string to hold the output. Don't forget to free this before exiting to prevent leaks.
/// char* output_string = NULL;
///
/// const int ec = rc_replica_truncate(comm, &truncate_doi, &output_string);
/// if (ec < 0) {
/// // Error handling. Perhaps use the "message" field inside the output_string.
/// }
/// \endcode
/// \endparblock
///
/// \return An integer representing an iRODS error code, or 0.
/// \retval 0 on success.
/// \retval <0 on failure; an iRODS error code.
///
/// \since 4.3.2
int rc_replica_truncate(RcComm* _comm, DataObjInp* _inp, char** _out);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // IRODS_REPLICA_TRUNCATE_H
14 changes: 14 additions & 0 deletions lib/api/src/rc_replica_truncate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "irods/replica_truncate.h"

#include "irods/apiNumber.h"
#include "irods/procApiRequest.h"
#include "irods/rodsErrorTable.h"

auto rc_replica_truncate(RcComm* _comm, DataObjInp* _inp, char** _out) -> int
{
if (!_comm || !_inp || !_out) {
return SYS_INVALID_INPUT_PARAM;
}

return procApiRequest(_comm, REPLICA_TRUNCATE_AN, _inp, nullptr, reinterpret_cast<void**>(_out), nullptr);
} // rc_replica_truncate
5 changes: 5 additions & 0 deletions lib/core/include/irods/library_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@
/// \since 4.3.1
#define IRODS_HAS_API_ENDPOINT_CHECK_AUTH_CREDENTIALS 202307L

/// Defined if the development library supports #rc_replica_truncate.
///
/// \since 4.3.2
#define IRODS_HAS_API_ENDPOINT_REPLICA_TRUNCATE 202403L

#endif // IRODS_LIBRARY_FEATURES_H
4 changes: 3 additions & 1 deletion server/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_library(
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_register_physical_path.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_replica_close.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_replica_open.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_replica_truncate.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_set_delay_server_migration_info.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_set_grid_configuration_value.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/rs_touch.cpp"
Expand Down Expand Up @@ -211,8 +212,9 @@ install(
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_get_library_features.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_get_resource_info_for_operation.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_register_physical_path.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_replica_open.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_replica_close.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_replica_open.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_replica_truncate.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_set_delay_server_migration_info.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_set_grid_configuration_value.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/include/irods/rs_touch.hpp"
Expand Down
82 changes: 82 additions & 0 deletions server/api/include/irods/rs_replica_truncate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef IRODS_RS_REPLICA_TRUNCATE_HPP
#define IRODS_RS_REPLICA_TRUNCATE_HPP

struct RsComm;
struct DataObjInp;

#ifdef __cplusplus
extern "C" {
#endif

/// Truncate a replica for the specified data object to the specified size.
///
/// \parblock
/// This API selects a replica to truncate according to the rules of POSIX truncate(2). The caller may provide keywords
/// via condInput in order to influence the hierarchy resolution for selecting a replica to truncate.
/// \endparblock
///
/// \param[in] _comm A pointer to a RcComm.
/// \param[in] _inp \parblock
/// DataObjInp structure which requires the following inputs:
/// objPath - The full logical path to the target data object.
/// dataSize - The desired size of the replica after truncating.
///
/// The condInput supports the following keywords for hierarchy resolution for a "write" operation:
/// replNum - The replica number of the replica to truncate.
/// rescName - The name of the resource with the replica to truncate. Must be a root resource.
/// defRescName - The default resource to target in the absence of any other inputs or policy.
/// resc_hier - Full resource hierarchy to the replica to truncate. Use with caution.
/// irodsAdmin - Flag indicating that the operation is to be performed with elevated privileges. No value required.
/// \endparblock
/// \param[out] _out \parblock
/// Character string representing a JSON structure with the following form:
/// \code{.js}
/// {
/// // Resource hierarchy of the selected replica for truncate.
/// "resource_hierarchy": <string>,
/// // Replica number of the selected replica for truncate.
/// "replica_number": <integer>,
/// // A string containing any relevant message the client may wish to send to the user (including error messages).
/// "message": <string>
/// }
/// \endcode
/// \endparblock
///
/// \usage \parblock
/// \code{c}
/// // Because this is a server-side function, we will assume that there is access to an RsComm;
/// RsComm* comm;
///
/// // Don't forget to call clearKeyVal on truncate_doi.condInput before exiting to prevent leaks.
/// DataObjInp truncate_doi;
/// memset(&truncate_doi, 0, sizeof(DataObjInp));
///
/// // Set the path and the desired size.
/// strncpy(truncate_doi.objPath, "/tempZone/home/alice/foo", MAX_NAME_LEN);
/// truncate_doi.size = 0;
///
/// // Target a specific replica, if desired.
/// addKeyVal(&truncate_doi.condInput, "replNum", "3");
///
/// // Need a character string to hold the output. Don't forget to free this before exiting to prevent leaks.
/// char* output_string = NULL;
///
/// const int ec = rs_replica_truncate(comm, &truncate_doi, &output_string);
/// if (ec < 0) {
/// // Error handling. Perhaps use the "message" field inside the output_string.
/// }
/// \endcode
/// \endparblock
///
/// \return An integer representing an iRODS error code, or 0.
/// \retval 0 on success.
/// \retval <0 on failure; an iRODS error code.
///
/// \since 4.3.2
int rs_replica_truncate(RsComm* _comm, DataObjInp* _inp, char** _out);

#ifdef __cplusplus
} // extern "C"
#endif

#endif // IRODS_RS_REPLICA_TRUNCATE_HPP
1 change: 1 addition & 0 deletions server/api/src/rs_get_library_features.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ auto rs_get_library_features(RsComm* _comm, char** _features) -> int
IRODS_FEATURE(IRODS_HAS_LIBRARY_SYSTEM_ERROR)
IRODS_FEATURE(IRODS_HAS_FEATURE_PROXY_USER_SUPPORT_FOR_CLIENT_CONNECTION_LIBRARIES)
IRODS_FEATURE(IRODS_HAS_API_ENDPOINT_CHECK_AUTH_CREDENTIALS)
IRODS_FEATURE(IRODS_HAS_API_ENDPOINT_REPLICA_TRUNCATE)
}.dump().c_str());
// clang-format on

Expand Down
Loading

0 comments on commit 99218ca

Please sign in to comment.