Skip to content

Commit 7bef555

Browse files
committedFeb 2, 2024
Updates for PR comments
1 parent c4e3834 commit 7bef555

File tree

8 files changed

+162
-167
lines changed

8 files changed

+162
-167
lines changed
 

‎common/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ pub enum CrucibleError {
159159
#[error("missing block context for non-empty block")]
160160
MissingBlockContext,
161161

162-
#[error("Incompatable RegionDefinition {0}")]
163-
RegionIncompatable(String),
162+
#[error("Incompatible RegionDefinition {0}")]
163+
RegionIncompatible(String),
164164
}
165165

166166
impl From<std::io::Error> for CrucibleError {
@@ -366,7 +366,7 @@ impl From<CrucibleError> for dropshot::HttpError {
366366
| CrucibleError::ModifyingReadOnlyRegion
367367
| CrucibleError::OffsetInvalid
368368
| CrucibleError::OffsetUnaligned
369-
| CrucibleError::RegionIncompatable(_)
369+
| CrucibleError::RegionIncompatible(_)
370370
| CrucibleError::ReplaceRequestInvalid(_)
371371
| CrucibleError::SnapshotExistsAlready(_)
372372
| CrucibleError::Unsupported(_) => {

‎common/src/region.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -189,39 +189,39 @@ impl RegionDefinition {
189189
) -> Result<(), CrucibleError> {
190190
// These fields should be the same.
191191
if self.block_size != other.block_size {
192-
return Err(CrucibleError::RegionIncompatable(
192+
return Err(CrucibleError::RegionIncompatible(
193193
"block_size".to_string(),
194194
));
195195
}
196196
if self.extent_size != other.extent_size {
197-
return Err(CrucibleError::RegionIncompatable(
197+
return Err(CrucibleError::RegionIncompatible(
198198
"extent_size".to_string(),
199199
));
200200
}
201201
if self.extent_count != other.extent_count {
202-
return Err(CrucibleError::RegionIncompatable(
202+
return Err(CrucibleError::RegionIncompatible(
203203
"extent_count".to_string(),
204204
));
205205
}
206206
if self.encrypted != other.encrypted {
207-
return Err(CrucibleError::RegionIncompatable(
207+
return Err(CrucibleError::RegionIncompatible(
208208
"encrypted".to_string(),
209209
));
210210
}
211211
if self.database_read_version != other.database_read_version {
212-
return Err(CrucibleError::RegionIncompatable(
212+
return Err(CrucibleError::RegionIncompatible(
213213
"database_read_version".to_string(),
214214
));
215215
}
216216
if self.database_write_version != other.database_write_version {
217-
return Err(CrucibleError::RegionIncompatable(
217+
return Err(CrucibleError::RegionIncompatible(
218218
"database_write_version".to_string(),
219219
));
220220
}
221221

222222
// If the UUIDs are the same, this is invalid.
223223
if self.uuid == other.uuid {
224-
return Err(CrucibleError::RegionIncompatable(
224+
return Err(CrucibleError::RegionIncompatible(
225225
"UUIDs are the same".to_string(),
226226
));
227227
}

‎downstairs/src/extent.rs

+29-29
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl ExtentMeta {
144144
}
145145
}
146146

147-
#[derive(Debug, Clone)]
147+
#[derive(Debug, Copy, Clone)]
148148
#[allow(clippy::enum_variant_names)]
149149
pub enum ExtentType {
150150
Data,
@@ -169,7 +169,7 @@ impl fmt::Display for ExtentType {
169169
* FileType from the repair client.
170170
*/
171171
impl ExtentType {
172-
pub fn to_file_type(&self) -> FileType {
172+
pub fn to_file_type(self) -> FileType {
173173
match self {
174174
ExtentType::Data => FileType::Data,
175175
ExtentType::Db => FileType::Db,
@@ -654,15 +654,27 @@ pub(crate) fn move_replacement_extent<P: AsRef<Path>>(
654654
sync_path(&original_file, log)?;
655655

656656
// We distinguish between SQLite-backend and raw-file extents based on the
657-
// presence of the `.db` file. Under normal conditions, we should never
658-
// do extent repair across different extent formats; in fact, we should
659-
// never extent repair SQLite-backed extents at all, but must still
660-
// handle the case of unfinished migrations.
661-
// If we are replacing a downstairs, and have created the region empty
662-
// with the plan to replace it, then we can have a mismatch between
663-
// what files we have and what files we want to replace them with. When
664-
// repairing a downstairs, we don't know in advance if the source of our
665-
// repair will be SQLite-backend or not.
657+
// presence of the `.db` file. We should never do extent repair across
658+
// different extent formats; it must be SQLite-to-SQLite or raw-to-raw.
659+
//
660+
// It is uncommon to perform extent repair on SQLite-backed extents at all,
661+
// because they are automatically migrated into raw file extents or
662+
// read-only. However, it must be supported for two cases:
663+
//
664+
// - If there was an unfinished replacement, we must finish that replacement
665+
// before migrating from SQLite -> raw file backend, which happens
666+
// automatically later in startup.
667+
// - We use this same code path to perform clones of read-only regions,
668+
// which may be SQLite-backed (and will never migrate to raw files,
669+
// because they are read only). This is only the case when the `clone`
670+
// argument is `true`.
671+
//
672+
// In the first case, we know that we are repairing an SQLite-based extent
673+
// because the target (original) extent includes a `.db` file.
674+
//
675+
// In the second case, the target (original) extent is not present, so we
676+
// check whether the new files include a `.db` file.
677+
666678
new_file.set_extension("db");
667679
original_file.set_extension("db");
668680

@@ -676,12 +688,6 @@ pub(crate) fn move_replacement_extent<P: AsRef<Path>>(
676688
e
677689
);
678690
}
679-
info!(
680-
log,
681-
"Moved file {:?} to {:?}",
682-
new_file.clone(),
683-
original_file.clone()
684-
);
685691
sync_path(&original_file, log)?;
686692

687693
// The .db-shm and .db-wal files may or may not exist. If they don't
@@ -701,14 +707,11 @@ pub(crate) fn move_replacement_extent<P: AsRef<Path>>(
701707
e
702708
);
703709
}
704-
info!(
705-
log,
706-
"Moved db-shm file {:?} to {:?}",
707-
new_file.clone(),
708-
original_file.clone()
709-
);
710710
sync_path(&original_file, log)?;
711711
} else if original_file.exists() {
712+
// If we are cloning, then our new region will have been
713+
// created with Backend::RawFile, and we should have no SQLite
714+
// files.
712715
assert!(!clone);
713716
info!(
714717
log,
@@ -732,14 +735,11 @@ pub(crate) fn move_replacement_extent<P: AsRef<Path>>(
732735
e
733736
);
734737
}
735-
info!(
736-
log,
737-
"Moved db-wal file {:?} to {:?}",
738-
new_file.clone(),
739-
original_file.clone()
740-
);
741738
sync_path(&original_file, log)?;
742739
} else if original_file.exists() {
740+
// If we are cloning, then our new region will have been
741+
// created with Backend::RawFile, and we should have no SQLite
742+
// files.
743743
assert!(!clone);
744744
info!(
745745
log,

‎downstairs/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3356,12 +3356,12 @@ pub async fn start_downstairs(
33563356
/// Use the reconcile/repair extent methods to copy another downstairs.
33573357
/// The source downstairs must have the same RegionDefinition as we do,
33583358
/// and both downstairs must be running in read only mode.
3359-
pub async fn start_clone(
3359+
pub async fn clone_region(
33603360
d: Arc<Mutex<Downstairs>>,
33613361
source: SocketAddr,
33623362
) -> Result<()> {
33633363
let info = crucible_common::BuildInfo::default();
3364-
let log = d.lock().await.log.new(o!("task" => "main".to_string()));
3364+
let log = d.lock().await.log.new(o!("task" => "clone".to_string()));
33653365
info!(log, "Crucible Version: {}", info);
33663366
info!(
33673367
log,

‎downstairs/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ async fn main() -> Result<()> {
298298
)
299299
.await?;
300300

301-
start_clone(d, source).await
301+
clone_region(d, source).await
302302
}
303303
Args::Create {
304304
block_size,

0 commit comments

Comments
 (0)