Preserve DB flags (use metapage#1) when main DB is empty.
Fail if metapage root != actual root in output file.
* <li>#MDB_CP_COMPACT - Perform compaction while copying: omit free
* pages and sequentially renumber all pages in output. This option
* consumes more CPU and runs more slowly than the default.
* <li>#MDB_CP_COMPACT - Perform compaction while copying: omit free
* pages and sequentially renumber all pages in output. This option
* consumes more CPU and runs more slowly than the default.
+ * Currently it fails if the environment has suffered a page leak.
* </ul>
* @return A non-zero error value on failure and 0 on success.
*/
* </ul>
* @return A non-zero error value on failure and 0 on success.
*/
mdb_copy my = {0};
MDB_txn *txn = NULL;
pthread_t thr;
mdb_copy my = {0};
MDB_txn *txn = NULL;
pthread_t thr;
int rc = MDB_SUCCESS;
#ifdef _WIN32
int rc = MDB_SUCCESS;
#ifdef _WIN32
*(MDB_meta *)METADATA(mp) = *mm;
mm = (MDB_meta *)METADATA(mp);
*(MDB_meta *)METADATA(mp) = *mm;
mm = (MDB_meta *)METADATA(mp);
- /* Count the number of free pages, subtract from lastpg to find
- * number of active pages
- */
- {
+ /* Set metapage 1 with current main DB */
+ root = new_root = txn->mt_dbs[MAIN_DBI].md_root;
+ if (root != P_INVALID) {
+ /* Count free pages + freeDB pages. Subtract from last_pg
+ * to find the new last_pg, which also becomes the new root.
+ */
MDB_ID freecount = 0;
MDB_cursor mc;
MDB_val key, data;
MDB_ID freecount = 0;
MDB_cursor mc;
MDB_val key, data;
txn->mt_dbs[FREE_DBI].md_leaf_pages +
txn->mt_dbs[FREE_DBI].md_overflow_pages;
txn->mt_dbs[FREE_DBI].md_leaf_pages +
txn->mt_dbs[FREE_DBI].md_overflow_pages;
- /* Set metapage 1 */
- mm->mm_last_pg = txn->mt_next_pgno - freecount - 1;
+ new_root = txn->mt_next_pgno - 1 - freecount;
+ mm->mm_last_pg = new_root;
mm->mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
mm->mm_dbs[MAIN_DBI] = txn->mt_dbs[MAIN_DBI];
- if (mm->mm_last_pg > NUM_METAS-1) {
- mm->mm_dbs[MAIN_DBI].md_root = mm->mm_last_pg;
- mm->mm_txnid = 1;
- } else {
- mm->mm_dbs[MAIN_DBI].md_root = P_INVALID;
- }
+ mm->mm_dbs[MAIN_DBI].md_root = new_root;
+ } else {
+ /* When the DB is empty, handle it specially to
+ * fix any breakage like page leaks from ITS#8174.
+ */
+ mm->mm_dbs[MAIN_DBI].md_flags = txn->mt_dbs[MAIN_DBI].md_flags;
+ }
+ if (root != P_INVALID || mm->mm_dbs[MAIN_DBI].md_flags) {
+ mm->mm_txnid = 1; /* use metapage 1 */
my.mc_wlen[0] = env->me_psize * NUM_METAS;
my.mc_txn = txn;
my.mc_wlen[0] = env->me_psize * NUM_METAS;
my.mc_txn = txn;
- rc = mdb_env_cwalk(&my, &txn->mt_dbs[MAIN_DBI].md_root, 0);
+ rc = mdb_env_cwalk(&my, &root, 0);
+ if (rc == MDB_SUCCESS && root != new_root) {
+ rc = MDB_INCOMPATIBLE; /* page leak or corrupt DB */
+ }
Compact while copying. Only current data pages will be copied; freed
or unused pages will be omitted from the copy. This option will
slow down the backup process as it is more CPU-intensive.
Compact while copying. Only current data pages will be copied; freed
or unused pages will be omitted from the copy. This option will
slow down the backup process as it is more CPU-intensive.
+Currently it fails if the environment has suffered a page leak.
.TP
.BR \-n
Open LDMB environment(s) which do not use subdirectories.
.TP
.BR \-n
Open LDMB environment(s) which do not use subdirectories.