mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-10-31 03:29:01 +08:00 
			
		
		
		
	mdbx: refactor mdbx_drop_tree() & drop mdbx_retire pgno().
				
					
				
			Change-Id: I37f33d7a11e958ccc1c48a6af31599deb677038d
This commit is contained in:
		
							
								
								
									
										99
									
								
								src/core.c
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								src/core.c
									
									
									
									
									
								
							| @@ -3762,7 +3762,8 @@ static int __must_check_result mdbx_xcursor_init2(MDBX_cursor *mc, | ||||
|                                                   bool new_dupdata); | ||||
| static void cursor_copy_internal(const MDBX_cursor *csrc, MDBX_cursor *cdst); | ||||
|  | ||||
| static int __must_check_result mdbx_drop0(MDBX_cursor *mc, bool subs); | ||||
| static int __must_check_result mdbx_drop_tree(MDBX_cursor *mc, | ||||
|                                               const bool may_have_subDBs); | ||||
| static int __must_check_result mdbx_fetch_sdb(MDBX_txn *txn, MDBX_dbi dbi); | ||||
| static int __must_check_result mdbx_setup_dbx(MDBX_dbx *const dbx, | ||||
|                                               const MDBX_db *const db, | ||||
| @@ -14747,7 +14748,7 @@ int mdbx_cursor_del(MDBX_cursor *mc, MDBX_put_flags_t flags) { | ||||
|  | ||||
|     if (node_flags(node) & F_SUBDATA) { | ||||
|       /* add all the child DB's pages to the free list */ | ||||
|       rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, false); | ||||
|       rc = mdbx_drop_tree(&mc->mc_xcursor->mx_cursor, false); | ||||
|       if (unlikely(rc)) | ||||
|         goto fail; | ||||
|     } | ||||
| @@ -19097,30 +19098,7 @@ int mdbx_dbi_flags(MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) { | ||||
| } | ||||
| #endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */ | ||||
|  | ||||
| static __must_check_result __always_inline int | ||||
| mdbx_retire_pgno(MDBX_cursor *mc, const pgno_t pgno) { | ||||
|   MDBX_page *mp; | ||||
|   int rc; | ||||
|   if (mdbx_audit_enabled()) { | ||||
|     const unsigned save_flags = mc->mc_flags; | ||||
|     mc->mc_flags |= C_RETIRING; | ||||
|     rc = mdbx_page_get(mc, pgno, &mp, NULL, mc->mc_txn->mt_txnid); | ||||
|     if (likely(rc == MDBX_SUCCESS)) | ||||
|       rc = mdbx_page_retire(mc, mp); | ||||
|     mc->mc_flags = (mc->mc_flags & ~C_RETIRING) | (save_flags & C_RETIRING); | ||||
|   } else { | ||||
|     rc = mdbx_page_get(mc, pgno, &mp, NULL, mc->mc_txn->mt_txnid); | ||||
|     if (likely(rc == MDBX_SUCCESS)) | ||||
|       rc = mdbx_page_retire(mc, mp); | ||||
|   } | ||||
|   return rc; | ||||
| } | ||||
|  | ||||
| /* Add all the DB's pages to the free list. | ||||
|  * [in] mc Cursor on the DB to free. | ||||
|  * [in] subs non-Zero to check for sub-DBs in this DB. | ||||
|  * Returns 0 on success, non-zero on failure. */ | ||||
| static int mdbx_drop0(MDBX_cursor *mc, bool subs) { | ||||
| static int mdbx_drop_tree(MDBX_cursor *mc, const bool may_have_subDBs) { | ||||
|   int rc = mdbx_page_search(mc, NULL, MDBX_PS_FIRST); | ||||
|   if (likely(rc == MDBX_SUCCESS)) { | ||||
|     MDBX_txn *txn = mc->mc_txn; | ||||
| @@ -19131,19 +19109,20 @@ static int mdbx_drop0(MDBX_cursor *mc, bool subs) { | ||||
|      * This also avoids any P_LEAF2 pages, which have no nodes. | ||||
|      * Also if the DB doesn't have sub-DBs and has no overflow | ||||
|      * pages, omit scanning leaves. */ | ||||
|     if ((mc->mc_flags & C_SUB) || (subs | mc->mc_db->md_overflow_pages) == 0) | ||||
|     if ((mc->mc_flags & C_SUB) || | ||||
|         !(may_have_subDBs | mc->mc_db->md_overflow_pages)) | ||||
|       mdbx_cursor_pop(mc); | ||||
|  | ||||
|     rc = mdbx_pnl_need(&txn->tw.retired_pages, | ||||
|                        mc->mc_db->md_branch_pages + mc->mc_db->md_leaf_pages + | ||||
|                            mc->mc_db->md_overflow_pages); | ||||
|     if (unlikely(rc)) | ||||
|       goto done; | ||||
|     if (unlikely(rc != MDBX_SUCCESS)) | ||||
|       goto bailout; | ||||
|  | ||||
|     cursor_copy_internal(mc, &mx); | ||||
|     while (mc->mc_snum > 0) { | ||||
|       MDBX_page *mp = mc->mc_pg[mc->mc_top]; | ||||
|       unsigned n = page_numkeys(mp); | ||||
|       MDBX_page *const mp = mc->mc_pg[mc->mc_top]; | ||||
|       const unsigned n = page_numkeys(mp); | ||||
|       if (IS_LEAF(mp)) { | ||||
|         for (i = 0; i < n; i++) { | ||||
|           MDBX_node *node = page_node(mp, i); | ||||
| @@ -19151,45 +19130,52 @@ static int mdbx_drop0(MDBX_cursor *mc, bool subs) { | ||||
|             MDBX_page *omp; | ||||
|             rc = mdbx_page_get(mc, node_largedata_pgno(node), &omp, NULL, | ||||
|                                pp_txnid4chk(mp, mc->mc_txn)); | ||||
|             if (unlikely(rc)) | ||||
|               goto done; | ||||
|             if (unlikely(rc != MDBX_SUCCESS)) | ||||
|               goto bailout; | ||||
|             mdbx_cassert(mc, IS_OVERFLOW(omp)); | ||||
|             rc = mdbx_page_retire(mc, omp); | ||||
|             if (unlikely(rc)) | ||||
|               goto done; | ||||
|             if (!mc->mc_db->md_overflow_pages && !subs) | ||||
|               break; | ||||
|           } else if (subs && (node_flags(node) & F_SUBDATA)) { | ||||
|             if (unlikely(rc != MDBX_SUCCESS)) | ||||
|               goto bailout; | ||||
|             if (!(may_have_subDBs | mc->mc_db->md_overflow_pages)) | ||||
|               goto pop; | ||||
|           } else if (node_flags(node) & F_SUBDATA) { | ||||
|             if (unlikely((node_flags(node) & F_DUPDATA) == 0)) { | ||||
|               rc = /* disallowing implicit subDB deletion */ MDBX_INCOMPATIBLE; | ||||
|               goto done; | ||||
|               goto bailout; | ||||
|             } | ||||
|             rc = mdbx_xcursor_init1(mc, node, mp); | ||||
|             if (unlikely(rc != MDBX_SUCCESS)) | ||||
|               goto done; | ||||
|             rc = mdbx_drop0(&mc->mc_xcursor->mx_cursor, false); | ||||
|             if (unlikely(rc)) | ||||
|               goto done; | ||||
|               goto bailout; | ||||
|             rc = mdbx_drop_tree(&mc->mc_xcursor->mx_cursor, false); | ||||
|             if (unlikely(rc != MDBX_SUCCESS)) | ||||
|               goto bailout; | ||||
|           } | ||||
|         } | ||||
|         if (!subs && !mc->mc_db->md_overflow_pages) | ||||
|           goto pop; | ||||
|       } else { | ||||
|         if (mdbx_audit_enabled()) | ||||
|           mc->mc_flags |= C_RETIRING; | ||||
|         for (i = 0; i < n; i++) { | ||||
|           /* free it */ | ||||
|           rc = mdbx_retire_pgno(mc, node_pgno(page_node(mp, i))); | ||||
|           if (unlikely(rc)) | ||||
|             goto done; | ||||
|           MDBX_page *np; | ||||
|           rc = mdbx_page_get(mc, node_pgno(page_node(mp, i)), &np, NULL, | ||||
|                              pp_txnid4chk(mp, mc->mc_txn)); | ||||
|           /* TODO: strive to use here only the pgno for retiring, i.e. try to | ||||
|            * avoid read leaf pages without sub-trees nor overflow nodes. */ | ||||
|           if (likely(rc == MDBX_SUCCESS)) | ||||
|             rc = mdbx_page_retire(mc, np); | ||||
|           if (unlikely(rc != MDBX_SUCCESS)) | ||||
|             goto bailout; | ||||
|         } | ||||
|         if (mdbx_audit_enabled()) | ||||
|           mc->mc_flags -= C_RETIRING; | ||||
|       } | ||||
|       if (!mc->mc_top) | ||||
|         break; | ||||
|       mdbx_cassert(mc, i <= UINT16_MAX); | ||||
|       mc->mc_ki[mc->mc_top] = (indx_t)i; | ||||
|       rc = mdbx_cursor_sibling(mc, SIBLING_RIGHT); | ||||
|       if (rc) { | ||||
|       if (unlikely(rc != MDBX_SUCCESS)) { | ||||
|         if (unlikely(rc != MDBX_NOTFOUND)) | ||||
|           goto done; | ||||
|           goto bailout; | ||||
|       /* no more siblings, go back to beginning | ||||
|        * of previous level. */ | ||||
|       pop: | ||||
| @@ -19201,10 +19187,9 @@ static int mdbx_drop0(MDBX_cursor *mc, bool subs) { | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     /* free it */ | ||||
|     rc = mdbx_retire_pgno(mc, mc->mc_db->md_root); | ||||
|   done: | ||||
|     if (unlikely(rc)) | ||||
|     rc = mdbx_page_retire(mc, mc->mc_pg[0]); | ||||
|   bailout: | ||||
|     if (unlikely(rc != MDBX_SUCCESS)) | ||||
|       txn->mt_flags |= MDBX_TXN_ERROR; | ||||
|   } else if (rc == MDBX_NOTFOUND) { | ||||
|     rc = MDBX_SUCCESS; | ||||
| @@ -19223,8 +19208,8 @@ int mdbx_drop(MDBX_txn *txn, MDBX_dbi dbi, bool del) { | ||||
|   if (unlikely(rc != MDBX_SUCCESS)) | ||||
|     return rc; | ||||
|  | ||||
|   rc = mdbx_drop0(mc, | ||||
|                   dbi == MAIN_DBI || (mc->mc_db->md_flags & MDBX_DUPSORT) != 0); | ||||
|   rc = mdbx_drop_tree(mc, dbi == MAIN_DBI || | ||||
|                               (mc->mc_db->md_flags & MDBX_DUPSORT) != 0); | ||||
|   /* Invalidate the dropped DB's cursors */ | ||||
|   for (MDBX_cursor *m2 = txn->tw.cursors[dbi]; m2; m2 = m2->mc_next) | ||||
|     m2->mc_flags &= ~(C_INITIALIZED | C_EOF); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user