diff --git a/ledger/src/blockstore.rs b/ledger/src/blockstore.rs index 984932a0e08ab7..bcbb552bb42aed 100644 --- a/ledger/src/blockstore.rs +++ b/ledger/src/blockstore.rs @@ -731,7 +731,7 @@ impl Blockstore { fn try_shred_recovery( &self, - erasure_metas: &HashMap, + erasure_metas: &HashMap, index_working_set: &mut HashMap, prev_inserted_shreds: &HashMap, reed_solomon_cache: &ReedSolomonCache, @@ -742,7 +742,7 @@ impl Blockstore { // 2. For new data shreds, check if an erasure set exists. If not, don't try recovery // 3. Before trying recovery, check if enough number of shreds have been received // 3a. Enough number of shreds = (#data + #coding shreds) > erasure.num_data - for (erasure_set, erasure_meta) in erasure_metas.iter() { + for (erasure_set, (erasure_meta, _)) in erasure_metas.iter() { let slot = erasure_set.slot(); let index_meta_entry = index_working_set.get_mut(&slot).expect("Index"); let index = &mut index_meta_entry.index; @@ -1017,11 +1017,20 @@ impl Blockstore { &mut write_batch, )?; - for (erasure_set, erasure_meta) in erasure_metas { - write_batch.put::(erasure_set.store_key(), &erasure_meta)?; + for (erasure_set, (erasure_meta, is_new)) in erasure_metas { + if !is_new { + // No need to rewrite the column + continue; + } + let (slot, fec_set_index) = erasure_set.store_key(); + write_batch.put::((slot, fec_set_index), &erasure_meta)?; } - for (erasure_set, merkle_root_meta) in merkle_root_metas { + for (erasure_set, (merkle_root_meta, is_new)) in merkle_root_metas { + if !is_new { + // No need to rewrite the column + continue; + } write_batch.put::(erasure_set.key(), &merkle_root_meta)?; } @@ -1181,8 +1190,8 @@ impl Blockstore { fn check_insert_coding_shred( &self, shred: Shred, - erasure_metas: &mut HashMap, - merkle_root_metas: &mut HashMap, + erasure_metas: &mut HashMap, + merkle_root_metas: &mut HashMap, index_working_set: &mut HashMap, write_batch: &mut WriteBatch, just_received_shreds: &mut HashMap, @@ -1203,7 +1212,7 @@ impl Blockstore { if let HashMapEntry::Vacant(entry) = merkle_root_metas.entry(erasure_set) { if let Some(meta) = self.merkle_root_meta(erasure_set).unwrap() { - entry.insert(meta); + entry.insert((meta, /* is_new */ false)); } } @@ -1222,10 +1231,16 @@ impl Blockstore { } } - let erasure_meta = erasure_metas.entry(erasure_set).or_insert_with(|| { + let (erasure_meta, _) = erasure_metas.entry(erasure_set).or_insert_with(|| { self.erasure_meta(erasure_set) .expect("Expect database get to succeed") - .unwrap_or_else(|| ErasureMeta::from_coding_shred(&shred).unwrap()) + .map(|erasure_meta| (erasure_meta, false /* is_new */)) + .unwrap_or_else(|| { + ( + ErasureMeta::from_coding_shred(&shred).unwrap(), + true, /* is_new */ + ) + }) }); if !erasure_meta.check_coding_shred(&shred) { @@ -1287,7 +1302,7 @@ impl Blockstore { merkle_root_metas .entry(erasure_set) - .or_insert(MerkleRootMeta::from_shred(&shred)); + .or_insert((MerkleRootMeta::from_shred(&shred), true /* is _new */)); } if let HashMapEntry::Vacant(entry) = just_received_shreds.entry(shred.id()) { @@ -1370,8 +1385,8 @@ impl Blockstore { fn check_insert_data_shred( &self, shred: Shred, - erasure_metas: &mut HashMap, - merkle_root_metas: &mut HashMap, + erasure_metas: &mut HashMap, + merkle_root_metas: &mut HashMap, index_working_set: &mut HashMap, slot_meta_working_set: &mut HashMap, write_batch: &mut WriteBatch, @@ -1400,7 +1415,7 @@ impl Blockstore { let erasure_set = shred.erasure_set(); if let HashMapEntry::Vacant(entry) = merkle_root_metas.entry(erasure_set) { if let Some(meta) = self.merkle_root_meta(erasure_set).unwrap() { - entry.insert(meta); + entry.insert((meta, false /* is_new */)); } } @@ -1446,13 +1461,13 @@ impl Blockstore { )?; merkle_root_metas .entry(erasure_set) - .or_insert(MerkleRootMeta::from_shred(&shred)); + .or_insert((MerkleRootMeta::from_shred(&shred), true /* is_new */)); just_inserted_shreds.insert(shred.id(), shred); index_meta_working_set_entry.did_insert_occur = true; slot_meta_entry.did_insert_occur = true; if let HashMapEntry::Vacant(entry) = erasure_metas.entry(erasure_set) { if let Some(meta) = self.erasure_meta(erasure_set).unwrap() { - entry.insert(meta); + entry.insert((meta, false /* is_new */)); } } Ok(newly_completed_data_sets) @@ -6808,6 +6823,7 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .merkle_root(), coding_shred.merkle_root().ok(), ); @@ -6815,6 +6831,7 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), index ); @@ -6822,11 +6839,12 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .first_received_shred_type(), ShredType::Code, ); - for (erasure_set, merkle_root_meta) in merkle_root_metas { + for (erasure_set, (merkle_root_meta, _)) in merkle_root_metas { write_batch .put::(erasure_set.key(), &merkle_root_meta) .unwrap(); @@ -6864,6 +6882,7 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .merkle_root(), coding_shred.merkle_root().ok() ); @@ -6871,6 +6890,7 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), index ); @@ -6920,6 +6940,7 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .merkle_root(), coding_shred.merkle_root().ok() ); @@ -6927,6 +6948,7 @@ pub mod tests { merkle_root_metas .get(&coding_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), index ); @@ -6934,6 +6956,7 @@ pub mod tests { merkle_root_metas .get(&new_coding_shred.erasure_set()) .unwrap() + .0 .merkle_root(), new_coding_shred.merkle_root().ok() ); @@ -6941,6 +6964,7 @@ pub mod tests { merkle_root_metas .get(&new_coding_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), new_index ); @@ -6988,6 +7012,7 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .merkle_root(), data_shred.merkle_root().ok() ); @@ -6995,6 +7020,7 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), index ); @@ -7002,11 +7028,12 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .first_received_shred_type(), ShredType::Data, ); - for (erasure_set, merkle_root_meta) in merkle_root_metas { + for (erasure_set, (merkle_root_meta, _)) in merkle_root_metas { write_batch .put::(erasure_set.key(), &merkle_root_meta) .unwrap(); @@ -7048,6 +7075,7 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .merkle_root(), data_shred.merkle_root().ok() ); @@ -7055,6 +7083,7 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), index ); @@ -7114,6 +7143,7 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .merkle_root(), data_shred.merkle_root().ok() ); @@ -7121,6 +7151,7 @@ pub mod tests { merkle_root_metas .get(&data_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), index ); @@ -7128,6 +7159,7 @@ pub mod tests { merkle_root_metas .get(&new_data_shred.erasure_set()) .unwrap() + .0 .merkle_root(), new_data_shred.merkle_root().ok() ); @@ -7135,6 +7167,7 @@ pub mod tests { merkle_root_metas .get(&new_data_shred.erasure_set()) .unwrap() + .0 .first_received_shred_index(), new_index );