how is this slower? 2021-04-sample-optimized-persister
authorMatt Corallo <git@bluematt.me>
Thu, 8 Apr 2021 02:55:27 +0000 (22:55 -0400)
committerMatt Corallo <git@bluematt.me>
Thu, 8 Apr 2021 02:55:44 +0000 (22:55 -0400)
lightning-persister/src/lib.rs
lightning-persister/src/util.rs

index 69319afd1077ae63a96e628ecb5f29ef4fc63434..5ae16a6df1a7533ce6f550cb32d449c955fdfaa5 100644 (file)
@@ -24,16 +24,16 @@ use lightning::ln::channelmanager::ChannelManager;
 use lightning::util::logger::Logger;
 use lightning::util::ser::Writeable;
 use std::fs;
+use std::collections::HashMap;
 use std::io::{Error, Write};
 use std::path::PathBuf;
-use std::sync::Arc;
+use std::sync::{Arc, RwLock, Mutex};
 
 #[cfg(test)]
 use {
        lightning::util::ser::ReadableArgs,
        bitcoin::{BlockHash, Txid},
        bitcoin::hashes::hex::FromHex,
-       std::collections::HashMap,
        std::io::Cursor
 };
 
@@ -51,6 +51,7 @@ use {
 /// FilesystemPersister.
 pub struct FilesystemPersister {
        path_to_channel_data: String,
+    monitor_logs: RwLock<HashMap<String, Mutex<fs::File>>>, // This locking structure is insane
 }
 
 impl<Signer: Sign> DiskWriteable for ChannelMonitor<Signer> {
@@ -83,6 +84,7 @@ impl FilesystemPersister {
        pub fn new(path_to_channel_data: String) -> Self {
                return Self {
                        path_to_channel_data,
+            monitor_logs: RwLock::new(HashMap::new()),
                }
        }
 
@@ -157,9 +159,21 @@ impl<ChannelSigner: Sign + Send + Sync> channelmonitor::Persist<ChannelSigner> f
        }
 
        fn update_persisted_channel(&self, funding_txo: OutPoint, update: &ChannelMonitorUpdate, _monitor: &ChannelMonitor<ChannelSigner>) -> Result<(), ChannelMonitorUpdateErr> {
-               let filename = format!("{}_{}_{}", funding_txo.txid.to_hex(), funding_txo.index, update.update_id);
-               util::write_to_new_file(self.path_to_monitor_data(), &filename, update)
-                 .map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)
+               let filename = format!("{}_{}.log", funding_txo.txid.to_hex(), funding_txo.index);
+               {
+                       let logs = self.monitor_logs.read().unwrap();
+                       match logs.get(&filename) {
+                               Some(file) => {
+                                       return util::write_to_open_file(&mut *file.lock().unwrap(), update).map_err(|_| ChannelMonitorUpdateErr::PermanentFailure);
+                               },
+                               None => {},
+                       }
+               }
+               let mut logs = self.monitor_logs.write().unwrap();
+               let mut f = util::open_file(self.path_to_monitor_data(), &filename).map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)?;
+               util::write_to_open_file(&mut f, update).map_err(|_| ChannelMonitorUpdateErr::PermanentFailure)?;
+               assert!(logs.insert(filename, Mutex::new(f)).is_none(), "We cannot have parallel calls to update a single monitor");
+               Ok(())
        }
 }
 
index 8e34178bb3056d8f9c922e7f69613afba9389866..b330006cdb3a26165e51094da5137db2526d31a0 100644 (file)
@@ -38,18 +38,26 @@ fn path_to_windows_str<T: AsRef<OsStr>>(path: T) -> Vec<winapi::shared::ntdef::W
        path.as_ref().encode_wide().chain(Some(0)).collect()
 }
 
-pub(crate) fn write_to_new_file<D: DiskWriteable>(path: PathBuf, filename: &str, data: &D) -> std::io::Result<()> {
-       let filename_with_path = get_full_filepath(path.clone(), &filename);
-       fs::create_dir_all(path)?;
-
+pub(crate) fn write_to_open_file<D: DiskWriteable>(f: &mut fs::File, data: &D) -> std::io::Result<()> {
        // Note that going by rust-lang/rust@d602a6b, on MacOS it is only safe to use
        // rust stdlib 1.36 or higher.
-       let mut f = fs::File::create(filename_with_path)?;
-       data.write_to_file(&mut f)?;
+       data.write_to_file(f)?;
        f.sync_all()?;
        Ok(())
 }
 
+pub(crate) fn open_file(path: PathBuf, filename: &str) -> std::io::Result<fs::File> {
+       let filename_with_path = get_full_filepath(path.clone(), &filename);
+       fs::create_dir_all(path)?; //XXX
+
+       fs::File::create(filename_with_path)
+}
+
+pub(crate) fn write_to_new_file<D: DiskWriteable>(path: PathBuf, filename: &str, data: &D) -> std::io::Result<()> {
+       let mut f = open_file(path, filename)?;
+       write_to_open_file(&mut f, data)
+}
+
 
 #[allow(bare_trait_objects)]
 pub(crate) fn write_to_file<D: DiskWriteable>(path: PathBuf, filename: String, data: &D) -> std::io::Result<()> {