Keep failed LMDB opens retryable and stop backend copies from losing short all-zero keys (#5267) * Keep a failed LMDB open from leaving its environment behind backend_lmdb::open_impl stored the new environment in the backend before it opened the schema's tables. When a required table was missing, such as on a read-only open of a database that lacks it, open_table threw and the environment stayed assigned while the backend reported itself closed. Retrying the open on the same backend then aborted on the "environment already open" assert. The environment now stays local until every table has opened and the opening transaction has committed, and is adopted together with the table handles. A failed open closes it on unwinding, after aborting the transaction, and leaves the backend closed and retryable, as the RocksDB backend already does. * Start the first parallel traversal partition at the table's beginning backend::for_each_par split a table into partitions at 32 byte keys whose first byte is the partition boundary, and the first partition started at a lower bound of 32 zero bytes. Keys sort bytewise with a shorter prefix first, so an all-zero key shorter than 32 bytes sorts below that bound and no partition visited it. copy_to traverses every table this way, so a migration dropped such keys without an error: an online weight record at timestamp 0, whose key is 8 zero bytes, never reached the destination. The first partition now starts at begin (), the way the last one already ends at end (). The boundaries between partitions were not affected: a short key just below one still sorts above the previous one and lands in the partition before it. * Fail copy_to when a table copies fewer entries than its source holds copy_to counted each source table up front, but used the count only for progress reports. When the traversal visited fewer entries, as it did for all-zero keys shorter than 32 bytes, the copy finished without an error and the destination stayed short, so the LMDB to RocksDB migration reported success over lost records. After each table, copy_to now compares the entries it copied with the source count and throws when they differ, naming the table and both numbers. Tables whose backend only estimates its count, the RocksDB pruned and final vote tables, are not checked; an LMDB source, the one the migration copies from, counts every table exactly. The test makes the traversal miss a key through a new before_count hook on hooked_backend: it deletes a source key after copy_to opened the transaction it counts in, so the key is counted but no longer traversed. Without the check the copy completes on both backends.
__________
Type: commit
Hash: fb528ae4e8bd810c852937205f1acea59a6af44f
Created: today
__________
gr0v1ty/nano-node:fb528ae4e8bd810c852937205f1acea59a6af44f
| Test Case | Status | Duration | Median Deviation | Log | Graph |
|---|---|---|---|---|---|
| 5n4pr_conf_10k_bintree | PASS | 122 s | 10.0 s | GitHub job logs | Show |
| 5n4pr_conf_10k_change | PASS | 124 s | -11.0 s | GitHub job logs | Show |
| 5n4pr_conf_change_dependant | PASS | 127 s | 10.0 s | GitHub job logs | - |
| 5n4pr_conf_change_independant | PASS | 108 s | -4.0 s | GitHub job logs | - |
| 5n4pr_conf_send_dependant | PASS | 120 s | 5.0 s | GitHub job logs | - |
| 5n4pr_conf_send_independant | PASS | 132 s | 19.0 s | GitHub job logs | - |
| 5n4pr_rocks_10k_bintree | PASS | 110 s | -2.0 s | GitHub job logs | - |
| 5n4pr_rocks_10k_change | PASS | 436 s | 278.0 s | GitHub job logs | - |