mellib/imap: don't flood user with sqlite3 errors if db is corrupted

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/299/head
Manos Pitsidianakis 2023-09-08 17:10:07 +03:00
parent bb4d200036
commit 9b9c38f769
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
5 changed files with 40 additions and 23 deletions

View File

@ -169,11 +169,24 @@ pub mod sqlite3_m {
impl Sqlite3Cache {
pub fn get(uid_store: Arc<UIDStore>) -> Result<Box<dyn ImapCache>> {
let connection =
match sqlite3::open_or_create_db(&DB_DESCRIPTION, Some(&uid_store.account_name)) {
Ok(c) => Ok(c),
Err(err) => {
// try resetting database on error, but only one time.
if Self::reset_db(&uid_store).is_ok() {
sqlite3::open_or_create_db(
&DB_DESCRIPTION,
Some(&uid_store.account_name),
)
} else {
Err(err)
}
}
}?;
Ok(Box::new(Self {
connection: sqlite3::open_or_create_db(
&DB_DESCRIPTION,
Some(&uid_store.account_name),
)?,
connection,
loaded_mailboxes: BTreeSet::default(),
uid_store,
}))
@ -712,7 +725,7 @@ pub(super) async fn fetch_cached_envs(state: &mut FetchState) -> Result<Option<V
cache_handle: _,
} = state;
let mailbox_hash = *mailbox_hash;
if !uid_store.keep_offline_cache {
if !*uid_store.keep_offline_cache.lock().unwrap() {
return Ok(None);
}
{

View File

@ -628,7 +628,7 @@ impl ImapConnection {
#[cfg(debug_assertions)]
id,
server_conf: server_conf.clone(),
sync_policy: if uid_store.keep_offline_cache {
sync_policy: if *uid_store.keep_offline_cache.lock().unwrap() {
SyncPolicy::Basic
} else {
SyncPolicy::None
@ -984,7 +984,7 @@ impl ImapConnection {
format!("Could not parse select response for mailbox {}", imap_path)
})?;
{
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
#[cfg(not(feature = "sqlite3"))]
let mut cache_handle = super::cache::DefaultCache::get(self.uid_store.clone())?;
#[cfg(feature = "sqlite3")]

View File

@ -148,7 +148,7 @@ macro_rules! get_conf_val {
pub struct UIDStore {
account_hash: AccountHash,
account_name: Arc<str>,
keep_offline_cache: bool,
keep_offline_cache: Arc<Mutex<bool>>,
capabilities: Arc<Mutex<Capabilities>>,
hash_index: Arc<Mutex<HashMap<EnvelopeHash, (UID, MailboxHash)>>>,
uid_index: Arc<Mutex<HashMap<(MailboxHash, UID), EnvelopeHash>>>,
@ -179,7 +179,7 @@ impl UIDStore {
Self {
account_hash,
account_name,
keep_offline_cache: false,
keep_offline_cache: Arc::new(Mutex::new(false)),
capabilities: Default::default(),
uidvalidity: Default::default(),
envelopes: Default::default(),
@ -301,7 +301,7 @@ impl MailBackend for ImapType {
) -> Result<Pin<Box<dyn Stream<Item = Result<Vec<Envelope>>> + Send + 'static>>> {
let cache_handle = {
#[cfg(feature = "sqlite3")]
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
match cache::Sqlite3Cache::get(self.uid_store.clone()).chain_err_summary(|| {
format!(
"Could not initialize cache for IMAP account {}. Resetting database.",
@ -317,9 +317,11 @@ impl MailBackend for ImapType {
{
Ok(v) => Some(v),
Err(err) => {
(self.uid_store.event_consumer)(
self.uid_store.account_hash,
err.into(),
*self.uid_store.keep_offline_cache.lock().unwrap() = false;
log::trace!(
"{}: sqlite3 cache error: {}",
self.uid_store.account_name,
err
);
None
}
@ -333,7 +335,7 @@ impl MailBackend for ImapType {
None
};
let mut state = FetchState {
stage: if self.uid_store.keep_offline_cache && cache_handle.is_some() {
stage: if *self.uid_store.keep_offline_cache.lock().unwrap() && cache_handle.is_some() {
FetchStage::InitialCache
} else {
FetchStage::InitialFresh
@ -1294,7 +1296,7 @@ impl ImapType {
let account_hash = AccountHash::from_bytes(s.name.as_bytes());
let account_name = s.name.to_string().into();
let uid_store: Arc<UIDStore> = Arc::new(UIDStore {
keep_offline_cache,
keep_offline_cache: Arc::new(Mutex::new(keep_offline_cache)),
..UIDStore::new(
account_hash,
account_name,

View File

@ -147,7 +147,7 @@ impl ImapConnection {
},
));
}
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
cache_handle.update(mailbox_hash, &events)?;
}
for (_, event) in events {
@ -190,7 +190,7 @@ impl ImapConnection {
kind: Remove(deleted_hash),
},
)];
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
cache_handle.update(mailbox_hash, &event)?;
}
self.add_refresh_event(std::mem::replace(
@ -282,7 +282,7 @@ impl ImapConnection {
mailbox.path(),
);
}
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
if let Err(err) = cache_handle
.insert_envelopes(mailbox_hash, &v)
.chain_err_summary(|| {
@ -384,7 +384,7 @@ impl ImapConnection {
}
mailbox.exists.lock().unwrap().insert_new(env.hash());
}
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
if let Err(err) = cache_handle
.insert_envelopes(mailbox_hash, &v)
.chain_err_summary(|| {
@ -525,7 +525,7 @@ impl ImapConnection {
kind: NewFlags(env_hash, flags),
},
)];
if self.uid_store.keep_offline_cache {
if *self.uid_store.keep_offline_cache.lock().unwrap() {
cache_handle.update(mailbox_hash, &event)?;
}
self.add_refresh_event(std::mem::replace(

View File

@ -90,7 +90,7 @@ pub async fn idle(kit: ImapWatchKit) -> Result<()> {
if let Some(v) = uidvalidities.get(&mailbox_hash) {
if *v != select_response.uidvalidity {
if uid_store.keep_offline_cache {
if *uid_store.keep_offline_cache.lock().unwrap() {
#[cfg(not(feature = "sqlite3"))]
let mut cache_handle = super::cache::DefaultCache::get(uid_store.clone())?;
#[cfg(feature = "sqlite3")]
@ -232,7 +232,7 @@ pub async fn examine_updates(
if let Some(v) = uidvalidities.get(&mailbox_hash) {
if *v != select_response.uidvalidity {
if uid_store.keep_offline_cache {
if *uid_store.keep_offline_cache.lock().unwrap() {
cache_handle.clear(mailbox_hash, &select_response)?;
}
conn.add_refresh_event(RefreshEvent {
@ -383,7 +383,9 @@ pub async fn examine_updates(
}
}
}
if uid_store.keep_offline_cache && cache_handle.mailbox_state(mailbox_hash)?.is_some() {
if *uid_store.keep_offline_cache.lock().unwrap()
&& cache_handle.mailbox_state(mailbox_hash)?.is_some()
{
cache_handle
.insert_envelopes(mailbox_hash, &v)
.chain_err_summary(|| {