mirror of
				https://github.com/isar/libmdbx.git
				synced 2025-10-31 15:38:57 +08:00 
			
		
		
		
	mdbx: rework nested transactions and write-transaction state.
This resolves https://github.com/leo-yuriev/libmdbx/issues/62 Change-Id: Icbd762ca69ab1ccf8c3440c71931d2ac14599a1b
This commit is contained in:
		
							
								
								
									
										1075
									
								
								src/elements/core.c
									
									
									
									
									
								
							
							
						
						
									
										1075
									
								
								src/elements/core.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -658,7 +658,7 @@ typedef pgno_t *MDBX_PNL; | |||||||
| #define MDBX_PNL_DISORDERED(first, last) ((first) <= (last)) | #define MDBX_PNL_DISORDERED(first, last) ((first) <= (last)) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* List of txnid, only for MDBX_env.mt_lifo_reclaimed */ | /* List of txnid, only for MDBX_txn.tw.lifo_reclaimed */ | ||||||
| typedef txnid_t *MDBX_TXL; | typedef txnid_t *MDBX_TXL; | ||||||
|  |  | ||||||
| /* An Dirty-Page list item is an pgno/pointer pair. */ | /* An Dirty-Page list item is an pgno/pointer pair. */ | ||||||
| @@ -747,31 +747,42 @@ struct MDBX_txn { | |||||||
|    * aborts, the ID may be re-used by the next writer. */ |    * aborts, the ID may be re-used by the next writer. */ | ||||||
|   txnid_t mt_txnid; |   txnid_t mt_txnid; | ||||||
|   MDBX_env *mt_env; /* the DB environment */ |   MDBX_env *mt_env; /* the DB environment */ | ||||||
|                     /* The list of reclaimed txns from freeDB */ |  | ||||||
|   MDBX_TXL mt_lifo_reclaimed; |  | ||||||
|   /* The list of pages that became unused during this transaction. */ |  | ||||||
|   MDBX_PNL mt_retired_pages; |  | ||||||
|   /* The list of loose pages that became unused and may be reused |  | ||||||
|    * in this transaction, linked through NEXT_LOOSE_PAGE(page). */ |  | ||||||
|   MDBX_page *mt_loose_pages; |  | ||||||
|   /* Number of loose pages (mt_loose_pages) */ |  | ||||||
|   unsigned mt_loose_count; |  | ||||||
|   /* The sorted list of dirty pages we temporarily wrote to disk |  | ||||||
|    * because the dirty list was full. page numbers in here are |  | ||||||
|    * shifted left by 1, deleted slots have the LSB set. */ |  | ||||||
|   MDBX_PNL mt_spill_pages; |  | ||||||
|   union { |  | ||||||
|     /* For write txns: Modified pages. Sorted when not MDBX_WRITEMAP. */ |  | ||||||
|     MDBX_DPL mt_rw_dirtylist; |  | ||||||
|     /* For read txns: This thread/txn's reader table slot, or NULL. */ |  | ||||||
|     MDBX_reader *mt_ro_reader; |  | ||||||
|   }; |  | ||||||
|   /* Array of records for each DB known in the environment. */ |   /* Array of records for each DB known in the environment. */ | ||||||
|   MDBX_dbx *mt_dbxs; |   MDBX_dbx *mt_dbxs; | ||||||
|   /* Array of MDBX_db records for each known DB */ |   /* Array of MDBX_db records for each known DB */ | ||||||
|   MDBX_db *mt_dbs; |   MDBX_db *mt_dbs; | ||||||
|   /* Array of sequence numbers for each DB handle */ |   /* Array of sequence numbers for each DB handle */ | ||||||
|   unsigned *mt_dbiseqs; |   unsigned *mt_dbiseqs; | ||||||
|  |   union { | ||||||
|  |     struct { | ||||||
|  |       /* For read txns: This thread/txn's reader table slot, or NULL. */ | ||||||
|  |       MDBX_reader *reader; | ||||||
|  |     } to; | ||||||
|  |     struct { | ||||||
|  |       /* The list of reclaimed txns from GC */ | ||||||
|  |       MDBX_TXL lifo_reclaimed; | ||||||
|  |       /* The list of pages that became unused during this transaction. */ | ||||||
|  |       MDBX_PNL retired_pages; | ||||||
|  |       /* The list of loose pages that became unused and may be reused | ||||||
|  |        * in this transaction, linked through NEXT_LOOSE_PAGE(page). */ | ||||||
|  |       MDBX_page *loose_pages; | ||||||
|  |       /* Number of loose pages (tw.loose_pages) */ | ||||||
|  |       unsigned loose_count; | ||||||
|  |       /* The sorted list of dirty pages we temporarily wrote to disk | ||||||
|  |        * because the dirty list was full. page numbers in here are | ||||||
|  |        * shifted left by 1, deleted slots have the LSB set. */ | ||||||
|  |       MDBX_PNL spill_pages; | ||||||
|  |       /* dirtylist room: Array size - dirty pages visible to this txn. | ||||||
|  |        * Includes ancestor txns' dirty pages not hidden by other txns' | ||||||
|  |        * dirty/spilled pages. Thus commit(nested txn) has room to merge | ||||||
|  |        * dirtylist into mt_parent after freeing hidden mt_parent pages. */ | ||||||
|  |       unsigned dirtyroom; | ||||||
|  |       /* For write txns: Modified pages. Sorted when not MDBX_WRITEMAP. */ | ||||||
|  |       MDBX_DPL dirtylist; | ||||||
|  |       pgno_t *reclaimed_pglist; /* Reclaimed freeDB pages */ | ||||||
|  |       txnid_t last_reclaimed;   /* ID of last used record */ | ||||||
|  |     } tw; | ||||||
|  |   }; | ||||||
|  |  | ||||||
| /* Transaction DB Flags */ | /* Transaction DB Flags */ | ||||||
| #define DB_DIRTY MDBX_TBL_DIRTY /* DB was written in this txn */ | #define DB_DIRTY MDBX_TBL_DIRTY /* DB was written in this txn */ | ||||||
| @@ -790,11 +801,6 @@ struct MDBX_txn { | |||||||
|    * This number only ever increments until the txn finishes; we |    * This number only ever increments until the txn finishes; we | ||||||
|    * don't decrement it when individual DB handles are closed. */ |    * don't decrement it when individual DB handles are closed. */ | ||||||
|   MDBX_dbi mt_numdbs; |   MDBX_dbi mt_numdbs; | ||||||
|   /* dirtylist room: Array size - dirty pages visible to this txn. |  | ||||||
|    * Includes ancestor txns' dirty pages not hidden by other txns' |  | ||||||
|    * dirty/spilled pages. Thus commit(nested txn) has room to merge |  | ||||||
|    * dirtylist into mt_parent after freeing hidden mt_parent pages. */ |  | ||||||
|   unsigned mt_dirtyroom; |  | ||||||
|   size_t mt_owner; /* thread ID that owns this transaction */ |   size_t mt_owner; /* thread ID that owns this transaction */ | ||||||
|   mdbx_canary mt_canary; |   mdbx_canary mt_canary; | ||||||
| }; | }; | ||||||
| @@ -843,7 +849,7 @@ struct MDBX_cursor { | |||||||
| #define C_DEL 0x08                /* last op was a cursor_del */ | #define C_DEL 0x08                /* last op was a cursor_del */ | ||||||
| #define C_UNTRACK 0x10            /* Un-track cursor when closing */ | #define C_UNTRACK 0x10            /* Un-track cursor when closing */ | ||||||
| #define C_RECLAIMING 0x20         /* FreeDB lookup is prohibited */ | #define C_RECLAIMING 0x20         /* FreeDB lookup is prohibited */ | ||||||
| #define C_GCFREEZE 0x40           /* me_reclaimed_pglist must not be updated */ | #define C_GCFREEZE 0x40           /* reclaimed_pglist must not be updated */ | ||||||
|   unsigned mc_flags;              /* see mdbx_cursor */ |   unsigned mc_flags;              /* see mdbx_cursor */ | ||||||
|   MDBX_page *mc_pg[CURSOR_STACK]; /* stack of pushed pages */ |   MDBX_page *mc_pg[CURSOR_STACK]; /* stack of pushed pages */ | ||||||
|   indx_t mc_ki[CURSOR_STACK];     /* stack of page indices */ |   indx_t mc_ki[CURSOR_STACK];     /* stack of page indices */ | ||||||
| @@ -884,13 +890,6 @@ typedef struct MDBX_cursor_couple { | |||||||
|       (mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node);                \ |       (mc)->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(xr_node);                \ | ||||||
|   } while (0) |   } while (0) | ||||||
|  |  | ||||||
| /* State of FreeDB old pages, stored in the MDBX_env */ |  | ||||||
| typedef struct MDBX_pgstate { |  | ||||||
|   pgno_t *mf_reclaimed_pglist; /* Reclaimed freeDB pages, or NULL before use */ |  | ||||||
|   txnid_t mf_last_reclaimed;   /* ID of last used record, or 0 if |  | ||||||
|                                   !mf_reclaimed_pglist */ |  | ||||||
| } MDBX_pgstate; |  | ||||||
|  |  | ||||||
| /* The database environment. */ | /* The database environment. */ | ||||||
| struct MDBX_env { | struct MDBX_env { | ||||||
| #define MDBX_ME_SIGNATURE UINT32_C(0x9A899641) | #define MDBX_ME_SIGNATURE UINT32_C(0x9A899641) | ||||||
| @@ -932,9 +931,6 @@ struct MDBX_env { | |||||||
|   uint16_t *me_dbflags;        /* array of flags from MDBX_db.md_flags */ |   uint16_t *me_dbflags;        /* array of flags from MDBX_db.md_flags */ | ||||||
|   unsigned *me_dbiseqs;        /* array of dbi sequence numbers */ |   unsigned *me_dbiseqs;        /* array of dbi sequence numbers */ | ||||||
|   volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */ |   volatile txnid_t *me_oldest; /* ID of oldest reader last time we looked */ | ||||||
|   MDBX_pgstate me_pgstate;     /* state of old pages from freeDB */ |  | ||||||
| #define me_last_reclaimed me_pgstate.mf_last_reclaimed |  | ||||||
| #define me_reclaimed_pglist me_pgstate.mf_reclaimed_pglist |  | ||||||
|   MDBX_page *me_dpages;        /* list of malloc'd blocks for re-use */ |   MDBX_page *me_dpages;        /* list of malloc'd blocks for re-use */ | ||||||
|   /* PNL of pages that became unused in a write txn */ |   /* PNL of pages that became unused in a write txn */ | ||||||
|   MDBX_PNL me_retired_pages; |   MDBX_PNL me_retired_pages; | ||||||
| @@ -991,12 +987,6 @@ struct MDBX_env { | |||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Nested transaction */ |  | ||||||
| typedef struct MDBX_ntxn { |  | ||||||
|   MDBX_txn mnt_txn;         /* the transaction */ |  | ||||||
|   MDBX_pgstate mnt_pgstate; /* parent transaction's saved freestate */ |  | ||||||
| } MDBX_ntxn; |  | ||||||
|  |  | ||||||
| /*----------------------------------------------------------------------------*/ | /*----------------------------------------------------------------------------*/ | ||||||
| /* Debug and Logging stuff */ | /* Debug and Logging stuff */ | ||||||
|  |  | ||||||
| @@ -1235,7 +1225,7 @@ MDBX_INTERNAL_FUNC void mdbx_rthc_thread_dtor(void *ptr); | |||||||
| /* The number of overflow pages needed to store the given size. */ | /* The number of overflow pages needed to store the given size. */ | ||||||
| #define OVPAGES(env, size) (bytes2pgno(env, PAGEHDRSZ - 1 + (size)) + 1) | #define OVPAGES(env, size) (bytes2pgno(env, PAGEHDRSZ - 1 + (size)) + 1) | ||||||
|  |  | ||||||
| /* Link in MDBX_txn.mt_loose_pages list. | /* Link in MDBX_txn.tw.loose_pages list. | ||||||
|  * Kept outside the page header, which is needed when reusing the page. */ |  * Kept outside the page header, which is needed when reusing the page. */ | ||||||
| #define NEXT_LOOSE_PAGE(p) (*(MDBX_page **)((p) + 2)) | #define NEXT_LOOSE_PAGE(p) (*(MDBX_page **)((p) + 2)) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user