From d45edfad5c99a448ebc2876a4aefb3a7090d368c Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 13 Nov 2025 16:37:55 +0100 Subject: [PATCH 1/3] py10 related fixes --- dbzero/dbzero/dbzero.py | 2 +- run_tests.sh | 2 + src/dbzero/bindings/python/Memo.cpp | 55 ++++++++++++++++--- src/dbzero/bindings/python/PyTypeManager.cpp | 7 +-- src/dbzero/bindings/python/PyTypeManager.hpp | 2 +- .../core/collections/SGB_Tree/SGB_Tree.hpp | 2 + .../collections/SGB_Tree/sgb_tree_node.hpp | 29 ++++++++-- 7 files changed, 81 insertions(+), 18 deletions(-) diff --git a/dbzero/dbzero/dbzero.py b/dbzero/dbzero/dbzero.py index c9e4f4dc..21899e3d 100644 --- a/dbzero/dbzero/dbzero.py +++ b/dbzero/dbzero/dbzero.py @@ -10,7 +10,7 @@ def load_dynamic(name, path): def __bootstrap__(): global __bootstrap__, __loader__, __file__ - paths = [os.path.join(os.path.split(__file__)[0]), "/src/dev/build/release", "/usr/local/lib/python3/dist-packages/dbzero/"] + paths = [os.path.join(os.path.split(__file__)[0]), "/src/dev/build/debug", "/usr/local/lib/python3/dist-packages/dbzero/"] __file__ = None for path in paths: if os.path.isdir(path): diff --git a/run_tests.sh b/run_tests.sh index 894c16b6..cd9c70e2 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -1,3 +1,5 @@ #!/bin/bash export PYTHONIOENCODING=utf8 +export LD_PRELOAD=$(gcc -print-file-name=libasan.so) + python3 -m pytest -m 'not integration_test' -m 'not stress_test' -c pytest.ini --capture=no "$@" -vv diff --git a/src/dbzero/bindings/python/Memo.cpp b/src/dbzero/bindings/python/Memo.cpp index 15e4b0be..3f4a08b7 100644 --- a/src/dbzero/bindings/python/Memo.cpp +++ b/src/dbzero/bindings/python/Memo.cpp @@ -205,6 +205,22 @@ namespace db0::python memo_obj->destroy(); Py_TYPE(memo_obj)->tp_free((PyObject*)memo_obj); } + + template + int MemoObject_traverse(MemoImplT *self, visitproc visit, void *arg) + { + // No Python object references to traverse in memo objects + // They only contain dbzero native objects + return 0; + } + + template + int MemoObject_clear(MemoImplT *self) + { + // No Python object references to clear in memo objects + // They only contain dbzero native objects + return 0; + } template int PyAPI_MemoObject_init(MemoImplT *self, PyObject* args, PyObject* kwds) @@ -481,7 +497,9 @@ namespace db0::python {Py_tp_getattro, (void *)PyAPI_MemoObject_getattro}, {Py_tp_setattro, (void *)PyAPI_MemoObject_setattro}, {Py_tp_richcompare, (void *)PyAPI_MemoObject_rq}, - {Py_tp_hash, (void *)PyAPI_MemoHash}, + {Py_tp_hash, (void *)PyAPI_MemoHash}, + {Py_tp_traverse, (void *)MemoObject_traverse}, + {Py_tp_clear, (void *)MemoObject_clear}, {0, 0} }; @@ -494,7 +512,9 @@ namespace db0::python // set available only on pre-initialized objects {Py_tp_setattro, (void *)PyAPI_MemoObject_setattro}, {Py_tp_richcompare, (void *)PyAPI_MemoObject_rq}, - {Py_tp_hash, (void *)PyAPI_MemoHash}, + {Py_tp_hash, (void *)PyAPI_MemoHash}, + {Py_tp_traverse, (void *)MemoObject_traverse}, + {Py_tp_clear, (void *)MemoObject_clear}, {0, 0} }; @@ -517,7 +537,15 @@ namespace db0::python // fill-in common slots first auto slot_ptr = getCommonSlots(); while (slot_ptr->slot || slot_ptr->pfunc) { +#if PY_VERSION_HEX < 0x030B0000 // Python < 3.11 + // Include all slots including traverse/clear for GC compatibility slots.push_back(*slot_ptr); +#else + // Skip traverse/clear slots for Python 3.11+ where GC is disabled + if (slot_ptr->slot != Py_tp_traverse && slot_ptr->slot != Py_tp_clear) { + slots.push_back(*slot_ptr); + } +#endif ++slot_ptr; } @@ -529,11 +557,18 @@ namespace db0::python } slots.push_back({0, 0}); - + + // Enable GC for Python 3.10 compatibility - required for inheritance hierarchies + std::uint32_t flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; +#if PY_VERSION_HEX < 0x030B0000 // Python < 3.11 + flags |= Py_TPFLAGS_HAVE_GC; +#endif + flags &= ~Py_TPFLAGS_MANAGED_DICT; + auto type_spec = PyType_Spec { .name = tp_name, .basicsize = MemoImplT::sizeOf(), - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE) & ~(Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT), + .flags = flags, .slots = slots.data() }; @@ -577,17 +612,21 @@ namespace db0::python auto [type_name, full_type_name] = getMemoTypeName(py_class); TypeObjectSharedPtr new_type = nullptr; + + // For Python 3.10 compatibility: ensure tp_name string persists beyond this scope + // by using pooled string to avoid segfault due to tp_name pointer being copied literally + auto &type_manager = PyToolkit::getTypeManager(); + const char* safe_tp_name = type_manager.getPooledString(full_type_name); + // NOTE: MemoObject and MemoImmutableObject have different implementations if (immutable) { - new_type = Py_OWN(PyMemoType_FromSpec(base_class, full_type_name.c_str(), is_singleton)); + new_type = Py_OWN(PyMemoType_FromSpec(base_class, safe_tp_name, is_singleton)); } else { - new_type = Py_OWN(PyMemoType_FromSpec(base_class, full_type_name.c_str(), is_singleton)); + new_type = Py_OWN(PyMemoType_FromSpec(base_class, safe_tp_name, is_singleton)); } if (!new_type) { return nullptr; } - - auto &type_manager = PyToolkit::getTypeManager(); MemoFlags type_flags = no_default_tags ? MemoFlags { MemoOptions::NO_DEFAULT_TAGS } : MemoFlags(); if (no_cache) { type_flags.set(MemoOptions::NO_CACHE); diff --git a/src/dbzero/bindings/python/PyTypeManager.cpp b/src/dbzero/bindings/python/PyTypeManager.cpp index 80c28bf7..6300378a 100644 --- a/src/dbzero/bindings/python/PyTypeManager.cpp +++ b/src/dbzero/bindings/python/PyTypeManager.cpp @@ -37,6 +37,8 @@ namespace db0::python { + std::vector > PyTypeManager::m_string_pool; + PyTypeManager::PyTypeManager() { if (!Py_IsInitialized()) { @@ -96,9 +98,6 @@ namespace db0::python PyTypeManager::~PyTypeManager() { - for (auto &str: m_string_pool) { - delete str; - } if (!Py_IsInitialized()) { for (auto &pair: m_type_cache) { pair.second.steal(); @@ -342,7 +341,7 @@ namespace db0::python const char *PyTypeManager::getPooledString(std::string str) { - m_string_pool.push_back(new std::string(str)); + m_string_pool.push_back(std::make_unique(std::move(str))); return m_string_pool.back()->c_str(); } diff --git a/src/dbzero/bindings/python/PyTypeManager.hpp b/src/dbzero/bindings/python/PyTypeManager.hpp index 16493bf3..7d7d6cbd 100644 --- a/src/dbzero/bindings/python/PyTypeManager.hpp +++ b/src/dbzero/bindings/python/PyTypeManager.hpp @@ -188,7 +188,7 @@ namespace db0::python void close(); private: - std::vector m_string_pool; + static std::vector > m_string_pool; // the registry of memo types, used for retrieving type decorators std::unordered_map m_type_registry; std::unordered_map m_py_type_map; diff --git a/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp b/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp index b7b9767b..471b3770 100644 --- a/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp +++ b/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp @@ -148,6 +148,8 @@ namespace db0 auto max_item_index = node->indexOf(max_item_ptr); auto new_node = super_t::insert_equal(*max_item_ptr, m_node_capacity, m_heap_comp); node.modify().erase_existing(max_item_index, m_heap_comp); + // must not be empty after removing a single item + assert(!new_node->empty()); // rebalance the nodes node.modify().rebalance(new_node.modify(), m_heap_comp); // append to either of the nodes diff --git a/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp b/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp index a593b16a..ad9a135c 100644 --- a/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp +++ b/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp @@ -65,7 +65,7 @@ DB0_PACKED_BEGIN return itemComp(rhs, lhs); } }; - + // Notice: header stored as variable-length to allow 0-bytes type (default) inline HeaderT &header() { return this->getDynFirst(HeaderT::type()); @@ -78,6 +78,8 @@ DB0_PACKED_BEGIN o_sgb_tree_node(CapacityT capacity) : m_capacity(capacity) { + // FIXME: log + std::cout << "Empty node created @" << this << std::endl; // initialize header with default arguments this->arrangeMembers() (HeaderT::type()); @@ -88,6 +90,8 @@ DB0_PACKED_BEGIN : o_sgb_tree_node(capacity) { this->append(comp, item); + // FIXME: log + std::cout << "Node created size = 1 @" << this << std::endl; } static std::size_t measure(CapacityT capacity) { @@ -98,8 +102,12 @@ DB0_PACKED_BEGIN return capacity; } - inline ItemT &at(unsigned int index) + inline ItemT &at(unsigned int index) { + // FIXME: log + if (index >= m_size) { + std::cout << "!!! empty node accessed: @" << this << std::endl; + } // items stored in the dynamic area assert(index < m_size); return begin()[index]; @@ -107,6 +115,10 @@ DB0_PACKED_BEGIN inline const ItemT &at(unsigned int index) const { + // FIXME: log + if (index >= m_size) { + std::cout << "!!! empty node accessed: @" << this << std::endl; + } // items stored in the dynamic area assert(index < m_size); return cbegin()[index]; @@ -172,6 +184,8 @@ DB0_PACKED_BEGIN } dheap::erase(begin(), end(), item_ptr, comp); --m_size; + // FIXME: log + assert(m_size > 0); return true; } @@ -373,6 +387,9 @@ DB0_PACKED_BEGIN return; } + assert(size() > other.size()); + assert(size() > 0 ); + assert(other.size() > 0); // pick the split point assuming that elements are already approximately sorted (heap sorted) int iter_max = 2; while (iter_max-- > 0 && size() > other.size()) { @@ -382,8 +399,12 @@ DB0_PACKED_BEGIN if (comp.itemComp(*it, split_item)) { ++it; } else { - other.append(comp, *it); - this->erase_existing(it, comp); + if (size() > 1) { + other.append(comp, *it); + this->erase_existing(it, comp); + // must not be empty after removing a single item + assert(!this->empty()); + } --end_; } } From 6d725eb58f7b3a95070ad7ec185856888945722c Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 13 Nov 2025 21:05:07 +0100 Subject: [PATCH 2/3] v_object cast safety + integration + fixes to erase_existing --- dbzero/dbzero/dbzero.py | 2 +- run_tests.sh | 2 - .../SGB_Tree/SGB_CompressedLookupTree.hpp | 1 + .../collections/SGB_Tree/SGB_LookupTree.hpp | 7 +- .../core/collections/SGB_Tree/SGB_Tree.hpp | 26 +- .../collections/SGB_Tree/sgb_tree_node.hpp | 34 +-- .../core/collections/vector/LimitedVector.hpp | 2 +- src/dbzero/core/intrusive/base_traits.hpp | 8 +- .../core/intrusive/detail/tree_algorithms.hpp | 281 +++++++++--------- src/dbzero/core/storage/DiffIndex.cpp | 2 +- src/dbzero/core/storage/DiffIndex.hpp | 11 +- src/dbzero/core/storage/SparseIndexBase.hpp | 4 +- src/dbzero/core/vspace/vtypeless.cpp | 14 +- src/dbzero/core/vspace/vtypeless.hpp | 6 +- src/dbzero/object_model/class/Schema.cpp | 6 +- 15 files changed, 203 insertions(+), 203 deletions(-) diff --git a/dbzero/dbzero/dbzero.py b/dbzero/dbzero/dbzero.py index 21899e3d..c9e4f4dc 100644 --- a/dbzero/dbzero/dbzero.py +++ b/dbzero/dbzero/dbzero.py @@ -10,7 +10,7 @@ def load_dynamic(name, path): def __bootstrap__(): global __bootstrap__, __loader__, __file__ - paths = [os.path.join(os.path.split(__file__)[0]), "/src/dev/build/debug", "/usr/local/lib/python3/dist-packages/dbzero/"] + paths = [os.path.join(os.path.split(__file__)[0]), "/src/dev/build/release", "/usr/local/lib/python3/dist-packages/dbzero/"] __file__ = None for path in paths: if os.path.isdir(path): diff --git a/run_tests.sh b/run_tests.sh index cd9c70e2..894c16b6 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -1,5 +1,3 @@ #!/bin/bash export PYTHONIOENCODING=utf8 -export LD_PRELOAD=$(gcc -print-file-name=libasan.so) - python3 -m pytest -m 'not integration_test' -m 'not stress_test' -c pytest.ini --capture=no "$@" -vv diff --git a/src/dbzero/core/collections/SGB_Tree/SGB_CompressedLookupTree.hpp b/src/dbzero/core/collections/SGB_Tree/SGB_CompressedLookupTree.hpp index 8f487c55..1ac822d8 100644 --- a/src/dbzero/core/collections/SGB_Tree/SGB_CompressedLookupTree.hpp +++ b/src/dbzero/core/collections/SGB_Tree/SGB_CompressedLookupTree.hpp @@ -48,6 +48,7 @@ DB0_PACKED_BEGIN // initialize header by compressing the key item (first item in the node) // need to append with base, otherwise is_sorted_flag would be erased base_t::append(comp, this->header().compressFirst(item)); + assert(this->size() == 1); } static std::size_t measure(const KeyItemT &, CapacityT capacity, const HeapCompT &) { diff --git a/src/dbzero/core/collections/SGB_Tree/SGB_LookupTree.hpp b/src/dbzero/core/collections/SGB_Tree/SGB_LookupTree.hpp index 11734316..23c263da 100644 --- a/src/dbzero/core/collections/SGB_Tree/SGB_LookupTree.hpp +++ b/src/dbzero/core/collections/SGB_Tree/SGB_LookupTree.hpp @@ -272,8 +272,11 @@ DB0_PACKED_BEGIN if (comp.itemComp(*it, split_item)) { it += step_; } else { - other.append(comp, *it); - this->erase_existing(it, comp); + // prevents from leaving an empty node + if (this->size() > 1) { + other.append(comp, *it); + this->erase_existing(it, comp); + } end_ -= step_; } } diff --git a/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp b/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp index 471b3770..84eece70 100644 --- a/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp +++ b/src/dbzero/core/collections/SGB_Tree/SGB_Tree.hpp @@ -146,10 +146,10 @@ namespace db0 // erase the max element and create the new node auto max_item_ptr = node->find_max(m_heap_comp); auto max_item_index = node->indexOf(max_item_ptr); - auto new_node = super_t::insert_equal(*max_item_ptr, m_node_capacity, m_heap_comp); + auto new_node = super_t::insert_equal(*max_item_ptr, m_node_capacity, m_heap_comp); node.modify().erase_existing(max_item_index, m_heap_comp); // must not be empty after removing a single item - assert(!new_node->empty()); + assert(!node->empty()); // rebalance the nodes node.modify().rebalance(new_node.modify(), m_heap_comp); // append to either of the nodes @@ -159,7 +159,7 @@ namespace db0 } return { node.modify().append(m_heap_comp, std::forward(args)...), node }; } - + /** * Remove element from the collection if it exists * @@ -192,11 +192,13 @@ namespace db0 { assert(item.validate()); --(super_t::modify().m_sgb_size); - auto item_index = item.second->indexOf(item.first); - // erase by index since item pointer gets modified (due to CoW) - if (const_cast(item.second).modify().erase_existing(item_index, m_heap_comp)) { - // delete the entire node + if (item.second->size() == 1) { + // deleting the only item in the node, remove the entire node super_t::erase(const_cast(item.second)); + } else { + auto item_index = item.second->indexOf(item.first); + // erase by index since item pointer gets modified (due to CoW) + const_cast(item.second).modify().erase_existing(item_index, m_heap_comp); } #ifndef NDEBUG item.first = nullptr; @@ -364,10 +366,14 @@ namespace db0 { assert(!item.is_end()); --(super_t::modify().m_sgb_size); - auto item_index = item.m_item_it.getIndex(); - if (item.m_item_it.second.modify().erase_existing(item_index, m_heap_comp)) { - // delete the entire node + if (item.m_item_it.second->size() == 1) { + // deleting the only item in the node, remove the entire node super_t::erase(item.m_item_it.second); + item.m_item_it.first = nullptr; + item.m_is_end = true; + } else { + auto item_index = item.m_item_it.getIndex(); + item.m_item_it.second.modify().erase_existing(item_index, m_heap_comp); } } diff --git a/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp b/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp index ad9a135c..c6bc828d 100644 --- a/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp +++ b/src/dbzero/core/collections/SGB_Tree/sgb_tree_node.hpp @@ -75,23 +75,11 @@ DB0_PACKED_BEGIN return this->getDynFirst(HeaderT::type()); } - o_sgb_tree_node(CapacityT capacity) - : m_capacity(capacity) - { - // FIXME: log - std::cout << "Empty node created @" << this << std::endl; - // initialize header with default arguments - this->arrangeMembers() - (HeaderT::type()); - } - /// Must be initialized with an item o_sgb_tree_node(const ItemT &item, CapacityT capacity, const HeapCompT &comp = {}) : o_sgb_tree_node(capacity) { this->append(comp, item); - // FIXME: log - std::cout << "Node created size = 1 @" << this << std::endl; } static std::size_t measure(CapacityT capacity) { @@ -104,10 +92,6 @@ DB0_PACKED_BEGIN inline ItemT &at(unsigned int index) { - // FIXME: log - if (index >= m_size) { - std::cout << "!!! empty node accessed: @" << this << std::endl; - } // items stored in the dynamic area assert(index < m_size); return begin()[index]; @@ -115,10 +99,6 @@ DB0_PACKED_BEGIN inline const ItemT &at(unsigned int index) const { - // FIXME: log - if (index >= m_size) { - std::cout << "!!! empty node accessed: @" << this << std::endl; - } // items stored in the dynamic area assert(index < m_size); return cbegin()[index]; @@ -170,7 +150,7 @@ DB0_PACKED_BEGIN // heapify (as min heap), return pointer to the position of the item return dheap::push(begin(), end(), comp); } - + /** * Erase item by key if it exists * @@ -184,8 +164,6 @@ DB0_PACKED_BEGIN } dheap::erase(begin(), end(), item_ptr, comp); --m_size; - // FIXME: log - assert(m_size > 0); return true; } @@ -421,6 +399,16 @@ DB0_PACKED_BEGIN return sizeof(o_sgb_tree_node) + HeaderT::sizeOf() + item_count * sizeof(ItemT); } + protected: + + o_sgb_tree_node(CapacityT capacity) + : m_capacity(capacity) + { + // initialize header with default arguments + this->arrangeMembers() + (HeaderT::type()); + } + private: /** diff --git a/src/dbzero/core/collections/vector/LimitedVector.hpp b/src/dbzero/core/collections/vector/LimitedVector.hpp index 2d97f211..5e17ff47 100644 --- a/src/dbzero/core/collections/vector/LimitedVector.hpp +++ b/src/dbzero/core/collections/vector/LimitedVector.hpp @@ -179,7 +179,7 @@ namespace db0 { m_root.commit(); for (auto &block: m_cache) { - if (block) { + if (!!block) { block.commit(); } } diff --git a/src/dbzero/core/intrusive/base_traits.hpp b/src/dbzero/core/intrusive/base_traits.hpp index 92e53818..54b652b8 100644 --- a/src/dbzero/core/intrusive/base_traits.hpp +++ b/src/dbzero/core/intrusive/base_traits.hpp @@ -17,7 +17,7 @@ namespace db0 static node_ptr get_parent(const node_ptr &n) { - if (n) { + if (!!n) { // NOTE: Address::fromOffset is in case ptr_set is of a regular numeric type return node_ptr(n.getMemspace().myPtr(Address::fromOffset(n->ptr_set.parent))); } else { @@ -31,7 +31,7 @@ namespace db0 static node_ptr get_left(const node_ptr &n) { - if (n) { + if (!!n) { // NOTE: Address::fromOffset is in case ptr_set is of a regular numeric type return node_ptr(n.getMemspace().myPtr(Address::fromOffset(n->ptr_set.left))); } else { @@ -45,7 +45,7 @@ namespace db0 static node_ptr get_right(const node_ptr &n) { - if (n) { + if (!!n) { // NOTE: Address::fromOffset is in case ptr_set is of a regular numeric type return node_ptr(n.getMemspace().myPtr(Address::fromOffset(n->ptr_set.right))); } else { @@ -61,5 +61,5 @@ namespace db0 n->checkIntegrity(n.getMemspace()); } }; - + } \ No newline at end of file diff --git a/src/dbzero/core/intrusive/detail/tree_algorithms.hpp b/src/dbzero/core/intrusive/detail/tree_algorithms.hpp index be199292..45618f7e 100755 --- a/src/dbzero/core/intrusive/detail/tree_algorithms.hpp +++ b/src/dbzero/core/intrusive/detail/tree_algorithms.hpp @@ -422,13 +422,12 @@ class tree_algorithms static node_ptr next_node(const node_ptr &p) { node_ptr p_right(NodeTraits::get_right(p)); - if(p_right){ + if (!!p_right){ return minimum(p_right); - } - else { - node_ptr p_temp = p; + } else { + node_ptr p_temp = p; node_ptr x = NodeTraits::get_parent(p_temp); - while(p_temp == NodeTraits::get_right(x)){ + while (!!(p_temp == NodeTraits::get_right(x))) { p_temp = x; x = NodeTraits::get_parent(x); } @@ -446,29 +445,26 @@ class tree_algorithms static node_ptr prev_node(const node_ptr &p) { if (is_header(p)) { - if (NodeTraits::get_parent(p)) { - return maximum(NodeTraits::get_parent(p)); - } - else { - return p; - } - } - else { - if (NodeTraits::get_left(p)) { - return maximum(NodeTraits::get_left(p)); - } - else { - node_ptr p_temp = p; - node_ptr x = NodeTraits::get_parent(p_temp); - while (p_temp==NodeTraits::get_left(x)) { - p_temp = x; - x = NodeTraits::get_parent(x); - } - return x; - } + if (!!NodeTraits::get_parent(p)) { + return maximum(NodeTraits::get_parent(p)); + } else { + return p; + } + } else { + if (!!NodeTraits::get_left(p)) { + return maximum(NodeTraits::get_left(p)); + } else { + node_ptr p_temp = p; + node_ptr x = NodeTraits::get_parent(p_temp); + while (!!(p_temp == NodeTraits::get_left(x))) { + p_temp = x; + x = NodeTraits::get_parent(x); + } + return x; + } } } - + //! Requires: p is a node of a tree but not the header. //! //! Effects: Returns the minimum node of the subtree starting at p. @@ -476,9 +472,10 @@ class tree_algorithms //! Complexity: Logarithmic to the size of the subtree. //! //! Throws: Nothing. - static node_ptr minimum (node_ptr p) { - for(node_ptr p_left = NodeTraits::get_left(p) - ;p_left + static node_ptr minimum(node_ptr p) + { + for (node_ptr p_left = NodeTraits::get_left(p) + ;!!p_left ;p_left = NodeTraits::get_left(p)){ p = p_left; } @@ -492,11 +489,12 @@ class tree_algorithms //! Complexity: Logarithmic to the size of the subtree. //! //! Throws: Nothing. - static node_ptr maximum (node_ptr p) { + static node_ptr maximum (node_ptr p) + { node_ptr p_right = NodeTraits::get_right(p); - while (p_right) { - p = p_right; - p_right = NodeTraits::get_right(p); + while (!!p_right) { + p = p_right; + p_right = NodeTraits::get_right(p); } return p; } @@ -510,7 +508,8 @@ class tree_algorithms //! Throws: Nothing. //! //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init(node_ptr &node) { + static void init(node_ptr &node) + { NodeTraits::set_parent(node, 0); NodeTraits::set_left(node, 0); NodeTraits::set_right(node, 0); @@ -526,7 +525,8 @@ class tree_algorithms //! Throws: Nothing. //! //! Nodes: If node is inserted in a tree, this function corrupts the tree. - static void init_header(node_ptr &header) { + static void init_header(node_ptr &header) + { NodeTraits::set_parent(header, 0); NodeTraits::set_left(header, header); NodeTraits::set_right(header, header); @@ -544,9 +544,10 @@ class tree_algorithms //! //! Throws: If cloner functor throws. If this happens target nodes are disposed. template - static void clear_and_dispose(const node_ptr &header, Disposer disposer) { + static void clear_and_dispose(const node_ptr &header, Disposer disposer) + { node_ptr source_root = NodeTraits::get_parent(header); - if(!source_root) + if (!source_root) return; dispose_subtree(source_root, disposer); init_header(header); @@ -604,20 +605,21 @@ class tree_algorithms //! Throws: Nothing. static std::size_t count(const node_ptr &subtree) { - if(!subtree) return 0; + if (!subtree) + return 0; + std::size_t count = 0; node_ptr p = minimum(subtree); bool continue_looping = true; - while(continue_looping){ + while (continue_looping) { ++count; node_ptr p_right(NodeTraits::get_right(p)); - if(p_right){ + if (!!p_right) { p = minimum(p_right); - } - else { - for(;;){ + } else { + for (;;) { node_ptr q; - if (p == subtree){ + if (p == subtree) { continue_looping = false; break; } @@ -658,7 +660,7 @@ class tree_algorithms //! Throws: Nothing. static void swap_tree(node_ptr header1, node_ptr header2) { - if(header1 == header2) + if (header1 == header2) return; node_ptr tmp; @@ -696,18 +698,19 @@ class tree_algorithms } } - static bool is_header(const node_ptr &p) { + static bool is_header(const node_ptr &p) + { bool result = false; - node_ptr p_parent = NodeTraits::get_parent(p); - if(!p_parent || p_parent==p){ + node_ptr p_parent = NodeTraits::get_parent(p); + if (!p_parent || p_parent==p) { result = true; } - else if(NodeTraits::get_parent(p_parent) == p){ - if(NodeTraits::get_left(p) != 0){ - if(NodeTraits::get_parent(NodeTraits::get_left(p)) != p){ + else if (NodeTraits::get_parent(p_parent) == p) { + if (!!NodeTraits::get_left(p)) { + if (NodeTraits::get_parent(NodeTraits::get_left(p)) != p) { result = true; } - if(p_parent == NodeTraits::get_left(p)){ + if (p_parent == NodeTraits::get_left(p)) { result = true; } } @@ -829,23 +832,23 @@ class tree_algorithms node_ptr y = header; // start with root node node_ptr x = NodeTraits::get_parent(header); - while (x) { + while (!!x) { if (comp(key, x)) { // potential result y = x; x = NodeTraits::get_left(x); } else { - if (comp(x, key)) { - x = NodeTraits::get_right(x); - } else { - y = NodeTraits::get_right(x); - // continue with equal values - if (!y || comp(y, key) || comp(key, y)) { - return x; - } - x = y; - } + if (comp(x, key)) { + x = NodeTraits::get_right(x); + } else { + y = NodeTraits::get_right(x); + // continue with equal values + if (!y || comp(y, key) || comp(key, y)) { + return x; + } + x = y; + } } } return y; @@ -869,7 +872,7 @@ class tree_algorithms { node_ptr y = header; node_ptr x = NodeTraits::get_parent(header); - while (x) { + while (!!x) { if (comp(x, key)) { x = NodeTraits::get_right(x); } else { @@ -897,15 +900,16 @@ class tree_algorithms divide(NodeTraits::get_parent(header), N, result); return result; } - + // @return last lower or equal node template static node_ptr lower_equal_bound (const node_ptr &header, const KeyType &key, KeyNodePtrCompare comp) { + assert(!!header); node_ptr y = header; node_ptr x = NodeTraits::get_parent(header); - while (x) { + while (!!x) { if (comp(x, key)) { y = x; x = NodeTraits::get_right(x); @@ -937,7 +941,7 @@ class tree_algorithms { assert (it.empty()); node_ptr x = NodeTraits::get_parent(header); - if (x) { + if (!!x) { it.push_back(x); x = NodeTraits::get_left(header); while (comp(key, x)) { @@ -961,7 +965,7 @@ class tree_algorithms x = *it; } } - while (x) { + while (!!x) { if (comp(x, key)) { x = NodeTraits::get_right(x); } @@ -984,19 +988,20 @@ class tree_algorithms { assert (it.empty()); node_ptr x = NodeTraits::get_parent(header); - if (x) { + if (!!x) { it.push_back(x); x = NodeTraits::get_right(header); - if (x && comp(x,key)) { + if (!!x && comp(x,key)) { it.push_back(x); } } } - static void beginJoinBackward (const node_ptr &header,join_stack &it) { + static void beginJoinBackward (const node_ptr &header,join_stack &it) + { assert (it.empty()); node_ptr x = NodeTraits::get_parent(header); - while (x) { + while (!!x) { it.push_back(x); x = NodeTraits::get_right(x); } @@ -1016,7 +1021,7 @@ class tree_algorithms x = *it; } } - while (x) { + while (!!x) { if (comp(key,x)) { x = NodeTraits::get_left(x); } @@ -1045,7 +1050,7 @@ class tree_algorithms x = *it; } } - while (x) { + while (!!x) { if (comp(key,x)) { it.push_back(x); x = NodeTraits::get_left(x); @@ -1085,7 +1090,7 @@ class tree_algorithms (node_ptr &header, node_ptr &new_value, insert_commit_data &commit_data) { //Check if commit_data has not been initialized by a insert_unique_check call. - assert(commit_data.node != 0); + assert(!!commit_data.node); link(header, new_value, commit_data.node, commit_data.link_left); } @@ -1137,26 +1142,26 @@ class tree_algorithms //Find the upper bound, cache the previous value and if we should //store it in the left or right node bool left_child = true; - while(x){ + while (!!x) { ++depth; y = x; x = (left_child = comp(key, x)) ? NodeTraits::get_left(x) : (prev = y, NodeTraits::get_right(x)); } - if(pdepth) *pdepth = depth; + if (pdepth) *pdepth = depth; //Since we've found the upper bound there is no other value with the same key if: // - There is no previous node // - The previous node is less than the key - if(!prev || comp(prev, key)){ + if (!prev || comp(prev, key)) { commit_data.link_left = left_child; commit_data.node = y; return std::pair(node_ptr(), true); } //If the previous value was not less than key, it means that it's equal //(because we've checked the upper bound) - else{ + else { return std::pair(prev, false); } } @@ -1166,24 +1171,24 @@ class tree_algorithms (const node_ptr &header, const node_ptr &hint, const KeyType &key ,KeyNodePtrCompare comp, insert_commit_data &commit_data, std::size_t *pdepth = 0) { - //hint must be bigger than the key - if(hint == header || comp(key, hint)){ + // hint must be bigger than the key + if(hint == header || comp(key, hint)) { node_ptr prev = hint; //The previous value should be less than the key - if(prev == NodeTraits::get_left(header) || comp((prev = prev_node(hint)), key)){ + if (prev == NodeTraits::get_left(header) || comp((prev = prev_node(hint)), key)) { commit_data.link_left = unique(header) || !NodeTraits::get_left(hint); commit_data.node = commit_data.link_left ? hint : prev; - if(pdepth){ + if (pdepth) { *pdepth = commit_data.node == header ? 0 : depth(commit_data.node) + 1; } return std::pair(node_ptr(), true); } - else{ + else { return insert_unique_check(header, key, comp, commit_data, pdepth); } } //The hint was wrong, use hintless insert - else{ + else { return insert_unique_check(header, key, comp, commit_data, pdepth); } } @@ -1206,24 +1211,24 @@ class tree_algorithms static node_ptr insert_equal (node_ptr &header, node_ptr &hint, node_ptr &new_node, NodePtrCompare comp, std::size_t *pdepth = 0) { - if(hint == header || !comp(hint, new_node)){ + if (hint == header || !comp(hint, new_node)) { node_ptr prev(hint); - if(hint == NodeTraits::get_left(header) || - !comp(new_node, (prev = prev_node(hint)))){ + if (hint == NodeTraits::get_left(header) || + !comp(new_node, (prev = prev_node(hint)))) { bool link_left = unique(header) || !NodeTraits::get_left(hint); link(header, new_node, link_left ? hint : prev, link_left); - if(pdepth) *pdepth = depth(new_node) + 1; + if (pdepth) *pdepth = depth(new_node) + 1; return new_node; } - else{ + else { return insert_equal_upper_bound(header, new_node, comp, pdepth); } } - else{ + else { return insert_equal_lower_bound(header, new_node, comp, pdepth); } } - + //! Requires: p can't be a header node. //! //! Effects: Calculates the depth of a node: the depth of a @@ -1249,19 +1254,19 @@ class tree_algorithms static void link_equal_upper_bound (node_ptr &h, const KeyType &key, KeyNodePtrCompare comp, link_data &ld, std::size_t *pdepth = 0) { - std::size_t depth = 0; - ld.y = h; + std::size_t depth = 0; + ld.y = h; node_ptr x(NodeTraits::get_parent(ld.y)); - while(x){ + while(!!x) { ++depth; ld.y = x; x = comp(key, x) ? NodeTraits::get_left(x) : NodeTraits::get_right(x); } - + ld.link_left = (ld.y == h) || comp(key, ld.y); - if(pdepth) *pdepth = depth; + if( pdepth) *pdepth = depth; } template @@ -1272,7 +1277,7 @@ class tree_algorithms node_ptr y(h); node_ptr x(NodeTraits::get_parent(y)); - while(x){ + while (!!x) { ++depth; y = x; x = comp(new_node, x) ? @@ -1281,7 +1286,7 @@ class tree_algorithms bool link_left = (y == h) || comp(new_node, y); link(h, new_node, y, link_left); - if(pdepth) *pdepth = depth; + if( pdepth) *pdepth = depth; return new_node; } @@ -1293,7 +1298,7 @@ class tree_algorithms node_ptr y(h); node_ptr x(NodeTraits::get_parent(y)); - while(x){ + while(!!x) { ++depth; y = x; x = !comp(x, new_node) ? @@ -1314,7 +1319,7 @@ class tree_algorithms ld.y = h; node_ptr x(NodeTraits::get_parent(ld.y)); - while(x){ + while (!!x) { ++depth; ld.y = x; x = !comp(x, key) ? @@ -1322,7 +1327,7 @@ class tree_algorithms } ld.link_left = (ld.y == h) || !comp(ld.y, key); - if(pdepth) *pdepth = depth; + if( pdepth) *pdepth = depth; } //! Requires: "cloner" must be a function @@ -1346,7 +1351,7 @@ class tree_algorithms static void clone (const node_ptr &source_header, node_ptr &target_header, Cloner cloner, Disposer disposer) { - if(!unique(target_header)){ + if (!unique(target_header)) { clear_and_dispose(target_header, disposer); } @@ -1354,7 +1359,7 @@ class tree_algorithms node_ptr new_root = clone_subtree (source_header, target_header, cloner, disposer, leftmost, rightmost); - //Now update header node + // Now update header node NodeTraits::set_parent(target_header, new_root); NodeTraits::set_left (target_header, leftmost); NodeTraits::set_right (target_header, rightmost); @@ -1369,10 +1374,10 @@ class tree_algorithms { node_ptr target_sub_root = target_parent; node_ptr source_root = NodeTraits::get_parent(source_parent); - if(!source_root){ + if (!source_root) { leftmost_out = rightmost_out = source_root; } - else{ + else { //We'll calculate leftmost and rightmost nodes while iterating node_ptr current = source_root; node_ptr insertion_point = target_sub_root = cloner(current); @@ -1639,7 +1644,7 @@ class tree_algorithms //information to restore the original relationship after //the algorithm is applied. node_ptr super_root = NodeTraits::get_parent(old_root); - assert(super_root); + assert(!!super_root); //Get info node_ptr super_root_right_backup = NodeTraits::get_right(super_root); @@ -1650,9 +1655,9 @@ class tree_algorithms node_ptr new_root(x); node_ptr save; bool moved_to_right = false; - for( ; x; x = save){ + for ( ; !!x; x = save) { save = NodeTraits::get_left(x); - if(save){ + if (!!save) { // Right rotation node_ptr save_right = NodeTraits::get_right(save); node_ptr x_parent = NodeTraits::get_parent(x); @@ -1661,19 +1666,18 @@ class tree_algorithms NodeTraits::set_parent(x, save); NodeTraits::set_right (save, x); NodeTraits::set_left(x, save_right); - if(save_right) + if (!!save_right) NodeTraits::set_parent(save_right, x); - if(!moved_to_right) + if (!moved_to_right) new_root = save; - } - else{ + } else { moved_to_right = true; save = NodeTraits::get_right(x); ++len; } } - if(super_root_is_header){ + if (super_root_is_header) { NodeTraits::set_right(super_root, super_root_right_backup); NodeTraits::set_parent(super_root, new_root); } @@ -1684,10 +1688,10 @@ class tree_algorithms NodeTraits::set_right(super_root, super_root_right_backup); NodeTraits::set_left(super_root, new_root); } - if(plen) *plen = len; + if (plen) *plen = len; return new_root; } - + static node_ptr vine_to_subtree(const node_ptr &old_root, std::size_t count) { std::size_t leaf_nodes = count + 1 - ((size_t) 1 << floor_log2 (count + 1)); @@ -1703,7 +1707,7 @@ class tree_algorithms static node_ptr compress_subtree(const node_ptr &old_root, std::size_t count) { - if(!old_root) return old_root; + if (!old_root) return old_root; //To avoid irregularities in the algorithm (old_root can be //left or right child or even the root of the tree) just put the @@ -1711,7 +1715,7 @@ class tree_algorithms //information to restore the original relationship after //the algorithm is applied. node_ptr super_root = NodeTraits::get_parent(old_root); - assert(super_root); + assert(!!super_root); //Get info node_ptr super_root_right_backup = NodeTraits::get_right(super_root); @@ -1725,16 +1729,16 @@ class tree_algorithms node_ptr even_parent = super_root; node_ptr new_root = old_root; - while(count--){ + while (count--) { node_ptr even = NodeTraits::get_right(even_parent); node_ptr odd = NodeTraits::get_right(even); - if(new_root == old_root) + if (new_root == old_root) new_root = odd; node_ptr even_right = NodeTraits::get_left(odd); NodeTraits::set_right(even, even_right); - if (even_right) + if (!!even_right) NodeTraits::set_parent(even_right, even); NodeTraits::set_right(even_parent, odd); @@ -1760,8 +1764,9 @@ class tree_algorithms private: - static uint64_t get_height(const node_ptr &root, uint64_t current) { - if(root) { + static uint64_t get_height(const node_ptr &root, uint64_t current) + { + if (!!root) { return std::max( get_height(NodeTraits::get_left(root), current + 1), get_height(NodeTraits::get_right(root), current +1)); @@ -1772,22 +1777,23 @@ class tree_algorithms /** * @return number of chunks created */ - static int divide(const node_ptr &root, int N, std::vector &result) { + static int divide(const node_ptr &root, int N, std::vector &result) + { int count = 0; - if(root) { + if (!!root) { std::vector right_result; - if(N > 1) { + if (N > 1) { int left_count = divide(NodeTraits::get_left(root), N / 2, result); count += left_count; count += divide(NodeTraits::get_right(root), N - left_count, right_result); } // if less than requested also register root element - if(count < N) { + if (count < N) { result.emplace_back(root); ++count; } // this push is postponed to guarantee proper ascending order - for(const node_ptr &ptr: right_result) { + for (const node_ptr &ptr: right_result) { result.emplace_back(ptr); } } @@ -1801,26 +1807,25 @@ class tree_algorithms node_ptr x_parent(NodeTraits::get_null()); node_ptr z_left(NodeTraits::get_left(z)); node_ptr z_right(NodeTraits::get_right(z)); - if(!z_left){ + if (!z_left) { x = z_right; // x might be null. } - else if(!z_right){ // z has exactly one non-null child. y == z. + else if (!z_right) { // z has exactly one non-null child. y == z. x = z_left; // x is not null. - } - else{ + } else { // find z's successor y = tree_algorithms::minimum (z_right); x = NodeTraits::get_right(y); // x might be null. } - if(y != z){ + if (y != z) { // relink y in place of z. y is z's successor - node_ptr zLeft = NodeTraits::get_left(z); + node_ptr zLeft = NodeTraits::get_left(z); NodeTraits::set_parent(zLeft, y); NodeTraits::set_left(y, NodeTraits::get_left(z)); if(y != NodeTraits::get_right(z)){ x_parent = NodeTraits::get_parent(y); - if(x) + if(!!x) NodeTraits::set_parent(x, x_parent); NodeTraits::set_left(x_parent, x); // y must be a child of left_ NodeTraits::set_right(y, NodeTraits::get_right(z)); @@ -1834,16 +1839,16 @@ class tree_algorithms } else { // y == z --> z has only one child, or none x_parent = NodeTraits::get_parent(z); - if(x) + if(!!x) NodeTraits::set_parent(x, x_parent); tree_algorithms::replace_own (z, x, header); if(NodeTraits::get_left(header) == z){ - NodeTraits::set_left(header, NodeTraits::get_right(z) == 0 ? // z->get_left() must be null also + NodeTraits::set_left(header, !NodeTraits::get_right(z) ? // z->get_left() must be null also NodeTraits::get_parent(z) : // makes leftmost == header if z == root tree_algorithms::minimum (x)); } if(NodeTraits::get_right(header) == z){ - NodeTraits::set_right(header, NodeTraits::get_left(z) == 0 ? // z->get_right() must be null also + NodeTraits::set_right(header, !NodeTraits::get_left(z) ? // z->get_right() must be null also NodeTraits::get_parent(z) : // makes rightmost == header if z == root tree_algorithms::maximum(x)); } diff --git a/src/dbzero/core/storage/DiffIndex.cpp b/src/dbzero/core/storage/DiffIndex.cpp index f7de2ad2..2b10dc1d 100644 --- a/src/dbzero/core/storage/DiffIndex.cpp +++ b/src/dbzero/core/storage/DiffIndex.cpp @@ -115,7 +115,7 @@ namespace db0 auto base_storage_page_num = SI_CompressedItem::getStoragePageNum(); // state & storage page numbers should be non-decreasing values assert(state_num >= base_state_num); - assert(storage_page_num > base_storage_page_num); + assert(storage_page_num >= base_storage_page_num); if (!DiffArrayT::__const_ref(m_diff_data.data()). canEmplaceBack(state_num - base_state_num, storage_page_num - base_storage_page_num)) { diff --git a/src/dbzero/core/storage/DiffIndex.hpp b/src/dbzero/core/storage/DiffIndex.hpp index f87395c2..9c3563c2 100644 --- a/src/dbzero/core/storage/DiffIndex.hpp +++ b/src/dbzero/core/storage/DiffIndex.hpp @@ -11,13 +11,14 @@ namespace db0 { -DB0_PACKED_BEGIN + // DiffIndex is a specialization of SparseIndexBase for storing // references do diff-pages // Each element consists of: page num (logical) / state num + physical page num + sequence of encoded: page num / state num // One element can encode variable number of state updates (transactions) +DB0_PACKED_BEGIN struct DB0_PACKED_ATTR DI_Item: public SI_Item { using CompT = SI_ItemCompT; @@ -81,7 +82,9 @@ DB0_PACKED_BEGIN // @return the smallest state number such that state >= state_num std::uint32_t findUpper(std::uint32_t state_num) const; }; - +DB0_PACKED_END + +DB0_PACKED_BEGIN struct DB0_PACKED_ATTR DI_CompressedItem: public SI_CompressedItem { using CompT = SI_CompressedItemCompT; @@ -106,7 +109,8 @@ DB0_PACKED_BEGIN // append relative values void append(std::uint32_t state_num, std::uint64_t storage_page_num); }; - +DB0_PACKED_END + class DiffIndex: protected SparseIndexBase { public: @@ -143,5 +147,4 @@ DB0_PACKED_BEGIN void refresh(); }; -DB0_PACKED_END } diff --git a/src/dbzero/core/storage/SparseIndexBase.hpp b/src/dbzero/core/storage/SparseIndexBase.hpp index 440b6106..b549588c 100644 --- a/src/dbzero/core/storage/SparseIndexBase.hpp +++ b/src/dbzero/core/storage/SparseIndexBase.hpp @@ -12,7 +12,6 @@ namespace db0 { -DB0_PACKED_BEGIN class DRAM_Prefix; class DRAM_Allocator; @@ -125,6 +124,7 @@ DB0_PACKED_BEGIN std::string toString(const CompressedItemT &) const; }; +DB0_PACKED_BEGIN // tree-level header type struct DB0_PACKED_ATTR o_sparse_index_header: o_fixed_versioned { @@ -135,6 +135,7 @@ DB0_PACKED_BEGIN // reserved space for future use std::array m_reserved = {0, 0, 0, 0}; }; +DB0_PACKED_END // DRAM space deployed sparse index (in-memory) using IndexT = SGB_CompressedLookupTree< @@ -407,5 +408,4 @@ DB0_PACKED_BEGIN m_index.commit(); } -DB0_PACKED_END } diff --git a/src/dbzero/core/vspace/vtypeless.cpp b/src/dbzero/core/vspace/vtypeless.cpp index 9c7f390e..80a7e429 100644 --- a/src/dbzero/core/vspace/vtypeless.cpp +++ b/src/dbzero/core/vspace/vtypeless.cpp @@ -13,18 +13,14 @@ namespace db0 assert(!(m_resource_flags.load() & RESOURCE_LOCK)); } - vtypeless::vtypeless(const vtypeless &other) - : m_memspace_ptr(other.m_memspace_ptr) - { + vtypeless::vtypeless(const vtypeless &other) { *this = other; } - vtypeless::vtypeless(vtypeless &&other) - : m_memspace_ptr(other.m_memspace_ptr) - { + vtypeless::vtypeless(vtypeless &&other) { *this = std::move(other); } - + vtypeless::vtypeless(Memspace &memspace, Address address, MemLock &&mem_lock, std::uint16_t resource_flags, FlagSet access_mode) : m_address(address) @@ -83,6 +79,10 @@ namespace db0 break; } } + + // invalidate the other instance + other.m_address = {}; + other.m_memspace_ptr = nullptr; } unsigned int vtypeless::use_count() const { diff --git a/src/dbzero/core/vspace/vtypeless.hpp b/src/dbzero/core/vspace/vtypeless.hpp index 1d1e5409..7de46e77 100644 --- a/src/dbzero/core/vspace/vtypeless.hpp +++ b/src/dbzero/core/vspace/vtypeless.hpp @@ -100,11 +100,7 @@ namespace db0 inline bool isNull() const { return !m_address.isValid(); } - - inline operator bool() const { - return m_address.isValid(); - } - + bool operator!() const { return !m_address.isValid(); } diff --git a/src/dbzero/object_model/class/Schema.cpp b/src/dbzero/object_model/class/Schema.cpp index 3590083c..4ad49274 100644 --- a/src/dbzero/object_model/class/Schema.cpp +++ b/src/dbzero/object_model/class/Schema.cpp @@ -144,11 +144,11 @@ namespace db0::object_model } if (!extra_items.empty()) { - assert(type_vector); + assert(!!type_vector); // register the extra items type_vector.bulkInsertUnique(extra_items.begin(), extra_items.end(), nullptr); // type vector's address might've been changed - if (type_vector && m_type_vector_ptr.getAddress() != type_vector.getAddress()) { + if (!!type_vector && m_type_vector_ptr.getAddress() != type_vector.getAddress()) { m_type_vector_ptr = db0::db0_ptr(type_vector); } } @@ -190,7 +190,7 @@ namespace db0::object_model } initTypeVector(memspace, type_vector); - assert(type_vector); + assert(!!type_vector); o_type_item max_item, second_max_item; for (auto &type_item : type_vector) { From 7d625c1366ea40374e6863d7bbbec60df611c76e Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 13 Nov 2025 21:10:32 +0100 Subject: [PATCH 3/3] sync --- run_asan_tests.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 run_asan_tests.sh diff --git a/run_asan_tests.sh b/run_asan_tests.sh new file mode 100755 index 00000000..cd9c70e2 --- /dev/null +++ b/run_asan_tests.sh @@ -0,0 +1,5 @@ +#!/bin/bash +export PYTHONIOENCODING=utf8 +export LD_PRELOAD=$(gcc -print-file-name=libasan.so) + +python3 -m pytest -m 'not integration_test' -m 'not stress_test' -c pytest.ini --capture=no "$@" -vv