mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-10-31 03:29:01 +08:00 
			
		
		
		
	mdbx: packing the 16-bit representations of grow step and shrink threshold values.
				
					
				
			Using float point (exponential quantized) representation for internal 16-bit values of grow step and shrink threshold when huge ones . To minimize the impact on compatibility, only the odd values inside the upper half of the range (i.e. 32769..65533) are used for the new representation. Resolve https://github.com/erthink/libmdbx/issues/166 Change-Id: I273127c1842deef0d7d8885b55a805b1463556eb
This commit is contained in:
		| @@ -23,6 +23,10 @@ New features: | ||||
|    The `MDBX_DISABLE_PAGECHECKS=1` provides a performance boost of about 10% in CRUD scenarios, | ||||
|    and conjointly with the `MDBX_ENV_CHECKPID=0` and `MDBX_TXN_CHECKOWNER=0` options can yield | ||||
|    up to 30% more performance compared to LMDB. | ||||
|  - Using float point (exponential quantized) representation for internal 16-bit values | ||||
|    of grow step and shrink threshold when huge ones (https://github.com/erthink/libmdbx/issues/166). | ||||
|    To minimize the impact on compatibility, only the odd values inside the upper half | ||||
|    of the range (i.e. 32769..65533) are used for the new representation. | ||||
|  | ||||
| Fixes: | ||||
|  | ||||
|   | ||||
							
								
								
									
										238
									
								
								src/core.c
									
									
									
									
									
								
							
							
						
						
									
										238
									
								
								src/core.c
									
									
									
									
									
								
							| @@ -57,6 +57,59 @@ MDBX_NOTHROW_CONST_FUNCTION static unsigned log2n(size_t value) { | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* Pack/Unpack 16-bit values for Grow step & Shrink threshold */ | ||||
| MDBX_NOTHROW_CONST_FUNCTION static __inline pgno_t me2v(unsigned m, | ||||
|                                                         unsigned e) { | ||||
|   assert(m < 2048 && e < 8); | ||||
|   return (pgno_t)(32768 + ((m + 1) << (e + 5))); | ||||
| } | ||||
|  | ||||
| MDBX_NOTHROW_CONST_FUNCTION static __inline uint16_t v2me(size_t v, | ||||
|                                                           unsigned e) { | ||||
|   assert(v > (e ? me2v(2047, e - 1) : 32768)); | ||||
|   assert(v <= me2v(2047, e)); | ||||
|   size_t m = (v - 32768 + (1 << (e + 5)) - 1) >> (e + 5); | ||||
|   m -= m > 0; | ||||
|   assert(m < 2048 && e < 8); | ||||
|   // f e d c b a 9 8 7 6 5 4 3 2 1 0 | ||||
|   // 1 e e e m m m m m m m m m m m 1 | ||||
|   const uint16_t pv = (uint16_t)(0x8001 + (e << 12) + (m << 1)); | ||||
|   assert(pv != 65535); | ||||
|   return pv; | ||||
| } | ||||
|  | ||||
| /* Convert 16-bit packed (exponential quantized) value to number of pages */ | ||||
| MDBX_NOTHROW_CONST_FUNCTION static pgno_t pv2pages(uint16_t pv) { | ||||
|   if ((pv & 0x8001) != 0x8001) | ||||
|     return pv; | ||||
|   if (pv == 65535) | ||||
|     return 65536; | ||||
|   // f e d c b a 9 8 7 6 5 4 3 2 1 0 | ||||
|   // 1 e e e m m m m m m m m m m m 1 | ||||
|   return me2v((pv >> 1) & 2047, (pv >> 12) & 7); | ||||
| } | ||||
|  | ||||
| /* Convert number of pages to 16-bit packed (exponential quantized) value */ | ||||
| MDBX_NOTHROW_CONST_FUNCTION static uint16_t pages2pv(size_t pages) { | ||||
|   if (pages < 32769 || (pages < 65536 && (pages & 1) == 0)) | ||||
|     return (uint16_t)pages; | ||||
|   if (pages <= me2v(2047, 0)) | ||||
|     return v2me(pages, 0); | ||||
|   if (pages <= me2v(2047, 1)) | ||||
|     return v2me(pages, 1); | ||||
|   if (pages <= me2v(2047, 2)) | ||||
|     return v2me(pages, 2); | ||||
|   if (pages <= me2v(2047, 3)) | ||||
|     return v2me(pages, 3); | ||||
|   if (pages <= me2v(2047, 4)) | ||||
|     return v2me(pages, 4); | ||||
|   if (pages <= me2v(2047, 5)) | ||||
|     return v2me(pages, 5); | ||||
|   if (pages <= me2v(2047, 6)) | ||||
|     return v2me(pages, 6); | ||||
|   return (pages < me2v(2046, 7)) ? v2me(pages, 7) : 65533; | ||||
| } | ||||
|  | ||||
| /*------------------------------------------------------------------------------ | ||||
|  * Unaligned access */ | ||||
|  | ||||
| @@ -1296,6 +1349,17 @@ __cold void mdbx_rthc_global_init(void) { | ||||
|   } | ||||
|  | ||||
|   bootid = mdbx_osal_bootid(); | ||||
| #if 0 /* debug */ | ||||
|   for (unsigned i = 0; i < 65536; ++i) { | ||||
|     size_t pages = pv2pages(i); | ||||
|     unsigned x = pages2pv(pages); | ||||
|     size_t xp = pv2pages(x); | ||||
|     if (!(x == i || (x % 2 == 0 && x < 65536)) || pages != xp) | ||||
|       printf("%u => %zu => %u => %zu\n", i, pages, x, xp); | ||||
|     assert(pages == xp); | ||||
|   } | ||||
|   fflush(stdout); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /* dtor called for thread, i.e. for all mdbx's environment objects */ | ||||
| @@ -6072,10 +6136,11 @@ no_loose: | ||||
|     rc = MDBX_NOTFOUND; | ||||
|     if (flags & MDBX_ALLOC_NEW) { | ||||
|       rc = MDBX_MAP_FULL; | ||||
|       if (next <= txn->mt_geo.upper && txn->mt_geo.grow) { | ||||
|       if (next <= txn->mt_geo.upper && txn->mt_geo.grow_pv) { | ||||
|         mdbx_assert(env, next > txn->mt_end_pgno); | ||||
|         const pgno_t grow_step = pv2pages(txn->mt_geo.grow_pv); | ||||
|         pgno_t aligned = pgno_align2os_pgno( | ||||
|             env, pgno_add(next, txn->mt_geo.grow - next % txn->mt_geo.grow)); | ||||
|             env, pgno_add(next, grow_step - next % grow_step)); | ||||
|  | ||||
|         if (aligned > txn->mt_geo.upper) | ||||
|           aligned = txn->mt_geo.upper; | ||||
| @@ -9681,7 +9746,7 @@ mdbx_validate_meta(MDBX_env *env, MDBX_meta *const meta, uint64_t *filesize, | ||||
|              page->mp_pgno, meta->mm_dbs[MAIN_DBI].md_root, | ||||
|              meta->mm_dbs[FREE_DBI].md_root, meta->mm_geo.lower, | ||||
|              meta->mm_geo.next, meta->mm_geo.now, meta->mm_geo.upper, | ||||
|              meta->mm_geo.grow, meta->mm_geo.shrink, | ||||
|              pv2pages(meta->mm_geo.grow_pv), pv2pages(meta->mm_geo.shrink_pv), | ||||
|              unaligned_peek_u64(4, meta->mm_txnid_a), mdbx_durable_str(meta)); | ||||
|  | ||||
|   /* LY: check min-pages value */ | ||||
| @@ -9935,8 +10000,9 @@ static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model, | ||||
|  | ||||
|   model_meta->mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); | ||||
|   model_meta->mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); | ||||
|   model_meta->mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); | ||||
|   model_meta->mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); | ||||
|   model_meta->mm_geo.grow_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.grow)); | ||||
|   model_meta->mm_geo.shrink_pv = | ||||
|       pages2pv(bytes2pgno(env, env->me_dbgeo.shrink)); | ||||
|   model_meta->mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); | ||||
|   model_meta->mm_geo.next = NUM_METAS; | ||||
|  | ||||
| @@ -9946,10 +10012,10 @@ static MDBX_page *__cold mdbx_meta_model(const MDBX_env *env, MDBX_page *model, | ||||
|   mdbx_ensure(env, model_meta->mm_geo.now <= model_meta->mm_geo.upper); | ||||
|   mdbx_ensure(env, model_meta->mm_geo.next >= MIN_PAGENO); | ||||
|   mdbx_ensure(env, model_meta->mm_geo.next <= model_meta->mm_geo.now); | ||||
|   mdbx_ensure(env, | ||||
|               model_meta->mm_geo.grow == bytes2pgno(env, env->me_dbgeo.grow)); | ||||
|   mdbx_ensure(env, model_meta->mm_geo.shrink == | ||||
|                        bytes2pgno(env, env->me_dbgeo.shrink)); | ||||
|   mdbx_ensure(env, model_meta->mm_geo.grow_pv == | ||||
|                        pages2pv(pv2pages(model_meta->mm_geo.grow_pv))); | ||||
|   mdbx_ensure(env, model_meta->mm_geo.shrink_pv == | ||||
|                        pages2pv(pv2pages(model_meta->mm_geo.shrink_pv))); | ||||
|  | ||||
|   model_meta->mm_psize = env->me_psize; | ||||
|   model_meta->mm_flags = (uint16_t)env->me_flags; | ||||
| @@ -10074,13 +10140,17 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags, | ||||
|  | ||||
|     /* LY: check conditions to shrink datafile */ | ||||
|     const pgno_t backlog_gap = 3 + pending->mm_dbs[FREE_DBI].md_depth * 3; | ||||
|     if (pending->mm_geo.shrink && pending->mm_geo.now - pending->mm_geo.next > | ||||
|                                       pending->mm_geo.shrink + backlog_gap) { | ||||
|     pgno_t shrink_step = 0; | ||||
|     if (pending->mm_geo.shrink_pv && | ||||
|         pending->mm_geo.now - pending->mm_geo.next > | ||||
|             (shrink_step = pv2pages(pending->mm_geo.shrink_pv)) + backlog_gap) { | ||||
|       if (pending->mm_geo.now > largest_pgno && | ||||
|           pending->mm_geo.now - largest_pgno > | ||||
|               pending->mm_geo.shrink + backlog_gap) { | ||||
|         const pgno_t aligner = pending->mm_geo.grow ? pending->mm_geo.grow | ||||
|                                                     : pending->mm_geo.shrink; | ||||
|           pending->mm_geo.now - largest_pgno > shrink_step + backlog_gap) { | ||||
|         pgno_t grow_step = 0; | ||||
|         const pgno_t aligner = | ||||
|             pending->mm_geo.grow_pv | ||||
|                 ? (grow_step = pv2pages(pending->mm_geo.grow_pv)) | ||||
|                 : shrink_step; | ||||
|         const pgno_t with_backlog_gap = largest_pgno + backlog_gap; | ||||
|         const pgno_t aligned = pgno_align2os_pgno( | ||||
|             env, with_backlog_gap + aligner - with_backlog_gap % aligner); | ||||
| @@ -10168,15 +10238,15 @@ static int mdbx_sync_locked(MDBX_env *env, unsigned flags, | ||||
|   } | ||||
|  | ||||
|   /* LY: step#2 - update meta-page. */ | ||||
|   mdbx_debug("writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO | ||||
|              ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO | ||||
|              " +%u -%u, txn_id %" PRIaTXN ", %s", | ||||
|              data_page(target)->mp_pgno, pending->mm_dbs[MAIN_DBI].md_root, | ||||
|              pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower, | ||||
|              pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper, | ||||
|              pending->mm_geo.grow, pending->mm_geo.shrink, | ||||
|              unaligned_peek_u64(4, pending->mm_txnid_a), | ||||
|              mdbx_durable_str(pending)); | ||||
|   mdbx_debug( | ||||
|       "writing meta%" PRIaPGNO " = root %" PRIaPGNO "/%" PRIaPGNO | ||||
|       ", geo %" PRIaPGNO "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO | ||||
|       " +%u -%u, txn_id %" PRIaTXN ", %s", | ||||
|       data_page(target)->mp_pgno, pending->mm_dbs[MAIN_DBI].md_root, | ||||
|       pending->mm_dbs[FREE_DBI].md_root, pending->mm_geo.lower, | ||||
|       pending->mm_geo.next, pending->mm_geo.now, pending->mm_geo.upper, | ||||
|       pv2pages(pending->mm_geo.grow_pv), pv2pages(pending->mm_geo.shrink_pv), | ||||
|       unaligned_peek_u64(4, pending->mm_txnid_a), mdbx_durable_str(pending)); | ||||
|  | ||||
|   mdbx_debug("meta0: %s, %s, txn_id %" PRIaTXN ", root %" PRIaPGNO | ||||
|              "/%" PRIaPGNO, | ||||
| @@ -10458,9 +10528,9 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, | ||||
|     if (size_upper < 0) | ||||
|       size_upper = pgno2bytes(env, head->mm_geo.upper); | ||||
|     if (growth_step < 0) | ||||
|       growth_step = pgno2bytes(env, head->mm_geo.grow); | ||||
|       growth_step = pgno2bytes(env, pv2pages(head->mm_geo.grow_pv)); | ||||
|     if (shrink_threshold < 0) | ||||
|       shrink_threshold = pgno2bytes(env, head->mm_geo.shrink); | ||||
|       shrink_threshold = pgno2bytes(env, pv2pages(head->mm_geo.shrink_pv)); | ||||
|  | ||||
|     if (pagesize != (intptr_t)env->me_psize) { | ||||
|       rc = MDBX_EINVAL; | ||||
| @@ -10603,21 +10673,18 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, | ||||
|   if (growth_step == 0 && shrink_threshold > 0) | ||||
|     growth_step = 1; | ||||
|   growth_step = ceil_powerof2(growth_step, unit); | ||||
|   if (bytes2pgno(env, growth_step) > UINT16_MAX) | ||||
|     growth_step = pgno2bytes(env, UINT16_MAX); | ||||
|  | ||||
|   if (shrink_threshold < 0) | ||||
|     shrink_threshold = growth_step + growth_step; | ||||
|   shrink_threshold = ceil_powerof2(shrink_threshold, unit); | ||||
|   if (bytes2pgno(env, shrink_threshold) > UINT16_MAX) | ||||
|     shrink_threshold = pgno2bytes(env, UINT16_MAX); | ||||
|  | ||||
|   /* save user's geo-params for future open/create */ | ||||
|   env->me_dbgeo.lower = size_lower; | ||||
|   env->me_dbgeo.now = size_now; | ||||
|   env->me_dbgeo.upper = size_upper; | ||||
|   env->me_dbgeo.grow = growth_step; | ||||
|   env->me_dbgeo.shrink = shrink_threshold; | ||||
|   env->me_dbgeo.grow = pv2pages(pages2pv(growth_step / pagesize)) * pagesize; | ||||
|   env->me_dbgeo.shrink = | ||||
|       pv2pages(pages2pv(shrink_threshold / pagesize)) * pagesize; | ||||
|   rc = MDBX_SUCCESS; | ||||
|  | ||||
|   mdbx_ensure(env, pagesize >= MIN_PAGESIZE); | ||||
| @@ -10650,7 +10717,7 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, | ||||
|     mdbx_ensure(env, pagesize == (intptr_t)env->me_psize); | ||||
|     MDBX_meta meta; | ||||
|     MDBX_meta *head = nullptr; | ||||
|     const mdbx_geo_t *current_geo; | ||||
|     const MDBX_geo *current_geo; | ||||
|     if (inside_txn) { | ||||
|       current_geo = &env->me_txn->mt_geo; | ||||
|     } else { | ||||
| @@ -10659,12 +10726,12 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, | ||||
|       current_geo = &meta.mm_geo; | ||||
|     } | ||||
|  | ||||
|     mdbx_geo_t new_geo; | ||||
|     MDBX_geo new_geo; | ||||
|     new_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); | ||||
|     new_geo.now = bytes2pgno(env, env->me_dbgeo.now); | ||||
|     new_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); | ||||
|     new_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); | ||||
|     new_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); | ||||
|     new_geo.grow_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.grow)); | ||||
|     new_geo.shrink_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.shrink)); | ||||
|     new_geo.next = current_geo->next; | ||||
|  | ||||
|     mdbx_ensure(env, | ||||
| @@ -10673,10 +10740,9 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, | ||||
|                 pgno_align2os_bytes(env, new_geo.upper) == env->me_dbgeo.upper); | ||||
|     mdbx_ensure(env, | ||||
|                 pgno_align2os_bytes(env, new_geo.now) == env->me_dbgeo.now); | ||||
|     mdbx_ensure(env, new_geo.grow_pv == pages2pv(pv2pages(new_geo.grow_pv))); | ||||
|     mdbx_ensure(env, | ||||
|                 pgno_align2os_bytes(env, new_geo.grow) == env->me_dbgeo.grow); | ||||
|     mdbx_ensure(env, pgno_align2os_bytes(env, new_geo.shrink) == | ||||
|                          env->me_dbgeo.shrink); | ||||
|                 new_geo.shrink_pv == pages2pv(pv2pages(new_geo.shrink_pv))); | ||||
|  | ||||
|     mdbx_ensure(env, env->me_dbgeo.lower >= MIN_MAPSIZE); | ||||
|     mdbx_ensure(env, new_geo.lower >= MIN_PAGENO); | ||||
| @@ -10686,11 +10752,12 @@ mdbx_env_set_geometry(MDBX_env *env, intptr_t size_lower, intptr_t size_now, | ||||
|     mdbx_ensure(env, new_geo.upper >= new_geo.now); | ||||
|     mdbx_ensure(env, new_geo.now >= new_geo.lower); | ||||
|  | ||||
|     if (memcmp(current_geo, &new_geo, sizeof(mdbx_geo_t)) != 0) { | ||||
|     if (memcmp(current_geo, &new_geo, sizeof(MDBX_geo)) != 0) { | ||||
| #if defined(_WIN32) || defined(_WIN64) | ||||
|       /* Was DB shrinking disabled before and now it will be enabled? */ | ||||
|       if (new_geo.lower < new_geo.upper && new_geo.shrink && | ||||
|           !(current_geo->lower < current_geo->upper && current_geo->shrink)) { | ||||
|       if (new_geo.lower < new_geo.upper && new_geo.shrink_pv && | ||||
|           !(current_geo->lower < current_geo->upper && | ||||
|             current_geo->shrink_pv)) { | ||||
|         if (!env->me_lck) { | ||||
|           rc = MDBX_EPERM; | ||||
|           goto bailout; | ||||
| @@ -10823,13 +10890,13 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   mdbx_verbose("header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO | ||||
|                "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO | ||||
|                " +%u -%u, txn_id %" PRIaTXN ", %s", | ||||
|                meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, | ||||
|                meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, | ||||
|                meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink, | ||||
|                unaligned_peek_u64(4, meta.mm_txnid_a), mdbx_durable_str(&meta)); | ||||
|   mdbx_verbose( | ||||
|       "header: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO "/%" PRIaPGNO | ||||
|       "-%" PRIaPGNO "/%" PRIaPGNO " +%u -%u, txn_id %" PRIaTXN ", %s", | ||||
|       meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, | ||||
|       meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, meta.mm_geo.upper, | ||||
|       pv2pages(meta.mm_geo.grow_pv), pv2pages(meta.mm_geo.shrink_pv), | ||||
|       unaligned_peek_u64(4, meta.mm_txnid_a), mdbx_durable_str(&meta)); | ||||
|  | ||||
|   mdbx_setup_pagesize(env, meta.mm_psize); | ||||
|   const size_t used_bytes = pgno2bytes(env, meta.mm_geo.next); | ||||
| @@ -10842,8 +10909,8 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|     const size_t pagesize = meta.mm_psize; | ||||
|     err = mdbx_env_set_geometry( | ||||
|         env, meta.mm_geo.lower * pagesize, meta.mm_geo.now * pagesize, | ||||
|         meta.mm_geo.upper * pagesize, meta.mm_geo.grow * pagesize, | ||||
|         meta.mm_geo.shrink * pagesize, meta.mm_psize); | ||||
|         meta.mm_geo.upper * pagesize, pv2pages(meta.mm_geo.grow_pv) * pagesize, | ||||
|         pv2pages(meta.mm_geo.shrink_pv) * pagesize, meta.mm_psize); | ||||
|     if (unlikely(err != MDBX_SUCCESS)) { | ||||
|       mdbx_error("%s: err %d", "could not apply preconfigured geometry from db", | ||||
|                  err); | ||||
| @@ -10865,9 +10932,9 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|         bytes_align2os_bytes(env, env->me_dbgeo.lower) != | ||||
|             pgno2bytes(env, meta.mm_geo.lower) || | ||||
|         bytes_align2os_bytes(env, env->me_dbgeo.shrink) != | ||||
|             pgno2bytes(env, meta.mm_geo.shrink) || | ||||
|             pgno2bytes(env, pv2pages(meta.mm_geo.shrink_pv)) || | ||||
|         bytes_align2os_bytes(env, env->me_dbgeo.grow) != | ||||
|             pgno2bytes(env, meta.mm_geo.grow)) { | ||||
|             pgno2bytes(env, pv2pages(meta.mm_geo.grow_pv))) { | ||||
|  | ||||
|       if (env->me_dbgeo.shrink && env->me_dbgeo.now > used_bytes) | ||||
|         /* pre-shrink if enabled */ | ||||
| @@ -10887,15 +10954,16 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|       meta.mm_geo.now = bytes2pgno(env, env->me_dbgeo.now); | ||||
|       meta.mm_geo.lower = bytes2pgno(env, env->me_dbgeo.lower); | ||||
|       meta.mm_geo.upper = bytes2pgno(env, env->me_dbgeo.upper); | ||||
|       meta.mm_geo.grow = (uint16_t)bytes2pgno(env, env->me_dbgeo.grow); | ||||
|       meta.mm_geo.shrink = (uint16_t)bytes2pgno(env, env->me_dbgeo.shrink); | ||||
|       meta.mm_geo.grow_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.grow)); | ||||
|       meta.mm_geo.shrink_pv = pages2pv(bytes2pgno(env, env->me_dbgeo.shrink)); | ||||
|  | ||||
|       mdbx_verbose("amended: root %" PRIaPGNO "/%" PRIaPGNO ", geo %" PRIaPGNO | ||||
|                    "/%" PRIaPGNO "-%" PRIaPGNO "/%" PRIaPGNO | ||||
|                    " +%u -%u, txn_id %" PRIaTXN ", %s", | ||||
|                    meta.mm_dbs[MAIN_DBI].md_root, meta.mm_dbs[FREE_DBI].md_root, | ||||
|                    meta.mm_geo.lower, meta.mm_geo.next, meta.mm_geo.now, | ||||
|                    meta.mm_geo.upper, meta.mm_geo.grow, meta.mm_geo.shrink, | ||||
|                    meta.mm_geo.upper, pv2pages(meta.mm_geo.grow_pv), | ||||
|                    pv2pages(meta.mm_geo.shrink_pv), | ||||
|                    unaligned_peek_u64(4, meta.mm_txnid_a), | ||||
|                    mdbx_durable_str(&meta)); | ||||
|     } else { | ||||
| @@ -10910,8 +10978,8 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|     env->me_dbgeo.now = pgno2bytes(env, meta.mm_geo.now); | ||||
|     env->me_dbgeo.lower = pgno2bytes(env, meta.mm_geo.lower); | ||||
|     env->me_dbgeo.upper = pgno2bytes(env, meta.mm_geo.upper); | ||||
|     env->me_dbgeo.grow = pgno2bytes(env, meta.mm_geo.grow); | ||||
|     env->me_dbgeo.shrink = pgno2bytes(env, meta.mm_geo.shrink); | ||||
|     env->me_dbgeo.grow = pgno2bytes(env, pv2pages(meta.mm_geo.grow_pv)); | ||||
|     env->me_dbgeo.shrink = pgno2bytes(env, pv2pages(meta.mm_geo.shrink_pv)); | ||||
|   } | ||||
|  | ||||
|   mdbx_ensure(env, | ||||
| @@ -11133,14 +11201,15 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|     if (memcmp(&meta.mm_geo, &head->mm_geo, sizeof(meta.mm_geo))) { | ||||
|       if ((env->me_flags & MDBX_RDONLY) != 0 || | ||||
|           /* recovery mode */ env->me_stuck_meta >= 0) { | ||||
|         mdbx_warning("skipped update meta.geo in %s mode: from l%" PRIaPGNO | ||||
|                      "-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u, to l%" PRIaPGNO | ||||
|                      "-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u", | ||||
|                      (env->me_stuck_meta < 0) ? "read-only" : "recovery", | ||||
|                      head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper, | ||||
|                      head->mm_geo.shrink, head->mm_geo.grow, meta.mm_geo.lower, | ||||
|                      meta.mm_geo.now, meta.mm_geo.upper, meta.mm_geo.shrink, | ||||
|                      meta.mm_geo.grow); | ||||
|         mdbx_warning( | ||||
|             "skipped update meta.geo in %s mode: from l%" PRIaPGNO | ||||
|             "-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u, to l%" PRIaPGNO | ||||
|             "-n%" PRIaPGNO "-u%" PRIaPGNO "/s%u-g%u", | ||||
|             (env->me_stuck_meta < 0) ? "read-only" : "recovery", | ||||
|             head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper, | ||||
|             pv2pages(head->mm_geo.shrink_pv), pv2pages(head->mm_geo.grow_pv), | ||||
|             meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper, | ||||
|             pv2pages(meta.mm_geo.shrink_pv), pv2pages(meta.mm_geo.grow_pv)); | ||||
|       } else { | ||||
|         const txnid_t txnid = mdbx_meta_txnid_stable(env, head); | ||||
|         const txnid_t next_txnid = safe64_txnid_next(txnid); | ||||
| @@ -11154,9 +11223,11 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|                     "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO | ||||
|                     "/s%u-g%u (txn#%" PRIaTXN ")", | ||||
|                     head->mm_geo.lower, head->mm_geo.now, head->mm_geo.upper, | ||||
|                     head->mm_geo.shrink, head->mm_geo.grow, txnid, | ||||
|                     meta.mm_geo.lower, meta.mm_geo.now, meta.mm_geo.upper, | ||||
|                     meta.mm_geo.shrink, meta.mm_geo.grow, next_txnid); | ||||
|                     pv2pages(head->mm_geo.shrink_pv), | ||||
|                     pv2pages(head->mm_geo.grow_pv), txnid, meta.mm_geo.lower, | ||||
|                     meta.mm_geo.now, meta.mm_geo.upper, | ||||
|                     pv2pages(meta.mm_geo.shrink_pv), | ||||
|                     pv2pages(meta.mm_geo.grow_pv), next_txnid); | ||||
|  | ||||
|         mdbx_ensure(env, mdbx_meta_eq(env, &meta, head)); | ||||
|         mdbx_meta_set_txnid(env, &meta, next_txnid); | ||||
| @@ -11168,10 +11239,11 @@ static __cold int mdbx_setup_dxb(MDBX_env *env, const int lck_rc) { | ||||
|                      "to l%" PRIaPGNO "-n%" PRIaPGNO "-u%" PRIaPGNO | ||||
|                      "/s%u-g%u (txn#%" PRIaTXN ")", | ||||
|                      err, head->mm_geo.lower, head->mm_geo.now, | ||||
|                      head->mm_geo.upper, head->mm_geo.shrink, head->mm_geo.grow, | ||||
|                      txnid, meta.mm_geo.lower, meta.mm_geo.now, | ||||
|                      meta.mm_geo.upper, meta.mm_geo.shrink, meta.mm_geo.grow, | ||||
|                      next_txnid); | ||||
|                      head->mm_geo.upper, pv2pages(head->mm_geo.shrink_pv), | ||||
|                      pv2pages(head->mm_geo.grow_pv), txnid, meta.mm_geo.lower, | ||||
|                      meta.mm_geo.now, meta.mm_geo.upper, | ||||
|                      pv2pages(meta.mm_geo.shrink_pv), | ||||
|                      pv2pages(meta.mm_geo.grow_pv), next_txnid); | ||||
|           return err; | ||||
|         } | ||||
|       } | ||||
| @@ -17729,8 +17801,8 @@ static __cold void compact_fixup_meta(MDBX_env *env, MDBX_meta *meta) { | ||||
|   /* Calculate filesize taking in account shrink/growing thresholds */ | ||||
|   if (meta->mm_geo.next != meta->mm_geo.now) { | ||||
|     meta->mm_geo.now = meta->mm_geo.next; | ||||
|     const pgno_t aligner = | ||||
|         meta->mm_geo.grow ? meta->mm_geo.grow : meta->mm_geo.shrink; | ||||
|     const pgno_t aligner = pv2pages( | ||||
|         meta->mm_geo.grow_pv ? meta->mm_geo.grow_pv : meta->mm_geo.shrink_pv); | ||||
|     if (aligner) { | ||||
|       const pgno_t aligned = pgno_align2os_pgno( | ||||
|           env, meta->mm_geo.next + aligner - meta->mm_geo.next % aligner); | ||||
| @@ -17751,13 +17823,13 @@ static __cold void compact_fixup_meta(MDBX_env *env, MDBX_meta *meta) { | ||||
| /* Make resizeable */ | ||||
| static __cold void make_sizeable(MDBX_meta *meta) { | ||||
|   meta->mm_geo.lower = MIN_PAGENO; | ||||
|   if (meta->mm_geo.grow == 0) { | ||||
|     const size_t step = 1 + (meta->mm_geo.upper - meta->mm_geo.lower) / 42; | ||||
|     meta->mm_geo.grow = (step < UINT16_MAX) ? (uint16_t)step : UINT16_MAX; | ||||
|   if (meta->mm_geo.grow_pv == 0) { | ||||
|     const pgno_t step = 1 + (meta->mm_geo.upper - meta->mm_geo.lower) / 42; | ||||
|     meta->mm_geo.grow_pv = pages2pv(step); | ||||
|   } | ||||
|   if (meta->mm_geo.shrink == 0) { | ||||
|     const size_t step = meta->mm_geo.grow + meta->mm_geo.grow; | ||||
|     meta->mm_geo.shrink = (step < UINT16_MAX) ? (uint16_t)step : UINT16_MAX; | ||||
|   if (meta->mm_geo.shrink_pv == 0) { | ||||
|     const pgno_t step = pv2pages(meta->mm_geo.grow_pv) << 1; | ||||
|     meta->mm_geo.shrink_pv = pages2pv(step); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -18410,8 +18482,8 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn, | ||||
|     } | ||||
|     arg->mi_geo.lower = pgno2bytes(env, txn_meta->mm_geo.lower); | ||||
|     arg->mi_geo.upper = pgno2bytes(env, txn_meta->mm_geo.upper); | ||||
|     arg->mi_geo.shrink = pgno2bytes(env, txn_meta->mm_geo.shrink); | ||||
|     arg->mi_geo.grow = pgno2bytes(env, txn_meta->mm_geo.grow); | ||||
|     arg->mi_geo.shrink = pgno2bytes(env, pv2pages(txn_meta->mm_geo.shrink_pv)); | ||||
|     arg->mi_geo.grow = pgno2bytes(env, pv2pages(txn_meta->mm_geo.grow_pv)); | ||||
|     unsynced_pages = atomic_load32(env->me_unsynced_pages, mo_Relaxed) + | ||||
|                      (atomic_load32(env->me_meta_sync_txnid, mo_Relaxed) != | ||||
|                       (uint32_t)arg->mi_last_pgno); | ||||
|   | ||||
| @@ -300,15 +300,17 @@ typedef struct MDBX_db { | ||||
| } MDBX_db; | ||||
|  | ||||
| /* database size-related parameters */ | ||||
| typedef struct mdbx_geo_t { | ||||
|   uint16_t grow;   /* datafile growth step in pages */ | ||||
|   uint16_t shrink; /* datafile shrink threshold in pages */ | ||||
|   pgno_t lower;    /* minimal size of datafile in pages */ | ||||
|   pgno_t upper;    /* maximal size of datafile in pages */ | ||||
|   pgno_t now;      /* current size of datafile in pages */ | ||||
|   pgno_t next;     /* first unused page in the datafile, | ||||
|                     * but actually the file may be shorter. */ | ||||
| } mdbx_geo_t; | ||||
| typedef struct MDBX_geo { | ||||
|   uint16_t grow_pv;   /* datafile growth step as a 16-bit packed (exponential | ||||
|                            quantized) value */ | ||||
|   uint16_t shrink_pv; /* datafile shrink threshold as a 16-bit packed | ||||
|                            (exponential quantized) value */ | ||||
|   pgno_t lower;       /* minimal size of datafile in pages */ | ||||
|   pgno_t upper;       /* maximal size of datafile in pages */ | ||||
|   pgno_t now;         /* current size of datafile in pages */ | ||||
|   pgno_t next;        /* first unused page in the datafile, | ||||
|                          but actually the file may be shorter. */ | ||||
| } MDBX_geo; | ||||
|  | ||||
| /* Meta page content. | ||||
|  * A meta page is the start point for accessing a database snapshot. | ||||
| @@ -327,7 +329,7 @@ typedef struct MDBX_meta { | ||||
|   uint8_t mm_extra_pagehdr; /* extra bytes in the page header, | ||||
|                              * zero (nothing) for now */ | ||||
|  | ||||
|   mdbx_geo_t mm_geo; /* database size-related parameters */ | ||||
|   MDBX_geo mm_geo; /* database size-related parameters */ | ||||
|  | ||||
|   MDBX_db mm_dbs[CORE_DBS]; /* first is free space, 2nd is main db */ | ||||
|                             /* The size of pages used in this DB */ | ||||
| @@ -731,7 +733,7 @@ struct MDBX_txn { | ||||
|   MDBX_txn *mt_parent; /* parent of a nested txn */ | ||||
|   /* Nested txn under this txn, set together with flag MDBX_TXN_HAS_CHILD */ | ||||
|   MDBX_txn *mt_child; | ||||
|   mdbx_geo_t mt_geo; | ||||
|   MDBX_geo mt_geo; | ||||
|   /* next unallocated page */ | ||||
| #define mt_next_pgno mt_geo.next | ||||
|   /* corresponding to the current size of datafile */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user