12
12
* <http://www.OpenLDAP.org/license.html>. */
13
13
14
14
#define xMDBX_ALLOY 1
15
- #define MDBX_BUILD_SOURCERY c5b9a3e9ba7c98987e7554f0c84c1e12e9f82d0d470ad881d54923ecf3599c17_v0_11_2_15_gca197965
15
+ #define MDBX_BUILD_SOURCERY eceee647cf2c0dcedb1c09cb1f7c82a14d9efc74380e3954b5a3f158d5b8c29b_v0_11_2_22_gc70d2d62
16
16
#ifdef MDBX_CONFIG_H
17
17
#include MDBX_CONFIG_H
18
18
#endif
@@ -7091,7 +7091,8 @@ static void mdbx_node_del(MDBX_cursor *mc, size_t ksize);
7091
7091
static void mdbx_node_shrink(MDBX_page *mp, unsigned indx);
7092
7092
static int __must_check_result mdbx_node_move(MDBX_cursor *csrc,
7093
7093
MDBX_cursor *cdst, bool fromleft);
7094
- static int __must_check_result mdbx_node_read(MDBX_cursor *mc, MDBX_node *leaf,
7094
+ static int __must_check_result mdbx_node_read(MDBX_cursor *mc,
7095
+ const MDBX_node *leaf,
7095
7096
MDBX_val *data,
7096
7097
const txnid_t front);
7097
7098
static int __must_check_result mdbx_rebalance(MDBX_cursor *mc);
@@ -10350,7 +10351,7 @@ __cold static int mdbx_env_sync_internal(MDBX_env *env, bool force,
10350
10351
int rc = MDBX_RESULT_TRUE /* means "nothing to sync" */;
10351
10352
10352
10353
retry:;
10353
- unsigned flags = env->me_flags & ~MDBX_NOMETASYNC;
10354
+ unsigned flags = env->me_flags & ~( MDBX_NOMETASYNC | MDBX_SHRINK_ALLOWED) ;
10354
10355
if (unlikely((flags & (MDBX_RDONLY | MDBX_FATAL_ERROR | MDBX_ENV_ACTIVE)) !=
10355
10356
MDBX_ENV_ACTIVE)) {
10356
10357
rc = MDBX_EACCESS;
@@ -10434,17 +10435,19 @@ retry:;
10434
10435
mdbx_assert(env, head_txnid == meta_txnid(env, head, false));
10435
10436
mdbx_assert(env, head_txnid == mdbx_recent_committed_txnid(env));
10436
10437
mdbx_find_oldest(env->me_txn0);
10438
+ flags |= MDBX_SHRINK_ALLOWED;
10437
10439
}
10438
10440
10439
10441
mdbx_assert(env, inside_txn || locked);
10442
+ mdbx_assert(env, !inside_txn || (flags & MDBX_SHRINK_ALLOWED) == 0);
10440
10443
10441
10444
if (!META_IS_STEADY(head) ||
10442
10445
((flags & MDBX_SAFE_NOSYNC) == 0 && unsynced_pages)) {
10443
10446
mdbx_debug("meta-head %" PRIaPGNO ", %s, sync_pending %" PRIaPGNO,
10444
10447
data_page(head)->mp_pgno, mdbx_durable_str(head),
10445
10448
unsynced_pages);
10446
10449
MDBX_meta meta = *head;
10447
- rc = mdbx_sync_locked(env, flags | MDBX_SHRINK_ALLOWED , &meta);
10450
+ rc = mdbx_sync_locked(env, flags, &meta);
10448
10451
if (unlikely(rc != MDBX_SUCCESS))
10449
10452
goto bailout;
10450
10453
}
@@ -14092,6 +14095,10 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags,
14092
14095
unaligned_peek_u64(4, pending->mm_txnid_a))) {
14093
14096
const txnid_t txnid =
14094
14097
safe64_txnid_next(unaligned_peek_u64(4, pending->mm_txnid_a));
14098
+ mdbx_notice("force-forward pending-txn %" PRIaTXN " -> %" PRIaTXN,
14099
+ unaligned_peek_u64(4, pending->mm_txnid_a), txnid);
14100
+ mdbx_ensure(env, env->me_txn0->mt_owner != mdbx_thread_self() &&
14101
+ !env->me_txn);
14095
14102
if (unlikely(txnid > MAX_TXNID)) {
14096
14103
rc = MDBX_TXN_FULL;
14097
14104
mdbx_error("txnid overflow, raise %d", rc);
@@ -15681,16 +15688,12 @@ __cold static int __must_check_result mdbx_override_meta(
15681
15688
MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
15682
15689
if (unlikely(rc != MDBX_SUCCESS))
15683
15690
return rc;
15684
- MDBX_meta *live = METAPAGE(env, target);
15685
- mdbx_meta_update_begin(env, live, unaligned_peek_u64(4, model->mm_txnid_a));
15691
+ /* mdbx_override_meta() called only while current process have exclusive
15692
+ * lock of a DB file. So meta-page could be updated directly without
15693
+ * clearing consistency flag by mdbx_meta_update_begin() */
15694
+ memcpy(pgno2page(env, target), page, env->me_psize);
15686
15695
mdbx_flush_incoherent_cpu_writeback();
15687
- mdbx_meta_update_begin(env, model,
15688
- unaligned_peek_u64(4, model->mm_txnid_a));
15689
- unaligned_poke_u64(4, model->mm_datasync_sign, MDBX_DATASIGN_WEAK);
15690
- memcpy((void *)data_page(live), page, env->me_psize);
15691
- mdbx_meta_update_end(env, live, unaligned_peek_u64(4, model->mm_txnid_b));
15692
- mdbx_flush_incoherent_cpu_writeback();
15693
- rc = mdbx_msync(&env->me_dxb_mmap, 0, pgno_align2os_bytes(env, target),
15696
+ rc = mdbx_msync(&env->me_dxb_mmap, 0, pgno_align2os_bytes(env, target + 1),
15694
15697
MDBX_SYNC_DATA | MDBX_SYNC_IODQ);
15695
15698
} else {
15696
15699
const mdbx_filehandle_t fd = (env->me_dsync_fd != INVALID_HANDLE_VALUE)
@@ -16941,8 +16944,9 @@ __hot static int mdbx_page_search(MDBX_cursor *mc, const MDBX_val *key,
16941
16944
* [out] data Updated to point to the node's data.
16942
16945
*
16943
16946
* Returns 0 on success, non-zero on failure. */
16944
- static __always_inline int mdbx_node_read(MDBX_cursor *mc, MDBX_node *node,
16945
- MDBX_val *data, const txnid_t front) {
16947
+ static __always_inline int mdbx_node_read(MDBX_cursor *mc,
16948
+ const MDBX_node *node, MDBX_val *data,
16949
+ const txnid_t front) {
16946
16950
data->iov_len = node_ds(node);
16947
16951
data->iov_base = node_data(node);
16948
16952
if (unlikely(F_ISSET(node_flags(node), F_BIGDATA))) {
@@ -17848,7 +17852,7 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
17848
17852
break;
17849
17853
case MDBX_FIRST_DUP:
17850
17854
mfunc = mdbx_cursor_first;
17851
- mmove :
17855
+ move :
17852
17856
if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED)))
17853
17857
return MDBX_EINVAL;
17854
17858
if (unlikely(mc->mc_xcursor == NULL))
@@ -17876,7 +17880,8 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
17876
17880
break;
17877
17881
case MDBX_LAST_DUP:
17878
17882
mfunc = mdbx_cursor_last;
17879
- goto mmove;
17883
+ goto move;
17884
+ case MDBX_SET_UPPERBOUND: /* mostly same as MDBX_SET_LOWERBOUND */
17880
17885
case MDBX_SET_LOWERBOUND: {
17881
17886
if (unlikely(key == NULL || data == NULL))
17882
17887
return MDBX_EINVAL;
@@ -17909,6 +17914,15 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
17909
17914
}
17910
17915
if (rc == MDBX_SUCCESS && !csr.exact)
17911
17916
rc = MDBX_RESULT_TRUE;
17917
+ if (unlikely(op == MDBX_SET_UPPERBOUND)) {
17918
+ /* minor fixups for MDBX_SET_UPPERBOUND */
17919
+ if (rc == MDBX_RESULT_TRUE)
17920
+ /* already at great-than by MDBX_SET_LOWERBOUND */
17921
+ rc = MDBX_SUCCESS;
17922
+ else if (rc == MDBX_SUCCESS)
17923
+ /* exactly match, going next */
17924
+ rc = mdbx_cursor_next(mc, key, data, MDBX_NEXT);
17925
+ }
17912
17926
break;
17913
17927
}
17914
17928
default:
@@ -17920,6 +17934,122 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
17920
17934
return rc;
17921
17935
}
17922
17936
17937
+ static int cursor_first_batch(MDBX_cursor *mc) {
17938
+ if (!(mc->mc_flags & C_INITIALIZED) || mc->mc_top) {
17939
+ int err = mdbx_page_search(mc, NULL, MDBX_PS_FIRST);
17940
+ if (unlikely(err != MDBX_SUCCESS))
17941
+ return err;
17942
+ }
17943
+ mdbx_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
17944
+
17945
+ mc->mc_flags |= C_INITIALIZED;
17946
+ mc->mc_flags &= ~C_EOF;
17947
+ mc->mc_ki[mc->mc_top] = 0;
17948
+ return MDBX_SUCCESS;
17949
+ }
17950
+
17951
+ static int cursor_next_batch(MDBX_cursor *mc) {
17952
+ if (unlikely(!(mc->mc_flags & C_INITIALIZED)))
17953
+ return cursor_first_batch(mc);
17954
+
17955
+ MDBX_page *mp = mc->mc_pg[mc->mc_top];
17956
+ if (unlikely(mc->mc_flags & C_EOF)) {
17957
+ if ((unsigned)mc->mc_ki[mc->mc_top] + 1 >= page_numkeys(mp))
17958
+ return MDBX_NOTFOUND;
17959
+ mc->mc_flags ^= C_EOF;
17960
+ }
17961
+
17962
+ int ki = mc->mc_ki[mc->mc_top];
17963
+ mc->mc_ki[mc->mc_top] = (indx_t)++ki;
17964
+ const int numkeys = page_numkeys(mp);
17965
+ if (likely(ki >= numkeys)) {
17966
+ mdbx_debug("%s", "=====> move to next sibling page");
17967
+ mc->mc_ki[mc->mc_top] = (indx_t)(numkeys - 1);
17968
+ int err = mdbx_cursor_sibling(mc, SIBLING_RIGHT);
17969
+ if (unlikely(err != MDBX_SUCCESS)) {
17970
+ mc->mc_flags |= C_EOF;
17971
+ return err;
17972
+ }
17973
+ mp = mc->mc_pg[mc->mc_top];
17974
+ mdbx_debug("next page is %" PRIaPGNO ", key index %u", mp->mp_pgno,
17975
+ mc->mc_ki[mc->mc_top]);
17976
+ }
17977
+ return MDBX_SUCCESS;
17978
+ }
17979
+
17980
+ int mdbx_cursor_get_batch(MDBX_cursor *mc, size_t *count, MDBX_val *pairs,
17981
+ size_t limit, MDBX_cursor_op op) {
17982
+ if (unlikely(mc == NULL || count == NULL || limit < 4))
17983
+ return MDBX_EINVAL;
17984
+
17985
+ if (unlikely(mc->mc_signature != MDBX_MC_LIVE))
17986
+ return (mc->mc_signature == MDBX_MC_READY4CLOSE) ? MDBX_EINVAL
17987
+ : MDBX_EBADSIGN;
17988
+
17989
+ int rc = check_txn(mc->mc_txn, MDBX_TXN_BLOCKED);
17990
+ if (unlikely(rc != MDBX_SUCCESS))
17991
+ return rc;
17992
+
17993
+ if (unlikely(mc->mc_db->md_flags & MDBX_DUPSORT))
17994
+ return MDBX_INCOMPATIBLE /* must be a non-dupsort subDB */;
17995
+
17996
+ switch (op) {
17997
+ case MDBX_FIRST:
17998
+ rc = cursor_first_batch(mc);
17999
+ break;
18000
+ case MDBX_NEXT:
18001
+ rc = cursor_next_batch(mc);
18002
+ break;
18003
+ case MDBX_GET_CURRENT:
18004
+ rc = likely(mc->mc_flags & C_INITIALIZED) ? MDBX_SUCCESS : MDBX_ENODATA;
18005
+ break;
18006
+ default:
18007
+ mdbx_debug("unhandled/unimplemented cursor operation %u", op);
18008
+ rc = EINVAL;
18009
+ break;
18010
+ }
18011
+
18012
+ if (unlikely(rc != MDBX_SUCCESS)) {
18013
+ *count = 0;
18014
+ return rc;
18015
+ }
18016
+
18017
+ const MDBX_page *const page = mc->mc_pg[mc->mc_top];
18018
+ const unsigned nkeys = page_numkeys(page);
18019
+ unsigned i = mc->mc_ki[mc->mc_top], n = 0;
18020
+ if (unlikely(i >= nkeys)) {
18021
+ mdbx_cassert(mc, op == MDBX_GET_CURRENT);
18022
+ mdbx_cassert(mc, mdbx_cursor_on_last(mc) == MDBX_RESULT_TRUE);
18023
+ *count = 0;
18024
+ if (mc->mc_flags & C_EOF) {
18025
+ mdbx_cassert(mc, mdbx_cursor_on_last(mc) == MDBX_RESULT_TRUE);
18026
+ return MDBX_ENODATA;
18027
+ }
18028
+ if (mdbx_cursor_on_last(mc) != MDBX_RESULT_TRUE)
18029
+ return MDBX_EINVAL /* again MDBX_GET_CURRENT after MDBX_GET_CURRENT */;
18030
+ mc->mc_flags |= C_EOF;
18031
+ return MDBX_NOTFOUND;
18032
+ }
18033
+
18034
+ const txnid_t pp_txnid = pp_txnid4chk(page, mc->mc_txn);
18035
+ do {
18036
+ if (unlikely(n + 2 > limit)) {
18037
+ rc = MDBX_RESULT_TRUE;
18038
+ break;
18039
+ }
18040
+ const MDBX_node *leaf = page_node(page, i);
18041
+ get_key(leaf, &pairs[n]);
18042
+ rc = mdbx_node_read(mc, leaf, &pairs[n + 1], pp_txnid);
18043
+ if (unlikely(rc != MDBX_SUCCESS))
18044
+ break;
18045
+ n += 2;
18046
+ } while (++i < nkeys);
18047
+
18048
+ mc->mc_ki[mc->mc_top] = (indx_t)i;
18049
+ *count = n;
18050
+ return rc;
18051
+ }
18052
+
17923
18053
static int mdbx_touch_dbi(MDBX_cursor *mc) {
17924
18054
mdbx_cassert(mc, (*mc->mc_dbistate & DBI_DIRTY) == 0);
17925
18055
*mc->mc_dbistate |= DBI_DIRTY;
@@ -28535,9 +28665,9 @@ __dll_export
28535
28665
0,
28536
28666
11,
28537
28667
2,
28538
- 15 ,
28539
- {"2021-12-09T15:54:16 +03:00", "b9a59a0f8051a9596747d2cdc7b4dd9f07ffea68 ", "ca19796514122e7980cb42c9cf9aeccb0e544705 ",
28540
- "v0.11.2-15-gca197965 "},
28668
+ 22 ,
28669
+ {"2021-12-13T13:03:49 +03:00", "85a340e46868508e5b9d6b93c83fec220f8a7930 ", "c70d2d62d1d5fe5659790703390d3fd2d4c5ff60 ",
28670
+ "v0.11.2-22-gc70d2d62 "},
28541
28671
sourcery};
28542
28672
28543
28673
__dll_export
0 commit comments