From fe837a9fa2600dcdce4ea40313db270b6fc89b2a Mon Sep 17 00:00:00 2001 From: Edward Tremel Date: Thu, 12 Jun 2025 13:19:22 -0400 Subject: [PATCH 1/5] Added an install script for boolinq This is an optional prerequisite, but it's a library that doesn't have a package or clear installation method (you have to copy the header to /usr/local/include manually) so it's nice to have a script that shows you how to install it. --- scripts/prerequisites/install-boolinq.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 scripts/prerequisites/install-boolinq.sh diff --git a/scripts/prerequisites/install-boolinq.sh b/scripts/prerequisites/install-boolinq.sh new file mode 100755 index 00000000..c0daf454 --- /dev/null +++ b/scripts/prerequisites/install-boolinq.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -eu +export TMPDIR=/var/tmp +WORKPATH=`mktemp -d` +INSTALL_PREFIX="/usr/local" +if [[ $# -gt 0 ]]; then + INSTALL_PREFIX=$1 +fi + +echo "Using INSTALL_PREFIX=${INSTALL_PREFIX}" + +cd ${WORKPATH} +git clone https://github.com/k06a/boolinq.git +cd boolinq +cp -r include/ ${INSTALL_PREFIX} +rm -rf ${WORKPATH} From c2f067367ecc3d8d913ab9b5707f0b5242124354 Mon Sep 17 00:00:00 2001 From: Edward Tremel Date: Mon, 14 Jul 2025 12:28:19 -0400 Subject: [PATCH 2/5] Fixed prerequisite scripts to allow a choice of install locations The install scripts for some optional prerequisites (ANN, CPPFlow, libtorch, OpenCV, and TensorFlow) had a hard-coded value of INSTALL_PREFIX instead of allowing the user to pass it as an argument. This is essentially a cherry-pick of commit 4683a66e131cca7d443bbf5db1f9b5a30deb02d5 from the cascade_chain branch, but without the other changes that added Docker support. --- scripts/prerequisites/install-ann.sh | 5 ++++- scripts/prerequisites/install-cppflow.sh | 5 ++++- scripts/prerequisites/install-libtorch.sh | 7 +++++-- scripts/prerequisites/install-opencv.sh | 5 ++++- scripts/prerequisites/install-tensorflow.sh | 5 ++++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/scripts/prerequisites/install-ann.sh b/scripts/prerequisites/install-ann.sh index 0cf02b2a..96a15c42 100755 --- a/scripts/prerequisites/install-ann.sh +++ b/scripts/prerequisites/install-ann.sh @@ -1,5 +1,8 @@ #!/bin/bash -INSTALL_PREFIX=${HOME}/opt-dev +INSTALL_PREFIX="/usr/local" +if [[ $# -gt 0 ]]; then + INSTALL_PREFIX=$1 +fi wget https://www.cs.umd.edu/~mount/ANN/Files/1.1.2/ann_1.1.2.tar.gz tar -xf ann_1.1.2.tar.gz diff --git a/scripts/prerequisites/install-cppflow.sh b/scripts/prerequisites/install-cppflow.sh index 797b6380..82d718e4 100755 --- a/scripts/prerequisites/install-cppflow.sh +++ b/scripts/prerequisites/install-cppflow.sh @@ -1,5 +1,8 @@ #!/bin/bash -export INSTALL_PREFIX=$HOME/opt-dev/ +INSTALL_PREFIX="/usr/local" +if [[ $# -gt 0 ]]; then + INSTALL_PREFIX=$1 +fi git clone https://github.com/serizba/cppflow.git cd cppflow git checkout 9ea9519c66d9b1893e2d298db8aa1ee866f903a2 diff --git a/scripts/prerequisites/install-libtorch.sh b/scripts/prerequisites/install-libtorch.sh index 16d2b75f..66e5ce1e 100755 --- a/scripts/prerequisites/install-libtorch.sh +++ b/scripts/prerequisites/install-libtorch.sh @@ -1,11 +1,14 @@ #!/bin/bash -if [ $# != 1 ]; then +if [ $# -lt 1 ]; then echo "USAGE: $0 " exit 0 fi -INSTALL_PREFIX=${HOME}/opt-dev +INSTALL_PREFIX="/usr/local" +if [[ $# -gt 0 ]]; then + INSTALL_PREFIX=$2 +fi INSTALL_TYPE=$1 ZIP_FILE=libtorch-cxx11.zip if [ $INSTALL_TYPE == 'cpu' ]; then diff --git a/scripts/prerequisites/install-opencv.sh b/scripts/prerequisites/install-opencv.sh index 41d80e1f..03817574 100755 --- a/scripts/prerequisites/install-opencv.sh +++ b/scripts/prerequisites/install-opencv.sh @@ -1,5 +1,8 @@ #!/bin/bash -export INSTALL_PREFIX=$HOME/opt-dev/ +INSTALL_PREFIX="/usr/local" +if [[ $# -gt 0 ]]; then + INSTALL_PREFIX=$1 +fi # install python opencv sudo apt-get -y install python3-opencv # Download and unpack sources diff --git a/scripts/prerequisites/install-tensorflow.sh b/scripts/prerequisites/install-tensorflow.sh index bbed1e20..6b0757cf 100755 --- a/scripts/prerequisites/install-tensorflow.sh +++ b/scripts/prerequisites/install-tensorflow.sh @@ -6,7 +6,10 @@ if [ $# -lt 2 ]; then fi # pip3 install tensorflow==${VERSION} -INSTALL_PREFIX=$HOME/opt-dev/ +INSTALL_PREFIX="/usr/local" +if [[ $# -gt 0 ]]; then + INSTALL_PREFIX=$3 +fi VERSION=$1 ENGINE=$2 FILENAME=libtensorflow-${ENGINE}-linux-x86_64-${VERSION}.tar.gz From e2821f85a3cb6cbbfcccd95d8049925563c05ed3 Mon Sep 17 00:00:00 2001 From: Edward Tremel Date: Mon, 14 Jul 2025 17:22:48 -0400 Subject: [PATCH 3/5] Improved documentation in service.hpp, fixed compiler warnings The comments on the main API functions in service.hpp were missing some details and were sometimes out-of-date with respect to the code. Also, a newer g++ (version 13.3) emitted some warnings about existing code that needed to be updated (e.g. to remove unnecessary std::moves). Finally, the string constants in service.hpp should be declared as constexpr strings, not macros, to match Derecho's usage of these types of constants for Conf strings. --- include/cascade/detail/service_impl.hpp | 2 +- include/cascade/service.hpp | 278 ++++++++++-------- .../cascade_as_subgroup_classes/perf.cpp | 8 +- src/service/client.cpp | 4 +- src/service/fuse/fuse_client_context.hpp | 72 ++--- src/service/perftest.cpp | 4 +- 6 files changed, 208 insertions(+), 160 deletions(-) diff --git a/include/cascade/detail/service_impl.hpp b/include/cascade/detail/service_impl.hpp index 82624c62..7d992e54 100644 --- a/include/cascade/detail/service_impl.hpp +++ b/include/cascade/detail/service_impl.hpp @@ -2440,7 +2440,7 @@ void ExecutionEngine::workhorse(uint32_t worker_id, struct acti dbg_default_trace("Cascade context workhorse[{}] started", worker_id); while(is_running) { // waiting for an action - Action action = std::move(aq.action_buffer_dequeue(is_running)); + Action action = aq.action_buffer_dequeue(is_running); // if action_buffer_dequeue return with is_running == false, value_ptr is invalid(nullptr). action.fire(this,worker_id); diff --git a/include/cascade/service.hpp b/include/cascade/service.hpp index b343cb01..9c52b07c 100644 --- a/include/cascade/service.hpp +++ b/include/cascade/service.hpp @@ -322,34 +322,11 @@ namespace cascade { }; /** - * Create the critical data path callback function. - * Application should provide corresponding callbacks. The application MUST hold the ownership of the - * callback objects and make sure its availability during service lifecycle. - * - template - std::shared_ptr> create_critical_data_path_callback(); - */ - - /** - * defining key strings used in the [CASCADE] section of configuration file. - */ - #define MIN_NODES_BY_SHARD "min_nodes_by_shard" - #define MAX_NODES_BY_SHARD "max_nodes_by_shard" - #define DELIVERY_MODES_BY_SHARD "delivery_modes_by_shard" - #define DELIVERY_MODE_ORDERED "Ordered" - #define DELIVERY_MODE_RAW "Raw" - #define PROFILES_BY_SHARD "profiles_by_shard" - - /** - * The ServiceClient template class contains all APIs needed for read/write data. The four core APIs are put, remove, - * get, and get_by_time. We also provide a set of helper APIs for the client to get the group topology. By default, the - * core APIs are talking a random but fix member of the specified subgroup and shard. The client can override this - * behaviour by specifying other member selection policy (ShardMemberSelectionPolicy). - * - * The default policy behaviour depends on the + * Options for the policy the ServiceClient will use to select which member of a shard to + * communicate with when executing a put() or get() operation. */ enum ShardMemberSelectionPolicy { - FirstMember, // use the first member in the list returned from get_shard_members(), this is the default behaviour. + FirstMember, // use the first member in the list returned from get_shard_members() LastMember, // use the last member in the list returned from get_shard_members() Random, // use a random member in the shard for each operations(put/remove/get/get_by_time). FixedRandom, // use a random member and stick to that for the following operations. @@ -358,7 +335,6 @@ namespace cascade { UserSpecified, // user specify which member to contact. InvalidPolicy = -1 }; - // #define DEFAULT_SHARD_MEMBER_SELECTION_POLICY (ShardMemberSelectionPolicy::FirstMember) #define DEFAULT_SHARD_MEMBER_SELECTION_POLICY (ShardMemberSelectionPolicy::RoundRobin) std::ostream& operator<<(std::ostream& stream, const ShardMemberSelectionPolicy& policy); @@ -461,7 +437,12 @@ namespace cascade { template using per_type_notification_handler_registry_t = std::unordered_map>; - + /** + * The ServiceClient template class contains all APIs needed to read/write data. The four core APIs are put, remove, + * get, and get_by_time. We also provide a set of helper APIs for the client to get the group topology. The core APIs + * target a specific subgroup and shard of the service, or a specific object pool (which maps to a subgroup). + * The client uses a ShardMemberSelectionPolicy to determine which member of that subgroup/shard to communicate with. + */ template class ServiceClient { static_assert(have_same_object_type()); @@ -482,7 +463,7 @@ namespace cascade { * case of ShardMemorySelectionPolicy::UserSpecified. The user specified node id is used as member index if the * policy is ShardMemberSelectionPolicy::RoundRobin * - * The default member selection policy is defined as SHARD_MEMBER_SELECTION_POLICY (ShardMemberSelectionPolicy::FirstMember). + * The default member selection policy is defined as DEFAULT_SHARD_MEMBER_SELECTION_POLICY. */ std::unordered_map< std::tuple, @@ -560,16 +541,6 @@ namespace cascade { template void refresh_member_cache_entry(uint32_t subgroup_index, uint32_t shard_index); - /** - * Deprecated: Please use key_to_shard() instead - * - * Metadata API Helper: turn a string key to subgroup index and shard index - * - template - std::pair key_to_subgroup_index_and_shard_index(const typename SubgroupType::KeyType& key, - bool check_object_location = true); - */ - /** * Metadata API Helper: turn a string key to subgroup type index, subgroup index, and shard index. */ @@ -689,19 +660,26 @@ namespace cascade { int32_t get_my_shard(const std::string& object_pool_pathname); /** - * Member selection policy control API. - * - set_member_selection_policy updates the member selection policies. - * - get_member_selection_policy read the member selection policies. + * Updates the member selection policy for a shard. + * + * @tparam SubgroupType The Cascade subgroup type the shard is in * @param[in] subgroup_index * @param[in] shard_index - * @param[in] policy - * @param[in] user_specified_node_id - * @return get_member_selection_policy returns a 2-tuple of policy and user_specified_node_id. + * @param[in] policy - the new policy + * @param[in] user_specified_node_id - optional, the node ID to contact if the policy is UserSpecified */ template void set_member_selection_policy(uint32_t subgroup_index,uint32_t shard_index, ShardMemberSelectionPolicy policy,node_id_t user_specified_node_id=INVALID_NODE_ID); + /** + * Reads the member selection policy for a shard. + * + * @tparam SubgroupType The Cascade subgroup type the shard is in + * @param[in] subgroup_index + * @param[in] shard_index + * @return a 2-tuple of policy and user_specified_node_id. + */ template std::tuple get_member_selection_policy( uint32_t subgroup_index, uint32_t shard_index) const; @@ -761,7 +739,7 @@ namespace cascade { bool as_trigger = false); public: /** - * object pool version + * object pool version of "put" * @param[in] object the object to write, the object pool is extracted from the object key. * @param[in] as_trigger If true, the object will NOT apply to the K/V store. The object will only be * used to update the state. @@ -793,6 +771,7 @@ namespace cascade { void put_and_forget(const typename SubgroupType::ObjectType& object, uint32_t subgroup_index, uint32_t shard_index, bool as_trigger = false); + protected: /** * "type_recursive_put_and_forget" is a helper function for internal use only. * @param[in] type_index the index of the subgroup type in the CascadeTypes... list. and the FirstType, @@ -804,7 +783,6 @@ namespace cascade { * @param[in] as_trigger If true, the object will NOT apply to the K/V store. The object will only be * used to update the state. */ - protected: template void type_recursive_put_and_forget( uint32_t type_index, @@ -822,7 +800,7 @@ namespace cascade { bool as_trigger = false); public: /** - * object pool version + * object pool version of "put_and_forget" * @param[in] object the object to write, the object pool is extracted from the object key. * @param[in] as_trigger If true, the object will NOT apply to the K/V store. The object will only be * used to update the state. @@ -842,7 +820,7 @@ namespace cascade { template derecho::rpc::QueryResults trigger_put(const typename SubgroupType::ObjectType& object, uint32_t subgroup_index, uint32_t shard_index); - + protected: /** * "type_recursive_trigger_put" is a helper function for internal use only. * @param[in] type_index the index of the subgroup type in the CascadeTypes... list. and the FirstType, @@ -854,7 +832,6 @@ namespace cascade { * * @return future */ - protected: template derecho::rpc::QueryResults type_recursive_trigger_put( uint32_t type_index, @@ -870,7 +847,7 @@ namespace cascade { uint32_t shard_index); public: /** - * object pool version + * object pool version of "trigger_put" * @param[in] object the object to write, the object pool is extracted from the object key. */ template @@ -908,6 +885,7 @@ namespace cascade { derecho::rpc::QueryResults remove(const typename SubgroupType::KeyType& key, uint32_t subgroup_index, uint32_t shard_index); + protected: /** * "type_recursive_remove" is a helper function for internal use only. * @param[in] type_index the index of the subgroup type in the CascadeTypes... list. and the FirstType, @@ -918,7 +896,6 @@ namespace cascade { * * @return a future to the version and timestamp of the put operation. */ - protected: template derecho::rpc::QueryResults type_recursive_remove( uint32_t type_index, @@ -934,7 +911,7 @@ namespace cascade { uint32_t shard_index); public: /** - * object pool version + * object pool version of "remove" * @param[in] key the object key * * @return returns a future @@ -946,11 +923,15 @@ namespace cascade { * "get" retrieve the object of a given key * * @param[in] key the object key - * @param[in] version if version is CURRENT_VERSION, this "get" will fire a ordered send to get the latest - * state of the key. Otherwise, it will try to read the key's state at version. - * @param[in] stable if true, get only report the version whose persistent data is safe, meaning the - * persistent data is persisted on all replicas. - * @param[in] subgroup_index the subgroup index of CascadeType + * @param[in] version the version of the object to read. If equal to CURRENT_VERSION, get will either + * read the current object from memory of the replica that handles the get request + * (if stable is false), or read the latest stable version that is persisted (if + * stable is true). Note that in any case "get" will contact only a single replica; + * to use an atomic multicast to get the latest version that is present on all replicas, + * use multi_get. + * @param[in] stable if true, get will wait until the requested version's persistent data is safe, meaning the + * persistent data is persisted on all replicas. + * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * * @return a future to the retrieved object. @@ -963,6 +944,7 @@ namespace cascade { bool stable = true, uint32_t subgroup_index = 0, uint32_t shard_index = 0); + protected: /** * "type_recursive_get" is a helper function for internal use only. * @param[in] type_index the index of the subgroup type in the CascadeTypes... list. and the FirstType, @@ -975,7 +957,6 @@ namespace cascade { * * @return a future for the object. */ - protected: template auto type_recursive_get( uint32_t type_index, @@ -995,7 +976,18 @@ namespace cascade { uint32_t shard_index); public: /** - * object pool version + * object pool version of "get" + * + * @param[in] key the object key; the object pool is extracted from this key + * @param[in] version the version of the object to read. If equal to CURRENT_VERSION, get will either + * read the current object from memory of the replica that handles the get request + * (if stable is false), or read the latest stable version that is persisted (if + * stable is true). Note that in any case "get" will contact only a single replica; + * to use an atomic multicast to get the latest version that is present on all replicas, + * use multi_get. + * @param[in] stable if true, get will wait until the requested version's persistent data is safe, meaning the + * persistent data is persisted on all replicas. + * @return a future to the retrieved object. */ template auto get( @@ -1004,13 +996,15 @@ namespace cascade { bool stable = true); /** - * "multi_get" retrieve the object of a given key, this operation involves atomic broadcast + * "multi_get" retrieves the latest version of the object for a given key using an atomic broadcast. + * This ensures that the get request is mutually exclusive and linearizable with any concurrent put + * requests to the same key. * * @param[in] key the object key - * @param[in] subgroup_index the subgroup index of CascadeType + * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * - * @return a future to the retrieved object. + * @return a future to the retrieved object, including a response from each replica in the shard. */ template derecho::rpc::QueryResults multi_get(const typename SubgroupType::KeyType& key, @@ -1043,7 +1037,11 @@ namespace cascade { public: /** - * object pool version + * object pool version of "multi_get" + * + * @param[in] key the object key; the object pool is extracted from this key + * + * @return a future for the retrieved object, including a response from each replica in the object pool */ template auto multi_get(const KeyType& key); @@ -1101,7 +1099,13 @@ namespace cascade { public: /** - * object pool version + * object pool version of "get_by_time" + * + * @param[in] key the object key; the object pool is extracted from this key + * @param[in] ts_us Wall clock time in microseconds. + * @param[in] stable stable get or not + * + * @return a future for the retrieved object. */ template auto get_by_time( @@ -1113,10 +1117,14 @@ namespace cascade { * "get_size" retrieve size of the object of a given key * * @param[in] key the object key - * @param[in] version if version is CURRENT_VERSION, this "get" will fire a ordered send to get the latest - * state of the key. Otherwise, it will try to read the key's state at version. + * @param[in] version the version of the object to read. If equal to CURRENT_VERSION, this will either + * get the size of the current object from memory of the replica that handles the request + * (if stable is false), or get the size of the latest stable version that is persisted + * (if stable is true). Note that in any case "get_size" will contact only a single replica; + * to use an atomic multicast to check the latest version that is present on all replicas, + * use multi_get_size. * @param[in] stable stable get or not - * @param[in] subgroup_index the subgroup index of CascadeType + * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * * @return a future to the retrieved size. @@ -1130,6 +1138,7 @@ namespace cascade { uint32_t subgroup_index = 0, uint32_t shard_index = 0); + protected: /** * "type_recursive_get_size" is a helper function for internal use only. * @param[in] type_index the index of the subgroup type in the CascadeTypes... list. and the FirstType, @@ -1140,9 +1149,8 @@ namespace cascade { * @param[in] subgroup_index the subgroup index in the subgroup type designated by type_index * @param[in] shard_index the shard index * - * @return a future for the object. + * @return a future for the retrieved size. */ - protected: template derecho::rpc::QueryResults type_recursive_get_size( uint32_t type_index, @@ -1163,7 +1171,16 @@ namespace cascade { public: /** - * object pool version + * object pool version of "get_size" + * @param[in] key the object key + * @param[in] version the version of the object to read. If equal to CURRENT_VERSION, this will either + * get the size of the current object from memory of the replica that handles the request + * (if stable is false), or get the size of the latest stable version that is persisted + * (if stable is true). Note that in any case "get_size" will contact only a single replica; + * to use an atomic multicast to check the latest version that is present on all replicas, + * use multi_get_size. + * @param[in] stable stable get or not + * @return a future for the retrieved size. */ template derecho::rpc::QueryResults get_size( @@ -1172,10 +1189,10 @@ namespace cascade { const bool stable = true); /** - * "multi_get_size" retrieve size of the object of a given key + * "multi_get_size" retrieves the size of the current version of the object with a given key, using an atomic broadcast. * * @param[in] key the object key - * @param[in] subgroup_index the subgroup index of CascadeType + * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * * @return a future to the retrieved size. @@ -1212,7 +1229,11 @@ namespace cascade { public: /** - * object pool version + * object pool version of "multi_get_size" + * + * @param[in] key the object key; the object pool is extracted from this key + * + * @return a future for the retrieved size. */ template derecho::rpc::QueryResults multi_get_size(const KeyType& key); @@ -1237,6 +1258,7 @@ namespace cascade { uint32_t subgroup_index = 0, uint32_t shard_index = 0); + protected: /** * "type_recursive_get_size" is a helper function for internal use only. * @param[in] type_index the index of the subgroup type in the CascadeTypes... list. and the FirstType, @@ -1249,7 +1271,6 @@ namespace cascade { * * @return a future for the object. */ - protected: template derecho::rpc::QueryResults type_recursive_get_size_by_time( uint32_t type_index, @@ -1270,7 +1291,13 @@ namespace cascade { public: /** - * object pool version + * object pool version of "get_size_by_time" + * + * @param[in] key the object key + * @param[in] ts_us Wall clock time in microseconds. + * @param[in] stable stable get or not + * + * @return a future for the retrieved size. */ template derecho::rpc::QueryResults get_size_by_time( @@ -1281,13 +1308,15 @@ namespace cascade { /** * "list_keys" retrieve the list of keys in a shard * - * @param[in] version if version is CURRENT_VERSION, this "get" will fire a ordered send to get the latest - * state of the key. Otherwise, it will try to read the key's state at version. - * @param[in] stable stable or not - * @param[in] subgroup_index the subgroup index of CascadeType + * @param[in] version the version at which to list the keys; all keys that existed at or before this version + * will be included. If equal to CURRENT_VERSION, list_keys will list all keys currently + * in memory at the replica that handles the request. + * @param[in] stable if true, list_keys will wait until the requested version's persistent data is safe, meaning the + * persistent data is persisted on all replicas, before listing the keys present at that version. + * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * - * @return a future to the retrieved object. + * @return a future for the vector of keys * TODO: check if the user application is responsible for reclaim the future by reading it sometime. */ template @@ -1315,27 +1344,40 @@ namespace cascade { __list_keys(const persistent::version_t& version, const bool stable, const std::string& object_pool_pathname); public: /** - * @brief object pool version + * @brief object pool version of "list_keys"; lists all keys in an object pool * - * @param[in] version if version is - * @param[in] stable is stable or not + * @param[in] version the version at which to list the keys; all keys that existed at or before this version + * will be included. If equal to CURRENT_VERSION, list_keys will list all keys currently + * in memory at the replica that handles the request. + * @param[in] stable if true, list_keys will wait until the requested version's persistent data is safe, meaning the + * persistent data is persisted on all replicas, before listing the keys present at that version. * @param[in] object_pool_pathname the object pathname * - * @return a vector of keys. + * @return a vector of futures for key lists, with one key list for each shard in the object pool. + * The return value's type will look like vector>>>, where KeyType is either string or uint64_t */ auto list_keys(const persistent::version_t& version, const bool stable, const std::string& object_pool_pathname); + /** + * A function that helps unpack the return value of list_keys (object-pool version). Iterates through the + * vector of QueryResults and waits for each one to complete, then combines the resulting vectors of keys + * into a single vector of keys (across all shards in the object pool). + * + * @tparam KeyType The type of a key in this object pool + * @param future The vector-of-futures returned by list_keys or multi_list_keys + * @return a vector of keys in the object pool + */ template std::vector wait_list_keys( std::vector>>>& future); /** - * "multi_list_keys" retrieve the list of keys in a shard + * "multi_list_keys" retrieves the list of keys in a shard at the current version, using an atomic multicast * * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * - * @return a future to the retrieved object. + * @return a future for the list of keys. */ template derecho::rpc::QueryResults> multi_list_keys( @@ -1356,20 +1398,24 @@ namespace cascade { __multi_list_keys(const std::string& object_pool_pathname); public: /** - * object pool version + * object pool version of "multi_list_keys" + * * @param[in] object_pool_pathname the object pathname + * + * @return a vector of futures for key lists, with one key list for each shard in the object pool. + * The return value's type will look like vector>>>, where KeyType is either string or uint64_t */ auto multi_list_keys(const std::string& object_pool_pathname); /** - * "list_keys_by_time" retrieve the list of keys in a shard + * "list_keys_by_time" retrieves the list of keys in a shard at a specific time * * @param[in] ts_us Wall clock time in microseconds. - * @param[in] stable - * @param[in] subgroup_index the subgroup index of CascadeType + * @param[in] stable stable get or not + * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] shard_index the shard index. * - * @return a future to the retrieved object. + * @return a future for the list of keys */ template derecho::rpc::QueryResults> list_keys_by_time( @@ -1396,16 +1442,20 @@ namespace cascade { __list_keys_by_time(const uint64_t& ts_us, const bool stable, const std::string& object_pool_pathname); public: /** - * object pool version + * object pool version of "list_keys_by_time" + * * @param[in] ts_us timestamp * @param[in] stable stable flag * @param[in] object_pool_pathname the object pathname + * + * @return a vector of futures for key lists, with one key list for each shard in the object pool. + * The return value's type will look like vector>>>, where KeyType is either string or uint64_t */ auto list_keys_by_time(const uint64_t& ts_us, const bool stable, const std::string& object_pool_pathname); /** * Object Pool Management API: refresh object pool cache - * We load 'unstable' (commited by may not persisted) metadata here. + * We load 'unstable' (committed but maybe not persisted) metadata here. */ void refresh_object_pool_metadata_cache(); @@ -1430,7 +1480,7 @@ namespace cascade { const std::string& affinity_set_regex = ""); /** - * ObjectPoolManagement API: remote object pool + * ObjectPoolManagement API: remove object pool * * @param[in] pathname Object pool pathname * @@ -1674,13 +1724,13 @@ namespace cascade { /** * configuration keys */ - #define CASCADE_CONTEXT_NUM_STATELESS_WORKERS_MULTICAST "CASCADE/num_stateless_workers_for_multicast_ocdp" - #define CASCADE_CONTEXT_NUM_STATELESS_WORKERS_P2P "CASCADE/num_stateless_workers_for_p2p_ocdp" - #define CASCADE_CONTEXT_NUM_STATEFUL_WORKERS_MULTICAST "CASCADE/num_stateful_workers_for_multicast_ocdp" - #define CASCADE_CONTEXT_NUM_STATEFUL_WORKERS_P2P "CASCADE/num_stateful_workers_for_p2p_ocdp" - #define CASCADE_CONTEXT_CPU_CORES "CASCADE/cpu_cores" - #define CASCADE_CONTEXT_GPUS "CASCADE/gpus" - #define CASCADE_CONTEXT_WORKER_CPU_AFFINITY "CASCADE/worker_cpu_affinity" + static constexpr const char* CASCADE_CONTEXT_NUM_STATELESS_WORKERS_MULTICAST = "CASCADE/num_stateless_workers_for_multicast_ocdp"; + static constexpr const char* CASCADE_CONTEXT_NUM_STATELESS_WORKERS_P2P = "CASCADE/num_stateless_workers_for_p2p_ocdp"; + static constexpr const char* CASCADE_CONTEXT_NUM_STATEFUL_WORKERS_MULTICAST = "CASCADE/num_stateful_workers_for_multicast_ocdp"; + static constexpr const char* CASCADE_CONTEXT_NUM_STATEFUL_WORKERS_P2P = "CASCADE/num_stateful_workers_for_p2p_ocdp"; + static constexpr const char* CASCADE_CONTEXT_CPU_CORES = "CASCADE/cpu_cores"; + static constexpr const char* CASCADE_CONTEXT_GPUS = "CASCADE/gpus"; + static constexpr const char* CASCADE_CONTEXT_WORKER_CPU_AFFINITY = "CASCADE/worker_cpu_affinity"; /** * A class describing the resources available in the Cascade context. @@ -1689,7 +1739,7 @@ namespace cascade { public: /** cpu cores, loaded from configuration **/ std::vector cpu_cores; - /** worker cpu aworker cpu ffinity, loaded from configuration **/ + /** worker cpu affinity, loaded from configuration **/ std::map> multicast_ocdp_worker_to_cpu_cores; std::map> p2p_ocdp_worker_to_cpu_cores; /** gpu list**/ @@ -1702,15 +1752,6 @@ namespace cascade { void dump() const; }; - /** - * The cascade context - * - * The cascade context manages computation resources like CPU cores, GPU, and memory. It works as the container for all - * "off-critical" path logics. The main components of cascade context includes: - * 1 - a thread pool for the off-critical path logics. - * 2 - a prefix registry. - * 3 - a bounded Action buffer. - */ /** * @struct prefix_ocdpo_info_t @@ -1728,14 +1769,12 @@ namespace cascade { }; struct PrefixOCDPOInfoHash { - // inline size_t operator() (const prefix_ocdpo_info_t& info) const { size_t operator() (const prefix_ocdpo_info_t& info) const { return std::hash{}(info.udl_id + info.config_string); } }; struct PrefixOCDPOInfoCompare { - // inline bool operator() (const prefix_ocdpo_info_t& l, const prefix_ocdpo_info_t& r) const { bool operator() (const prefix_ocdpo_info_t& l, const prefix_ocdpo_info_t& r) const { return (l.udl_id == r.udl_id) && (l.config_string == r.config_string) && @@ -1743,6 +1782,15 @@ namespace cascade { } }; + /** + * The cascade context + * + * The cascade context manages computation resources like CPU cores, GPU, and memory. It works as the container for all + * "off-critical" path logics. The main components of cascade context includes: + * 1 - a thread pool for the off-critical path logics. + * 2 - a prefix registry. + * 3 - a bounded Action buffer. + */ template class CascadeContext:public ICascadeContext { public: @@ -1828,8 +1876,6 @@ namespace cascade { * constructor, which happens before main(), it might miss extra configuration from commandline. Therefore, * CascadeContext singleton needs to be initialized in main() by calling CascadeContext::construct(). Moreover, it * needs the off critical data path handler from main(); - * - * @param[in] group_ptr The group handle */ void construct(); /** diff --git a/src/applications/tests/cascade_as_subgroup_classes/perf.cpp b/src/applications/tests/cascade_as_subgroup_classes/perf.cpp index 05fff96d..852fde66 100644 --- a/src/applications/tests/cascade_as_subgroup_classes/perf.cpp +++ b/src/applications/tests/cascade_as_subgroup_classes/perf.cpp @@ -109,9 +109,11 @@ class PerfCDPO: public CriticalDataPathObserver { // @override virtual void operator () (const uint32_t sgidx, const uint32_t shidx, + const derecho::node_id_t sender_id, const typename CascadeType::KeyType& key, const typename CascadeType::ObjectType& value, - void* cascade_context){ + ICascadeContext* cascade_context, + bool is_trigger = false) { dbg_default_info("Watcher is called with\n\tsubgroup idx = {},\n\tshard idx = {},\n\tkey = {},\n\tvalue = [hidden].", sgidx, shidx, key); } }; @@ -347,7 +349,7 @@ int do_client(int argc,char** args) { for(uint64_t i = 0; i < num_messages; i++) { ObjectWithUInt64Key o(randomize_key(i)%max_distinct_objects,Blob(bbuf, msg_size)); - cs.do_send(i,[&o,&pcs_ec,&server_id](){return std::move(pcs_ec.p2p_send(server_id,o,false));}); + cs.do_send(i,[&o,&pcs_ec,&server_id](){return pcs_ec.p2p_send(server_id,o,false);}); } free(bbuf); @@ -367,7 +369,7 @@ int do_client(int argc,char** args) { for(uint64_t i = 0; i < num_messages; i++) { ObjectWithUInt64Key o(randomize_key(i)%max_distinct_objects,Blob(bbuf, msg_size)); - cs.do_send(i,[&o,&vcs_ec,&server_id](){return std::move(vcs_ec.p2p_send(server_id,o,false));}); + cs.do_send(i,[&o,&vcs_ec,&server_id](){return vcs_ec.p2p_send(server_id,o,false);}); } free(bbuf); diff --git a/src/service/client.cpp b/src/service/client.cpp index 992d2721..a8611374 100644 --- a/src/service/client.cpp +++ b/src/service/client.cpp @@ -361,10 +361,10 @@ void collective_trigger_put(ServiceClientAPI& capi, const std::string& key, cons template void remove(ServiceClientAPI& capi, const std::string& key, uint32_t subgroup_index, uint32_t shard_index) { if constexpr (std::is_same::value) { - derecho::rpc::QueryResults result = std::move(capi.template remove(static_cast(std::stol(key,nullptr,0)), subgroup_index, shard_index)); + derecho::rpc::QueryResults result = capi.template remove(static_cast(std::stol(key,nullptr,0)), subgroup_index, shard_index); check_put_and_remove_result(result); } else if constexpr (std::is_same::value) { - derecho::rpc::QueryResults result = std::move(capi.template remove(key, subgroup_index, shard_index)); + derecho::rpc::QueryResults result = capi.template remove(key, subgroup_index, shard_index); check_put_and_remove_result(result); } else { print_red(std::string("Unhandled KeyType:") + typeid(typename SubgroupType::KeyType).name()); diff --git a/src/service/fuse/fuse_client_context.hpp b/src/service/fuse/fuse_client_context.hpp index 383fb0b4..902273c7 100644 --- a/src/service/fuse/fuse_client_context.hpp +++ b/src/service/fuse/fuse_client_context.hpp @@ -90,7 +90,7 @@ class FuseClientINode { virtual void initialize(){ } - + // Helper function for get_dir_entries() and read_file() void check_update(){ struct timespec now; @@ -127,8 +127,8 @@ const char *TypeName::name = "PersistentCas template <> const char *TypeName::name = "TriggerCascadeNoStoreWithStringKey"; -#define CONF_LAYOUT "layout" - +#define CONF_LAYOUT "layout" + template class SubgroupINode; @@ -173,9 +173,9 @@ class CascadeTypeINode : public FuseClientINode { this->display_name = group_layout["type_alias"]; uint32_t sidx=0; for (auto subgroup_it:group_layout[CONF_LAYOUT]) { - + children.emplace_back(std::make_unique>(sidx,reinterpret_cast(this))); - size_t num_shards = subgroup_it[MIN_NODES_BY_SHARD].size(); + size_t num_shards = subgroup_it[min_nodes_by_shard_field].size(); for (uint32_t shidx = 0; shidx < num_shards; shidx ++) { this->children[sidx]->children.emplace_back( std::make_unique>( @@ -189,7 +189,7 @@ class CascadeTypeINode : public FuseClientINode { class RootMetaINode : public FuseClientINode { ServiceClientAPI& capi; std::string contents; - + public: RootMetaINode (ServiceClientAPI& _capi) : capi(_capi) { @@ -214,7 +214,7 @@ class RootMetaINode : public FuseClientINode { contents += std::to_string(nid) + ","; } contents += "\n"; - + auto objectpools = capi.list_object_pools(false,true); contents += "number of objectpool in cascade service: " + std::to_string(objectpools.size()) + ".\nObjectpool paths: "; for (auto& objectpool_path : objectpools) { @@ -250,7 +250,7 @@ class ShardINode : public FuseClientINode { ServiceClientAPI& capi; std::map key_to_ino; - ShardINode (uint32_t shidx, fuse_ino_t pino, ServiceClientAPI& _capi) : + ShardINode (uint32_t shidx, fuse_ino_t pino, ServiceClientAPI& _capi) : shard_index (shidx), capi(_capi) { this->type = INodeType::SHARD; this->display_name = "shard-" + std::to_string(shidx); @@ -284,7 +284,7 @@ class ShardINode : public FuseClientINode { return FuseClientINode::get_dir_entries(); } }; - + template <> class ShardINode : public FuseClientINode { public: @@ -292,7 +292,7 @@ class ShardINode : public FuseClientINode { ServiceClientAPI& capi; std::map key_to_ino; - ShardINode (uint32_t shidx, fuse_ino_t pino, ServiceClientAPI& _capi) : + ShardINode (uint32_t shidx, fuse_ino_t pino, ServiceClientAPI& _capi) : shard_index (shidx), capi(_capi) { this->type = INodeType::SHARD; this->display_name = "shard-" + std::to_string(shidx); @@ -392,11 +392,11 @@ class KeyINode : public FuseClientINode { uint64_t file_size; persistent::version_t version; uint64_t timestamp_us; - persistent::version_t previous_version; + persistent::version_t previous_version; persistent::version_t previous_version_by_key; // previous version by key, INVALID_VERSION for the first value of the key. ServiceClientAPI& capi; - - KeyINode(typename CascadeType::KeyType& k, fuse_ino_t pino, ServiceClientAPI& _capi) : + + KeyINode(typename CascadeType::KeyType& k, fuse_ino_t pino, ServiceClientAPI& _capi) : key(k), file_bytes(std::make_unique()), capi(_capi){ @@ -414,7 +414,7 @@ class KeyINode : public FuseClientINode { this->display_name = std::string("key-") + key.to_string(); } // '/' in display name, will cause: reading directory '.': input/output error - std::replace( this->display_name.begin(), this->display_name.end(), '/', '\\'); + std::replace( this->display_name.begin(), this->display_name.end(), '/', '\\'); this->parent = pino; dbg_default_trace("[{}]leaving {}.", gettid(), __func__); } @@ -491,11 +491,11 @@ class ObjectPoolMetaINode : public FuseClientINode { private: std::string cur_pathname; /** objp_collection contains the all the objp with the same cur_pathname prefix - * i.e. if cur_path name is "/a", + * i.e. if cur_path name is "/a", * object pools "/a/b1", "/a/b2" share this level of ObjectPoolPathINode*/ std::vector objp_collection; bool is_object_pool; - uint32_t subgroup_type_index; + uint32_t subgroup_type_index; uint32_t subgroup_index; sharding_policy_t sharding_policy; bool deleted; @@ -526,7 +526,7 @@ class ObjectPoolMetaINode : public FuseClientINode { } this->contents += objp_contents; } - + /** * Only fill the object pool contents when cur_pathname is an object pool */ @@ -589,7 +589,7 @@ class ObjectPoolMetaINode : public FuseClientINode { return 0; } }; - + class ObjectPoolPathINode : public FuseClientINode { public: @@ -625,7 +625,7 @@ class ObjectPoolPathINode : public FuseClientINode { this->children.emplace_back(std::make_unique(cur_pathname, capi)); } - /** Helper function: + /** Helper function: * @param[in] object_pool_pathname: the object pool pathname to parse * @return: next level pathname * e.g. if cur_pathname is "/a", for object_pool_pathname "/a/b/c" this function returns "/a/b" @@ -665,7 +665,7 @@ class ObjectPoolPathINode : public FuseClientINode { if(static_cast(inode.get())->cur_pathname == next_level_pathname){ return; } - } + } } // case2: If this level ObjectPoolPathInode doesn't exists, create one // std::unique_lock wlck(this->children_mutex); @@ -673,7 +673,7 @@ class ObjectPoolPathINode : public FuseClientINode { objp_children.insert(cur_pathname); } - + void update_objpINodes(){ size_t cur_len = cur_pathname.length(); std::vector reply = capi.list_object_pools(false,true); @@ -710,9 +710,9 @@ class ObjectPoolPathINode : public FuseClientINode { }else{ ++it; } - } + } } - + void update_keyINodes(){ // case1. if object pool of cur_pathname donesn't exists anymore, remove all the keyINode from children if(!this->is_object_pool){ @@ -735,7 +735,7 @@ class ObjectPoolPathINode : public FuseClientINode { if(key_children.find(key) == key_children.end() ){ this->children.emplace_back(std::make_unique(key,reinterpret_cast(this),capi)); key_children.insert(key); - } + } } // Check if need to remove existing keyINode from children inodes auto it = this->children.begin(); @@ -744,11 +744,11 @@ class ObjectPoolPathINode : public FuseClientINode { if ((*it)->type == INodeType::KEY && (std::find(reply.begin(),reply.end(), name ) == reply.end())){ key_children.erase(key_children.find(name)); it = this->children.erase(it); - + }else{ ++it; } - } + } } @@ -764,7 +764,7 @@ class ObjectPoolPathINode : public FuseClientINode { update_keyINodes(); } }; - + class ObjectPoolRootINode : public ObjectPoolPathINode { public: ObjectPoolRootINode (ServiceClientAPI& _capi, fuse_ino_t pino=FUSE_ROOT_ID) : @@ -773,7 +773,7 @@ class ObjectPoolRootINode : public ObjectPoolPathINode { this->parent = pino; } - /** this function constructs the whole object pool directories at the beginning + /** this function constructs the whole object pool directories at the beginning * for all the object pools stored in metadata service */ virtual std::map get_dir_entries() override { @@ -796,7 +796,7 @@ class ObjectPoolKeyINode : public FuseClientINode{ std::unique_ptr file_bytes; persistent::version_t version; uint64_t timestamp_us; - persistent::version_t previous_version; + persistent::version_t previous_version; persistent::version_t previous_version_by_key; // previous version by key, INVALID_VERSION for the first value of the key. ServiceClientAPI& capi; @@ -827,7 +827,7 @@ class ObjectPoolKeyINode : public FuseClientINode{ virtual uint64_t get_file_size() override { dbg_default_debug("----GET FILE SIZE key is [{}].", this->key); check_update(); - return this->file_bytes.get()->size; + return this->file_bytes.get()->size; } virtual ~ObjectPoolKeyINode() { @@ -875,7 +875,7 @@ class MetadataServiceRootINode : public FuseClientINode { children.emplace_back(std::make_unique(capi, reinterpret_cast(this))); this->children.back().get()->initialize(); } - + }; /** @@ -908,7 +908,7 @@ class DLLINode : public FuseClientINode { public: std::string file_name; // DLL id? ServiceClientAPI& capi; - DLLINode(std::string& _filename, fuse_ino_t pino, ServiceClientAPI& _capi) : + DLLINode(std::string& _filename, fuse_ino_t pino, ServiceClientAPI& _capi) : file_name(_filename), capi(_capi) { dbg_default_trace("[{}]entering {}.", gettid(), __func__); this->type = INodeType::DLL; @@ -916,7 +916,7 @@ class DLLINode : public FuseClientINode { this->parent = pino; dbg_default_trace("[{}]leaving {}.", gettid(), __func__); } - + virtual uint64_t read_file(FileBytes* file_bytes) override { dbg_default_trace("[{}]entering {}.", gettid(), __func__); dbg_default_trace("[{}]leaving {}.", gettid(), __func__); @@ -944,7 +944,7 @@ class DLLINode : public FuseClientINode { } }; - + /** * The fuse filesystem context for fuse_client. This context will be used as 'userdata' on starting a fuse session. */ @@ -1101,7 +1101,7 @@ class FuseClientContext { stbuf.st_blocks = (stbuf.st_size+FUSE_CLIENT_BLK_SIZE-1)/FUSE_CLIENT_BLK_SIZE; stbuf.st_blksize = FUSE_CLIENT_BLK_SIZE; break; - case INodeType::DATAPATH_LOGIC: + case INodeType::DATAPATH_LOGIC: stbuf.st_mode = S_IFDIR | 0755; stbuf.st_size = pfci->get_file_size(); stbuf.st_blocks = (stbuf.st_size+FUSE_CLIENT_BLK_SIZE-1)/FUSE_CLIENT_BLK_SIZE; @@ -1130,7 +1130,7 @@ class FuseClientContext { int open_file(fuse_ino_t ino, struct fuse_file_info *fi) { dbg_default_trace("[{}]entering {} with ino={:x}.", gettid(), __func__, ino); FuseClientINode* pfci = reinterpret_cast(ino); - if (pfci->type != INodeType::KEY && + if (pfci->type != INodeType::KEY && pfci->type != INodeType::META) { return EISDIR; } diff --git a/src/service/perftest.cpp b/src/service/perftest.cpp index fb0ce87e..a1b5cc65 100644 --- a/src/service/perftest.cpp +++ b/src/service/perftest.cpp @@ -537,8 +537,8 @@ bool PerfTestServer::eval_get_by_time(uint64_t ms_in_past, timestamp_to_request = std::get<1>(first_object_version_tuple) + timestamp_offset_us; put_futures_queue.pop(); // Wait for the other puts to complete - persistent::version_t last_object_version; - std::size_t last_object_put; + persistent::version_t last_object_version = -1; + std::size_t last_object_put = -1; while(put_futures_queue.size() > 0) { auto& replies = put_futures_queue.front().second.get(); std::size_t object_index = put_futures_queue.front().first; From 400aa3eba7d4cbec01b2b1e8768d0f4ac12d3396 Mon Sep 17 00:00:00 2001 From: Edward Tremel Date: Tue, 15 Jul 2025 10:32:17 -0400 Subject: [PATCH 4/5] Fixed some more compiler warnings These showed up after a clean rebuild, mostly complaining about documentation comments not matching the function signature. --- include/cascade/cascade_interface.hpp | 12 ++++-------- include/cascade/detail/prefix_registry.hpp | 2 -- include/cascade/service.hpp | 2 -- include/cascade/utils.hpp | 1 - .../cascade_as_subgroup_classes/cli_example.cpp | 9 +++++---- src/udl_zoo/mproc/object_commit_protocol.hpp | 2 +- 6 files changed, 10 insertions(+), 18 deletions(-) diff --git a/include/cascade/cascade_interface.hpp b/include/cascade/cascade_interface.hpp index 4b1df133..fcc9f447 100644 --- a/include/cascade/cascade_interface.hpp +++ b/include/cascade/cascade_interface.hpp @@ -49,8 +49,6 @@ class CriticalDataPathObserver : public derecho::DeserializationContext { * @param[in] value The value of the K/V pair * @param[in] cascade_ctxt The cascade context to be used later * @param[in] is_trigger True for critical data path of `p2p_send`; otherwise, the critical data path of `ordered_send`. - * - * @return void */ virtual void operator()(const uint32_t subgroup_idx, const uint32_t shard_idx, @@ -111,8 +109,6 @@ class ICascadeStore { * * @param[in] value The K/V pair value * @param[in] as_trigger The object will NOT be used to update the K/V state. - * - * @return void */ virtual void put_and_forget(const VT& value, bool as_trigger) const = 0; @@ -149,7 +145,7 @@ class ICascadeStore { * If `stable == false`, we only return the data reflecting the latest locally delivered atomic * broadcast. Otherwise, stable data will be returned, meaning that the persisted states returned * is safe: they will survive after whole system recovery. - * @param[in] exact + * @param[in] exact * The exact match flag: this function try to return the value of that key at the 'ver'. If such a * value does not exists and exact is true, it will throw an exception. If such a value does not * exists and exact is false, it will return the latest state of the value for 'key' before 'ver'. @@ -272,7 +268,7 @@ class ICascadeStore { * @param[in] key The key * @param[in] ver Version, if `ver == CURRENT_VERSION`, get the latest value. * @param[in] stable - * @param[in] exact + * @param[in] exact * The exact match flag: this function try to return the value of that key at the 'ver'. If such a * value does not exists and exact is true, it will throw an exception. If such a value does not * exists and exact is false, it will return the latest state of the value for 'key' before 'ver'. @@ -427,7 +423,7 @@ VT create_null_object_cb(const KT& key = *IK); * We use both the concepts of null and valid object in Cascade. A null object precisely means 'no data'; while a * valid object literarily means an object is 'valid'. Technically, a null object has a valid key while invalid * object does not. - * + * * @tparam KT The key type. * @tparam VT The value type. */ @@ -489,7 +485,7 @@ class IKeepVersion { /** * @brief The version getter - * + * * Get the version * * @return The K/V object's version. diff --git a/include/cascade/detail/prefix_registry.hpp b/include/cascade/detail/prefix_registry.hpp index ae97ccff..8e166b79 100644 --- a/include/cascade/detail/prefix_registry.hpp +++ b/include/cascade/detail/prefix_registry.hpp @@ -115,8 +115,6 @@ class PrefixRegistry { * * @param path - the full path. * @param collector - the lambda function to collect values for all prefixes of a string. - * - * @return */ void collect_values_for_prefixes(const std::string& path, const std::function& value)>& collector) const; diff --git a/include/cascade/service.hpp b/include/cascade/service.hpp index 9c52b07c..891d26f0 100644 --- a/include/cascade/service.hpp +++ b/include/cascade/service.hpp @@ -863,8 +863,6 @@ namespace cascade { * @param[in] object the object to write. * @param[in] subgroup_index the subgroup index of CascadeType * @param[in] nodes_and_futures map from node ids to futures. - * - * @return an array of void futures, which length is nodes.size() */ template void collective_trigger_put(const typename SubgroupType::ObjectType& object, diff --git a/include/cascade/utils.hpp b/include/cascade/utils.hpp index 4e24d5e7..a39f70a2 100644 --- a/include/cascade/utils.hpp +++ b/include/cascade/utils.hpp @@ -85,7 +85,6 @@ class OpenLoopLatencyCollectorClient { * @param id The event id for corresponding event. * @param use_local_ts Using loca timestamp. * - * @return N/A */ virtual void ack(uint32_t type, uint32_t id, bool use_local_ts = false) = 0; diff --git a/src/applications/tests/cascade_as_subgroup_classes/cli_example.cpp b/src/applications/tests/cascade_as_subgroup_classes/cli_example.cpp index df89e258..f82226ea 100644 --- a/src/applications/tests/cascade_as_subgroup_classes/cli_example.cpp +++ b/src/applications/tests/cascade_as_subgroup_classes/cli_example.cpp @@ -32,7 +32,7 @@ static std::vector tokenize(std::string& line) { } static void client_help() { - static const char* HELP_STR = + static const char* HELP_STR = "(v/p/t)put \n" " - Put an object\n" "(v/p)get [-t timestamp_in_us | -v version_number]\n" @@ -67,7 +67,7 @@ static void client_put(derecho::ExternalGroupClient& group, } uint64_t key = std::stoll(tokens[1]); - + //TODO: the previous_version should be used to enforce version check. INVALID_VERSION disables the feature. ObjectWithUInt64Key o(key,Blob(reinterpret_cast(tokens[2].c_str()),tokens[2].size())); @@ -95,7 +95,7 @@ static void client_trigger_put(derecho::ExternalGroupClient& group, } uint64_t key = std::stoll(tokens[1]); - + ObjectWithUInt64Key o(key,Blob(reinterpret_cast(tokens[2].c_str()),tokens[2].size())); ExternalClientCaller::type>& vcs_ec = group.get_subgroup_caller(); @@ -203,7 +203,7 @@ static void client_remove(derecho::ExternalGroupClient& group, } uint64_t key = std::stoll(tokens[1]); - + if (is_persistent) { ExternalClientCaller::type>& pcs_ec = group.get_subgroup_caller(); auto result = pcs_ec.p2p_send(member,key); @@ -300,6 +300,7 @@ class PerfCDPO : public CriticalDataPathObserver { // @overload void operator () (const uint32_t sgidx, const uint32_t shidx, + const derecho::node_id_t sender_id, const typename CascadeType::KeyType& key, const typename CascadeType::ObjectType& value, ICascadeContext* cascade_context, diff --git a/src/udl_zoo/mproc/object_commit_protocol.hpp b/src/udl_zoo/mproc/object_commit_protocol.hpp index 9180c928..da5c48f8 100644 --- a/src/udl_zoo/mproc/object_commit_protocol.hpp +++ b/src/udl_zoo/mproc/object_commit_protocol.hpp @@ -42,7 +42,7 @@ class ObjectCommitRequestHeader { /** * @brief The version assigned to this put operation. */ - version_t version; + persistent::version_t version; /** * @brief Control flags for the request * - `flags & OBJECT_COMMIT_REQUEST_MEMORY_MASK` tells memory type: inline or shared memory From 01e5904dce68c90d532c8ef6fba1763caf6f2bcd Mon Sep 17 00:00:00 2001 From: Edward Tremel Date: Tue, 15 Jul 2025 14:52:06 -0400 Subject: [PATCH 5/5] Fixed two typos in c2f067367ecc3d8d913ab9b5707f0b5242124354 I made two stupid mistakes when copying and pasting the changes to scripts that had more than one existing argument. Good thing I double-checked the diff on GitHub. --- scripts/prerequisites/install-libtorch.sh | 2 +- scripts/prerequisites/install-tensorflow.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/prerequisites/install-libtorch.sh b/scripts/prerequisites/install-libtorch.sh index 66e5ce1e..97ef470a 100755 --- a/scripts/prerequisites/install-libtorch.sh +++ b/scripts/prerequisites/install-libtorch.sh @@ -6,7 +6,7 @@ if [ $# -lt 1 ]; then fi INSTALL_PREFIX="/usr/local" -if [[ $# -gt 0 ]]; then +if [[ $# -gt 1 ]]; then INSTALL_PREFIX=$2 fi INSTALL_TYPE=$1 diff --git a/scripts/prerequisites/install-tensorflow.sh b/scripts/prerequisites/install-tensorflow.sh index 6b0757cf..ce6799ea 100755 --- a/scripts/prerequisites/install-tensorflow.sh +++ b/scripts/prerequisites/install-tensorflow.sh @@ -7,7 +7,7 @@ fi # pip3 install tensorflow==${VERSION} INSTALL_PREFIX="/usr/local" -if [[ $# -gt 0 ]]; then +if [[ $# -gt 2 ]]; then INSTALL_PREFIX=$3 fi VERSION=$1