Try to workaround #17 - windows not letting to open the file while rqbit has it
This commit is contained in:
parent
a800048b7e
commit
e1a3f86a24
2 changed files with 39 additions and 3 deletions
|
|
@ -173,10 +173,10 @@ impl TorrentManager {
|
||||||
options: Option<TorrentManagerOptions>,
|
options: Option<TorrentManagerOptions>,
|
||||||
) -> anyhow::Result<TorrentManagerHandle> {
|
) -> anyhow::Result<TorrentManagerHandle> {
|
||||||
let options = options.unwrap_or_default();
|
let options = options.unwrap_or_default();
|
||||||
let files = {
|
let (files, filenames) = {
|
||||||
let mut files =
|
let mut files =
|
||||||
Vec::<Arc<Mutex<File>>>::with_capacity(info.iter_file_lengths()?.count());
|
Vec::<Arc<Mutex<File>>>::with_capacity(info.iter_file_lengths()?.count());
|
||||||
|
let mut filenames = Vec::new();
|
||||||
for (path_bits, _) in info.iter_filenames_and_lengths()? {
|
for (path_bits, _) in info.iter_filenames_and_lengths()? {
|
||||||
let mut full_path = out.as_ref().to_owned();
|
let mut full_path = out.as_ref().to_owned();
|
||||||
let relative_path = path_bits
|
let relative_path = path_bits
|
||||||
|
|
@ -200,9 +200,10 @@ impl TorrentManager {
|
||||||
.with_context(|| format!("error creating {:?}", &full_path))?;
|
.with_context(|| format!("error creating {:?}", &full_path))?;
|
||||||
OpenOptions::new().read(true).write(true).open(&full_path)?
|
OpenOptions::new().read(true).write(true).open(&full_path)?
|
||||||
};
|
};
|
||||||
|
filenames.push(full_path);
|
||||||
files.push(Arc::new(Mutex::new(file)))
|
files.push(Arc::new(Mutex::new(file)))
|
||||||
}
|
}
|
||||||
files
|
(files, filenames)
|
||||||
};
|
};
|
||||||
|
|
||||||
let peer_id = options.peer_id.unwrap_or_else(generate_peer_id);
|
let peer_id = options.peer_id.unwrap_or_else(generate_peer_id);
|
||||||
|
|
@ -270,6 +271,7 @@ impl TorrentManager {
|
||||||
info_hash,
|
info_hash,
|
||||||
peer_id,
|
peer_id,
|
||||||
files,
|
files,
|
||||||
|
filenames,
|
||||||
chunk_tracker,
|
chunk_tracker,
|
||||||
lengths,
|
lengths,
|
||||||
initial_check_results.have_bytes,
|
initial_check_results.have_bytes,
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fs::File,
|
fs::File,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
|
path::PathBuf,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicU64, Ordering},
|
atomic::{AtomicU64, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
|
|
@ -232,6 +233,7 @@ pub struct TorrentState {
|
||||||
info: TorrentMetaV1Info<ByteString>,
|
info: TorrentMetaV1Info<ByteString>,
|
||||||
locked: Arc<RwLock<TorrentStateLocked>>,
|
locked: Arc<RwLock<TorrentStateLocked>>,
|
||||||
files: Vec<Arc<Mutex<File>>>,
|
files: Vec<Arc<Mutex<File>>>,
|
||||||
|
filenames: Vec<PathBuf>,
|
||||||
info_hash: Id20,
|
info_hash: Id20,
|
||||||
peer_id: Id20,
|
peer_id: Id20,
|
||||||
lengths: Lengths,
|
lengths: Lengths,
|
||||||
|
|
@ -253,6 +255,7 @@ impl TorrentState {
|
||||||
info_hash: Id20,
|
info_hash: Id20,
|
||||||
peer_id: Id20,
|
peer_id: Id20,
|
||||||
files: Vec<Arc<Mutex<File>>>,
|
files: Vec<Arc<Mutex<File>>>,
|
||||||
|
filenames: Vec<PathBuf>,
|
||||||
chunk_tracker: ChunkTracker,
|
chunk_tracker: ChunkTracker,
|
||||||
lengths: Lengths,
|
lengths: Lengths,
|
||||||
have_bytes: u64,
|
have_bytes: u64,
|
||||||
|
|
@ -271,6 +274,7 @@ impl TorrentState {
|
||||||
chunks: chunk_tracker,
|
chunks: chunk_tracker,
|
||||||
})),
|
})),
|
||||||
files,
|
files,
|
||||||
|
filenames,
|
||||||
stats: AtomicStats {
|
stats: AtomicStats {
|
||||||
have: AtomicU64::new(have_bytes),
|
have: AtomicU64::new(have_bytes),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
@ -894,6 +898,35 @@ impl PeerHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reopen_read_only(&self) -> anyhow::Result<()> {
|
||||||
|
fn dummy_file() -> anyhow::Result<std::fs::File> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
const DEVNULL: &str = "NUL";
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
const DEVNULL: &str = "/dev/null";
|
||||||
|
|
||||||
|
std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(DEVNULL)
|
||||||
|
.with_context(|| format!("error opening {}", DEVNULL))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (file, filename) in self.state.files.iter().zip(self.state.filenames.iter()) {
|
||||||
|
let mut g = file.lock();
|
||||||
|
// this should close the original file
|
||||||
|
// putting in a block just in case to guarantee drop.
|
||||||
|
{
|
||||||
|
*g = dummy_file()?;
|
||||||
|
}
|
||||||
|
*g = std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(filename)
|
||||||
|
.with_context(|| format!("error re-opening {:?} readonly", filename))?;
|
||||||
|
debug!("reopened {:?} read-only", filename);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn on_i_am_unchoked(&self, handle: PeerHandle) {
|
fn on_i_am_unchoked(&self, handle: PeerHandle) {
|
||||||
debug!("we are unchoked by {}", handle);
|
debug!("we are unchoked by {}", handle);
|
||||||
let mut g = self.state.locked.write();
|
let mut g = self.state.locked.write();
|
||||||
|
|
@ -1032,6 +1065,7 @@ impl PeerHandler {
|
||||||
|
|
||||||
if self.state.get_left_to_download() == 0 {
|
if self.state.get_left_to_download() == 0 {
|
||||||
self.state.finished_notify.notify_waiters();
|
self.state.finished_notify.notify_waiters();
|
||||||
|
self.reopen_read_only()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.state.maybe_transmit_haves(chunk_info.piece_index);
|
self.state.maybe_transmit_haves(chunk_info.piece_index);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue