Skip to content

Commit 9a629aa

Browse files
authored
Simplification storage initialization of the dual-store database backend (#3870)
## Motivation After #3787, it is no longer needed to initialize the shard of the dual-store databases separately. ## Proposal Remove special code added in #2734 ## Test Plan CI
1 parent 01c6f6f commit 9a629aa

File tree

3 files changed

+117
-170
lines changed

3 files changed

+117
-170
lines changed

linera-service/src/cli_wrappers/local_net.rs

Lines changed: 62 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#[cfg(with_testing)]
55
use std::sync::LazyLock;
66
use std::{
7-
collections::{BTreeMap, HashSet},
7+
collections::BTreeMap,
88
env,
99
path::{Path, PathBuf},
1010
sync::Arc,
@@ -195,9 +195,9 @@ pub struct LocalNet {
195195
num_shards: usize,
196196
validator_keys: BTreeMap<usize, (String, String)>,
197197
running_validators: BTreeMap<usize, Validator>,
198-
namespace: String,
199-
validators_with_initialized_storage: HashSet<usize>,
200-
storage_config: StorageConfig,
198+
initialized_validator_storages: BTreeMap<usize, StorageConfigNamespace>,
199+
common_namespace: String,
200+
common_storage_config: StorageConfig,
201201
cross_chain_config: CrossChainConfig,
202202
path_provider: PathProvider,
203203
num_block_exporters: u32,
@@ -379,10 +379,10 @@ impl LocalNet {
379379
fn new(
380380
network: NetworkConfig,
381381
testing_prng_seed: Option<u64>,
382-
namespace: String,
382+
common_namespace: String,
383383
num_initial_validators: usize,
384384
num_shards: usize,
385-
storage_config: StorageConfig,
385+
common_storage_config: StorageConfig,
386386
cross_chain_config: CrossChainConfig,
387387
path_provider: PathProvider,
388388
num_block_exporters: u32,
@@ -395,9 +395,9 @@ impl LocalNet {
395395
num_shards,
396396
validator_keys: BTreeMap::new(),
397397
running_validators: BTreeMap::new(),
398-
namespace,
399-
validators_with_initialized_storage: HashSet::new(),
400-
storage_config,
398+
initialized_validator_storages: BTreeMap::new(),
399+
common_namespace,
400+
common_storage_config,
401401
cross_chain_config,
402402
path_provider,
403403
num_block_exporters,
@@ -559,12 +559,15 @@ impl LocalNet {
559559
}
560560

561561
async fn run_proxy(&mut self, validator: usize) -> Result<Child> {
562-
let storage = self.initialize_shared_storage(validator).await?;
562+
let storage = self
563+
.initialized_validator_storages
564+
.get(&validator)
565+
.expect("initialized storage");
563566
let child = self
564567
.command_for_binary("linera-proxy")
565568
.await?
566569
.arg(format!("server_{}.json", validator))
567-
.args(["--storage", &storage])
570+
.args(["--storage", &storage.to_string()])
568571
.args(["--genesis", "genesis.json"])
569572
.spawn_into()?;
570573

@@ -588,14 +591,17 @@ impl LocalNet {
588591
}
589592

590593
async fn run_exporter(&mut self, validator: usize, exporter_id: u32) -> Result<Child> {
591-
let storage = self.initialize_shared_storage(validator).await?;
592594
let config_path = format!("exporter_config_{validator}:{exporter_id}.toml");
595+
let storage = self
596+
.initialized_validator_storages
597+
.get(&validator)
598+
.expect("initialized storage");
593599

594600
let child = self
595601
.command_for_binary("linera-exporter")
596602
.await?
597603
.arg(config_path)
598-
.args(["--storage", &storage])
604+
.args(["--storage", &storage.to_string()])
599605
.args(["--genesis", "genesis.json"])
600606
.spawn_into()?;
601607

@@ -652,84 +658,43 @@ impl LocalNet {
652658
bail!("Failed to start {nickname}");
653659
}
654660

655-
async fn initialize_storage_internal(&mut self, storage: &str, genesis: &str) -> Result<()> {
656-
let max_try = 4;
657-
let mut i_try = 0;
658-
loop {
659-
let mut command = self.command_for_binary("linera-server").await?;
660-
if let Ok(var) = env::var(SERVER_ENV) {
661-
command.args(var.split_whitespace());
662-
}
663-
command.arg("initialize");
664-
let result = command
665-
.args(["--storage", storage])
666-
.args(["--genesis", genesis])
667-
.spawn_and_wait_for_stdout()
668-
.await;
669-
if result.is_ok() {
670-
return Ok(());
671-
}
672-
warn!(
673-
"Failed to initialize storage={} using linera-server, i_try={}, error={:?}",
674-
storage, i_try, result
675-
);
676-
i_try += 1;
677-
if i_try == max_try {
678-
bail!("Failed to initialize after {} attempts", max_try);
679-
}
680-
let one_second = linera_base::time::Duration::from_secs(1);
681-
std::thread::sleep(one_second);
682-
}
683-
}
684-
685-
async fn initialize_shared_storage(&mut self, validator: usize) -> Result<String> {
686-
let namespace = format!("{}_server_{}_db", self.namespace, validator);
687-
let storage_config = self.storage_config.get_shared_storage();
661+
async fn initialize_storage(&mut self, validator: usize) -> Result<()> {
662+
let namespace = format!("{}_server_{}_db", self.common_namespace, validator);
663+
let storage_config = self.common_storage_config.clone();
688664
let storage = StorageConfigNamespace {
689665
storage_config,
690666
namespace,
691-
}
692-
.to_string();
693-
if !self
694-
.validators_with_initialized_storage
695-
.contains(&validator)
696-
{
697-
self.initialize_storage_internal(&storage, "genesis.json")
698-
.await?;
699-
self.validators_with_initialized_storage.insert(validator);
700-
}
701-
Ok(storage)
702-
}
703-
704-
async fn initialize_storage(&mut self, validator: usize, shard: usize) -> Result<String> {
705-
if self.storage_config.are_chains_shared() {
706-
self.initialize_shared_storage(validator).await
707-
} else {
708-
let namespace = format!("{}_server_{}_db", self.namespace, validator);
709-
let mut storage_config = self.storage_config.clone();
710-
let shard_str = format!("shard_{}", shard);
711-
storage_config.append_shard_str(&shard_str);
712-
let storage = StorageConfigNamespace {
713-
storage_config,
714-
namespace,
715-
}
716-
.to_string();
667+
};
717668

718-
self.initialize_storage_internal(&storage, "genesis.json")
719-
.await?;
720-
Ok(storage)
669+
let mut command = self.command_for_binary("linera-server").await?;
670+
if let Ok(var) = env::var(SERVER_ENV) {
671+
command.args(var.split_whitespace());
721672
}
673+
command.arg("initialize");
674+
command
675+
.args(["--storage", &storage.to_string()])
676+
.args(["--genesis", "genesis.json"])
677+
.spawn_and_wait_for_stdout()
678+
.await?;
679+
680+
self.initialized_validator_storages
681+
.insert(validator, storage);
682+
Ok(())
722683
}
723684

724685
async fn run_server(&mut self, validator: usize, shard: usize) -> Result<Child> {
725-
let storage = self.initialize_storage(validator, shard).await?;
686+
let storage = self
687+
.initialized_validator_storages
688+
.get(&validator)
689+
.expect("initialized storage");
690+
726691
let mut command = self.command_for_binary("linera-server").await?;
727692
if let Ok(var) = env::var(SERVER_ENV) {
728693
command.args(var.split_whitespace());
729694
}
730695
command
731696
.arg("run")
732-
.args(["--storage", &storage])
697+
.args(["--storage", &storage.to_string()])
733698
.args(["--server", &format!("server_{}.json", validator)])
734699
.args(["--shard", &shard.to_string()])
735700
.args(["--genesis", "genesis.json"])
@@ -762,28 +727,34 @@ impl LocalNet {
762727
Ok(())
763728
}
764729

765-
pub async fn start_validator(&mut self, validator: usize) -> Result<()> {
766-
let proxy = self.run_proxy(validator).await?;
767-
let mut validator_proxy = Validator::new(proxy);
730+
/// Start a validator.
731+
pub async fn start_validator(&mut self, index: usize) -> Result<()> {
732+
self.initialize_storage(index).await?;
733+
self.restart_validator(index).await
734+
}
735+
736+
/// Restart a validator. This is similar to `start_validator` except that the
737+
/// database was already initialized once.
738+
pub async fn restart_validator(&mut self, index: usize) -> Result<()> {
739+
let proxy = self.run_proxy(index).await?;
740+
let mut validator = Validator::new(proxy);
768741
for shard in 0..self.num_shards {
769-
let server = self.run_server(validator, shard).await?;
770-
validator_proxy.add_server(server);
742+
let server = self.run_server(index, shard).await?;
743+
validator.add_server(server);
771744
}
772-
773745
for block_exporter in 0..self.num_block_exporters {
774-
let exporter = self.run_exporter(validator, block_exporter).await?;
775-
validator_proxy.add_block_exporter(exporter);
746+
let exporter = self.run_exporter(index, block_exporter).await?;
747+
validator.add_block_exporter(exporter);
776748
}
777-
778-
self.running_validators.insert(validator, validator_proxy);
749+
self.running_validators.insert(index, validator);
779750
Ok(())
780751
}
781752

782753
/// Terminates all the processes of a given validator.
783-
pub async fn stop_validator(&mut self, validator_index: usize) -> Result<()> {
784-
if let Some(mut validator) = self.running_validators.remove(&validator_index) {
754+
pub async fn stop_validator(&mut self, index: usize) -> Result<()> {
755+
if let Some(mut validator) = self.running_validators.remove(&index) {
785756
if let Err(error) = validator.terminate().await {
786-
error!("Failed to stop validator {validator_index}: {error}");
757+
error!("Failed to stop validator {index}: {error}");
787758
return Err(error);
788759
}
789760
}
@@ -857,7 +828,7 @@ impl LocalNet {
857828
let server = self.run_server(validator, shard).await?;
858829
self.running_validators
859830
.get_mut(&validator)
860-
.context("could not find server")?
831+
.context("could not find validator")?
861832
.add_server(server);
862833
Ok(())
863834
}

0 commit comments

Comments
 (0)