From a845522db76f73364ea8d7a7217c68e6c40aa5ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?= =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= Date: Sun, 15 Dec 2024 22:17:12 +0300 Subject: [PATCH] =?UTF-8?q?mdbx:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=80=D0=B5=D0=B3=D1=80=D0=B5?= =?UTF-8?q?=D1=81=D1=81=D0=B0=20=D1=81=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20dupsort-=D0=BA=D1=83=D1=80=D1=81=D0=BE=D1=80?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20`cursor=5Fput(APPEND)?= =?UTF-8?q?`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit При добавлении нового ключа в append-режиме, в случае когда в текущей (последней) позиции с ключом связаны несколько значений и (соответственно) вложенный dupsort-курсор инициализирован, вставка происходила без сброса вложенного курсора. В результате вложенный курсор логически оставался стоять на multivalue-данных связанных с предыдущей позицией основного курсора, т.е. переходил в неконсистентное состояние. Ошибка проявлялась возвратом неверных значений из mdbx_cursor_count() или срабатывание assert-проверки в отладочных сборках. --- src/cursor.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/cursor.c b/src/cursor.c index a4bffd76..5ec88a77 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -898,13 +898,16 @@ __hot int cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data, unsig if (insert_key) { /* The key does not exist */ DEBUG("inserting key at index %i", mc->ki[mc->top]); - if ((mc->tree->flags & MDBX_DUPSORT) && node_size(key, data) > env->leaf_nodemax) { - /* Too big for a node, insert in sub-DB. Set up an empty - * "old sub-page" for convert_to_subtree to expand to a full page. */ - fp->dupfix_ksize = (mc->tree->flags & MDBX_DUPFIXED) ? (uint16_t)data->iov_len : 0; - fp->lower = fp->upper = 0; - old_data.iov_len = PAGEHDRSZ; - goto convert_to_subtree; + if (mc->tree->flags & MDBX_DUPSORT) { + inner_gone(mc); + if (node_size(key, data) > env->leaf_nodemax) { + /* Too big for a node, insert in sub-DB. Set up an empty + * "old sub-page" for convert_to_subtree to expand to a full page. */ + fp->dupfix_ksize = (mc->tree->flags & MDBX_DUPFIXED) ? (uint16_t)data->iov_len : 0; + fp->lower = fp->upper = 0; + old_data.iov_len = PAGEHDRSZ; + goto convert_to_subtree; + } } } else { /* there's only a key anyway, so this is a no-op */