/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// Determines whether to check an SQLite database for corruption, /// and which checks to run. pubtrait IntoChecker<C> { fn into_checker(self) -> CheckerAction<C>;
}
impl IntoChecker<Checker> for ConnectionIncidents<'_> { fn into_checker(self) -> CheckerAction<Checker> { self.map(|incidents| { let (penalty, checks) = incidents.iter().fold(
(Penalty::default(), Checks::default()),
|(penalty, checks), incident| (penalty.adding(incident), checks.adding(incident)),
); if penalty < Penalty::MIN { // No incidents, or maybe some transient errors. // Keep any existing incidents, and skip checks for now.
CheckerAction::Skip
} elseif penalty < Penalty::MAX { // Check the database for potential corruption.
incidents.resolve();
CheckerAction::Check(Checker { checks })
} else { // Too many incidents; replace the database.
incidents.resolve();
CheckerAction::Replace
}
})
}
}
/// Whether to skip checking, check, or replace a corrupt SQLite database. #[derive(Debug)] pubenum CheckerAction<C> {
Skip,
Check(C),
Replace,
}
/// The penalty for one or more [`ConnectionIncidents`]. #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] struct Penalty(usize);
impl Penalty { /// The minimum penalty needed to check a database for errors. const MIN: Self = Penalty(5);
/// The maximum penalty before replacing a database. const MAX: Self = Penalty(20);
fn adding(self, incident: ConnectionIncident) -> Self { // Each incident contributes a (completely arbitrary) amount to // the penalty, depending on the severity and frequency. Self( self.0
+ match incident {
ConnectionIncident::CorruptFile => 3,
ConnectionIncident::CorruptIndex => 2,
ConnectionIncident::CorruptForeignKey => 1,
},
)
}
}
const _: () = {
assert!(
Penalty::MIN.0 < Penalty::MAX.0, "`Penalty::MIN` should be less than `Penalty::MAX`"
);
};
/// Checks to run on a potentially corrupt SQLite database. #[derive(Clone, Copy, Debug, Default)] struct Checks {
reindex: bool,
consistency: Option<ConsistencyCheck>,
foreign_keys: bool,
}
impl Checks { fn adding(self, incident: ConnectionIncident) -> Self { match incident {
ConnectionIncident::CorruptFile => Self {
consistency: Some( // If we haven't seen index corruption, a quick check will // likely find other problems faster than a full check. self.consistency
.unwrap_or(ConsistencyCheck::Quick)
.and(ConsistencyCheck::Quick),
),
..self
},
ConnectionIncident::CorruptIndex => Self { // Try to rebuild the indexes.
reindex: true,
consistency: Some( // If we have seen index corruption, we need to run a // full check. self.consistency
.unwrap_or(ConsistencyCheck::Full)
.and(ConsistencyCheck::Full),
),
..self
},
ConnectionIncident::CorruptForeignKey => Self { // Neither quick nor full checks look for foreign key errors.
foreign_keys: true,
..self
},
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.