diff --git a/chain/src/chain.rs b/chain/src/chain.rs index d11162f3c3..bc0bf17a2d 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -35,8 +35,7 @@ use crate::util::secp::pedersen::{Commitment, RangeProof}; use crate::util::{Mutex, RwLock, StopState}; use grin_store::Error::NotFoundErr; use std::collections::HashMap; -use std::env; -use std::fs::File; +use std::fs::{self, File}; use std::path::PathBuf; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; @@ -850,9 +849,39 @@ impl Chain { /// Clean the temporary sandbox folder pub fn clean_txhashset_sandbox(&self) { - let sandbox_dir = env::temp_dir(); - txhashset::clean_txhashset_folder(&sandbox_dir); - txhashset::clean_header_folder(&sandbox_dir); + txhashset::clean_txhashset_folder(&self.get_tmp_dir()); + txhashset::clean_header_folder(&self.get_tmp_dir()); + } + + /// Specific tmp dir. + /// Normally it's ~/.grin/main/tmp for mainnet + /// or ~/.grin/floo/tmp for floonet + pub fn get_tmp_dir(&self) -> PathBuf { + let mut tmp_dir = PathBuf::from(self.db_root.clone()); + tmp_dir = tmp_dir + .parent() + .expect("fail to get parent of db_root dir") + .to_path_buf(); + tmp_dir.push("tmp"); + tmp_dir + } + + /// Get a tmp file path in above specific tmp dir (create tmp dir if not exist) + /// Delete file if tmp file already exists + pub fn get_tmpfile_pathname(&self, tmpfile_name: String) -> PathBuf { + let mut tmp = self.get_tmp_dir(); + if !tmp.exists() { + if let Err(e) = fs::create_dir(tmp.clone()) { + warn!("fail to create tmp folder on {:?}. err: {}", tmp, e); + } + } + tmp.push(tmpfile_name); + if tmp.exists() { + if let Err(e) = fs::remove_file(tmp.clone()) { + warn!("fail to clean existing tmp file: {:?}. err: {}", tmp, e); + } + } + tmp } /// Writes a reading view on a txhashset state that's been provided to us. @@ -876,8 +905,8 @@ impl Chain { let header = self.get_block_header(&h)?; - // Write txhashset to sandbox (in the os temporary directory) - let sandbox_dir = env::temp_dir(); + // Write txhashset to sandbox (in the Grin specific tmp dir) + let sandbox_dir = self.get_tmp_dir(); txhashset::clean_txhashset_folder(&sandbox_dir); txhashset::clean_header_folder(&sandbox_dir); txhashset::zip_write(sandbox_dir.clone(), txhashset_data.try_clone()?, &header)?; diff --git a/p2p/src/peer.rs b/p2p/src/peer.rs index d964dc84f6..4787678134 100644 --- a/p2p/src/peer.rs +++ b/p2p/src/peer.rs @@ -16,6 +16,7 @@ use crate::util::{Mutex, RwLock}; use std::fmt; use std::fs::File; use std::net::{Shutdown, TcpStream}; +use std::path::PathBuf; use std::sync::Arc; use crate::conn; @@ -597,6 +598,14 @@ impl ChainAdapter for TrackingAdapter { self.adapter .txhashset_download_update(start_time, downloaded_size, total_size) } + + fn get_tmp_dir(&self) -> PathBuf { + self.adapter.get_tmp_dir() + } + + fn get_tmpfile_pathname(&self, tmpfile_name: String) -> PathBuf { + self.adapter.get_tmpfile_pathname(tmpfile_name) + } } impl NetAdapter for TrackingAdapter { diff --git a/p2p/src/peers.rs b/p2p/src/peers.rs index 3028b12a15..584cd9c622 100644 --- a/p2p/src/peers.rs +++ b/p2p/src/peers.rs @@ -15,6 +15,7 @@ use crate::util::RwLock; use std::collections::HashMap; use std::fs::File; +use std::path::PathBuf; use std::sync::Arc; use rand::{thread_rng, Rng}; @@ -586,6 +587,14 @@ impl ChainAdapter for Peers { self.adapter .txhashset_download_update(start_time, downloaded_size, total_size) } + + fn get_tmp_dir(&self) -> PathBuf { + self.adapter.get_tmp_dir() + } + + fn get_tmpfile_pathname(&self, tmpfile_name: String) -> PathBuf { + self.adapter.get_tmpfile_pathname(tmpfile_name) + } } impl NetAdapter for Peers { diff --git a/p2p/src/protocol.rs b/p2p/src/protocol.rs index cc49abd3f5..37636fd08c 100644 --- a/p2p/src/protocol.rs +++ b/p2p/src/protocol.rs @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +use rand::{thread_rng, Rng}; use std::cmp; -use std::env; -use std::fs::File; +use std::fs::{self, File, OpenOptions}; use std::io::{BufWriter, Write}; use std::sync::Arc; @@ -288,10 +288,15 @@ impl MessageHandler for Protocol { self.adapter .txhashset_download_update(download_start_time, 0, sm_arch.bytes); - let mut tmp = env::temp_dir(); - tmp.push("txhashset.zip"); + let nonce: u32 = thread_rng().gen_range(0, 1_000_000); + let tmp = self.adapter.get_tmpfile_pathname(format!( + "txhashset-{}-{}.zip", + download_start_time.timestamp(), + nonce + )); let mut save_txhashset_to_file = |file| -> Result<(), Error> { - let mut tmp_zip = BufWriter::new(File::create(file)?); + let mut tmp_zip = + BufWriter::new(OpenOptions::new().write(true).create_new(true).open(file)?); let total_size = sm_arch.bytes as usize; let mut downloaded_size: usize = 0; let mut request_size = cmp::min(48_000, total_size); @@ -332,7 +337,7 @@ impl MessageHandler for Protocol { tmp, ); - let tmp_zip = File::open(tmp)?; + let tmp_zip = File::open(tmp.clone())?; let res = self .adapter .txhashset_write(sm_arch.hash, tmp_zip, self.addr); @@ -342,6 +347,10 @@ impl MessageHandler for Protocol { sm_arch.hash, sm_arch.height, res ); + if let Err(e) = fs::remove_file(tmp.clone()) { + warn!("fail to remove tmp file: {:?}. err: {}", tmp, e); + } + Ok(None) } diff --git a/p2p/src/serv.rs b/p2p/src/serv.rs index 55e7ff8f18..ad19743563 100644 --- a/p2p/src/serv.rs +++ b/p2p/src/serv.rs @@ -14,6 +14,7 @@ use std::fs::File; use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream}; +use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use std::{io, thread}; @@ -278,6 +279,14 @@ impl ChainAdapter for DummyAdapter { ) -> bool { false } + + fn get_tmp_dir(&self) -> PathBuf { + unimplemented!() + } + + fn get_tmpfile_pathname(&self, _tmpfile_name: String) -> PathBuf { + unimplemented!() + } } impl NetAdapter for DummyAdapter { diff --git a/p2p/src/types.rs b/p2p/src/types.rs index 48f308dc92..16dadc46d8 100644 --- a/p2p/src/types.rs +++ b/p2p/src/types.rs @@ -17,6 +17,7 @@ use std::convert::From; use std::fs::File; use std::io; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; +use std::path::PathBuf; use std::sync::mpsc; use std::sync::Arc; @@ -506,6 +507,13 @@ pub trait ChainAdapter: Sync + Send { /// read as a zip file, unzipped and the resulting state files should be /// rewound to the provided indexes. fn txhashset_write(&self, h: Hash, txhashset_data: File, peer_addr: PeerAddr) -> bool; + + /// Get the Grin specific tmp dir + fn get_tmp_dir(&self) -> PathBuf; + + /// Get a tmp file path in above specific tmp dir (create tmp dir if not exist) + /// Delete file if tmp file already exists + fn get_tmpfile_pathname(&self, tmpfile_name: String) -> PathBuf; } /// Additional methods required by the protocol that don't need to be diff --git a/servers/src/common/adapters.rs b/servers/src/common/adapters.rs index b04e1ab704..8dade5750d 100644 --- a/servers/src/common/adapters.rs +++ b/servers/src/common/adapters.rs @@ -17,6 +17,7 @@ use crate::util::RwLock; use std::fs::File; +use std::path::PathBuf; use std::sync::{Arc, Weak}; use std::thread; use std::time::Instant; @@ -374,6 +375,14 @@ impl p2p::ChainAdapter for NetToChainAdapter { true } } + + fn get_tmp_dir(&self) -> PathBuf { + self.chain().get_tmp_dir() + } + + fn get_tmpfile_pathname(&self, tmpfile_name: String) -> PathBuf { + self.chain().get_tmpfile_pathname(tmpfile_name) + } } impl NetToChainAdapter {