release mutex before beginning media sync
And check media sync is not running on close
This commit is contained in:
parent
5f19048c93
commit
72bcef917e
@ -8,7 +8,7 @@ use crate::collection::{open_collection, Collection};
|
||||
use crate::err::{AnkiError, NetworkErrorKind, Result, SyncErrorKind};
|
||||
use crate::i18n::{tr_args, FString, I18n};
|
||||
use crate::latex::{extract_latex, extract_latex_expanding_clozes, ExtractedLatex};
|
||||
use crate::log::default_logger;
|
||||
use crate::log::{default_logger, Logger};
|
||||
use crate::media::check::MediaChecker;
|
||||
use crate::media::sync::MediaSyncProgress;
|
||||
use crate::media::MediaManager;
|
||||
@ -23,6 +23,7 @@ use crate::{backend_proto as pb, log};
|
||||
use fluent::FluentValue;
|
||||
use prost::Message;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
@ -157,13 +158,13 @@ impl Backend {
|
||||
/// If collection is not open, return an error.
|
||||
fn with_col<F, T>(&self, func: F) -> Result<T>
|
||||
where
|
||||
F: FnOnce(&Collection) -> Result<T>,
|
||||
F: FnOnce(&mut Collection) -> Result<T>,
|
||||
{
|
||||
func(
|
||||
self.col
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_ref()
|
||||
.as_mut()
|
||||
.ok_or(AnkiError::CollectionNotOpen)?,
|
||||
)
|
||||
}
|
||||
@ -249,8 +250,8 @@ impl Backend {
|
||||
}
|
||||
|
||||
fn open_collection(&self, input: pb::OpenCollectionIn) -> Result<()> {
|
||||
let mut mutex = self.col.lock().unwrap();
|
||||
if mutex.is_some() {
|
||||
let mut col = self.col.lock().unwrap();
|
||||
if col.is_some() {
|
||||
return Err(AnkiError::CollectionAlreadyOpen);
|
||||
}
|
||||
|
||||
@ -263,7 +264,7 @@ impl Backend {
|
||||
};
|
||||
let logger = default_logger(log_path)?;
|
||||
|
||||
let col = open_collection(
|
||||
let new_col = open_collection(
|
||||
input.collection_path,
|
||||
input.media_folder_path,
|
||||
input.media_db_path,
|
||||
@ -272,18 +273,22 @@ impl Backend {
|
||||
logger,
|
||||
)?;
|
||||
|
||||
*mutex = Some(col);
|
||||
*col = Some(new_col);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close_collection(&self) -> Result<()> {
|
||||
let mut mutex = self.col.lock().unwrap();
|
||||
if mutex.is_none() {
|
||||
let mut col = self.col.lock().unwrap();
|
||||
if col.is_none() {
|
||||
return Err(AnkiError::CollectionNotOpen);
|
||||
}
|
||||
|
||||
*mutex = None;
|
||||
if !col.as_ref().unwrap().can_close() {
|
||||
return Err(AnkiError::invalid_input("can't close yet"));
|
||||
}
|
||||
|
||||
*col = None;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -445,15 +450,38 @@ impl Backend {
|
||||
// fixme: will block other db access
|
||||
|
||||
fn sync_media(&self, input: SyncMediaIn) -> Result<()> {
|
||||
let mut guard = self.col.lock().unwrap();
|
||||
|
||||
let col = guard.as_mut().unwrap();
|
||||
col.set_media_sync_running()?;
|
||||
|
||||
let folder = col.media_folder.clone();
|
||||
let db = col.media_db.clone();
|
||||
let log = col.log.clone();
|
||||
|
||||
drop(guard);
|
||||
|
||||
let res = self.sync_media_inner(input, folder, db, log);
|
||||
|
||||
self.with_col(|col| col.set_media_sync_finished())?;
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn sync_media_inner(
|
||||
&self,
|
||||
input: pb::SyncMediaIn,
|
||||
folder: PathBuf,
|
||||
db: PathBuf,
|
||||
log: Logger,
|
||||
) -> Result<()> {
|
||||
let callback = |progress: &MediaSyncProgress| {
|
||||
self.fire_progress_callback(Progress::MediaSync(progress))
|
||||
};
|
||||
|
||||
self.with_col(|col| {
|
||||
let mgr = MediaManager::new(&col.media_folder, &col.media_db)?;
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
rt.block_on(mgr.sync_media(callback, &input.endpoint, &input.hkey, col.log.clone()))
|
||||
})
|
||||
let mgr = MediaManager::new(&folder, &db)?;
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
rt.block_on(mgr.sync_media(callback, &input.endpoint, &input.hkey, log))
|
||||
}
|
||||
|
||||
fn check_media(&self) -> Result<pb::MediaCheckOut> {
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright: Ankitects Pty Ltd and contributors
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
use crate::err::Result;
|
||||
use crate::err::{AnkiError, Result};
|
||||
use crate::i18n::I18n;
|
||||
use crate::log::Logger;
|
||||
use crate::storage::{SqliteStorage, StorageContext};
|
||||
@ -26,11 +26,19 @@ pub fn open_collection<P: Into<PathBuf>>(
|
||||
server,
|
||||
i18n,
|
||||
log,
|
||||
state: CollectionState::Normal,
|
||||
};
|
||||
|
||||
Ok(col)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum CollectionState {
|
||||
Normal,
|
||||
// in this state, the DB must not be closed
|
||||
MediaSyncRunning,
|
||||
}
|
||||
|
||||
pub struct Collection {
|
||||
pub(crate) storage: SqliteStorage,
|
||||
#[allow(dead_code)]
|
||||
@ -40,6 +48,7 @@ pub struct Collection {
|
||||
pub(crate) server: bool,
|
||||
pub(crate) i18n: I18n,
|
||||
pub(crate) log: Logger,
|
||||
state: CollectionState,
|
||||
}
|
||||
|
||||
pub(crate) enum CollectionOp {}
|
||||
@ -97,4 +106,26 @@ impl Collection {
|
||||
res
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn set_media_sync_running(&mut self) -> Result<()> {
|
||||
if self.state == CollectionState::Normal {
|
||||
self.state = CollectionState::MediaSyncRunning;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AnkiError::invalid_input("media sync already running"))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_media_sync_finished(&mut self) -> Result<()> {
|
||||
if self.state == CollectionState::MediaSyncRunning {
|
||||
self.state = CollectionState::Normal;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(AnkiError::invalid_input("media sync not running"))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn can_close(&self) -> bool {
|
||||
self.state == CollectionState::Normal
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user