|
@@ -32,6 +32,7 @@ use crate::whois::WhoIsInfo;
|
|
|
use std::collections::HashMap;
|
|
|
use std::error::Error;
|
|
|
use std::sync::atomic::AtomicBool;
|
|
|
+use std::sync::Weak;
|
|
|
use std::sync::{Arc, Mutex, RwLock};
|
|
|
use tokio::sync::mpsc;
|
|
|
use tokio::task::JoinHandle;
|
|
@@ -43,6 +44,7 @@ pub const DEFAULT_MAX_LOG_AGE_MS: u64 = DEFAULT_MAX_LOG_AGE * 1000;
|
|
|
pub const MAX_LOG_AGE_VALUE_MIN: u64 = 3600;
|
|
|
pub const MAX_LOG_AGE_VALUE_MAX: u64 = 365 * 24 * 60 * 60 * 10;
|
|
|
pub const MIN_FREE_DISK_SPACE: u64 = 1024 * 1024 * 8;
|
|
|
+pub const DB_FILE_NAME: &str = "smartdns.db";
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
pub struct OverviewData {
|
|
@@ -68,14 +70,16 @@ pub struct MetricsData {
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
pub struct DataServerConfig {
|
|
|
- pub data_root: String,
|
|
|
+ pub db_file: String,
|
|
|
+ pub data_path: String,
|
|
|
pub max_log_age_ms: u64,
|
|
|
}
|
|
|
|
|
|
impl DataServerConfig {
|
|
|
pub fn new() -> Self {
|
|
|
DataServerConfig {
|
|
|
- data_root: Plugin::dns_conf_data_dir() + "/smartdns.db",
|
|
|
+ data_path: Plugin::dns_conf_data_dir(),
|
|
|
+ db_file: Plugin::dns_conf_data_dir() + "/" + DB_FILE_NAME,
|
|
|
max_log_age_ms: DEFAULT_MAX_LOG_AGE_MS,
|
|
|
}
|
|
|
}
|
|
@@ -110,7 +114,7 @@ pub struct DataServerControl {
|
|
|
server_thread: Mutex<Option<JoinHandle<()>>>,
|
|
|
is_init: Mutex<bool>,
|
|
|
is_run: Mutex<bool>,
|
|
|
- plugin: Mutex<Option<Arc<SmartdnsPlugin>>>,
|
|
|
+ plugin: Mutex<Weak<SmartdnsPlugin>>,
|
|
|
}
|
|
|
|
|
|
impl DataServerControl {
|
|
@@ -120,7 +124,7 @@ impl DataServerControl {
|
|
|
server_thread: Mutex::new(None),
|
|
|
is_init: Mutex::new(false),
|
|
|
is_run: Mutex::new(false),
|
|
|
- plugin: Mutex::new(None),
|
|
|
+ plugin: Mutex::new(Weak::new()),
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -129,12 +133,19 @@ impl DataServerControl {
|
|
|
}
|
|
|
|
|
|
pub fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
|
|
|
- *self.plugin.lock().unwrap() = Some(plugin);
|
|
|
+ *self.plugin.lock().unwrap() = Arc::downgrade(&plugin);
|
|
|
}
|
|
|
|
|
|
- pub fn get_plugin(&self) -> Arc<SmartdnsPlugin> {
|
|
|
- let plugin = self.plugin.lock().unwrap();
|
|
|
- Arc::clone(&plugin.as_ref().unwrap())
|
|
|
+ pub fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
|
|
|
+ let plugin = match self.plugin.lock() {
|
|
|
+ Ok(plugin) => plugin,
|
|
|
+ Err(_) => return Err("Failed to lock plugin mutex".into()),
|
|
|
+ };
|
|
|
+
|
|
|
+ if let Some(plugin) = plugin.upgrade() {
|
|
|
+ return Ok(plugin);
|
|
|
+ }
|
|
|
+ Err("Plugin is not set".into())
|
|
|
}
|
|
|
|
|
|
pub fn init_db(&self, conf: &DataServerConfig) -> Result<(), Box<dyn Error>> {
|
|
@@ -155,8 +166,9 @@ impl DataServerControl {
|
|
|
return Err("data server not init".into());
|
|
|
}
|
|
|
|
|
|
- self.data_server.set_plugin(self.get_plugin());
|
|
|
- let rt = self.get_plugin().get_runtime();
|
|
|
+ let plugin = self.get_plugin()?;
|
|
|
+ self.data_server.set_plugin(plugin.clone());
|
|
|
+ let rt = plugin.get_runtime();
|
|
|
|
|
|
let server_thread = rt.spawn(async move {
|
|
|
let ret = DataServer::data_server_loop(inner_clone).await;
|
|
@@ -181,7 +193,18 @@ impl DataServerControl {
|
|
|
self.data_server.stop_data_server();
|
|
|
let _server_thread = self.server_thread.lock().unwrap().take();
|
|
|
if let Some(server_thread) = _server_thread {
|
|
|
- let rt = self.get_plugin().get_runtime();
|
|
|
+ let plugin = self.get_plugin();
|
|
|
+ if plugin.is_err() {
|
|
|
+ dns_log!(
|
|
|
+ LogLevel::ERROR,
|
|
|
+ "get plugin error: {}",
|
|
|
+ plugin.err().unwrap()
|
|
|
+ );
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ let plugin = plugin.unwrap();
|
|
|
+ let rt = plugin.get_runtime();
|
|
|
tokio::task::block_in_place(|| {
|
|
|
if let Err(e) = rt.block_on(server_thread) {
|
|
|
dns_log!(LogLevel::ERROR, "http server stop error: {}", e);
|
|
@@ -233,7 +256,7 @@ pub struct DataServer {
|
|
|
disable_handle_request: AtomicBool,
|
|
|
stat: Arc<DataStats>,
|
|
|
server_log: ServerLog,
|
|
|
- plugin: Mutex<Option<Arc<SmartdnsPlugin>>>,
|
|
|
+ plugin: Mutex<Weak<SmartdnsPlugin>>,
|
|
|
whois: whois::WhoIs,
|
|
|
startup_timestamp: u64,
|
|
|
recv_in_batch: Mutex<bool>,
|
|
@@ -252,7 +275,7 @@ impl DataServer {
|
|
|
db: db.clone(),
|
|
|
stat: DataStats::new(db, conf.clone()),
|
|
|
server_log: ServerLog::new(),
|
|
|
- plugin: Mutex::new(None),
|
|
|
+ plugin: Mutex::new(Weak::new()),
|
|
|
whois: whois::WhoIs::new(),
|
|
|
startup_timestamp: get_utc_time_ms(),
|
|
|
disable_handle_request: AtomicBool::new(false),
|
|
@@ -284,8 +307,17 @@ impl DataServer {
|
|
|
|
|
|
smartdns::smartdns_enable_update_neighbour(true);
|
|
|
|
|
|
- dns_log!(LogLevel::INFO, "open db: {}", conf_clone.data_root);
|
|
|
- let ret = self.db.open(&conf_clone.data_root);
|
|
|
+ if utils::is_dir_writable(&conf_clone.data_path) == false {
|
|
|
+ return Err(format!(
|
|
|
+ "data path '{}' is not exist or writable.",
|
|
|
+ conf_clone.data_path
|
|
|
+ )
|
|
|
+ .into());
|
|
|
+ }
|
|
|
+
|
|
|
+ conf_clone.db_file = conf_clone.data_path.clone() + "/" + DB_FILE_NAME;
|
|
|
+ dns_log!(LogLevel::INFO, "open db: {}", conf_clone.db_file);
|
|
|
+ let ret = self.db.open(&conf_clone.db_file);
|
|
|
if let Err(e) = ret {
|
|
|
return Err(e);
|
|
|
}
|
|
@@ -299,12 +331,19 @@ impl DataServer {
|
|
|
}
|
|
|
|
|
|
pub fn set_plugin(&self, plugin: Arc<SmartdnsPlugin>) {
|
|
|
- *self.plugin.lock().unwrap() = Some(plugin);
|
|
|
+ *self.plugin.lock().unwrap() = Arc::downgrade(&plugin);
|
|
|
}
|
|
|
|
|
|
- pub fn get_plugin(&self) -> Arc<SmartdnsPlugin> {
|
|
|
- let plugin = self.plugin.lock().unwrap();
|
|
|
- Arc::clone(&plugin.as_ref().unwrap())
|
|
|
+ pub fn get_plugin(&self) -> Result<Arc<SmartdnsPlugin>, Box<dyn Error>> {
|
|
|
+ let plugin = match self.plugin.lock() {
|
|
|
+ Ok(plugin) => plugin,
|
|
|
+ Err(_) => return Err("Failed to lock plugin mutex".into()),
|
|
|
+ };
|
|
|
+
|
|
|
+ if let Some(plugin) = plugin.upgrade() {
|
|
|
+ return Ok(plugin);
|
|
|
+ }
|
|
|
+ Err("Plugin is not set".into())
|
|
|
}
|
|
|
|
|
|
pub fn get_data_server_config(&self) -> DataServerConfig {
|
|
@@ -445,7 +484,7 @@ impl DataServer {
|
|
|
}
|
|
|
|
|
|
pub fn get_free_disk_space(&self) -> u64 {
|
|
|
- utils::get_free_disk_space(&self.get_data_server_config().data_root)
|
|
|
+ utils::get_free_disk_space(&self.get_data_server_config().db_file)
|
|
|
}
|
|
|
|
|
|
pub fn get_overview(&self) -> Result<OverviewData, Box<dyn Error + Send>> {
|
|
@@ -705,7 +744,15 @@ impl DataServer {
|
|
|
|
|
|
fn stop_data_server(&self) {
|
|
|
if let Some(tx) = self.notify_tx.as_ref().cloned() {
|
|
|
- let rt = self.get_plugin().get_runtime();
|
|
|
+ let plugin = match self.get_plugin() {
|
|
|
+ Ok(plugin) => plugin,
|
|
|
+ Err(e) => {
|
|
|
+ dns_log!(LogLevel::ERROR, "get plugin error: {}", e);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ let rt = plugin.get_runtime();
|
|
|
tokio::task::block_in_place(|| {
|
|
|
let _ = rt.block_on(async {
|
|
|
let _ = tx.send(()).await;
|
|
@@ -722,7 +769,7 @@ impl DataServer {
|
|
|
F: FnOnce() -> R + Send + 'static,
|
|
|
R: Send + 'static,
|
|
|
{
|
|
|
- let rt = this.get_plugin().get_runtime();
|
|
|
+ let rt = this.get_plugin().unwrap().get_runtime();
|
|
|
|
|
|
let ret = rt.spawn_blocking(move || -> R {
|
|
|
return func();
|