mbox: send envelope payload in chunks
parent
15b15854bf
commit
d3391e96c0
|
@ -636,6 +636,61 @@ pub fn mbox_parse(
|
||||||
Ok((&[], envelopes))
|
Ok((&[], envelopes))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MessageIterator<'a> {
|
||||||
|
index: Arc<Mutex<HashMap<EnvelopeHash, (Offset, Length)>>>,
|
||||||
|
input: &'a [u8],
|
||||||
|
file_offset: usize,
|
||||||
|
offset: usize,
|
||||||
|
reader: Option<MboxReader>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for MessageIterator<'a> {
|
||||||
|
type Item = Result<Envelope>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.input.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let mut index = self.index.lock().unwrap();
|
||||||
|
|
||||||
|
let reader = self.reader.unwrap_or(MboxReader::MboxCl2);
|
||||||
|
while !self.input[self.offset + self.file_offset..].is_empty() {
|
||||||
|
let (next_input, env) =
|
||||||
|
match reader.parse(&self.input[self.offset + self.file_offset..]) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
// Try to recover from this error by finding a new candidate From_ line
|
||||||
|
if let Some(next_offset) =
|
||||||
|
find_From__line!(&self.input[self.offset + self.file_offset..])
|
||||||
|
{
|
||||||
|
self.offset += next_offset;
|
||||||
|
if self.offset != self.input.len() {
|
||||||
|
// If we are not at EOF, we will be at this point
|
||||||
|
// "\n\nFrom ..."
|
||||||
|
// ↑
|
||||||
|
// So, skip those two newlines.
|
||||||
|
self.offset += 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.input = b"";
|
||||||
|
return Some(Err(e.into()));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let start: Offset = self.input[self.offset + self.file_offset..]
|
||||||
|
.find(b"\n")
|
||||||
|
.map(|v| v + 1)
|
||||||
|
.unwrap_or(0);
|
||||||
|
let len = self.input.len() - next_input.len() - self.offset - self.file_offset - start;
|
||||||
|
index.insert(env.hash(), (self.offset + self.file_offset + start, len));
|
||||||
|
self.offset += len + start;
|
||||||
|
|
||||||
|
return Some(Ok(env));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Mbox backend
|
/// Mbox backend
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct MboxType {
|
pub struct MboxType {
|
||||||
|
@ -692,25 +747,52 @@ impl MailBackend for MboxType {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mailboxes_lck = mailboxes.lock().unwrap();
|
let mailboxes_lck = mailboxes.lock().unwrap();
|
||||||
let mut mailbox_index_lck = mailbox_index.lock().unwrap();
|
|
||||||
let index = mailboxes_lck[&mailbox_hash].index.clone();
|
let index = mailboxes_lck[&mailbox_hash].index.clone();
|
||||||
drop(mailboxes_lck);
|
drop(mailboxes_lck);
|
||||||
let payload = mbox_parse(index, contents.as_slice(), 0, prefer_mbox_type)
|
let mut message_iter = MessageIterator {
|
||||||
.map_err(MeliError::from)
|
index,
|
||||||
.map(|(_, v)| {
|
input: &contents.as_slice(),
|
||||||
for v in v.iter() {
|
offset: 0,
|
||||||
mailbox_index_lck.insert(v.hash(), mailbox_hash);
|
file_offset: 0,
|
||||||
|
reader: prefer_mbox_type,
|
||||||
|
};
|
||||||
|
let mut err = None;
|
||||||
|
loop {
|
||||||
|
let mut payload = vec![];
|
||||||
|
'iter_for_loop: for _i in 0..150 {
|
||||||
|
match message_iter.next() {
|
||||||
|
Some(Ok(env)) => {
|
||||||
|
payload.push(env);
|
||||||
|
}
|
||||||
|
Some(Err(_err)) => {
|
||||||
|
debug!(&_err);
|
||||||
|
err = Some(_err);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
break 'iter_for_loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !payload.is_empty() {
|
||||||
|
err = None;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let mut mailbox_index_lck = mailbox_index.lock().unwrap();
|
||||||
|
for env in &payload {
|
||||||
|
mailbox_index_lck.insert(env.hash(), mailbox_hash);
|
||||||
|
}
|
||||||
|
tx.send(AsyncStatus::Payload(Ok(payload))).unwrap();
|
||||||
|
}
|
||||||
|
if let Some(err) = err {
|
||||||
|
tx.send(AsyncStatus::Payload(Err(err))).unwrap();
|
||||||
}
|
}
|
||||||
v
|
|
||||||
});
|
|
||||||
{
|
{
|
||||||
let mut mailbox_lock = mailboxes.lock().unwrap();
|
let mut mailbox_lock = mailboxes.lock().unwrap();
|
||||||
mailbox_lock
|
mailbox_lock
|
||||||
.entry(mailbox_hash)
|
.entry(mailbox_hash)
|
||||||
.and_modify(|f| f.content = contents);
|
.and_modify(|f| f.content = contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.send(AsyncStatus::Payload(payload)).unwrap();
|
|
||||||
tx.send(AsyncStatus::Finished).unwrap();
|
tx.send(AsyncStatus::Finished).unwrap();
|
||||||
};
|
};
|
||||||
Box::new(closure)
|
Box::new(closure)
|
||||||
|
|
Loading…
Reference in New Issue