-
Notifications
You must be signed in to change notification settings - Fork 31
Min-quorum reconciliation #1733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
ac5c71a
8e21369
cc512f4
51bcd24
cf1e0f8
bdcfc08
29dc1af
fb2b632
7518927
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2517,7 +2517,8 @@ async fn replace_before_active( | |
| // generation numbers. | ||
| fill_workload(volume, di, true).await?; | ||
| let ds_total = targets.len() - 1; | ||
| let mut old_ds = 0; | ||
| let mut old_ds_a = 0; | ||
| let mut old_ds_b = 1; | ||
| let mut new_ds = targets.len() - 1; | ||
| for c in 1.. { | ||
| info!(log, "[{c}] Touch every extent"); | ||
|
|
@@ -2533,41 +2534,44 @@ async fn replace_before_active( | |
| tokio::time::sleep(tokio::time::Duration::from_secs(4)).await; | ||
| } | ||
|
|
||
| // Stop a downstairs, wait for dsc to confirm it is stopped. | ||
| dsc_client.dsc_stop(old_ds).await.unwrap(); | ||
| loop { | ||
| let res = dsc_client.dsc_get_ds_state(old_ds).await.unwrap(); | ||
| let state = res.into_inner(); | ||
| if state == DownstairsState::Exit { | ||
| break; | ||
| // Stop two downstairs, wait for dsc to confirm they are stopped. | ||
| for old_ds in [old_ds_a, old_ds_b] { | ||
| dsc_client.dsc_stop(old_ds).await.unwrap(); | ||
| loop { | ||
| let res = dsc_client.dsc_get_ds_state(old_ds).await.unwrap(); | ||
| let state = res.into_inner(); | ||
| if state == DownstairsState::Exit { | ||
| break; | ||
| } | ||
| tokio::time::sleep(tokio::time::Duration::from_secs(4)).await; | ||
| } | ||
| tokio::time::sleep(tokio::time::Duration::from_secs(4)).await; | ||
| } | ||
|
|
||
| info!(log, "[{c}] Request the upstairs activate"); | ||
| // Spawn a task to re-activate, this will not finish till all three | ||
| // downstairs respond. | ||
| // Spawn a task to re-activate, this will not finish until 2-3 | ||
| // downstairs respond (and we have disabled all but 1) | ||
| gen += 1; | ||
| let gc = volume.clone(); | ||
| let handle = | ||
| tokio::spawn(async move { gc.activate_with_gen(gen).await }); | ||
|
|
||
| // Give the activation request time to percolate in the upstairs. | ||
| // Give the activation request time to percolate in the upstairs; it | ||
| // shouldn't get anywhere because we don't have enough downstairs | ||
| tokio::time::sleep(tokio::time::Duration::from_secs(4)).await; | ||
| let is_active = volume.query_is_active().await.unwrap(); | ||
| info!(log, "[{c}] activate should now be waiting {:?}", is_active); | ||
| assert!(!is_active); | ||
|
|
||
| info!( | ||
| log, | ||
| "[{c}] Replacing DS {old_ds}:{} with {new_ds}:{}", | ||
| targets[old_ds as usize], | ||
| "[{c}] Replacing DS {old_ds_a}:{} with {new_ds}:{}", | ||
| targets[old_ds_a as usize], | ||
| targets[new_ds], | ||
| ); | ||
| match volume | ||
| .replace_downstairs( | ||
| Uuid::new_v4(), | ||
| targets[old_ds as usize], | ||
| targets[old_ds_a as usize], | ||
| targets[new_ds], | ||
| ) | ||
| .await | ||
|
|
@@ -2578,6 +2582,9 @@ async fn replace_before_active( | |
| } | ||
| } | ||
|
|
||
| // At this point, we've got two Downstairs (one of which was provided | ||
| // initially, and one of which has just been replaced), so activation | ||
| // should happen! | ||
| info!(log, "[{c}] Wait for activation after replacement"); | ||
| loop { | ||
| let is_active = volume.query_is_active().await.unwrap(); | ||
|
|
@@ -2602,8 +2609,10 @@ async fn replace_before_active( | |
| } | ||
|
|
||
| // Start up the old downstairs so it is ready for the next loop. | ||
| let res = dsc_client.dsc_start(old_ds).await; | ||
| info!(log, "[{c}] Replay: started {old_ds}, returned:{:?}", res); | ||
| for old_ds in [old_ds_a, old_ds_b] { | ||
| let res = dsc_client.dsc_start(old_ds).await; | ||
| info!(log, "[{c}] Replay: started {old_ds}, returned:{:?}", res); | ||
| } | ||
|
|
||
| // Wait for all IO to finish before we continue | ||
| loop { | ||
|
|
@@ -2622,12 +2631,13 @@ async fn replace_before_active( | |
| tokio::time::sleep(tokio::time::Duration::from_secs(4)).await; | ||
| } | ||
|
|
||
| old_ds = (old_ds + 1) % (ds_total as u32 + 1); | ||
| old_ds_a = (old_ds_a + 1) % (ds_total as u32 + 1); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm... Will this test pass if you do 2 region sets?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question! I notice a CI failure in
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is fixed in It's somewhat subtle: the unused downstairs is always right before the downstairs we're about to replace, but the second downstairs in that set could either be before or after (and shifts over time). That commit tracks which downstairs is in which region set, so that we can always disable 2 in the same region set (and prevent activation, which is the whole point). |
||
| old_ds_b = (old_ds_b + 1) % (ds_total as u32 + 1); | ||
| new_ds = (new_ds + 1) % (ds_total + 1); | ||
|
|
||
| match wtq { | ||
| WhenToQuit::Count { count } => { | ||
| if c > count { | ||
| if c >= count { | ||
| break; | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.