diff --git a/src/dbzero/bindings/python/PyToolkit.cpp b/src/dbzero/bindings/python/PyToolkit.cpp index d40fddc1..373a3912 100644 --- a/src/dbzero/bindings/python/PyToolkit.cpp +++ b/src/dbzero/bindings/python/PyToolkit.cpp @@ -292,15 +292,25 @@ namespace db0::python return object_ptr; } - auto index_object = Py_OWN(IndexDefaultObject_new()); + auto py_index = Py_OWN(IndexDefaultObject_new()); // retrieve actual dbzero instance - index_object->unload(fixture, address, access_mode); + py_index->unload(fixture, address, access_mode); // add list object to cache - if (!index_object->ext().isNoCache()) { - lang_cache.add(address, index_object.get()); - } - return shared_py_cast(std::move(index_object)); + // NOTE: in case of Index (which requires a flush on update) we need to cache instance + // even if accessed as no-cache to prevent premature deletion + lang_cache.add(address, py_index.get()); + + auto py_index_ptr = py_index.get(); + py_index->ext().setDirtyCallback([py_index_ptr](bool incRef) { + if (incRef) { + Py_INCREF(py_index_ptr); + } else { + Py_DECREF(py_index_ptr); + } + }); + + return shared_py_cast(std::move(py_index)); } PyToolkit::ObjectSharedPtr PyToolkit::unloadSet(db0::swine_ptr fixture, diff --git a/src/dbzero/object_model/index/Index.cpp b/src/dbzero/object_model/index/Index.cpp index 7c4a3c4f..2dd16bbd 100644 --- a/src/dbzero/object_model/index/Index.cpp +++ b/src/dbzero/object_model/index/Index.cpp @@ -553,18 +553,6 @@ namespace db0::object_model super_t::moveTo(fixture); } - void Index::operator=(Index &&other) - { - other._flush(); - super_t::operator=(std::move(other)); - m_index = std::move(other.m_index); - m_mutation_log = std::move(other.m_mutation_log); - other.m_index = nullptr; - assert(!other.hasInstance()); - // if m_index exists then also must have a range tree - assert(!m_index || hasRangeTree()); - } - void Index::commit() const { // if m_index exists then also must have a range tree diff --git a/src/dbzero/object_model/index/Index.hpp b/src/dbzero/object_model/index/Index.hpp index b6aa8c64..5fbc09e8 100644 --- a/src/dbzero/object_model/index/Index.hpp +++ b/src/dbzero/object_model/index/Index.hpp @@ -83,7 +83,7 @@ namespace db0::object_model // Callback invoked when the index is marked dirty (or clean) // for proper lifecycle management (incRef prevents premature deletion e.g. from LangCache) // @param incRef true to increase ref count, false to decrease - void setDirtyCallback(std::function &&callback) { + void setDirtyCallback(std::function &&callback) const { m_dirty_callback = std::move(callback); } @@ -93,7 +93,7 @@ namespace db0::object_model friend struct Builder; void flush(bool revert); static void flushOp(void *, bool revert); - std::function m_dirty_callback; + mutable std::function m_dirty_callback; // Set or reset dirty state void setDirty(bool dirty); @@ -186,10 +186,9 @@ namespace db0::object_model private: // actual index instance (must be cast to a specific type) mutable std::shared_ptr m_index; - - Index(tag_no_gc, db0::swine_ptr &, const Index &); - void operator=(Index &&); + // Constructor required by moveTo (auto-hardening) + Index(tag_no_gc, db0::swine_ptr &, const Index &); bool hasRangeTree() const { return (*this)->m_index_addr.isValid();