Fix disk storage on termination (#151)

See #150 for more information
next
Sayan Nandan 3 years ago committed by GitHub
parent 3616793554
commit a61ab02cd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -2,6 +2,12 @@
All changes in this project will be noted in this file.
## Version 0.5.3 [2021-05-13]
> No breaking changes
Fix persistence (see [#150](https://github.com/skytable/skytable/issues/150))
## Version 0.5.2 [2021-05-07]
> No breaking changes

@ -287,7 +287,7 @@ impl CoreDB {
bgsave: BGSave,
snapshot_cfg: SnapshotConfig,
restore_file: Option<String>,
) -> TResult<(Self, Option<flock::FileLock>, flock::FileLock)> {
) -> TResult<(Self, Option<flock::FileLock>)> {
let coretable = diskstore::get_saved(restore_file)?;
let mut background_tasks: usize = 0;
if !bgsave.is_disabled() {
@ -325,13 +325,12 @@ impl CoreDB {
));
let lock = flock::FileLock::lock(&*PERSIST_FILE)
.map_err(|e| format!("Failed to acquire lock on data file with error '{}'", e))?;
let cloned_descriptor = lock.try_clone()?;
if bgsave.is_disabled() {
Ok((db, Some(lock), cloned_descriptor))
Ok((db, Some(lock)))
} else {
// Spawn the BGSAVE service in a separate task
tokio::spawn(diskstore::bgsave_scheduler(db.clone(), bgsave, lock));
Ok((db, None, cloned_descriptor))
Ok((db, None))
}
}
/// Create an empty in-memory table

@ -44,8 +44,7 @@ use crate::config::PortConfig;
use crate::config::SnapshotConfig;
use crate::config::SslOpts;
use crate::dbnet::tcp::Listener;
use crate::diskstore::{self, snapshot::DIR_REMOTE_SNAPSHOT};
use diskstore::flock;
use crate::diskstore::snapshot::DIR_REMOTE_SNAPSHOT;
mod tcp;
use crate::CoreDB;
use libsky::TResult;
@ -315,7 +314,7 @@ pub async fn run(
snapshot_cfg: SnapshotConfig,
sig: impl Future,
restore_filepath: Option<String>,
) -> (CoreDB, flock::FileLock) {
) -> CoreDB {
let (signal, _) = broadcast::channel(1);
let (terminate_tx, terminate_rx) = mpsc::channel(1);
match fs::create_dir_all(&*DIR_REMOTE_SNAPSHOT) {
@ -328,14 +327,13 @@ pub async fn run(
}
},
}
let (db, lock, cloned_descriptor) =
match CoreDB::new(bgsave_cfg, snapshot_cfg, restore_filepath) {
Ok((db, lock, cloned_descriptor)) => (db, lock, cloned_descriptor),
Err(e) => {
log::error!("ERROR: {}", e);
process::exit(0x100);
}
};
let (db, lock) = match CoreDB::new(bgsave_cfg, snapshot_cfg, restore_filepath) {
Ok((db, lock)) => (db, lock),
Err(e) => {
log::error!("ERROR: {}", e);
process::exit(0x100);
}
};
let climit = Arc::new(Semaphore::new(50000));
let mut server = match ports {
PortConfig::InsecureOnly { host, port } => {
@ -392,5 +390,5 @@ pub async fn run(
log::error!("Failed to release lock on data file with '{}'", e);
process::exit(0x100);
}
(db, cloned_descriptor)
db
}

@ -98,18 +98,6 @@ impl FileLock {
// Now write to the file
self.file.write_all(bytes)
}
pub fn try_clone(&self) -> Result<Self> {
Ok(Self {
file: self.file.try_clone()?,
unlocked: false,
})
}
/// Reacquire a lock
pub fn reacquire(&mut self) -> Result<()> {
Self::_lock(&self.file)?;
self.unlocked = false;
Ok(())
}
}
impl Drop for FileLock {

@ -33,6 +33,7 @@
use crate::config::BGSave;
use crate::config::PortConfig;
use crate::config::SnapshotConfig;
use crate::diskstore::PERSIST_FILE;
use std::io::{self, prelude::*};
mod config;
use std::env;
@ -77,10 +78,10 @@ fn main() {
.enable_all()
.build()
.unwrap();
let (db, mut descriptor) = runtime.block_on(async {
let db = runtime.block_on(async {
let (tcplistener, bgsave_config, snapshot_config, restore_filepath) =
check_args_and_get_cfg().await;
let (db, descriptor) = run(
let db = run(
tcplistener,
bgsave_config,
snapshot_config,
@ -88,7 +89,7 @@ fn main() {
restore_filepath,
)
.await;
(db, descriptor)
db
});
// Make sure all background workers terminate
drop(runtime);
@ -98,18 +99,21 @@ fn main() {
"Maybe the compiler reordered the drop causing more than one instance of CoreDB to live at this point"
);
// Try to acquire lock almost immediately
if let Err(e) = descriptor.reacquire() {
log::error!("Failed to reacquire lock on data file with error: '{}'", e);
panic!("FATAL: data file relocking failure");
}
if let Err(e) = flush_db!(db, descriptor) {
let mut lock = match diskstore::flock::FileLock::lock(&*PERSIST_FILE) {
Ok(lck) => lck,
Err(e) => {
log::error!("Failed to reacquire lock on data file with '{}'", e);
std::process::exit(0x100);
}
};
if let Err(e) = flush_db!(db, lock) {
log::error!("Failed to flush data to disk with '{}'", e);
loop {
// Keep looping until we successfully write the in-memory table to disk
log::warn!("Press enter to try again...");
io::stdout().flush().unwrap();
io::stdin().read(&mut [0]).unwrap();
if let Ok(_) = flush_db!(db, descriptor) {
if let Ok(_) = flush_db!(db, lock) {
log::info!("Successfully saved data to disk");
break;
} else {
@ -124,12 +128,7 @@ fn main() {
/// This function checks the command line arguments and either returns a config object
/// or prints an error to `stderr` and terminates the server
async fn check_args_and_get_cfg() -> (
PortConfig,
BGSave,
SnapshotConfig,
Option<String>,
) {
async fn check_args_and_get_cfg() -> (PortConfig, BGSave, SnapshotConfig, Option<String>) {
let cfg = config::get_config_file_or_return_cfg();
let binding_and_cfg = match cfg {
Ok(config::ConfigType::Custom(cfg, file)) => {

Loading…
Cancel
Save