diff --git a/apply-clang-format.sh b/apply-clang-format.sh index a2c1e5965..37cfc76e3 100755 --- a/apply-clang-format.sh +++ b/apply-clang-format.sh @@ -22,7 +22,7 @@ while getopts "v" opt; do esac done -find ./src -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' -o -iname '*.cc' | xargs clang-format -style=file -i -fallback-style=none +find ./src -iname '*.h' -o -iname '*.cpp' -o -iname '*.hpp' -o -iname '*.cc' -o -iname '*.ipp' | xargs clang-format -style=file -i -fallback-style=none if [ $VALIDATE ]; then EXIT_CODE=0 diff --git a/src/include/homestore/blk.hpp b/src/include/homestore/blk.hpp index 7b9930bf5..31679f0a3 100644 --- a/src/include/homestore/blk.hpp +++ b/src/include/homestore/blk.hpp @@ -143,7 +143,7 @@ struct multi_blk_id : public blk_id { iterator(multi_blk_id const& mb) : mbid_{mb} {} std::optional< blk_id > next() { if (next_blk_ == 0) { - auto bid = r_cast< blk_id const& >(mbid_); + auto bid = reinterpret_cast< blk_id const& >(mbid_); ++next_blk_; return (bid.is_valid()) ? std::make_optional(blk_id{bid.blk_num(), bid.blk_count(), bid.chunk_num()}) : std::nullopt; @@ -229,7 +229,8 @@ std::basic_ostream< charT, traits >& operator<<(std::basic_ostream< charT, trait } template < typename charT, typename traits > -std::basic_ostream< charT, traits >& operator<<(std::basic_ostream< charT, traits >& outStream, multi_blk_id const& blk) { +std::basic_ostream< charT, traits >& operator<<(std::basic_ostream< charT, traits >& outStream, + multi_blk_id const& blk) { return stream_op< charT, traits, multi_blk_id >(outStream, blk); } @@ -248,16 +249,16 @@ ENUM(BlkAllocStatus, uint32_t, ); struct blk_alloc_hints { - blk_temp_t desired_temp{0}; // Temperature hint for the device - std::optional< uint32_t > reserved_blks; // Reserved blks in a chunk - std::optional< uint32_t > pdev_id_hint; // which physical device to pick (hint if any) -1 for don't care - std::optional< chunk_num_t > chunk_id_hint; // any specific chunk id to pick for this allocation + blk_temp_t desired_temp{0}; // Temperature hint for the device + std::optional< uint32_t > reserved_blks; // Reserved blks in a chunk + std::optional< uint32_t > pdev_id_hint; // which physical device to pick (hint if any) -1 for don't care + std::optional< chunk_num_t > chunk_id_hint; // any specific chunk id to pick for this allocation std::optional< multi_blk_id > committed_blk_id; // blk id indicates the blk was already allocated and committed, - // don't allocate and commit again - std::optional< stream_id_t > stream_id_hint; // any specific stream to pick - std::optional< uint64_t > application_hint; // hints in uint64 what will be passed opaque to select_chunk - bool can_look_for_other_chunk{true}; // If alloc on device not available can I pick other device - bool is_contiguous{true}; // Should the entire allocation be one contiguous block + // don't allocate and commit again + std::optional< stream_id_t > stream_id_hint; // any specific stream to pick + std::optional< uint64_t > application_hint; // hints in uint64 what will be passed opaque to select_chunk + bool can_look_for_other_chunk{true}; // If alloc on device not available can I pick other device + bool is_contiguous{true}; // Should the entire allocation be one contiguous block bool partial_alloc_ok{false}; // ok to allocate only portion of nblks? Mutually exclusive with is_contiguous uint32_t min_blks_per_piece{1}; // blks allocated in a blkid should be atleast this size per entry uint32_t max_blks_per_piece{max_blks_per_blkid()}; // Number of blks on every entry diff --git a/src/include/homestore/btree/btree.ipp b/src/include/homestore/btree/btree.ipp index a0255c015..7a6961e5d 100644 --- a/src/include/homestore/btree/btree.ipp +++ b/src/include/homestore/btree/btree.ipp @@ -51,14 +51,15 @@ void Btree< K, V >::set_root_node_info(const BtreeLinkInfo& info) { } template < typename K, typename V > -uint16_t Btree< K, V >::get_btree_depth() const {return m_btree_depth;} +uint16_t Btree< K, V >::get_btree_depth() const { + return m_btree_depth; +} template < typename K, typename V > -std::pair Btree< K, V >::get_num_nodes() const { +std::pair< uint64_t, uint64_t > Btree< K, V >::get_num_nodes() const { return {m_total_interior_nodes, m_total_leaf_nodes}; } - template < typename K, typename V > std::pair< btree_status_t, uint64_t > Btree< K, V >::destroy_btree(void* context) { btree_status_t ret{btree_status_t::success}; diff --git a/src/include/homestore/btree/btree_kv.hpp b/src/include/homestore/btree/btree_kv.hpp index 807b83050..1b3512a0f 100644 --- a/src/include/homestore/btree/btree_kv.hpp +++ b/src/include/homestore/btree/btree_kv.hpp @@ -269,7 +269,7 @@ class BtreeLinkInfo : public BtreeValue { sisl::blob serialize() const override { sisl::blob b; b.set_size(sizeof(bnode_link_info)); - b.set_bytes(r_cast< const uint8_t* >(&info)); + b.set_bytes(reinterpret_cast< const uint8_t* >(&info)); return b; } uint32_t serialized_size() const override { return sizeof(bnode_link_info); } @@ -278,7 +278,7 @@ class BtreeLinkInfo : public BtreeValue { void deserialize(const sisl::blob& b, bool copy) override { DEBUG_ASSERT_EQ(b.size(), sizeof(bnode_link_info), "BtreeLinkInfo deserialize received invalid blob"); - auto other = r_cast< bnode_link_info const* >(b.cbytes()); + auto other = reinterpret_cast< bnode_link_info const* >(b.cbytes()); set_bnode_id(other->m_bnodeid); set_link_version(other->m_link_version); } diff --git a/src/include/homestore/btree/detail/btree_common.ipp b/src/include/homestore/btree/detail/btree_common.ipp index b4e730b67..2e8be83c5 100644 --- a/src/include/homestore/btree/detail/btree_common.ipp +++ b/src/include/homestore/btree/detail/btree_common.ipp @@ -96,23 +96,25 @@ btree_status_t Btree< K, V >::do_destroy(uint64_t& n_freed_nodes, void* context) } template < typename K, typename V > -std::pair Btree< K, V >::compute_node_count() { +std::pair< uint64_t, uint64_t > Btree< K, V >::compute_node_count() { uint64_t leaf_cnt = 0; uint64_t interior_cnt = 0; m_btree_lock.lock_shared(); get_child_node_count(m_root_node_info.bnode_id(), interior_cnt, leaf_cnt); m_total_leaf_nodes = leaf_cnt; - m_total_interior_nodes= interior_cnt; + m_total_interior_nodes = interior_cnt; m_btree_lock.unlock_shared(); return {interior_cnt, leaf_cnt}; } template < typename K, typename V > -uint16_t Btree< K, V >::compute_btree_depth() { +uint16_t Btree< K, V >::compute_btree_depth() { m_btree_lock.lock_shared(); BtreeNodePtr root; locktype_t acq_lock = locktype_t::READ; - if (read_and_lock_node(m_root_node_info.bnode_id(), root, acq_lock, acq_lock, nullptr) != btree_status_t::success){ return -1; } + if (read_and_lock_node(m_root_node_info.bnode_id(), root, acq_lock, acq_lock, nullptr) != btree_status_t::success) { + return -1; + } m_btree_depth = root->level(); unlock_node(root, acq_lock); m_btree_lock.unlock_shared(); @@ -124,16 +126,16 @@ void Btree< K, V >::get_child_node_count(bnodeid_t bnodeid, uint64_t& interior_c BtreeNodePtr node; locktype_t acq_lock = locktype_t::READ; - if (read_and_lock_node(bnodeid, node, acq_lock, acq_lock, nullptr) != btree_status_t::success) { return ; } - if(node->is_leaf()) { + if (read_and_lock_node(bnodeid, node, acq_lock, acq_lock, nullptr) != btree_status_t::success) { return; } + if (node->is_leaf()) { ++leaf_cnt; } else { ++interior_cnt; } if (!node->is_leaf()) { - if(node->level()==1){ - leaf_cnt += node->total_entries() + (node->has_valid_edge()?1:0); - }else{ + if (node->level() == 1) { + leaf_cnt += node->total_entries() + (node->has_valid_edge() ? 1 : 0); + } else { uint32_t i = 0; while (i < node->total_entries()) { BtreeLinkInfo p; @@ -141,11 +143,11 @@ void Btree< K, V >::get_child_node_count(bnodeid_t bnodeid, uint64_t& interior_c get_child_node_count(p.bnode_id(), interior_cnt, leaf_cnt); ++i; } - if (node->has_valid_edge()) {get_child_node_count(node->edge_id(), interior_cnt, leaf_cnt); } + if (node->has_valid_edge()) { get_child_node_count(node->edge_id(), interior_cnt, leaf_cnt); } } } unlock_node(node, acq_lock); - return ; + return; } template < typename K, typename V > @@ -248,8 +250,8 @@ uint64_t Btree< K, V >::count_keys(bnodeid_t bnodeid) const { return result; } -template -void Btree::validate_node_child_relation(BtreeNodePtr node, BtreeNodePtr& last_child_node) const { +template < typename K, typename V > +void Btree< K, V >::validate_node_child_relation(BtreeNodePtr node, BtreeNodePtr& last_child_node) const { if (node->is_leaf()) { return; } uint32_t nentries = node->has_valid_edge() ? node->total_entries() + 1 : node->total_entries(); BtreeNodePtr previous_child = nullptr; @@ -257,74 +259,90 @@ void Btree::validate_node_child_relation(BtreeNodePtr node, BtreeNodePtr& BtreeLinkInfo child_info; node->get_nth_value(ind, &child_info, false /* copy */); if (child_info.bnode_id() == empty_bnodeid) { - throw std::runtime_error(fmt::format("{}-th child of node [{}] info has empty bnode_id", ind, node->to_string())); + throw std::runtime_error( + fmt::format("{}-th child of node [{}] info has empty bnode_id", ind, node->to_string())); } BtreeNodePtr child_node; if (auto ret = read_node_impl(child_info.bnode_id(), child_node); ret != btree_status_t::success) { - throw std::runtime_error(fmt::format("Failed to read child node [{}] of node [{}]", child_info.bnode_id(), node->to_string())); + throw std::runtime_error( + fmt::format("Failed to read child node [{}] of node [{}]", child_info.bnode_id(), node->to_string())); } if (ind == nentries - 1) { last_child_node = child_node; } if (child_node->is_node_deleted()) { - throw std::runtime_error(fmt::format("Child node [{}] is deleted for parent [{}]", child_node->to_string(), node->to_string())); + throw std::runtime_error( + fmt::format("Child node [{}] is deleted for parent [{}]", child_node->to_string(), node->to_string())); } if (child_node->level() != node->level() - 1) { - throw std::runtime_error(fmt::format("Child node level mismatch node [{}] child level: {}, expected: {}",child_node->to_string(), child_node->level(), node->level() - 1)); + throw std::runtime_error(fmt::format("Child node level mismatch node [{}] child level: {}, expected: {}", + child_node->to_string(), child_node->level(), node->level() - 1)); } K child_first_key = child_node->get_first_key< K >(); K child_last_key = child_node->get_last_key< K >(); K parent_nth_key; - if(child_node->total_entries() >0) { - if(ind< node->total_entries()){ - parent_nth_key= node->get_nth_key(ind, false /* copy */); - if(child_first_key.compare(parent_nth_key) > 0) { - throw std::runtime_error(fmt::format("{}-th Child node [{}] first key is less than its corresponding parent node [{}] key",ind,child_node->to_string(),node->to_string())); - } - if(child_last_key.compare(parent_nth_key) > 0) { - throw std::runtime_error(fmt::format("{}-th Child node [{}] last key is greater than its corresponding parent node [{}] key",ind, child_node->to_string(), node->to_string())); - } - } + if (child_node->total_entries() > 0) { + if (ind < node->total_entries()) { + parent_nth_key = node->get_nth_key< K >(ind, false /* copy */); + if (child_first_key.compare(parent_nth_key) > 0) { + throw std::runtime_error(fmt::format( + "{}-th Child node [{}] first key is less than its corresponding parent node [{}] key", ind, + child_node->to_string(), node->to_string())); + } + if (child_last_key.compare(parent_nth_key) > 0) { + throw std::runtime_error(fmt::format( + "{}-th Child node [{}] last key is greater than its corresponding parent node [{}] key", ind, + child_node->to_string(), node->to_string())); + } + } } else if (!child_node->is_leaf() && !child_node->has_valid_edge()) { throw std::runtime_error(fmt::format("Interior Child node [{}] cannot be empty", child_node->to_string())); } - if(ind > 0){ - if (previous_child->next_bnode()!= child_node->node_id()) { - throw std::runtime_error(fmt::format("Broken child linkage: {}-th Child node [{}] node id is not equal to previous child node [{}] next node",ind, child_node->to_string(), child_node->node_id(), previous_child->to_string())); + if (ind > 0) { + if (previous_child->next_bnode() != child_node->node_id()) { + throw std::runtime_error(fmt::format("Broken child linkage: {}-th Child node [{}] node id is not equal " + "to previous child node [{}] next node", + ind, child_node->to_string(), child_node->node_id(), + previous_child->to_string())); } - K last_parent_key = node->get_nth_key< K >(ind-1, false /* copy */); + K last_parent_key = node->get_nth_key< K >(ind - 1, false /* copy */); K previous_child_last_key = previous_child->get_last_key< K >(); - if(child_node->total_entries()){ - if (previous_child->total_entries() && child_first_key.compare(previous_child_last_key) <= 0) { - throw std::runtime_error(fmt::format("Child node [{}] first key is not greater than previous child node [{}] last key",child_node->to_string(), previous_child->to_string())); + if (child_node->total_entries()) { + if (previous_child->total_entries() && child_first_key.compare(previous_child_last_key) <= 0) { + throw std::runtime_error( + fmt::format("Child node [{}] first key is not greater than previous child node [{}] last key", + child_node->to_string(), previous_child->to_string())); } - if(child_first_key.compare(last_parent_key) <= 0) { - throw std::runtime_error(fmt::format("Child node [{}] first key is not greater than previous key ({}-th) parent node [{}] key ",child_node->to_string(),ind-1, node->to_string())); + if (child_first_key.compare(last_parent_key) <= 0) { + throw std::runtime_error(fmt::format( + "Child node [{}] first key is not greater than previous key ({}-th) parent node [{}] key ", + child_node->to_string(), ind - 1, node->to_string())); } } } previous_child = child_node; } - if(node->has_valid_edge() && last_child_node->is_leaf() && last_child_node->next_bnode()!=empty_bnodeid) { - // If the last child node is a leaf and has a next_bnode, it cannot be a valid edge. - throw std::runtime_error(fmt::format("Last child node [{}] of node [{}] is the last child but has next_bnode", - last_child_node->to_string(), node->to_string())); - } - if(node->has_valid_edge() && !last_child_node->is_leaf() && !last_child_node->has_valid_edge()) { - throw std::runtime_error(fmt::format("Last child node [{}] of edge node [{}] is not edge", - last_child_node->to_string(), node->to_string())); - } - if(!node->has_valid_edge() && last_child_node->is_leaf() && last_child_node->next_bnode()==empty_bnodeid){ - throw std::runtime_error(fmt::format("node [{}] is not edge but last child node [{}] is leaf and has no next_bnode", - node->to_string(),last_child_node->to_string())); - } - if(!node->has_valid_edge() && !last_child_node->is_leaf() && last_child_node->has_valid_edge()){ - throw std::runtime_error(fmt::format("node [{}] is not edge but last child node [{}] has valid edge", - node->to_string(), last_child_node->to_string())); - } + if (node->has_valid_edge() && last_child_node->is_leaf() && last_child_node->next_bnode() != empty_bnodeid) { + // If the last child node is a leaf and has a next_bnode, it cannot be a valid edge. + throw std::runtime_error(fmt::format("Last child node [{}] of node [{}] is the last child but has next_bnode", + last_child_node->to_string(), node->to_string())); + } + if (node->has_valid_edge() && !last_child_node->is_leaf() && !last_child_node->has_valid_edge()) { + throw std::runtime_error(fmt::format("Last child node [{}] of edge node [{}] is not edge", + last_child_node->to_string(), node->to_string())); + } + if (!node->has_valid_edge() && last_child_node->is_leaf() && last_child_node->next_bnode() == empty_bnodeid) { + throw std::runtime_error( + fmt::format("node [{}] is not edge but last child node [{}] is leaf and has no next_bnode", + node->to_string(), last_child_node->to_string())); + } + if (!node->has_valid_edge() && !last_child_node->is_leaf() && last_child_node->has_valid_edge()) { + throw std::runtime_error(fmt::format("node [{}] is not edge but last child node [{}] has valid edge", + node->to_string(), last_child_node->to_string())); + } } template < typename K, typename V > @@ -332,26 +350,34 @@ void Btree< K, V >::validate_next_node_relation(BtreeNodePtr node, BtreeNodePtr BtreeNodePtr last_child_node) const { K last_key = node->get_last_key< K >(); - if (neighbor_node->total_entries() == 0 && !neighbor_node->has_valid_edge() && last_child_node &&last_child_node->next_bnode() != empty_bnodeid) { - throw std::runtime_error(fmt::format("neighbor [{}] has no entries nor valid edge but the last child, [{}] of the parent [{}] has next node id {}",neighbor_node->to_string(), last_child_node->to_string(), node->to_string(), last_child_node->next_bnode())); + if (neighbor_node->total_entries() == 0 && !neighbor_node->has_valid_edge() && last_child_node && + last_child_node->next_bnode() != empty_bnodeid) { + throw std::runtime_error(fmt::format("neighbor [{}] has no entries nor valid edge but the last child, [{}] of " + "the parent [{}] has next node id {}", + neighbor_node->to_string(), last_child_node->to_string(), + node->to_string(), last_child_node->next_bnode())); } - if ((neighbor_node->total_entries() != 0 || neighbor_node->has_valid_edge()) && last_child_node &&last_child_node->next_bnode() == empty_bnodeid) { - throw std::runtime_error(fmt::format("neighbor [{}] has entries or valid edge but the last child, [{}] of the parent [{}] has no next node id",neighbor_node->to_string(), last_child_node->to_string(), node->to_string())); + if ((neighbor_node->total_entries() != 0 || neighbor_node->has_valid_edge()) && last_child_node && + last_child_node->next_bnode() == empty_bnodeid) { + throw std::runtime_error(fmt::format( + "neighbor [{}] has entries or valid edge but the last child, [{}] of the parent [{}] has no next node id", + neighbor_node->to_string(), last_child_node->to_string(), node->to_string())); } if (neighbor_node->is_node_deleted()) { - throw std::runtime_error(fmt::format("Neighbor node [{}] is deleted " , neighbor_node->to_string())); + throw std::runtime_error(fmt::format("Neighbor node [{}] is deleted ", neighbor_node->to_string())); } if (neighbor_node->level() != node->level()) { throw std::runtime_error(fmt::format("Neighbor node [{}] level {} mismatch vs node [{}] level {}", - neighbor_node->to_string(), neighbor_node->level(), node->to_string(), - node->level())); + neighbor_node->to_string(), neighbor_node->level(), node->to_string(), + node->level())); } K neighbor_first_key = neighbor_node->get_first_key< K >(); auto neighbor_entities = neighbor_node->total_entries(); if (neighbor_entities && neighbor_first_key.compare(last_key) < 0) { - throw std::runtime_error(fmt::format("Neighbor's first key {} is not greater than node's last key {} (node=[{}], neighbor=[{}])", - neighbor_first_key.to_string(), last_key.to_string(), node->to_string(), neighbor_node->to_string())); + throw std::runtime_error(fmt::format( + "Neighbor's first key {} is not greater than node's last key {} (node=[{}], neighbor=[{}])", + neighbor_first_key.to_string(), last_key.to_string(), node->to_string(), neighbor_node->to_string())); } if (!node->is_leaf()) { if (!neighbor_node->has_valid_edge() && !neighbor_entities) { @@ -360,14 +386,15 @@ void Btree< K, V >::validate_next_node_relation(BtreeNodePtr node, BtreeNodePtr BtreeLinkInfo first_neighbor_info; neighbor_node->get_nth_value(0, &first_neighbor_info, false /* copy */); if (last_child_node->next_bnode() != first_neighbor_info.bnode_id()) { - throw std::runtime_error(fmt::format("Last child node's next_bnode (child=[{}]) does not match neighbor's first bnode_id (neighbor=[{}])", last_child_node->to_string(), neighbor_node->to_string())); - + throw std::runtime_error(fmt::format( + "Last child node's next_bnode (child=[{}]) does not match neighbor's first bnode_id (neighbor=[{}])", + last_child_node->to_string(), neighbor_node->to_string())); } } } -template -void Btree::validate_node(const bnodeid_t& bnodeid) const { +template < typename K, typename V > +void Btree< K, V >::validate_node(const bnodeid_t& bnodeid) const { BtreeNodePtr node; if (auto ret = read_node_impl(bnodeid, node); ret != btree_status_t::success) { throw std::runtime_error(fmt::format("node read failed for bnodeid: {} reason: {}", bnodeid, ret)); @@ -376,33 +403,37 @@ void Btree::validate_node(const bnodeid_t& bnodeid) const { if (node->is_node_deleted()) { return; } auto nentities = node->total_entries(); if (!node->is_leaf() && !nentities && !node->has_valid_edge()) { - throw std::runtime_error(fmt::format("Node [{}] has no entries and no valid edge", node->to_string())); - } + throw std::runtime_error(fmt::format("Node [{}] has no entries and no valid edge", node->to_string())); + } if (node->is_leaf() && node->has_valid_edge()) { - throw std::runtime_error(fmt::format("node [{}] is leaf but has valid edge", node->to_string())); - } - if(!node->validate_key_order()){ - throw std::runtime_error(fmt::format("unsorted node's entries [{}]", node->to_string())); - } + throw std::runtime_error(fmt::format("node [{}] is leaf but has valid edge", node->to_string())); + } + if (!node->validate_key_order< K >()) { + throw std::runtime_error(fmt::format("unsorted node's entries [{}]", node->to_string())); + } BtreeNodePtr last_child_node; validate_node_child_relation(node, last_child_node); auto neighbor_id = node->next_bnode(); if (neighbor_id != empty_bnodeid && node->has_valid_edge()) { - throw std::runtime_error(fmt::format("node [{}] has valid edge but next_bnode is not empty", node->to_string())); - } + throw std::runtime_error( + fmt::format("node [{}] has valid edge but next_bnode is not empty", node->to_string())); + } if (!node->is_leaf() && neighbor_id == empty_bnodeid && !node->has_valid_edge()) { - throw std::runtime_error(fmt::format("node [{}] is interior but has no valid edge and next_bnode is empty", node->to_string())); - } + throw std::runtime_error(fmt::format( + "node [{}] is interior but has no valid edge and next_bnode is empty", node->to_string())); + } if (bnodeid == neighbor_id) { - throw std::runtime_error(fmt::format("node [{}] has next_bnode same as itself", node->to_string())); - } + throw std::runtime_error(fmt::format("node [{}] has next_bnode same as itself", node->to_string())); + } if (neighbor_id != empty_bnodeid) { BtreeNodePtr neighbor_node; if (auto ret = read_node_impl(neighbor_id, neighbor_node); ret != btree_status_t::success) { - throw std::runtime_error(fmt::format("reading neighbor node of [{}] failed for bnodeid: {} reason : {}", node->to_string(), neighbor_id, ret)); + throw std::runtime_error( + fmt::format("reading neighbor node of [{}] failed for bnodeid: {} reason : {}", + node->to_string(), neighbor_id, ret)); } validate_next_node_relation(node, neighbor_node, last_child_node); } @@ -413,7 +444,6 @@ void Btree::validate_node(const bnodeid_t& bnodeid) const { } } - template < typename K, typename V > void Btree< K, V >::sanity_sub_tree(bnodeid_t bnodeid) const { if (bnodeid == 0) { bnodeid = m_root_node_info.bnode_id(); } @@ -471,16 +501,20 @@ void Btree< K, V >::validate_sanity_child(const BtreeNodePtr& parent_node, uint3 } for (uint32_t i = 0; i < child_node->total_entries(); ++i) { K cur_child_key = child_node->get_nth_key< K >(i, false); - if(ind < parent_node->total_entries()){ - BT_REL_ASSERT_LE(cur_child_key.compare(parent_key), 0, " child {} {}-th key is greater than its parent's {} {}-th key", child_node->to_string(), i , parent_node->to_string(), ind); - if(ind>0) { - if(cur_child_key.compare(previous_parent_key) <= 0){ - // there can be a transient case where a key appears in two children. When the replay is done, it should be fixed - // Consider the example Parent P, children C1, C2, C3, C4. A key is deleted resulting in a merge and C3 deleted, and the same key is inserted in the current cp - // Our case is that P is dirtied, C3 deleted, C4 updated and flushed. During recover, we will keep C3 and P remains the same. - // Since C4 is flushed, the key that was removd and inserted will showup in C3 and C4. - // After the replay post recovery, C3 should be gone and the tree is valid again. - BT_LOG(DEBUG, "child {} {}-th key is less than or equal to its parent's {} {}-th key", child_node->to_string(), i, parent_node->to_string(), ind - 1); + if (ind < parent_node->total_entries()) { + BT_REL_ASSERT_LE(cur_child_key.compare(parent_key), 0, + " child {} {}-th key is greater than its parent's {} {}-th key", child_node->to_string(), + i, parent_node->to_string(), ind); + if (ind > 0) { + if (cur_child_key.compare(previous_parent_key) <= 0) { + // there can be a transient case where a key appears in two children. When the replay is done, it + // should be fixed Consider the example Parent P, children C1, C2, C3, C4. A key is deleted + // resulting in a merge and C3 deleted, and the same key is inserted in the current cp Our case is + // that P is dirtied, C3 deleted, C4 updated and flushed. During recover, we will keep C3 and P + // remains the same. Since C4 is flushed, the key that was removd and inserted will showup in C3 and + // C4. After the replay post recovery, C3 should be gone and the tree is valid again. + BT_LOG(DEBUG, "child {} {}-th key is less than or equal to its parent's {} {}-th key", + child_node->to_string(), i, parent_node->to_string(), ind - 1); } } diff --git a/src/include/homestore/btree/detail/btree_internal.hpp b/src/include/homestore/btree/detail/btree_internal.hpp index 7c16b1409..926c1217b 100644 --- a/src/include/homestore/btree/detail/btree_internal.hpp +++ b/src/include/homestore/btree/detail/btree_internal.hpp @@ -276,7 +276,7 @@ struct BtreeConfig { m_suggested_min_size = (uint32_t)(m_node_data_size * m_suggested_min_pct) / 100; } - uint32_t split_size(uint32_t filled_size) const { return uint32_cast(filled_size * m_split_pct) / 100; } + uint32_t split_size(uint32_t filled_size) const { return static_cast< uint32_t >(filled_size * m_split_pct) / 100; } uint32_t ideal_fill_size() const { return m_ideal_fill_size; } uint32_t suggested_min_size() const { return m_suggested_min_size; } uint32_t node_data_size() const { return m_node_data_size; } diff --git a/src/include/homestore/btree/detail/btree_node.hpp b/src/include/homestore/btree/detail/btree_node.hpp index 810239fc2..ad2e33b08 100644 --- a/src/include/homestore/btree/detail/btree_node.hpp +++ b/src/include/homestore/btree/detail/btree_node.hpp @@ -122,16 +122,18 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { virtual ~BtreeNode() = default; // Identify if a node is a leaf node or not, from raw buffer, by just reading persistent_hdr_t - static bool identify_leaf_node(uint8_t* buf) { return (r_cast< persistent_hdr_t* >(buf))->leaf; } - static std::string to_string_buf(uint8_t* buf) { return (r_cast< persistent_hdr_t* >(buf))->to_compact_string(); } + static bool identify_leaf_node(uint8_t* buf) { return (reinterpret_cast< persistent_hdr_t* >(buf))->leaf; } + static std::string to_string_buf(uint8_t* buf) { + return (reinterpret_cast< persistent_hdr_t* >(buf))->to_compact_string(); + } static BtreeLinkInfo::bnode_link_info identify_edge_info(uint8_t* buf) { - return (r_cast< persistent_hdr_t* >(buf))->edge_info; + return (reinterpret_cast< persistent_hdr_t* >(buf))->edge_info; } static bool is_valid_node(sisl::blob const& buf) { - auto phdr = r_cast< persistent_hdr_t const* >(buf.cbytes()); + auto phdr = reinterpret_cast< persistent_hdr_t const* >(buf.cbytes()); if ((phdr->magic != BTREE_NODE_MAGIC) || (phdr->version != BTREE_NODE_VERSION)) { return false; } - if ((uint32_cast(phdr->node_size) + 1) != buf.size()) { return false; } + if ((static_cast< uint32_t >(phdr->node_size) + 1) != buf.size()) { return false; } if (phdr->node_id == empty_bnodeid) { return false; } auto const exp_checksum = crc16_t10dif(bt_init_crc_16, (buf.cbytes() + sizeof(persistent_hdr_t)), @@ -142,12 +144,12 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { } static void revert_node_delete(uint8_t* buf) { - auto phdr = r_cast< persistent_hdr_t* >(buf); + auto phdr = reinterpret_cast< persistent_hdr_t* >(buf); phdr->node_deleted = 0x0; } static int64_t get_modified_cp_id(uint8_t* buf) { - auto phdr = r_cast< persistent_hdr_t const* >(buf); + auto phdr = reinterpret_cast< persistent_hdr_t const* >(buf); return phdr->modified_cp_id; } @@ -323,7 +325,7 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { virtual void set_edge_value(const BtreeValue& v) { auto const b = v.serialize(); - auto const l = r_cast< BtreeLinkInfo::bnode_link_info const* >(b.cbytes()); + auto const l = reinterpret_cast< BtreeLinkInfo::bnode_link_info const* >(b.cbytes()); DEBUG_ASSERT_EQ(b.size(), sizeof(BtreeLinkInfo::bnode_link_info)); set_edge_info(*l); } @@ -460,7 +462,7 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { if ((end - start) <= 1) { return std::make_pair(found, end_of_search_index); } while ((end - start) > 1) { mid = start + (end - start) / 2; - DEBUG_ASSERT(mid >= 0 && mid < int_cast(total_entries()), "Invalid mid={}", mid); + DEBUG_ASSERT(mid >= 0 && mid < static_cast< int >(total_entries()), "Invalid mid={}", mid); int x = compare_nth_key(key, mid); if (x == 0) { found = true; @@ -484,9 +486,9 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { // This method is called when the physical buffer is updated. // Derived classes can override this method to perform additional actions. virtual void on_update_phys_buf() = 0; - persistent_hdr_t* get_persistent_header() { return r_cast< persistent_hdr_t* >(m_phys_node_buf); } + persistent_hdr_t* get_persistent_header() { return reinterpret_cast< persistent_hdr_t* >(m_phys_node_buf); } const persistent_hdr_t* get_persistent_header_const() const { - return r_cast< const persistent_hdr_t* >(m_phys_node_buf); + return reinterpret_cast< const persistent_hdr_t* >(m_phys_node_buf); } uint8_t* node_data_area() { return (m_phys_node_buf + sizeof(persistent_hdr_t)); } const uint8_t* node_data_area_const() const { return (m_phys_node_buf + sizeof(persistent_hdr_t)); } @@ -512,7 +514,7 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { bool is_leaf() const { return get_persistent_header_const()->leaf; } btree_node_type get_node_type() const { - return s_cast< btree_node_type >(get_persistent_header_const()->node_type); + return static_cast< btree_node_type >(get_persistent_header_const()->node_type); } void set_total_entries(uint32_t n) { get_persistent_header()->nentries = n; } @@ -523,10 +525,10 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { void sub_entries(uint32_t subn) { get_persistent_header()->nentries -= subn; } void set_leaf(bool leaf) { get_persistent_header()->leaf = leaf; } - void set_node_type(btree_node_type t) { get_persistent_header()->node_type = uint32_cast(t); } - void set_node_size(uint32_t size) { get_persistent_header()->node_size = s_cast< uint16_t >(size - 1); } + void set_node_type(btree_node_type t) { get_persistent_header()->node_type = static_cast< uint32_t >(t); } + void set_node_size(uint32_t size) { get_persistent_header()->node_size = static_cast< uint16_t >(size - 1); } uint64_t node_gen() const { return get_persistent_header_const()->node_gen; } - uint32_t node_size() const { return s_cast< uint32_t >(get_persistent_header_const()->node_size) + 1; } + uint32_t node_size() const { return static_cast< uint32_t >(get_persistent_header_const()->node_size) + 1; } uint32_t node_data_size() const { return node_size() - sizeof(persistent_hdr_t); } void inc_gen() { get_persistent_header()->node_gen++; } @@ -577,7 +579,7 @@ class BtreeNode : public sisl::ObjLifeCounter< BtreeNode > { struct btree_locked_node_info { BtreeNode* node; - Clock::time_point start_time; + sisl::Clock::time_point start_time; const char* fname; int line; diff --git a/src/include/homestore/btree/detail/btree_node_mgr.ipp b/src/include/homestore/btree/detail/btree_node_mgr.ipp index e5e74e2b0..6522868f3 100644 --- a/src/include/homestore/btree/detail/btree_node_mgr.ipp +++ b/src/include/homestore/btree/detail/btree_node_mgr.ipp @@ -146,8 +146,8 @@ btree_status_t Btree< K, V >::upgrade_node_locks(const BtreeNodePtr& parent_node // If the node things have been changed between unlock and lock example, it has been made invalid (probably by merge // nodes) ask caller to start over again. - if(parent_prev_gen != parent_node->node_gen() || child_prev_gen != child_node->node_gen()) { - COUNTER_INCREMENT(m_metrics, btree_num_pc_gen_mismatch, 1); + if (parent_prev_gen != parent_node->node_gen() || child_prev_gen != child_node->node_gen()) { + COUNTER_INCREMENT(m_metrics, btree_num_pc_gen_mismatch, 1); } if (parent_node->is_node_deleted() || (parent_prev_gen != parent_node->node_gen()) || child_node->is_node_deleted() || (child_prev_gen != child_node->node_gen())) { @@ -198,9 +198,7 @@ btree_status_t Btree< K, V >::upgrade_node_lock(const BtreeNodePtr& node, lockty auto ret = lock_node(node, locktype_t::WRITE, context); if (ret != btree_status_t::success) { return ret; } - if(prev_gen != node->node_gen()) { - COUNTER_INCREMENT(m_metrics, btree_num_gen_mismatch, 1); - } + if (prev_gen != node->node_gen()) { COUNTER_INCREMENT(m_metrics, btree_num_gen_mismatch, 1); } if (node->is_node_deleted() || (prev_gen != node->node_gen())) { unlock_node(node, locktype_t::WRITE); return btree_status_t::retry; @@ -307,7 +305,7 @@ void Btree< K, V >::free_node(const BtreeNodePtr& node, locktype_t cur_lock, voi node->set_node_deleted(); unlock_node(node, cur_lock); } - node->is_leaf()?--m_total_leaf_nodes:--m_total_interior_nodes; + node->is_leaf() ? --m_total_leaf_nodes : --m_total_interior_nodes; free_node_impl(node, context); // intrusive_ptr_release(node.get()); @@ -335,7 +333,7 @@ void Btree< K, V >::_start_of_lock(const BtreeNodePtr& node, locktype_t ltype, c info.line = line; #endif - info.start_time = Clock::now(); + info.start_time = sisl::Clock::now(); info.node = node.get(); if (ltype == locktype_t::WRITE) { bt_thread_vars()->wr_locked_nodes.push_back(info); @@ -360,7 +358,7 @@ bool Btree< K, V >::remove_locked_node(const BtreeNodePtr& node, locktype_t ltyp if (info.node == node.get()) { *out_info = info; pnode_infos->pop_back(); - LOGTRACEMOD(btree, "REMOVING node {} from {} locked nodes list, its size = {}",info.node->node_id(), + LOGTRACEMOD(btree, "REMOVING node {} from {} locked nodes list, its size = {}", info.node->node_id(), (ltype == locktype_t::WRITE) ? "write" : "read", pnode_infos->size()); return true; } else if (pnode_infos->size() > 1) { diff --git a/src/include/homestore/btree/detail/btree_query_impl.ipp b/src/include/homestore/btree/detail/btree_query_impl.ipp index 8d21c26b7..bb96edb88 100644 --- a/src/include/homestore/btree/detail/btree_query_impl.ipp +++ b/src/include/homestore/btree/detail/btree_query_impl.ipp @@ -90,9 +90,9 @@ btree_status_t Btree< K, V >::do_traversal_query(const BtreeNodePtr& my_node, Bt uint32_t start_ind{0}; uint32_t end_ind{0}; - auto cur_count = to_variant_node(my_node)->multi_get(qreq.working_range(), - qreq.batch_size() - uint32_cast(out_values.size()), - start_ind, end_ind, &out_values, qreq.filter()); + auto cur_count = to_variant_node(my_node)->multi_get( + qreq.working_range(), qreq.batch_size() - static_cast< uint32_t >(out_values.size()), start_ind, end_ind, + &out_values, qreq.filter()); if (qreq.route_tracing) { append_route_trace(qreq, my_node, btree_event_t::READ, start_ind, start_ind + cur_count); } diff --git a/src/include/homestore/btree/detail/btree_remove_impl.ipp b/src/include/homestore/btree/detail/btree_remove_impl.ipp index 2b5273a9c..ee0e70a76 100644 --- a/src/include/homestore/btree/detail/btree_remove_impl.ipp +++ b/src/include/homestore/btree/detail/btree_remove_impl.ipp @@ -274,15 +274,17 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const // string for detailed logging if assert is hit auto complete_info_str = [&]() { - std::string info_str = fmt::format("parent node {}, start_idx {}, end_idx {}\n", - parent_node->to_string(), start_idx, end_idx); + std::string info_str = + fmt::format("parent node {}, start_idx {}, end_idx {}\n", parent_node->to_string(), start_idx, end_idx); fmt::format_to(std::back_inserter(info_str), - "total_size {}, total_entries {}, total_entries_copied {}, balanced_size {}, available_size {}, num_nodes {}", - total_size, total_entries, total_entries_copied, balanced_size, available_size, num_nodes); + "total_size {}, total_entries {}, total_entries_copied {}, balanced_size {}, available_size {}, " + "num_nodes {}", + total_size, total_entries, total_entries_copied, balanced_size, available_size, num_nodes); - fmt::format_to(std::back_inserter(info_str), "leftmost_src last_node_upto {}, src_cursor ith node {}, src_cursor nth_entry {}", - leftmost_src.last_node_upto, src_cursor.ith_node, src_cursor.nth_entry); + fmt::format_to(std::back_inserter(info_str), + "leftmost_src last_node_upto {}, src_cursor ith node {}, src_cursor nth_entry {}", + leftmost_src.last_node_upto, src_cursor.ith_node, src_cursor.nth_entry); for (auto i = 0u; i < old_nodes.size(); ++i) { fmt::format_to(std::back_inserter(info_str), "old child node {}, [{}]\n", i, old_nodes[i]->to_string()); @@ -353,7 +355,8 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const "MERGE disqualified for parent node {} leftmost_node {}! current size {} is more than balanced size {}", parent_node->to_string(), leftmost_node->to_string(), leftmost_node->occupied_size(), balanced_size); BT_NODE_DBG_ASSERT(false, leftmost_node, - "Didn't expect current size is more than balanced size without rebalancing, info {}", complete_info_str()); + "Didn't expect current size is more than balanced size without rebalancing, info {}", + complete_info_str()); ret = btree_status_t::merge_not_required; goto out; } @@ -365,9 +368,7 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const available_size = static_cast< int32_t >(balanced_size) - leftmost_node->occupied_size(); total_size -= leftmost_node->occupied_size(); total_entries -= leftmost_node->total_entries(); - if (available_size > 0) { - total_size -= available_size; - } + if (available_size > 0) { total_size -= available_size; } if (leftmost_node->get_node_type() == btree_node_type::PREFIX) { auto cur_node = static_cast< FixedPrefixNode< K, V >* >(leftmost_node.get()); @@ -402,8 +403,8 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const expected_holes = c_used_slot > init_holes ? 0 : (expected_holes - c_used_slot); expected_tail = init_tail + (expected_holes > 0 ? 0 : (c_used_slot - init_holes)); BT_NODE_DBG_ASSERT_EQ(expected_tail >= init_tail, true, leftmost_node, - "Expected tail {} is not greater than initial tail {}, info {}", - expected_tail, init_tail, complete_info_str()); + "Expected tail {} is not greater than initial tail {}, info {}", expected_tail, + init_tail, complete_info_str()); auto prefix_increased_size = (expected_tail - init_tail) * FixedPrefixNode< K, V >::prefix_entry::size(); auto suffix_increased_size = cur_node->total_entries() * FixedPrefixNode< K, V >::suffix_entry::size(); @@ -414,7 +415,8 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const } else { available_size -= old_nodes[i]->occupied_size(); } - BT_NODE_DBG_ASSERT_EQ(available_size >= 0, true, leftmost_node, "negative available size, info {}", complete_info_str()); + BT_NODE_DBG_ASSERT_EQ(available_size >= 0, true, leftmost_node, "negative available size, info {}", + complete_info_str()); if (i >= old_nodes.size() - 1) { src_cursor.ith_node = i + 1; src_cursor.nth_entry = std::numeric_limits< uint32_t >::max(); @@ -444,8 +446,8 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const new_nodes.emplace_back(new_node); } if (!new_node) { - BT_NODE_DBG_ASSERT_EQ(total_entries, 0, parent_node, "No new node allocated but still have entries to copy, info {}", - complete_info_str()); + BT_NODE_DBG_ASSERT_EQ(total_entries, 0, parent_node, + "No new node allocated but still have entries to copy, info {}", complete_info_str()); break; } @@ -474,7 +476,8 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const } } - BT_NODE_DBG_ASSERT_EQ(total_entries, 0, parent_node, "Did not copy all the entries from old to new nodes, info {}", complete_info_str()); + BT_NODE_DBG_ASSERT_EQ(total_entries, 0, parent_node, "Did not copy all the entries from old to new nodes, info {}", + complete_info_str()); // There are degenerate case (especially if the first key/value is very big) that number of resultant nodes are // more than initial number of nodes before rebalance. In those cases, just give up the merging and hope for a @@ -579,8 +582,8 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const for (const auto& node : new_nodes) { num_copied += node->total_entries(); } - BT_NODE_DBG_ASSERT_EQ(num_copied, total_entries_copied, parent_node, "mismatch of total entries copied, info {}", - complete_info_str()); + BT_NODE_DBG_ASSERT_EQ(num_copied, total_entries_copied, parent_node, + "mismatch of total entries copied, info {}", complete_info_str()); // BT_DBG_ASSERT(!parent_node_step1.empty() && !parent_node_step2.empty() && !parent_node_step3.empty(), // "Empty string"); @@ -602,9 +605,10 @@ btree_status_t Btree< K, V >::merge_nodes(const BtreeNodePtr& parent_node, const "mismatch of link version of old nodes in unsuccessful merge"); } parent_node->get_nth_value(start_idx, &child_info, false /* copy */); - BT_NODE_DBG_ASSERT_EQ(child_info.link_version(), leftmost_node->link_version(), parent_node, - "parent_node, mismatch of link version of leftmost node in unsuccessful merge, info {}", - complete_info_str()); + BT_NODE_DBG_ASSERT_EQ( + child_info.link_version(), leftmost_node->link_version(), parent_node, + "parent_node, mismatch of link version of leftmost node in unsuccessful merge, info {}", + complete_info_str()); } if (leftmost_node->total_entries() && (start_idx < parent_node->total_entries())) { diff --git a/src/include/homestore/btree/detail/prefix_node.hpp b/src/include/homestore/btree/detail/prefix_node.hpp index cd75beca0..c6d313ac5 100644 --- a/src/include/homestore/btree/detail/prefix_node.hpp +++ b/src/include/homestore/btree/detail/prefix_node.hpp @@ -78,13 +78,13 @@ class FixedPrefixNode : public VariantNode< K, V > { void write_kv(BtreeKey const& key, BtreeValue const& val) { if constexpr (std::is_base_of_v< BtreeIntervalKey, K > && std::is_base_of_v< BtreeIntervalValue, V >) { - sisl::blob const kblob = s_cast< K const& >(key).serialize_prefix(); - sisl::blob const vblob = s_cast< V const& >(val).serialize_prefix(); + sisl::blob const kblob = static_cast< K const& >(key).serialize_prefix(); + sisl::blob const vblob = static_cast< V const& >(val).serialize_prefix(); DEBUG_ASSERT_EQ(kblob.size(), key_size(), "Prefix key size mismatch with serialized prefix size"); DEBUG_ASSERT_EQ(vblob.size(), value_size(), "Prefix value size mismatch with serialized prefix size"); - uint8_t* cur_ptr = uintptr_cast(this) + sizeof(prefix_entry); + uint8_t* cur_ptr = reinterpret_cast< uint8_t* >(this) + sizeof(prefix_entry); std::memcpy(cur_ptr, kblob.cbytes(), kblob.size()); cur_ptr += kblob.size(); std::memcpy(cur_ptr, vblob.cbytes(), vblob.size()); @@ -93,11 +93,11 @@ class FixedPrefixNode : public VariantNode< K, V > { int compare(BtreeKey const& key, BtreeValue const& val) const { if constexpr (std::is_base_of_v< BtreeIntervalKey, K > && std::is_base_of_v< BtreeIntervalValue, V >) { - sisl::blob const kblob = s_cast< K const& >(key).serialize_prefix(); - sisl::blob const vblob = s_cast< V const& >(val).serialize_prefix(); + sisl::blob const kblob = static_cast< K const& >(key).serialize_prefix(); + sisl::blob const vblob = static_cast< V const& >(val).serialize_prefix(); DEBUG_ASSERT_EQ(kblob.size(), key_size(), "Prefix key size mismatch with serialized prefix size"); DEBUG_ASSERT_EQ(vblob.size(), value_size(), "Prefix value size mismatch with serialized prefix size"); - uint8_t const* cur_ptr = r_cast< uint8_t const* >(this) + sizeof(prefix_entry); + uint8_t const* cur_ptr = reinterpret_cast< uint8_t const* >(this) + sizeof(prefix_entry); int cmp = std::memcmp(cur_ptr, kblob.cbytes(), kblob.size()); if (cmp) { return cmp; } cmp = std::memcmp(cur_ptr + kblob.size(), vblob.cbytes(), vblob.size()); @@ -107,7 +107,7 @@ class FixedPrefixNode : public VariantNode< K, V > { } sisl::blob key_buf() const { - return sisl::blob{r_cast< uint8_t const* >(this) + sizeof(prefix_entry), key_size()}; + return sisl::blob{reinterpret_cast< uint8_t const* >(this) + sizeof(prefix_entry), key_size()}; } sisl::blob val_buf() const { return sisl::blob{key_buf().cbytes() + key_buf().size(), value_size()}; } }; @@ -139,10 +139,10 @@ class FixedPrefixNode : public VariantNode< K, V > { sisl::blob kblob; sisl::blob vblob; - uint8_t* cur_ptr = uintptr_cast(this) + sizeof(suffix_entry); + uint8_t* cur_ptr = reinterpret_cast< uint8_t* >(this) + sizeof(suffix_entry); if constexpr (std::is_base_of_v< BtreeIntervalKey, K > && std::is_base_of_v< BtreeIntervalValue, V >) { - kblob = s_cast< K const& >(key).serialize_suffix(); - vblob = s_cast< V const& >(val).serialize_suffix(); + kblob = static_cast< K const& >(key).serialize_suffix(); + vblob = static_cast< V const& >(val).serialize_suffix(); } else { kblob = key.serialize(); vblob = val.serialize(); @@ -156,7 +156,7 @@ class FixedPrefixNode : public VariantNode< K, V > { } sisl::blob key_buf() const { - return sisl::blob{const_cast< uint8_t* >(r_cast< uint8_t const* >(this) + sizeof(suffix_entry)), + return sisl::blob{const_cast< uint8_t* >(reinterpret_cast< uint8_t const* >(this) + sizeof(suffix_entry)), key_size()}; } sisl::blob val_buf() const { return sisl::blob{key_buf().bytes() + key_buf().size(), value_size()}; } @@ -254,8 +254,8 @@ class FixedPrefixNode : public VariantNode< K, V > { if (prefix_slot == std::numeric_limits< uint16_t >::max()) { prefix_slot = add_prefix(cur_key, val); } - V new_val{s_cast< V const& >(val)}; - new_val.shift(s_cast< K const& >(cur_key).distance(first_input_key), app_ctx); + V new_val{static_cast< V const& >(val)}; + new_val.shift(static_cast< K const& >(cur_key).distance(first_input_key), app_ctx); if (get_prefix_entry_c(prefix_slot)->compare(cur_key, new_val)) { LOGTRACEMOD(btree, "Adding new prefix entry for key={} val={}", cur_key.to_string(), new_val.to_string()); @@ -318,7 +318,8 @@ class FixedPrefixNode : public VariantNode< K, V > { if (!filter_cb || filter_cb(cur_key, get_nth_value(idx, false))) { suffix_entry* sentry = get_suffix_entry(idx); deref_remove_prefix(sentry->prefix_slot); - std::memmove(uintptr_cast(sentry), uintptr_cast(get_suffix_entry(idx + 1)), + std::memmove(reinterpret_cast< uint8_t* >(sentry), + reinterpret_cast< uint8_t* >(get_suffix_entry(idx + 1)), (this->total_entries() - idx - 1) * suffix_entry::size()); this->dec_entries(); ++num_removed; @@ -343,20 +344,20 @@ class FixedPrefixNode : public VariantNode< K, V > { prefix_entry const* pentry = get_prefix_entry_c(sentry->prefix_slot); DEBUG_ASSERT(prefix_bitset_.is_bit_set(sentry->prefix_slot), "Prefix slot number is in suffix entry, but corresponding bit is not set"); - s_cast< BtreeIntervalKey& >(out_key).deserialize(pentry->key_buf(), sentry->key_buf(), true); + static_cast< BtreeIntervalKey& >(out_key).deserialize(pentry->key_buf(), sentry->key_buf(), true); } void get_nth_value(uint32_t idx, BtreeValue* out_val, bool) const override { if (idx == this->total_entries()) { DEBUG_ASSERT_EQ(this->is_leaf(), false, "get_nth_value out-of-bound"); DEBUG_ASSERT_EQ(this->has_valid_edge(), true, "get_nth_value out-of-bound"); - *(r_cast< BtreeLinkInfo* >(out_val)) = this->get_edge_value(); + *(reinterpret_cast< BtreeLinkInfo* >(out_val)) = this->get_edge_value(); } else { suffix_entry const* sentry = get_suffix_entry_c(idx); prefix_entry const* pentry = get_prefix_entry_c(sentry->prefix_slot); DEBUG_ASSERT(prefix_bitset_.is_bit_set(sentry->prefix_slot), "Prefix slot number is in suffix entry, but corresponding bit is not set"); - s_cast< BtreeIntervalValue* >(out_val)->deserialize(pentry->val_buf(), sentry->val_buf(), true); + static_cast< BtreeIntervalValue* >(out_val)->deserialize(pentry->val_buf(), sentry->val_buf(), true); } } @@ -403,7 +404,7 @@ class FixedPrefixNode : public VariantNode< K, V > { } uint32_t move_out_to_right_internal(const BtreeConfig& cfg, BtreeNode& on, bool by_size, uint32_t limit) { - FixedPrefixNode& dst_node = s_cast< FixedPrefixNode& >(on); + FixedPrefixNode& dst_node = static_cast< FixedPrefixNode& >(on); uint32_t dst_node_size = dst_node.occupied_size(); uint32_t num_moved{0}; @@ -435,7 +436,8 @@ class FixedPrefixNode : public VariantNode< K, V > { uint16_t dst_prefix_slot = dst_node.alloc_prefix(); prefix_entry* dst_pentry = dst_node.get_prefix_entry(dst_prefix_slot); - std::memcpy(voidptr_cast(dst_pentry), c_voidptr_cast(get_prefix_entry_c(this_prefix_slot)), + std::memcpy(reinterpret_cast< void* >(dst_pentry), + reinterpret_cast< void const* >(get_prefix_entry_c(this_prefix_slot)), prefix_entry::size()); dst_pentry->ref_count = 1; @@ -457,8 +459,8 @@ class FixedPrefixNode : public VariantNode< K, V > { // Step 2: Move the suffixes and adjust the num_entries in source and destination. All tomove suffixes have // adjusted to their new prefix slot already as part of Step 1 - std::memmove(uintptr_cast(dst_node.get_suffix_entry(0)), uintptr_cast(get_suffix_entry(idx + 1)), - num_moved * suffix_entry::size()); + std::memmove(reinterpret_cast< uint8_t* >(dst_node.get_suffix_entry(0)), + reinterpret_cast< uint8_t* >(get_suffix_entry(idx + 1)), num_moved * suffix_entry::size()); this->sub_entries(num_moved); dst_node.add_entries(num_moved); @@ -544,7 +546,7 @@ class FixedPrefixNode : public VariantNode< K, V > { } else { suffix_entry* sentry = get_suffix_entry(idx); deref_remove_prefix(sentry->prefix_slot); - std::memmove(uintptr_cast(sentry), uintptr_cast(get_suffix_entry(idx + 1)), + std::memmove(reinterpret_cast< uint8_t* >(sentry), reinterpret_cast< uint8_t* >(get_suffix_entry(idx + 1)), (this->total_entries() - idx - 1) * suffix_entry::size()); this->dec_entries(); } @@ -604,7 +606,7 @@ class FixedPrefixNode : public VariantNode< K, V > { uint32_t copy_internal(BtreeConfig const& cfg, BtreeNode const& o, uint32_t start_idx, bool by_size, uint32_t limit) { - FixedPrefixNode const& src_node = s_cast< FixedPrefixNode const& >(o); + FixedPrefixNode const& src_node = static_cast< FixedPrefixNode const& >(o); #ifdef _PRERELEASE if (by_size) { const uint32_t max_keys = this->max_keys_in_node(); @@ -622,7 +624,7 @@ class FixedPrefixNode : public VariantNode< K, V > { // suffixes. At the end of this step, all prefixes that needs to be coped are copied with correct bitset // settings on both source and destination std::map< uint16_t, uint16_t > src_to_my_prefix; - uint16_t src_idx{s_cast< uint16_t >(start_idx)}; + uint16_t src_idx{static_cast< uint16_t >(start_idx)}; uint16_t my_prefix_slot{0}; uint16_t my_idx = this->total_entries(); uint32_t num_copied{0}; @@ -643,7 +645,8 @@ class FixedPrefixNode : public VariantNode< K, V > { my_prefix_slot = alloc_prefix(); prefix_entry* my_pentry = get_prefix_entry(my_prefix_slot); - std::memcpy(voidptr_cast(my_pentry), c_voidptr_cast(src_node.get_prefix_entry_c(src_prefix_slot)), + std::memcpy(reinterpret_cast< void* >(my_pentry), + reinterpret_cast< void const* >(src_node.get_prefix_entry_c(src_prefix_slot)), prefix_entry::size()); my_pentry->ref_count = 1; @@ -658,7 +661,8 @@ class FixedPrefixNode : public VariantNode< K, V > { } suffix_entry* my_sentry = get_suffix_entry(my_idx++); - std::memcpy(voidptr_cast(my_sentry), c_voidptr_cast(src_sentry), suffix_entry::size()); + std::memcpy(reinterpret_cast< void* >(my_sentry), reinterpret_cast< void const* >(src_sentry), + suffix_entry::size()); my_sentry->prefix_slot = my_prefix_slot; ++src_idx; @@ -759,8 +763,8 @@ class FixedPrefixNode : public VariantNode< K, V > { } uint32_t available_size_without_compaction() const { - uint8_t const* suffix = r_cast< uint8_t const* >(get_suffix_entry_c(this->total_entries())); - uint8_t const* prefix = r_cast< uint8_t const* >(get_prefix_entry_c(cprefix_header()->tail_slot)); + uint8_t const* suffix = reinterpret_cast< uint8_t const* >(get_suffix_entry_c(this->total_entries())); + uint8_t const* prefix = reinterpret_cast< uint8_t const* >(get_prefix_entry_c(cprefix_header()->tail_slot)); if (suffix <= prefix + prefix_entry::size()) { return prefix - suffix + prefix_entry::size(); @@ -812,7 +816,7 @@ class FixedPrefixNode : public VariantNode< K, V > { DEBUG_ASSERT_LT(to_slot, prefix_header()->used_slots, "Couldn't find enough slots inside compactable area, not expected"); - std::memcpy(uintptr_cast(get_prefix_entry(to_slot)), (void*)get_prefix_entry(from_slot), + std::memcpy(reinterpret_cast< uint8_t* >(get_prefix_entry(to_slot)), (void*)get_prefix_entry(from_slot), prefix_entry::size()); prefix_bitset_.reset_bit(from_slot); prefix_bitset_.set_bit(to_slot); @@ -857,9 +861,9 @@ class FixedPrefixNode : public VariantNode< K, V > { sisl::CompactBitSet::size_multiples()); } - prefix_node_header* prefix_header() { return r_cast< prefix_node_header* >(this->node_data_area()); } + prefix_node_header* prefix_header() { return reinterpret_cast< prefix_node_header* >(this->node_data_area()); } prefix_node_header const* cprefix_header() const { - return r_cast< prefix_node_header const* >(this->node_data_area_const()); + return reinterpret_cast< prefix_node_header const* >(this->node_data_area_const()); } uint8_t* bitset_area() { return this->node_data_area() + sizeof(prefix_node_header); } @@ -869,22 +873,22 @@ class FixedPrefixNode : public VariantNode< K, V > { uint8_t const* csuffix_kv_area() const { return cbitset_area() + (prefix_bitset_.size() / 8); } prefix_entry* get_prefix_entry(uint16_t slot_num) { - return r_cast< prefix_entry* >( + return reinterpret_cast< prefix_entry* >( this->node_data_area() + (this->node_data_size() - (static_cast< uint16_t >(slot_num + 1) * prefix_entry::size()))); } prefix_entry const* get_prefix_entry_c(uint16_t slot_num) const { - return r_cast< prefix_entry const* >( + return reinterpret_cast< prefix_entry const* >( this->node_data_area_const() + (this->node_data_size() - (static_cast< uint16_t >(slot_num + 1) * prefix_entry::size()))); } suffix_entry* get_suffix_entry(uint16_t idx) { - return r_cast< suffix_entry* >(suffix_kv_area() + (idx * suffix_entry::size())); + return reinterpret_cast< suffix_entry* >(suffix_kv_area() + (idx * suffix_entry::size())); } suffix_entry const* get_suffix_entry_c(uint16_t idx) const { - return r_cast< suffix_entry const* >(csuffix_kv_area() + (idx * suffix_entry::size())); + return reinterpret_cast< suffix_entry const* >(csuffix_kv_area() + (idx * suffix_entry::size())); } static constexpr uint32_t get_key_size() { return prefix_entry::key_size() + suffix_entry::key_size(); } diff --git a/src/include/homestore/btree/detail/simple_node.hpp b/src/include/homestore/btree/detail/simple_node.hpp index c8cdb465c..1fd347df0 100644 --- a/src/include/homestore/btree/detail/simple_node.hpp +++ b/src/include/homestore/btree/detail/simple_node.hpp @@ -118,7 +118,7 @@ class SimpleNode : public VariantNode< K, V > { } uint32_t move_out_to_right_by_entries(const BtreeConfig& cfg, BtreeNode& o, uint32_t nentries) override { - auto& other_node = s_cast< SimpleNode< K, V >& >(o); + auto& other_node = static_cast< SimpleNode< K, V >& >(o); // Minimum of whats to be moved out and how many slots available in other node nentries = std::min({nentries, this->total_entries(), other_node.get_available_entries()}); @@ -157,13 +157,13 @@ class SimpleNode : public VariantNode< K, V > { } uint32_t copy_by_size(const BtreeConfig& cfg, const BtreeNode& o, uint32_t start_idx, uint32_t size) override { - auto& other = s_cast< const SimpleNode< K, V >& >(o); + auto& other = static_cast< const SimpleNode< K, V >& >(o); return copy_by_entries(cfg, o, start_idx, other.num_entries_by_size(start_idx, size)); } uint32_t copy_by_entries(const BtreeConfig& cfg, const BtreeNode& o, uint32_t start_idx, uint32_t nentries) override { - auto& other = s_cast< const SimpleNode< K, V >& >(o); + auto& other = static_cast< const SimpleNode< K, V >& >(o); nentries = std::min(nentries, other.total_entries() - start_idx); nentries = std::min(nentries, this->get_available_entries()); @@ -397,7 +397,7 @@ class SimpleNode : public VariantNode< K, V > { RELEASE_ASSERT_EQ(this->is_leaf(), false, "setting value outside bounds on leaf node"); DEBUG_ASSERT_EQ(b.size(), sizeof(BtreeLinkInfo::bnode_link_info), "Invalid value size being set for non-leaf node"); - this->set_edge_info(*r_cast< BtreeLinkInfo::bnode_link_info const* >(b.cbytes())); + this->set_edge_info(*reinterpret_cast< BtreeLinkInfo::bnode_link_info const* >(b.cbytes())); } else { uint8_t* entry = this->node_data_area() + (get_nth_obj_size(ind) * ind) + get_nth_key_size(ind); std::memcpy(entry, b.cbytes(), b.size()); diff --git a/src/include/homestore/btree/detail/varlen_node.hpp b/src/include/homestore/btree/detail/varlen_node.hpp index bce16e50d..b430fbad2 100644 --- a/src/include/homestore/btree/detail/varlen_node.hpp +++ b/src/include/homestore/btree/detail/varlen_node.hpp @@ -456,7 +456,7 @@ class VariableNode : public VariantNode< K, V > { const auto kb = key.serialize(); assert(ind < this->total_entries()); assert(kb.size() == get_nth_key_size(ind)); - memcpy(uintptr_cast(get_nth_obj(ind)), kb.cbytes(), kb.size()); + memcpy(reinterpret_cast< uint8_t* >(get_nth_obj(ind)), kb.cbytes(), kb.size()); } bool has_room_for_put(btree_put_type put_type, uint32_t key_size, uint32_t value_size) const override { @@ -535,7 +535,7 @@ class VariableNode : public VariantNode< K, V > { } // Create a room for a new record - uint8_t* rec_ptr = uintptr_cast(get_nth_record_mutable(ind)); + uint8_t* rec_ptr = reinterpret_cast< uint8_t* >(get_nth_record_mutable(ind)); memmove((void*)(rec_ptr + this->get_record_size()), rec_ptr, (this->total_entries() - ind) * this->get_record_size()); @@ -660,10 +660,12 @@ class VariableNode : public VariantNode< K, V > { const uint8_t* offset_to_ptr(uint16_t offset) const { return this->node_data_area_const() + offset; } ///////////// Other Private Methods ////////////////// - inline var_node_header* get_var_node_header() { return r_cast< var_node_header* >(this->node_data_area()); } + inline var_node_header* get_var_node_header() { + return reinterpret_cast< var_node_header* >(this->node_data_area()); + } inline const var_node_header* get_var_node_header_const() const { - return r_cast< const var_node_header* >(this->node_data_area_const()); + return reinterpret_cast< const var_node_header* >(this->node_data_area_const()); } uint16_t get_arena_free_space() const { @@ -682,13 +684,13 @@ class VarKeySizeNode : public VariableNode< K, V > { virtual ~VarKeySizeNode() = default; uint32_t get_nth_key_size(uint32_t ind) const override { - return r_cast< const var_key_record* >(this->get_nth_record(ind))->m_key_len; + return reinterpret_cast< const var_key_record* >(this->get_nth_record(ind))->m_key_len; } uint32_t get_nth_value_size(uint32_t ind) const override { return dummy_value< V >.serialized_size(); } uint32_t get_record_size() const override { return sizeof(var_key_record); } void set_nth_key_len(uint8_t* rec_ptr, uint32_t key_len) override { - r_cast< var_key_record* >(rec_ptr)->m_key_len = key_len; + reinterpret_cast< var_key_record* >(rec_ptr)->m_key_len = key_len; } void set_nth_value_len(uint8_t* rec_ptr, uint32_t value_len) override { assert(value_len == dummy_value< V >.serialized_size()); @@ -715,7 +717,7 @@ class VarValueSizeNode : public VariableNode< K, V > { uint32_t get_nth_key_size(uint32_t ind) const override { return dummy_key< K >.serialized_size(); } uint32_t get_nth_value_size(uint32_t ind) const override { - return r_cast< const var_value_record* >(this->get_nth_record(ind))->m_value_len; + return reinterpret_cast< const var_value_record* >(this->get_nth_record(ind))->m_value_len; } uint32_t get_record_size() const override { return sizeof(var_value_record); } @@ -723,7 +725,7 @@ class VarValueSizeNode : public VariableNode< K, V > { assert(key_len == dummy_key< K >.serialized_size()); } void set_nth_value_len(uint8_t* rec_ptr, uint32_t value_len) override { - r_cast< var_value_record* >(rec_ptr)->m_value_len = value_len; + reinterpret_cast< var_value_record* >(rec_ptr)->m_value_len = value_len; } private: @@ -746,18 +748,18 @@ class VarObjSizeNode : public VariableNode< K, V > { virtual ~VarObjSizeNode() = default; uint32_t get_nth_key_size(uint32_t ind) const override { - return r_cast< const var_obj_record* >(this->get_nth_record(ind))->m_key_len; + return reinterpret_cast< const var_obj_record* >(this->get_nth_record(ind))->m_key_len; } uint32_t get_nth_value_size(uint32_t ind) const override { - return r_cast< const var_obj_record* >(this->get_nth_record(ind))->m_value_len; + return reinterpret_cast< const var_obj_record* >(this->get_nth_record(ind))->m_value_len; } uint32_t get_record_size() const override { return sizeof(var_obj_record); } void set_nth_key_len(uint8_t* rec_ptr, uint32_t key_len) override { - r_cast< var_obj_record* >(rec_ptr)->m_key_len = key_len; + reinterpret_cast< var_obj_record* >(rec_ptr)->m_key_len = key_len; } void set_nth_value_len(uint8_t* rec_ptr, uint32_t value_len) override { - r_cast< var_obj_record* >(rec_ptr)->m_value_len = value_len; + reinterpret_cast< var_obj_record* >(rec_ptr)->m_value_len = value_len; } private: diff --git a/src/include/homestore/btree/mem_btree.hpp b/src/include/homestore/btree/mem_btree.hpp index ce606fc5a..1856805aa 100644 --- a/src/include/homestore/btree/mem_btree.hpp +++ b/src/include/homestore/btree/mem_btree.hpp @@ -48,7 +48,7 @@ class MemBtree : public Btree< K, V > { node_buf_ptr_vec.emplace_back(ptr); auto new_node = this->init_node(ptr.get(), bnodeid_t{0}, true, is_leaf); - new_node->set_node_id(bnodeid_t{r_cast< std::uintptr_t >(new_node)}); + new_node->set_node_id(bnodeid_t{reinterpret_cast< std::uintptr_t >(new_node)}); new_node->m_refcount.increment(); return BtreeNodePtr{new_node}; } @@ -56,7 +56,7 @@ class MemBtree : public Btree< K, V > { btree_status_t write_node_impl(const BtreeNodePtr& node, void* context) { return btree_status_t::success; } btree_status_t read_node_impl(bnodeid_t id, BtreeNodePtr& node) const override { - node.reset(r_cast< BtreeNode* >(id)); + node.reset(reinterpret_cast< BtreeNode* >(id)); return btree_status_t::success; } diff --git a/src/include/homestore/checkpoint/cp.hpp b/src/include/homestore/checkpoint/cp.hpp index b8e012372..1583abdd2 100644 --- a/src/include/homestore/checkpoint/cp.hpp +++ b/src/include/homestore/checkpoint/cp.hpp @@ -90,7 +90,7 @@ struct CP { std::array< std::unique_ptr< CPContext >, (size_t)cp_consumer_t::SENTINEL > m_contexts; // Broadcast completion for everyone who triggered this CP (assigned in CPManager::do_trigger_cp_flush). std::shared_ptr< sisl::async::shared_awaitable< bool > > m_comp; - Clock::time_point m_cp_start_time; + sisl::Clock::time_point m_cp_start_time; #ifdef _PRERELEASE std::atomic< bool > m_abrupt_cp{false}; #endif diff --git a/src/include/homestore/homestore.hpp b/src/include/homestore/homestore.hpp index d756de2db..857a3be43 100644 --- a/src/include/homestore/homestore.hpp +++ b/src/include/homestore/homestore.hpp @@ -68,7 +68,7 @@ ENUM(hs_vdev_type_t, uint32_t, DATA_VDEV = 1, INDEX_VDEV = 2, META_VDEV = 3, LOG struct hs_vdev_context { enum hs_vdev_type_t type; - sisl::blob to_blob() { return sisl::blob{uintptr_cast(this), sizeof(*this)}; } + sisl::blob to_blob() { return sisl::blob{reinterpret_cast< uint8_t* >(this), sizeof(*this)}; } }; #pragma pack() @@ -151,9 +151,9 @@ class home_store { home_store& with_data_service(cshared< ChunkSelector >& custom_chunk_selector = nullptr); home_store& with_log_service(); home_store& with_index_service(std::unique_ptr< IndexServiceCallbacks > cbs, - cshared< ChunkSelector >& custom_chunk_selector = nullptr); + cshared< ChunkSelector >& custom_chunk_selector = nullptr); home_store& with_repl_data_service(cshared< repl_application >& repl_app, - cshared< ChunkSelector >& custom_chunk_selector = nullptr); + cshared< ChunkSelector >& custom_chunk_selector = nullptr); home_store& with_fault_containment(std::unique_ptr< FaultContainmentCallback > cb); bool start(const hs_input_params& input, hs_before_services_starting_cb_t svcs_starting_cb = nullptr); diff --git a/src/include/homestore/homestore_decl.hpp b/src/include/homestore/homestore_decl.hpp index 5021b9630..c99427d47 100644 --- a/src/include/homestore/homestore_decl.hpp +++ b/src/include/homestore/homestore_decl.hpp @@ -64,15 +64,17 @@ constexpr uint32_t BLK_NUM_BITS{32}; constexpr uint32_t NBLKS_BITS{8}; constexpr uint32_t CHUNK_NUM_BITS{8}; constexpr uint32_t BLKID_SIZE_BITS{BLK_NUM_BITS + NBLKS_BITS + CHUNK_NUM_BITS}; -constexpr uint64_t MAX_CHUNK_ID{((uint64_cast(1) << CHUNK_NUM_BITS) - 2)}; // one less to indicate invalid chunks +constexpr uint64_t MAX_CHUNK_ID{ + ((static_cast< uint64_t >(1) << CHUNK_NUM_BITS) - 2)}; // one less to indicate invalid chunks constexpr uint64_t BLKID_SIZE{(BLKID_SIZE_BITS / 8) + (((BLKID_SIZE_BITS % 8) != 0) ? 1 : 0)}; constexpr uint32_t BLKS_PER_PORTION{1024}; constexpr uint32_t TOTAL_SEGMENTS{8}; -constexpr uint64_t MAX_BLK_NUM_BITS_PER_CHUNK{((uint64_cast(1) << BLK_NUM_BITS) - 1)}; +constexpr uint64_t MAX_BLK_NUM_BITS_PER_CHUNK{((static_cast< uint64_t >(1) << BLK_NUM_BITS) - 1)}; inline uint64_t MIN_DATA_CHUNK_SIZE(uint32_t blk_size) { return blk_size * BLKS_PER_PORTION * TOTAL_SEGMENTS; } inline uint64_t MAX_DATA_CHUNK_SIZE(uint32_t blk_size) { - return uint64_cast(sisl::round_down((MAX_BLK_NUM_BITS_PER_CHUNK * blk_size), MIN_DATA_CHUNK_SIZE(blk_size))); + return static_cast< uint64_t >( + sisl::round_down((MAX_BLK_NUM_BITS_PER_CHUNK * blk_size), MIN_DATA_CHUNK_SIZE(blk_size))); } // 16 TB constexpr uint32_t MAX_CHUNKS{128}; diff --git a/src/include/homestore/index/index_internal.hpp b/src/include/homestore/index/index_internal.hpp index 2316f7a37..4469a0677 100644 --- a/src/include/homestore/index/index_internal.hpp +++ b/src/include/homestore/index/index_internal.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -73,9 +74,12 @@ struct index_table_sb { chunk_id_ptr++; } } - chunk_num_t* get_chunk_ids_mutable() { return r_cast< chunk_num_t* >(uintptr_cast(this) + sizeof(index_table_sb)); } + chunk_num_t* get_chunk_ids_mutable() { + return reinterpret_cast< chunk_num_t* >(reinterpret_cast< uint8_t* >(this) + sizeof(index_table_sb)); + } const chunk_num_t* get_chunk_ids() const { - return r_cast< const chunk_num_t* >(reinterpret_cast< const uint8_t* >(this) + sizeof(index_table_sb)); + return reinterpret_cast< const chunk_num_t* >(reinterpret_cast< const uint8_t* >(this) + + sizeof(index_table_sb)); } }; #pragma pack() @@ -92,7 +96,9 @@ class IndexTableBase { virtual void recovery_completed() = 0; virtual uint32_t ordinal() const = 0; virtual uint64_t used_size() const = 0; - virtual btree_status_t destroy() = 0; + // Async: destroy co_awaits a forced CP flush before removing the superblk. It must not be sync-waited from + // an iomgr worker reactor (the flush needs those reactors) -- co_await it, or sync_get() it off-reactor. + virtual sisl::async::task< btree_status_t > destroy() = 0; virtual void stop() = 0; virtual void repair_node(IndexBufferPtr const& buf) = 0; virtual void repair_root_node(IndexBufferPtr const& buf) = 0; @@ -115,7 +121,7 @@ enum class index_buf_state_t : uint8_t { // m_up_buffer and each buffer is flushed only its wait_for_leaders reaches 0 // which means all its dependent buffers are flushed. struct IndexBuffer : public sisl::ObjLifeCounter< IndexBuffer > { - blk_id m_blkid; // blk_id where this needs to be persisted + blk_id m_blkid; // blk_id where this needs to be persisted cp_id_t m_dirtied_cp_id{-1}; // Last CP that dirtied this index buffer cp_id_t m_created_cp_id{-1}; // CP id when this buffer is created. std::atomic< index_buf_state_t > m_state{index_buf_state_t::CLEAN}; // Is buffer yet to persist? diff --git a/src/include/homestore/index/index_table.hpp b/src/include/homestore/index/index_table.hpp index aa9589424..1ee30d6fc 100644 --- a/src/include/homestore/index/index_table.hpp +++ b/src/include/homestore/index/index_table.hpp @@ -23,7 +23,6 @@ #include #include #include -#include "common/coro_helpers.hpp" // detail::sync_get (block on the forced CP flush; transitional path) #include #include #include @@ -133,8 +132,8 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { return true; } - btree_status_t destroy() override { - if (is_stopping()) return btree_status_t::stopping; + sisl::async::task< btree_status_t > destroy() override { + if (is_stopping()) co_return btree_status_t::stopping; incr_pending_request_num(); auto chunk_selector{hs()->index_service().get_chunk_selector()}; if (!chunk_selector) { @@ -147,11 +146,15 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { // If the process crashes after this point, recovery will not replay the // old journal (CP is complete), so repair_index_node will never be called // for an ordinal whose superblock no longer exists. - detail::sync_get(cp_mgr().trigger_cp_flush(true /* force */)); + // + // co_await (rather than blocking sync_wait): the flush's per-consumer IO runs on the iomgr worker + // reactors, so if destroy() is invoked on a worker reactor, suspending here yields that reactor back + // to its iomgr loop to service the flush -- a blocking wait would deadlock (parked reactor can't flush). + std::ignore = co_await cp_mgr().trigger_cp_flush(true /* force */); m_sb.destroy(); m_sb_buffer->m_valid = false; decr_pending_request_num(); - return btree_status_t::success; + co_return btree_status_t::success; } uuid_t uuid() const override { return m_sb->uuid; } @@ -302,7 +305,7 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { } btree_status_t write_node_impl(const BtreeNodePtr& node, void* context) override { - auto cp_ctx = r_cast< CPContext* >(context); + auto cp_ctx = reinterpret_cast< CPContext* >(context); auto idx_node = static_cast< IndexBtreeNode* >(node.get()); node->set_checksum(); @@ -332,12 +335,12 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { btree_status_t transact_nodes(const BtreeNodeList& new_nodes, const BtreeNodeList& freed_nodes, const BtreeNodePtr& left_child_node, const BtreeNodePtr& parent_node, void* context) override { - CPContext* cp_ctx = r_cast< CPContext* >(context); + CPContext* cp_ctx = reinterpret_cast< CPContext* >(context); IndexBufferPtrList new_node_bufs; for (const auto& right_child_node : new_nodes) { write_node_impl(right_child_node, context); - new_node_bufs.push_back(s_cast< IndexBtreeNode* >(right_child_node.get())->m_idx_buf); + new_node_bufs.push_back(static_cast< IndexBtreeNode* >(right_child_node.get())->m_idx_buf); } write_node_impl(left_child_node, context); // during recovery it is possible that there is no parent_node @@ -345,13 +348,13 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { IndexBufferPtrList freed_node_bufs; for (const auto& freed_node : freed_nodes) { - freed_node_bufs.push_back(s_cast< IndexBtreeNode* >(freed_node.get())->m_idx_buf); + freed_node_bufs.push_back(static_cast< IndexBtreeNode* >(freed_node.get())->m_idx_buf); this->free_node(freed_node, locktype_t::WRITE, context); } wb_cache().transact_bufs( - ordinal(), parent_node.get() ? s_cast< IndexBtreeNode* >(parent_node.get())->m_idx_buf : nullptr, - s_cast< IndexBtreeNode* >(left_child_node.get())->m_idx_buf, new_node_bufs, freed_node_bufs, cp_ctx); + ordinal(), parent_node.get() ? static_cast< IndexBtreeNode* >(parent_node.get())->m_idx_buf : nullptr, + static_cast< IndexBtreeNode* >(left_child_node.get())->m_idx_buf, new_node_bufs, freed_node_bufs, cp_ctx); return btree_status_t::success; } @@ -370,14 +373,14 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { btree_status_t refresh_node(const BtreeNodePtr& node, bool for_read_modify_write, void* context) const override { if (context == nullptr || !for_read_modify_write) { return btree_status_t::success; } - return wb_cache().get_writable_buf(node, r_cast< CPContext* >(context)) ? btree_status_t::success - : btree_status_t::cp_mismatch; + return wb_cache().get_writable_buf(node, reinterpret_cast< CPContext* >(context)) ? btree_status_t::success + : btree_status_t::cp_mismatch; } void free_node_impl(const BtreeNodePtr& node, void* context) override { auto n = static_cast< IndexBtreeNode* >(node.get()); n->m_idx_buf->m_node_level = node->level(); - wb_cache().free_buf(n->m_idx_buf, r_cast< CPContext* >(context)); + wb_cache().free_buf(n->m_idx_buf, reinterpret_cast< CPContext* >(context)); } btree_status_t on_root_changed(BtreeNodePtr const& new_root, void* context) override { @@ -391,13 +394,13 @@ class IndexTable : public IndexTableBase, public Btree< K, V > { m_sb->total_leaf_nodes = this->m_total_leaf_nodes; std::tie(m_sb->total_interior_nodes, m_sb->total_leaf_nodes) = this->get_num_nodes(); - if (!wb_cache().refresh_meta_buf(m_sb_buffer, r_cast< CPContext* >(context))) { + if (!wb_cache().refresh_meta_buf(m_sb_buffer, reinterpret_cast< CPContext* >(context))) { LOGTRACEMOD(wbcache, "CP mismatch error - discard transact for meta node"); return btree_status_t::cp_mismatch; } auto& root_buf = static_cast< IndexBtreeNode* >(new_root.get())->m_idx_buf; - wb_cache().transact_bufs(ordinal(), m_sb_buffer, root_buf, {}, {}, r_cast< CPContext* >(context)); + wb_cache().transact_bufs(ordinal(), m_sb_buffer, root_buf, {}, {}, reinterpret_cast< CPContext* >(context)); return btree_status_t::success; } diff --git a/src/include/homestore/logstore/log_store_internal.hpp b/src/include/homestore/logstore/log_store_internal.hpp index 0aeb514a2..b1ed14848 100644 --- a/src/include/homestore/logstore/log_store_internal.hpp +++ b/src/include/homestore/logstore/log_store_internal.hpp @@ -103,10 +103,10 @@ struct log_dump_req { std::shared_ptr< home_log_store > logstore = nullptr, logstore_seq_num_t s_seq = 0, logstore_seq_num_t e_seq = std::numeric_limits< int64_t >::max()) : verbosity_level{level}, log_store{logstore}, start_seq_num{s_seq}, end_seq_num{e_seq} {} - log_dump_verbosity verbosity_level; // How much information we need of log file (entire content or header) + log_dump_verbosity verbosity_level; // How much information we need of log file (entire content or header) std::shared_ptr< home_log_store > log_store; // if null all log stores are dumped - logstore_seq_num_t start_seq_num; // empty_key if from start of log file - logstore_seq_num_t end_seq_num; // empty_key if till last log entry + logstore_seq_num_t start_seq_num; // empty_key if from start of log file + logstore_seq_num_t end_seq_num; // empty_key if till last log entry }; struct logstore_record { @@ -121,13 +121,13 @@ struct logstore_record { class home_log_store; struct logstore_req { home_log_store* log_store; // Backpointer to the log store. We are not storing shared_ptr as user should not destroy - // it until all ios are not completed. + // it until all ios are not completed. logstore_seq_num_t seq_num; // Log store specific seq_num (which could be monotonically increaseing with logstore) sisl::io_blob data; // Data blob containing data void* cookie; // User generated cookie (considered as opaque) bool is_internal_req; // If the req is created internally by home_log_store itself log_req_comp_cb_t cb; // Callback upon completion of write (overridden than default) - Clock::time_point start_time; + sisl::Clock::time_point start_time; bool flush_wait{false}; // Wait for the flush to happen logstore_req(const logstore_req&) = delete; diff --git a/src/include/homestore/logstore_service.hpp b/src/include/homestore/logstore_service.hpp index 304e7ca90..aaea4e5d3 100644 --- a/src/include/homestore/logstore_service.hpp +++ b/src/include/homestore/logstore_service.hpp @@ -136,8 +136,9 @@ class log_store_service { * @return std::shared_ptr< home_log_store > */ sisl::async::task< shared< home_log_store > > open_log_store(logdev_id_t logdev_id, logstore_id_t store_id, - bool append_mode, log_found_cb_t log_found_cb = nullptr, - log_replay_done_cb_t log_replay_done_cb = nullptr); + bool append_mode, + log_found_cb_t log_found_cb = nullptr, + log_replay_done_cb_t log_replay_done_cb = nullptr); /** * @brief Close the log store instance and free-up the resources diff --git a/src/include/homestore/meta_service.hpp b/src/include/homestore/meta_service.hpp index c458f5336..dd6e1f7a5 100644 --- a/src/include/homestore/meta_service.hpp +++ b/src/include/homestore/meta_service.hpp @@ -80,14 +80,14 @@ struct meta_vdev_context; class meta_blk_service { private: static bool s_self_recover; - std::shared_ptr< VirtualDev > m_sb_vdev; // super block vdev - std::mutex m_meta_mtx; // mutex to access to meta_map; - std::mutex m_shutdown_mtx; // protects concurrent operations between recover and shutdown; - meta_blk_map_t m_meta_blks; // subsystem type to meta blk map; - ovf_hdr_map_t m_ovf_blk_hdrs; // ovf blk map; - client_info_map_t m_sub_info; // map of callbacks + std::shared_ptr< VirtualDev > m_sb_vdev; // super block vdev + std::mutex m_meta_mtx; // mutex to access to meta_map; + std::mutex m_shutdown_mtx; // protects concurrent operations between recover and shutdown; + meta_blk_map_t m_meta_blks; // subsystem type to meta blk map; + ovf_hdr_map_t m_ovf_blk_hdrs; // ovf blk map; + client_info_map_t m_sub_info; // map of callbacks std::unique_ptr< blk_id > m_last_mblk_id; // last meta blk; - meta_blk_sb* m_ssb{nullptr}; // meta super super blk; + meta_blk_sb* m_ssb{nullptr}; // meta super super blk; sisl::blob m_compress_info; MetablkMetrics m_metrics; bool m_inited{false}; diff --git a/src/include/homestore/replication/repl_decls.hpp b/src/include/homestore/replication/repl_decls.hpp index 516747f13..1f5413a8b 100644 --- a/src/include/homestore/replication/repl_decls.hpp +++ b/src/include/homestore/replication/repl_decls.hpp @@ -62,9 +62,7 @@ ENUM(ReplaceMemberStatus, int32_t, class repl_error_category : public std::error_category { public: const char* name() const noexcept override { return "homestore.replication"; } - std::string message(int ev) const override { - return std::string{enum_name(static_cast< ReplServiceError >(ev))}; - } + std::string message(int ev) const override { return std::string{enum_name(static_cast< ReplServiceError >(ev))}; } }; inline std::error_category const& repl_error_category_inst() noexcept { static repl_error_category inst; diff --git a/src/include/homestore/replication/repl_dev.hpp b/src/include/homestore/replication/repl_dev.hpp index 5957e2030..03b5c24e7 100644 --- a/src/include/homestore/replication/repl_dev.hpp +++ b/src/include/homestore/replication/repl_dev.hpp @@ -160,7 +160,7 @@ struct repl_req_ctx : public boost::intrusive_ref_counter< repl_req_ctx, boost:: friend class SoloReplDev; public: - repl_req_ctx() { m_start_time = Clock::now(); } + repl_req_ctx() { m_start_time = sisl::Clock::now(); } virtual ~repl_req_ctx(); ReplServiceError init(repl_key rkey, journal_type_t op_code, bool is_proposer, sisl::blob const& user_header, sisl::blob const& key, uint32_t data_size, cshared< repl_dev_listener >& listener); @@ -191,10 +191,10 @@ struct repl_req_ctx : public boost::intrusive_ref_counter< repl_req_ctx, boost:: const char* data() const { DEBUG_ASSERT(m_data != nullptr, "m_data is nullptr, use before save_pushed/fetched_data or after release_data()"); - return r_cast< const char* >(m_data); + return reinterpret_cast< const char* >(m_data); } repl_req_state_t state() const { return repl_req_state_t(m_state.load()); } - bool has_state(repl_req_state_t s) const { return m_state.load() & uint32_cast(s); } + bool has_state(repl_req_state_t s) const { return m_state.load() & static_cast< uint32_t >(s); } repl_journal_entry const* journal_entry() const { return m_journal_entry; } uint32_t journal_entry_size() const; uint32_t blkids_serialized_size() const; @@ -207,8 +207,8 @@ struct repl_req_ctx : public boost::intrusive_ref_counter< repl_req_ctx, boost:: std::string to_string() const; std::string to_compact_string() const; std::string blkids_to_string() const; - Clock::time_point created_time() const { return m_start_time; } - void set_created_time() { m_start_time = Clock::now(); } + sisl::Clock::time_point created_time() const { return m_start_time; } + void set_created_time() { m_start_time = sisl::Clock::now(); } bool is_expired() const; /////////////////////// All Modifiers methods ////////////////// @@ -281,7 +281,7 @@ struct repl_req_ctx : public boost::intrusive_ref_counter< repl_req_ctx, boost:: sisl::blob m_key; // User supplied key for this req int64_t m_lsn{-1}; // Lsn for this replication req bool m_is_proposer{false}; // Is the repl_req proposed by this node - Clock::time_point m_start_time; // Start time of the request + sisl::Clock::time_point m_start_time; // Start time of the request journal_type_t m_op_code{journal_type_t::HS_DATA_INLINED}; // Operation code for this request std::atomic< bool > m_is_volatile{true}; // Is the log still in memory and not flushed to disk yet @@ -289,7 +289,7 @@ struct repl_req_ctx : public boost::intrusive_ref_counter< repl_req_ctx, boost:: static inline multi_blk_id dummy_blkid; std::vector< multi_blk_id > m_local_blkids; // Local blk_id for the data remote_blk_id m_remote_blkid; // Corresponding remote blkid for the data - uint8_t const* m_data; // Raw data pointer containing the actual data + uint8_t const* m_data; // Raw data pointer containing the actual data /////////////// Journal/Buf related section ///////////////// std::variant< std::unique_ptr< uint8_t[] >, raft_buf_ptr_t > m_journal_buf; // Buf for the journal entry @@ -298,7 +298,8 @@ struct repl_req_ctx : public boost::intrusive_ref_counter< repl_req_ctx, boost:: nuraft::ptr< nuraft::log_entry > m_lentry; /////////////// Replication state related section ///////////////// - std::atomic< uint32_t > m_state{uint32_cast(repl_req_state_t::INIT)}; // State of the replication request + std::atomic< uint32_t > m_state{ + static_cast< uint32_t >(repl_req_state_t::INIT)}; // State of the replication request /////////////// Communication packet/builder section ///////////////// flatbuffers::FlatBufferBuilder m_fb_builder; @@ -557,8 +558,9 @@ class repl_dev { /// into that batch (the token submits on destruction). /// @return A Future with std::error_code to notify if it has successfully read the data or any error code in case /// of failure - virtual sisl::async::task< iomgr::io_result > async_read(multi_blk_id const& blkid, sisl::sg_list& sgs, uint32_t size, - io_batch* batch = nullptr, trace_id_t tid = 0) = 0; + virtual sisl::async::task< iomgr::io_result > async_read(multi_blk_id const& blkid, sisl::sg_list& sgs, + uint32_t size, io_batch* batch = nullptr, + trace_id_t tid = 0) = 0; /// @brief After data is replicated and on_commit to the listener is called. the blkids can be freed. /// diff --git a/src/include/homestore/replication_service.hpp b/src/include/homestore/replication_service.hpp index 014e7dacb..2a600e6b5 100644 --- a/src/include/homestore/replication_service.hpp +++ b/src/include/homestore/replication_service.hpp @@ -33,7 +33,7 @@ class replication_service { /// @param listener state machine listener of all the events happening on the repl_dev (commit, precommit etc) /// @return A Future repl_dev on success or Future ReplServiceError upon error virtual async_result< shared< repl_dev > > create_repl_dev(group_id_t group_id, - std::set< replica_id_t > const& members) = 0; + std::set< replica_id_t > const& members) = 0; /// @brief Removes the entire Repl Device. The underlying replica group is marked as destroy_pending and all its /// resources are not released until garbage collection of repl devices kick in. @@ -50,9 +50,8 @@ class replication_service { /// @param commit_quorum Commit quorum to be used for this operation. If 0, it will use the default commit quorum. /// @return A Future on replace the member accepted or Future ReplServiceError upon error virtual async_status replace_member(group_id_t group_id, std::string& task_id, - const replica_member_info& member_out, - const replica_member_info& member_in, uint32_t commit_quorum = 0, - uint64_t trace_id = 0) const = 0; + const replica_member_info& member_out, const replica_member_info& member_in, + uint32_t commit_quorum = 0, uint64_t trace_id = 0) const = 0; /// @brief Flips the learner flag for a specific replica member in the group. /// @param group_id The ID of the replica group. @@ -63,8 +62,8 @@ class replication_service { /// @param trace_id Optional trace ID for tracking (default: 0). /// @return A future result indicating success or error. virtual async_status flip_learner_flag(group_id_t group_id, const replica_member_info& member, bool target, - uint32_t commit_quorum, bool wait_and_verify = true, - uint64_t trace_id = 0) const = 0; + uint32_t commit_quorum, bool wait_and_verify = true, + uint64_t trace_id = 0) const = 0; /// @brief Remove the specific replica member from the group. /// @param group_id The ID of the replica group. @@ -74,7 +73,7 @@ class replication_service { /// @param trace_id Optional trace ID for tracking (default: 0). /// @return A future result indicating success or error. virtual async_status remove_member(group_id_t group_id, const replica_id_t& member, uint32_t commit_quorum, - bool wait_and_verify = true, uint64_t trace_id = 0) const = 0; + bool wait_and_verify = true, uint64_t trace_id = 0) const = 0; /// @brief Clean the replace member task. /// @param group_id The ID of the replica group. @@ -83,7 +82,7 @@ class replication_service { /// @param trace_id Optional trace ID for tracking (default: 0). /// @return A future result indicating success or error. virtual async_status clean_replace_member_task(group_id_t group_id, const std::string& task_id, - uint32_t commit_quorum, uint64_t trace_id = 0) const = 0; + uint32_t commit_quorum, uint64_t trace_id = 0) const = 0; /// @brief Lists all replace member tasks. /// @param trace_id Optional trace ID for tracking (default: 0). diff --git a/src/include/homestore/superblk_handler.hpp b/src/include/homestore/superblk_handler.hpp index 3b5db19dc..0d0d3a2e5 100644 --- a/src/include/homestore/superblk_handler.hpp +++ b/src/include/homestore/superblk_handler.hpp @@ -69,14 +69,15 @@ class superblk { m_meta_blk = mblk; m_raw_buf = meta_service().is_aligned_buf_needed(buf.size()) ? buf.extract(meta_service().align_size()) : buf.extract(0); - m_sb = r_cast< T* >(m_raw_buf->bytes()); + m_sb = reinterpret_cast< T* >(m_raw_buf->bytes()); return m_sb; } T* create(uint32_t size = sizeof(T)) { if (meta_service().is_aligned_buf_needed(size)) { auto al_sz = meta_service().align_size(); - m_raw_buf = sisl::make_byte_array(uint32_cast(sisl::round_up(size, al_sz)), al_sz, sisl::buftag::metablk); + m_raw_buf = sisl::make_byte_array(static_cast< uint32_t >(sisl::round_up(size, al_sz)), al_sz, + sisl::buftag::metablk); } else { m_raw_buf = sisl::make_byte_array(size, 0, sisl::buftag::metablk); } @@ -87,7 +88,7 @@ class superblk { T* resize(uint32_t size) { if (meta_service().is_aligned_buf_needed(size)) { auto al_sz = meta_service().align_size(); - m_raw_buf->buf_realloc(uint32_cast(sisl::round_up(size, al_sz)), al_sz, sisl::buftag::metablk); + m_raw_buf->buf_realloc(static_cast< uint32_t >(sisl::round_up(size, al_sz)), al_sz, sisl::buftag::metablk); } else { m_raw_buf->buf_realloc(size, 0, sisl::buftag::metablk); } @@ -155,7 +156,7 @@ class json_superblk { nlohmann::json& load(const sisl::byte_view& buf, struct meta_blk* mblk) { m_meta_blk = mblk; - std::string_view const b{c_charptr_cast(buf.bytes()), buf.size()}; + std::string_view const b{reinterpret_cast< char const* >(buf.bytes()), buf.size()}; try { m_json_sb = nlohmann::json::from_msgpack(b); @@ -194,7 +195,7 @@ class json_superblk { std::memcpy(buffer.bytes(), packed_data.data(), size); do_write(buffer); } else { - do_write(sisl::blob{r_cast< uint8_t const* >(packed_data.data()), uint32_cast(size)}); + do_write(sisl::blob{reinterpret_cast< uint8_t const* >(packed_data.data()), static_cast< uint32_t >(size)}); } } diff --git a/src/lib/checkpoint/cp_mgr.cpp b/src/lib/checkpoint/cp_mgr.cpp index a460db724..3d9faa1a2 100644 --- a/src/lib/checkpoint/cp_mgr.cpp +++ b/src/lib/checkpoint/cp_mgr.cpp @@ -48,8 +48,7 @@ CPManager::CPManager() : m_sb{"CPSuperBlock"} { meta_service().register_handler( "CPSuperBlock", - [this](meta_blk* mblk, sisl::byte_view buf, size_t size) { on_meta_blk_found(std::move(buf), mblk); }, - nullptr); + [this](meta_blk* mblk, sisl::byte_view buf, size_t size) { on_meta_blk_found(std::move(buf), mblk); }, nullptr); resource_mgr().register_dirty_buf_exceed_cb([this]([[maybe_unused]] int64_t dirty_buf_count, bool critical) { LOGINFO("Dirty buffer exceeded count {} critical {}", dirty_buf_count, critical); @@ -111,8 +110,11 @@ void CPManager::start_timer() { auto usecs = cp_timer_us(); LOGINFO("cp timer is set to {} usec", usecs); iomanager.run_on_wait(m_timer_reactor, [this, usecs]() { - m_cp_timer_hdl = iomanager.schedule_thread_timer(usecs * 1000, true /* recurring */, nullptr /* cookie */, - [this](void*) { detail::detach(trigger_cp_flush(false)); }); + m_cp_timer_hdl = iomanager.schedule_thread_timer( + usecs * 1000, true /* recurring */, nullptr /* cookie */, [this](void*, uint64_t exp_count) { + if (exp_count > 1) { LOGINFO("cp timer expired {} times, running once", exp_count); } + detail::detach(trigger_cp_flush(false)); + }); }); } @@ -434,7 +436,12 @@ CPWatchdog::CPWatchdog(CPManager* cp_mgr) : LOGINFO("CP watchdog timer setting to : {} seconds", m_timer_sec); m_timer_hdl = iomanager.schedule_global_timer(m_timer_sec * 1000 * 1000 * 1000, true, nullptr, iomgr::reactor_regex::all_user, - [this](void* cookie) { cp_watchdog_timer(); }); + [this](void*, uint64_t exp_count) { + if (exp_count > 1) { + LOGINFO("cp watchdog timer expired {} times, running once", exp_count); + } + cp_watchdog_timer(); + }); } void CPWatchdog::reset_cp() { diff --git a/src/lib/common/resource_mgr.cpp b/src/lib/common/resource_mgr.cpp index 0c6bb25f9..370721eb5 100644 --- a/src/lib/common/resource_mgr.cpp +++ b/src/lib/common/resource_mgr.cpp @@ -49,10 +49,10 @@ void ResourceMgr::stop() { // void ResourceMgr::trigger_truncate() { if (m_is_stopped_.load()) { - // when we are here, it means home_store is shutting down and since this API is called in timer thread, the timer - // thread might already been triggered while RM is tring to cancel it; - // and since shutdown and timer thread happen parallel, by the time we are here, shutdown might already cleaned - // up all replication service instances. and it will throw heap-use-after-free; + // when we are here, it means home_store is shutting down and since this API is called in timer thread, the + // timer thread might already been triggered while RM is tring to cancel it; and since shutdown and timer thread + // happen parallel, by the time we are here, shutdown might already cleaned up all replication service + // instances. and it will throw heap-use-after-free; LOGINFO("Resource manager is stopped, so not triggering truncate"); return; } @@ -87,7 +87,8 @@ void ResourceMgr::start_timer() { m_res_audit_timer_hdl = iomanager.schedule_global_timer( res_mgr_timer_ms * 1000 * 1000, true /* recurring */, nullptr /* cookie */, iomgr::reactor_regex::all_worker, - [this](void*) { + [this](void*, uint64_t exp_count) { + if (exp_count > 1) { LOGINFO("resource audit timer expired {} times, running once", exp_count); } // all resource timely audit routine should arrive here; this->trigger_truncate(); }, diff --git a/src/lib/logstore/log_dev.cpp b/src/lib/logstore/log_dev.cpp index 0db267188..3056d55c6 100644 --- a/src/lib/logstore/log_dev.cpp +++ b/src/lib/logstore/log_dev.cpp @@ -186,7 +186,10 @@ void LogDev::start_timer() { iomanager.run_on_wait(logstore_service().flush_reactor(), [this]() { m_flush_timer_hdl = iomanager.schedule_thread_timer( HS_DYNAMIC_CONFIG(logstore.flush_timer_frequency_us) * 1000, true /* recurring */, nullptr /* cookie */, - [this](void*) { flush_if_necessary(); }); + [this](void*, uint64_t exp_count) { + if (exp_count > 1) { LOGINFO("log flush timer expired {} times, running once", exp_count); } + flush_if_necessary(); + }); }); } @@ -740,8 +743,8 @@ std::shared_ptr< home_log_store > LogDev::create_new_log_store(bool append_mode) } sisl::async::task< shared< home_log_store > > LogDev::open_log_store(logstore_id_t store_id, bool append_mode, - log_found_cb_t log_found_cb, - log_replay_done_cb_t log_replay_done_cb) { + log_found_cb_t log_found_cb, + log_replay_done_cb_t log_replay_done_cb) { // The map insert must happen SYNCHRONOUSLY here (so replay's on_logfound finds the entry); only the wait for // the store to be opened is awaited. So this is NOT itself a coroutine -- it inserts under the lock, then // returns a task awaiting the entry's broadcast completion (copied out before the lock releases). diff --git a/src/lib/replication/service/raft_repl_service.cpp b/src/lib/replication/service/raft_repl_service.cpp index 773335f07..9d7c5e080 100644 --- a/src/lib/replication/service/raft_repl_service.cpp +++ b/src/lib/replication/service/raft_repl_service.cpp @@ -386,7 +386,7 @@ shared< nuraft_mesg::mesg_state_mgr > RaftReplService::create_state_mgr(int32_t } async_result< shared< repl_dev > > RaftReplService::create_repl_dev(group_id_t group_id, - std::set< replica_id_t > const& members) { + std::set< replica_id_t > const& members) { if (is_stopping()) return make_async_error< shared< repl_dev > >(ReplServiceError::STOPPING); init_req_counter counter(pending_request_num); // TODO: All operations are made sync here for convenience to caller. However, we should attempt to make this async @@ -516,9 +516,9 @@ void RaftReplService::load_repl_dev(sisl::byte_view const& buf, meta_blk* meta_c // a background reaper thread helps periodically check the member_in replication status, after in_member has caught up, // will trigger replDev complete_replace_member. async_status RaftReplService::replace_member(group_id_t group_id, std::string& task_id, - const replica_member_info& member_out, - const replica_member_info& member_in, uint32_t commit_quorum, - uint64_t trace_id) const { + const replica_member_info& member_out, + const replica_member_info& member_in, uint32_t commit_quorum, + uint64_t trace_id) const { if (is_stopping()) co_return std::unexpected(ReplServiceError::STOPPING); init_req_counter counter(pending_request_num); auto rdev_result = get_repl_dev(group_id); @@ -530,9 +530,8 @@ async_status RaftReplService::replace_member(group_id_t group_id, std::string& t co_return status{std::monostate{}}; } -async_status RaftReplService::flip_learner_flag(group_id_t group_id, const replica_member_info& member, - bool target, uint32_t commit_quorum, bool wait_and_verify, - uint64_t trace_id) const { +async_status RaftReplService::flip_learner_flag(group_id_t group_id, const replica_member_info& member, bool target, + uint32_t commit_quorum, bool wait_and_verify, uint64_t trace_id) const { if (is_stopping()) co_return std::unexpected(ReplServiceError::STOPPING); init_req_counter counter(pending_request_num); auto rdev_result = get_repl_dev(group_id); @@ -543,9 +542,8 @@ async_status RaftReplService::flip_learner_flag(group_id_t group_id, const repli co_return status{std::monostate{}}; } -async_status RaftReplService::remove_member(group_id_t group_id, const replica_id_t& member, - uint32_t commit_quorum, bool wait_and_verify, - uint64_t trace_id) const { +async_status RaftReplService::remove_member(group_id_t group_id, const replica_id_t& member, uint32_t commit_quorum, + bool wait_and_verify, uint64_t trace_id) const { if (is_stopping()) co_return std::unexpected(ReplServiceError::STOPPING); init_req_counter counter(pending_request_num); auto rdev_result = get_repl_dev(group_id); @@ -557,7 +555,7 @@ async_status RaftReplService::remove_member(group_id_t group_id, const replica_i } async_status RaftReplService::clean_replace_member_task(group_id_t group_id, const std::string& task_id, - uint32_t commit_quorum, uint64_t trace_id) const { + uint32_t commit_quorum, uint64_t trace_id) const { if (is_stopping()) co_return std::unexpected(ReplServiceError::STOPPING); init_req_counter counter(pending_request_num); auto rdev_result = get_repl_dev(group_id); @@ -632,7 +630,10 @@ void RaftReplService::start_repl_service_timers() { HS_DYNAMIC_CONFIG(generic.repl_dev_cleanup_interval_sec)); m_rdev_gc_timer_hdl = iomanager.schedule_thread_timer( HS_DYNAMIC_CONFIG(generic.repl_dev_cleanup_interval_sec) * 1000 * 1000 * 1000, true /* recurring */, - nullptr, [this](void*) { + nullptr, [this](void*, uint64_t exp_count) { + if (exp_count > 1) { + LOGINFOMOD(replication, "Reaper Thread: GC timer expired {} times, running once", exp_count); + } LOGDEBUGMOD(replication, "Reaper Thread: Doing GC"); gc_repl_reqs(); gc_repl_devs(); @@ -641,18 +642,34 @@ void RaftReplService::start_repl_service_timers() { // Check for queued fetches at the minimum every second uint64_t interval_ns = std::min(HS_DYNAMIC_CONFIG(consensus.wait_data_write_timer_ms) * 1000 * 1000, 1ul * 1000 * 1000 * 1000); - m_rdev_fetch_timer_hdl = iomanager.schedule_thread_timer(interval_ns, true /* recurring */, nullptr, - [this](void*) { fetch_pending_data(); }); + m_rdev_fetch_timer_hdl = iomanager.schedule_thread_timer( + interval_ns, true /* recurring */, nullptr, [this](void*, uint64_t exp_count) { + if (exp_count > 1) { + LOGINFOMOD(replication, "fetch pending data timer expired {} times, running once", exp_count); + } + fetch_pending_data(); + }); // Flush durable commit lsns to superblock // FIXUP: what is the best value for flush_durable_commit_interval_ms? m_flush_durable_commit_timer_hdl = iomanager.schedule_thread_timer( HS_DYNAMIC_CONFIG(consensus.flush_durable_commit_interval_ms) * 1000 * 1000, true /* recurring */, - nullptr, [this](void*) { flush_durable_commit_lsn(); }); + nullptr, [this](void*, uint64_t exp_count) { + if (exp_count > 1) { + LOGINFOMOD(replication, "flush durable commit timer expired {} times, running once", exp_count); + } + flush_durable_commit_lsn(); + }); m_replace_member_sync_check_timer_hdl = iomanager.schedule_thread_timer( HS_DYNAMIC_CONFIG(consensus.replace_member_sync_check_interval_ms) * 1000 * 1000, true /* recurring */, - nullptr, [this](void*) { monitor_replace_member_replication_status(); }); + nullptr, [this](void*, uint64_t exp_count) { + if (exp_count > 1) { + LOGINFOMOD(replication, "replace member sync check timer expired {} times, running once", + exp_count); + } + monitor_replace_member_replication_status(); + }); latch.count_down(); } }); diff --git a/src/tests/test_index_crash_recovery.cpp b/src/tests/test_index_crash_recovery.cpp index 97f60bb2c..e0fe34a36 100644 --- a/src/tests/test_index_crash_recovery.cpp +++ b/src/tests/test_index_crash_recovery.cpp @@ -354,7 +354,7 @@ struct IndexCrashTest : public test_common::HSTestHelper, BtreeTestHelper< TestT LOGINFO("Destroying index btree with uuid {} root id {}", boost::uuids::to_string(this->m_bt->uuid()), this->m_bt->root_node_id()); hs()->index_service().remove_index_table(this->m_bt); - this->m_bt->destroy(); + homestore::detail::sync_get(this->m_bt->destroy()); this->trigger_cp(true); ASSERT_EQ(hs()->index_service().num_tables(), 0) << "After destroying the index table, some table still exists"; @@ -370,7 +370,7 @@ struct IndexCrashTest : public test_common::HSTestHelper, BtreeTestHelper< TestT void destroy_btree() { hs()->index_service().remove_index_table(this->m_bt); - this->m_bt->destroy(); + homestore::detail::sync_get(this->m_bt->destroy()); this->trigger_cp(true); this->m_shadow_map.range_erase(0, SISL_OPTIONS["num_entries"].as< uint32_t >() - 1); this->m_shadow_map.save(m_shadow_filename); @@ -1067,7 +1067,7 @@ TYPED_TEST(IndexCrashTest, DestroyTableWithPendingCpCrash) { // dirty list because free_buf only marks m_node_freed — it does not touch the list. LOGINFO("Step 4: Destroy index table — meta superblock removed from disk"); hs()->index_service().remove_index_table(this->m_bt); - this->m_bt->destroy(); + homestore::detail::sync_get(this->m_bt->destroy()); // Step 5: Trigger the CP (do not wait). async_cp_flush will: // (a) write the txn_journal to disk (entries include the destroyed table's ordinal),