diff --git a/examples/simple.rs b/examples/simple.rs index 52940f96e..a7a03df9e 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -121,8 +121,8 @@ fn main() { } dc_chatlist_unref(chats); - *running.clone().write().unwrap() = false; - println!("stopping threads"); + thread::sleep(duration); + // let msglist = dc_get_chat_msgs(&ctx, chat_id, 0, 0); // for i in 0..dc_array_get_cnt(msglist) { // let msg_id = dc_array_get_id(msglist, i); @@ -133,6 +133,9 @@ fn main() { // } // dc_array_unref(msglist); + println!("stopping threads"); + + *running.clone().write().unwrap() = false; deltachat::dc_job::dc_interrupt_imap_idle(&ctx); deltachat::dc_job::dc_interrupt_smtp_idle(&ctx); diff --git a/src/dc_job.rs b/src/dc_job.rs index f69c3ca87..a50409c52 100644 --- a/src/dc_job.rs +++ b/src/dc_job.rs @@ -59,28 +59,15 @@ pub unsafe fn dc_perform_imap_jobs(context: &Context) { } unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: libc::c_int) { - let process_row = |row: &rusqlite::Row| { - let job = dc_job_t { - job_id: row.get(0)?, - action: row.get(1)?, - foreign_id: row.get(2)?, - desired_timestamp: row.get(5)?, - added_timestamp: row.get(4)?, - tries: row.get(6)?, - param: dc_param_new(), - try_again: 0, - pending_error: 0 as *mut libc::c_char, - }; - - let packed: String = row.get(3)?; - dc_param_set_packed(job.param, to_cstring(packed).as_ptr()); - Ok(job) - }; - let query = if probe_network == 0 { + // processing for first-try and after backoff-timeouts: + // process jobs in the order they were added. "SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries \ FROM jobs WHERE thread=? AND desired_timestamp<=? ORDER BY action DESC, added_timestamp;" } else { + // processing after call to dc_maybe_network(): + // process _all_ pending jobs that failed before + // in the order of their backoff-times. "SELECT id, action, foreign_id, param, added_timestamp, desired_timestamp, tries \ FROM jobs WHERE thread=? AND tries>0 ORDER BY desired_timestamp, action DESC;" }; @@ -95,10 +82,31 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: let jobs: Vec = context .sql - .query_map(query, params, process_row, |jobs| { - jobs.collect::, _>>() - .map_err(Into::into) - }) + .query_map( + query, + params, + |row| { + let job = dc_job_t { + job_id: row.get(0)?, + action: row.get(1)?, + foreign_id: row.get(2)?, + desired_timestamp: row.get(5)?, + added_timestamp: row.get(4)?, + tries: row.get(6)?, + param: dc_param_new(), + try_again: 0, + pending_error: 0 as *mut libc::c_char, + }; + + let packed: String = row.get(3)?; + dc_param_set_packed(job.param, to_cstring(packed).as_ptr()); + Ok(job) + }, + |jobs| { + jobs.collect::, _>>() + .map_err(Into::into) + }, + ) .unwrap_or_default(); for mut job in jobs { @@ -111,49 +119,34 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: job.action, ); + // some configuration jobs are "exclusive": + // - they are always executed in the imap-thread and the smtp-thread is suspended during execution + // - they may change the database handle change the database handle; we do not keep old pointers therefore + // - they can be re-executed one time AT_ONCE, but they are not save in the database for later execution if 900 == job.action || 910 == job.action { dc_job_kill_action(context, job.action); dc_jobthread_suspend(context, &context.sentbox_thread.clone().read().unwrap(), 1); dc_jobthread_suspend(context, &context.mvbox_thread.clone().read().unwrap(), 1); dc_suspend_smtp_thread(context, 1); } + let mut tries = 0; while tries <= 1 { + // this can be modified by a job using dc_job_try_again_later() job.try_again = 0; + match job.action { - 5901 => { - dc_job_do_DC_JOB_SEND(context, &mut job); - } - 110 => { - dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context, &mut job); - } - 130 => { - dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context, &mut job); - } - 120 => { - dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context, &mut job); - } - 200 => { - dc_job_do_DC_JOB_MOVE_MSG(context, &mut job); - } - 5011 => { - dc_job_do_DC_JOB_SEND(context, &mut job); - } - 900 => { - dc_job_do_DC_JOB_CONFIGURE_IMAP(context, &mut job); - } - 910 => { - dc_job_do_DC_JOB_IMEX_IMAP(context, &mut job); - } - 5005 => { - dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context, &mut job); - } - 5007 => { - dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context, &mut job); - } - 105 => { - sql::housekeeping(context); - } + 5901 => dc_job_do_DC_JOB_SEND(context, &mut job), + 110 => dc_job_do_DC_JOB_DELETE_MSG_ON_IMAP(context, &mut job), + 130 => dc_job_do_DC_JOB_MARKSEEN_MSG_ON_IMAP(context, &mut job), + 120 => dc_job_do_DC_JOB_MARKSEEN_MDN_ON_IMAP(context, &mut job), + 200 => dc_job_do_DC_JOB_MOVE_MSG(context, &mut job), + 5011 => dc_job_do_DC_JOB_SEND(context, &mut job), + 900 => dc_job_do_DC_JOB_CONFIGURE_IMAP(context, &mut job), + 910 => dc_job_do_DC_JOB_IMEX_IMAP(context, &mut job), + 5005 => dc_job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context, &mut job), + 5007 => dc_job_do_DC_JOB_MAYBE_SEND_LOC_ENDED(context, &mut job), + 105 => sql::housekeeping(context), _ => {} } if job.try_again != -1 { @@ -175,6 +168,7 @@ unsafe fn dc_job_perform(context: &Context, thread: libc::c_int, probe_network: dc_suspend_smtp_thread(context, 0); break; } else if job.try_again == 2 { + // just try over next loop unconditionally, the ui typically interrupts idle when the file (video) is ready info!( context, 0, diff --git a/src/dc_jobthread.rs b/src/dc_jobthread.rs index 732dd083d..4b35f7336 100644 --- a/src/dc_jobthread.rs +++ b/src/dc_jobthread.rs @@ -130,24 +130,24 @@ pub unsafe fn dc_jobthread_fetch( ******************************************************************************/ unsafe fn connect_to_imap(context: &Context, jobthread: &dc_jobthread_t) -> libc::c_int { - let mut ret_connected: libc::c_int; - if jobthread.imap.is_connected() { - ret_connected = 1; - } else { - ret_connected = dc_connect_to_configured_imap(context, &jobthread.imap); - if !(0 == ret_connected) { - if sql::get_config_int(context, &context.sql, "folders_configured", 0) < 3 { - jobthread.imap.configure_folders(context, 0x1); - } - let mvbox_name = - sql::get_config(context, &context.sql, jobthread.folder_config_name, None); - if let Some(name) = mvbox_name { - jobthread.imap.set_watch_folder(name); - } else { - jobthread.imap.disconnect(context); - ret_connected = 0; - } + return 1; + } + + let mut ret_connected = dc_connect_to_configured_imap(context, &jobthread.imap); + + if !(0 == ret_connected) { + if sql::get_config_int(context, &context.sql, "folders_configured", 0) < 3 { + jobthread.imap.configure_folders(context, 0x1); + } + + if let Some(mvbox_name) = + sql::get_config(context, &context.sql, jobthread.folder_config_name, None) + { + jobthread.imap.set_watch_folder(mvbox_name); + } else { + jobthread.imap.disconnect(context); + ret_connected = 0; } } diff --git a/src/dc_msg.rs b/src/dc_msg.rs index c4da7f9c7..fe807eec7 100644 --- a/src/dc_msg.rs +++ b/src/dc_msg.rs @@ -428,6 +428,10 @@ pub unsafe fn dc_msg_get_timestamp(msg: *const dc_msg_t) -> i64 { } pub fn dc_msg_load_from_db<'a>(msg: *mut dc_msg_t<'a>, context: &'a Context, id: u32) -> bool { + if msg.is_null() { + return false; + } + context.sql.query_row( "SELECT \ m.id,rfc724_mid,m.mime_in_reply_to,m.server_folder,m.server_uid,m.move_state,m.chat_id, \