/*
* meli - notmuch backend
*
* Copyright 2019 - 2020 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::backends::*;
use crate::conf::AccountSettings;
use crate::email::{Envelope, EnvelopeHash, Flag};
use crate::error::{MeliError, Result, ResultIntoMeliError};
use crate::shellexpand::ShellExpandTrait;
use smallvec::SmallVec;
use std::collections::{
hash_map::{DefaultHasher, HashMap},
BTreeMap,
};
use std::error::Error;
use std::ffi::{CStr, CString, OsStr};
use std::hash::{Hash, Hasher};
use std::io::Read;
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex, RwLock};
macro_rules! call {
($lib:expr, $func:ty) => {{
let func: libloading::Symbol<$func> = $lib.get(stringify!($func).as_bytes()).unwrap();
func
}};
}
macro_rules! try_call {
($lib:expr, $call:expr) => {{
let status = $call;
if status == _notmuch_status_NOTMUCH_STATUS_SUCCESS {
Ok(())
} else {
let c_str = call!($lib, notmuch_status_to_string)(status);
Err(NotmuchError(
CStr::from_ptr(c_str).to_string_lossy().into_owned(),
))
}
}};
}
pub mod bindings;
use bindings::*;
mod message;
pub use message::*;
mod tags;
pub use tags::*;
mod thread;
pub use thread::*;
#[derive(Debug)]
pub struct DbConnection {
pub lib: Arc<libloading::Library>,
pub inner: Arc<RwLock<*mut notmuch_database_t>>,
pub revision_uuid: Arc<RwLock<u64>>,
pub database_ph: std::marker::PhantomData<&'static mut notmuch_database_t>,
}
impl DbConnection {
pub fn get_revision_uuid(&self) -> u64 {
unsafe {
call!(self.lib, notmuch_database_get_revision)(
*self.inner.read().unwrap(),
std::ptr::null_mut(),
)
}
}
fn refresh(
&mut self,
mailboxes: Arc<RwLock<HashMap<MailboxHash, NotmuchMailbox>>>,
index: Arc<RwLock<HashMap<EnvelopeHash, CString>>>,
mailbox_index: Arc<RwLock<HashMap<EnvelopeHash, SmallVec<[MailboxHash; 16]>>>>,
tag_index: Arc<RwLock<BTreeMap<u64, String>>>,
account_hash: AccountHash,
event_consumer: BackendEventConsumer,
new_revision_uuid: u64,
) -> Result<()> {
use RefreshEventKind::*;
let query_str = format!(
"lastmod:{}..{}",
*self.revision_uuid.read().unwrap(),
new_revision_uuid
);
let query: Query = Query::new(self.lib.clone(), &self, &query_str)?;
let iter = query.search()?;
let mailbox_index_lck = mailbox_index.write().unwrap();
let mailboxes_lck = mailboxes.read().unwrap();
for message in iter {
let env_hash = message.env_hash();
if let Some(mailbox_hashes) = mailbox_index_lck.get(&env_hash) {
let tags: (Flag, Vec<String>) = message.tags().collect_flags_and_tags();
let mut tag_lock = tag_index.write().unwrap();
for