From 7aaf22c9239ae78472f4b9b4968c2a666b7ed323 Mon Sep 17 00:00:00 2001 From: Ethan O'Brien Date: Sat, 2 Nov 2024 12:09:35 -0500 Subject: [PATCH] Replace repeated Mutex lock functions with a macro --- src/main.rs | 44 ++++++------ src/router.rs | 4 +- src/router/clear_rate.rs | 48 ++++--------- src/router/event.rs | 4 +- src/router/event_ranking.rs | 44 ++++-------- src/sql.rs | 133 ++++++++++++++++-------------------- 6 files changed, 110 insertions(+), 167 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8f26a53..3902836 100644 --- a/src/main.rs +++ b/src/main.rs @@ -142,6 +142,7 @@ pub fn get_data_path(file_name: &str) -> String { format!("{}/{}", path, file_name) } +// include_file macro: includes a file compressed at compile time, and decompresses it on reference. Decreases binary size #[macro_export] macro_rules! include_file { ( $s:expr ) => { @@ -152,6 +153,7 @@ macro_rules! include_file { } }; } + pub fn decode(bytes: &[u8]) -> Vec { use std::io::{Cursor, Read}; @@ -161,32 +163,32 @@ pub fn decode(bytes: &[u8]) -> Vec { ret } +#[macro_export] +macro_rules! lock_onto_mutex { + ($mutex:expr) => {{ + loop { + match $mutex.lock() { + Ok(value) => { + break value; + } + Err(_) => { + actix_web::rt::time::sleep(std::time::Duration::from_millis(15)).await; + } + } + } + }}; +} + lazy_static! { static ref RUNNING: Mutex = Mutex::new(false); } async fn set_running(running: bool) { - loop { - match RUNNING.lock() { - Ok(mut result) => { - *result = running; - return; - } - Err(_) => { - actix_web::rt::time::sleep(Duration::from_millis(15)).await; - } - } - } + let mut result = lock_onto_mutex!(RUNNING); + *result = running; } + async fn get_running() -> bool { - loop { - match RUNNING.lock() { - Ok(result) => { - return *result; - } - Err(_) => { - actix_web::rt::time::sleep(Duration::from_millis(15)).await; - } - } - } + let result = lock_onto_mutex!(RUNNING); + return *result; } diff --git a/src/router.rs b/src/router.rs index e8ff1bb..c017a7e 100644 --- a/src/router.rs +++ b/src/router.rs @@ -93,7 +93,7 @@ async fn api_req(req: HttpRequest, body: String) -> HttpResponse { "/api/event" => event::event(req, body), "/api/event/star_event" => event::star_event(req, body), "/api/event/set/member" => event::set_member(req, body), - "/api/event/ranking" => event::ranking(req, body), + "/api/event/ranking" => event::ranking(req, body).await, "/api/event_star_live/change_target_music" => event::change_target_music(req, body), "/api/event_star_live/start" => live::event_start(req, body), "/api/event_star_live/end" => event::event_end(req, body), @@ -135,7 +135,7 @@ async fn api_req(req: HttpRequest, body: String) -> HttpResponse { "/api/gift" => home::gift_get(req), "/api/purchase" => purchase::purchase(req), "/api/friend/ids" => friend::ids(req), - "/api/live/clearRate" => clear_rate::clearrate(req), + "/api/live/clearRate" => clear_rate::clearrate(req).await, "/api/mission" => mission::mission(req), "/api/home" => home::home(req), "/api/home/preset" => home::preset_get(req), diff --git a/src/router/clear_rate.rs b/src/router/clear_rate.rs index dab0b87..292638e 100644 --- a/src/router/clear_rate.rs +++ b/src/router/clear_rate.rs @@ -2,7 +2,6 @@ use json::{object, array, JsonValue}; use actix_web::{HttpRequest}; use rusqlite::params; use std::sync::Mutex; -use std::thread; use lazy_static::lazy_static; use crate::encryption; @@ -167,42 +166,23 @@ fn get_json() -> JsonValue { } } -fn get_clearrate_json() -> JsonValue { - loop { - match CACHED_DATA.lock() { - Ok(mut result) => { - if result.is_none() { - result.replace(get_json()); - } - let cache = result.as_ref().unwrap(); - let rv = cache["cache"].clone(); - if cache["last_updated"].as_u64().unwrap() + (60 * 60) < global::timestamp() { - thread::spawn(|| { - loop { - match CACHED_DATA.lock() { - Ok(mut result) => { - let new = get_json(); - result.replace(new.clone()); - break; - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(15)); - } - } - } - }); - } - return rv; - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(15)); - } - } +async fn get_clearrate_json() -> JsonValue { + let mut result = crate::lock_onto_mutex!(CACHED_DATA); + if result.is_none() { + result.replace(get_json()); } + let cache = result.as_ref().unwrap(); + let rv = cache["cache"].clone(); + if cache["last_updated"].as_u64().unwrap() + (60 * 60) < global::timestamp() { + let mut result = crate::lock_onto_mutex!(CACHED_DATA); + let new = get_json(); + result.replace(new.clone()); + } + return rv; } -pub fn clearrate(_req: HttpRequest) -> Option { - Some(get_clearrate_json()) +pub async fn clearrate(_req: HttpRequest) -> Option { + Some(get_clearrate_json().await) } pub fn ranking(_req: HttpRequest, body: String) -> Option { diff --git a/src/router/event.rs b/src/router/event.rs index 735cf55..0a42133 100644 --- a/src/router/event.rs +++ b/src/router/event.rs @@ -219,10 +219,10 @@ fn get_rank(event: u32, user_id: u64) -> u32 { 0 } -pub fn ranking(_req: HttpRequest, body: String) -> Option { +pub async fn ranking(_req: HttpRequest, body: String) -> Option { let body = &encryption::decrypt_packet(&body).unwrap(); let body: EventRankingGet = serde_json::from_str(body).unwrap(); - let scores = crate::router::event_ranking::get_scores_json()[body.master_event_id.to_string()].clone(); + let scores = crate::router::event_ranking::get_scores_json().await[body.master_event_id.to_string()].clone(); let mut rv = array![]; let mut i=1; let start = if body.user_id == 0 { body.start_rank } else { get_rank(body.master_event_id, body.user_id) }; diff --git a/src/router/event_ranking.rs b/src/router/event_ranking.rs index 18d54d5..6c05157 100644 --- a/src/router/event_ranking.rs +++ b/src/router/event_ranking.rs @@ -1,7 +1,6 @@ use json::{object, array, JsonValue}; use rusqlite::params; use std::sync::Mutex; -use std::thread; use lazy_static::lazy_static; use crate::sql::SQLite; @@ -98,36 +97,17 @@ fn get_json() -> JsonValue { } } -pub fn get_scores_json() -> JsonValue { - loop { - match CACHED_DATA.lock() { - Ok(mut result) => { - if result.is_none() { - result.replace(get_json()); - } - let cache = result.as_ref().unwrap(); - let rv = cache["cache"].clone(); - if cache["last_updated"].as_u64().unwrap() + (60 * 60) < global::timestamp() { - thread::spawn(|| { - loop { - match CACHED_DATA.lock() { - Ok(mut result) => { - let new = get_json(); - result.replace(new.clone()); - break; - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(15)); - } - } - } - }); - } - return rv; - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(15)); - } - } +pub async fn get_scores_json() -> JsonValue { + let mut result = crate::lock_onto_mutex!(CACHED_DATA); + if result.is_none() { + result.replace(get_json()); } + let cache = result.as_ref().unwrap(); + let rv = cache["cache"].clone(); + if cache["last_updated"].as_u64().unwrap() + (60 * 60) < global::timestamp() { + let mut result = crate::lock_onto_mutex!(CACHED_DATA); + let new = get_json(); + result.replace(new.clone()); + } + return rv; } diff --git a/src/sql.rs b/src/sql.rs index c580112..40363d3 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -5,8 +5,23 @@ use json::{JsonValue, array}; use crate::router::clear_rate::Live; pub struct SQLite { - engine: Mutex, - sleep_duration: u64 + engine: Mutex +} + +// This is duplicated, for ease of people wanting to use this file in their project +macro_rules! lock_onto_mutex { + ($mutex:expr) => {{ + loop { + match $mutex.lock() { + Ok(value) => { + break value; + } + Err(_) => { + std::thread::sleep(std::time::Duration::from_millis(10)); + } + } + } + }}; } impl SQLite { @@ -14,94 +29,60 @@ impl SQLite { let conn = Connection::open(crate::get_data_path(path)).unwrap(); conn.execute("PRAGMA foreign_keys = ON;", ()).unwrap(); let instance = SQLite { - engine: Mutex::new(conn), - sleep_duration: 10 + engine: Mutex::new(conn) }; setup(&instance); instance } pub fn lock_and_exec(&self, command: &str, args: &[&dyn ToSql]) { - loop { - match self.engine.lock() { - Ok(conn) => { - conn.execute(command, args).unwrap(); - return; - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(self.sleep_duration)); - } - } - } + let conn = lock_onto_mutex!(self.engine); + conn.execute(command, args).unwrap(); } pub fn lock_and_select(&self, command: &str, args: &[&dyn ToSql]) -> Result { - loop { - match self.engine.lock() { - Ok(conn) => { - let mut stmt = conn.prepare(command)?; - return stmt.query_row(args, |row| { - match row.get::(0) { - Ok(val) => Ok(val.to_string()), - Err(_) => row.get(0) - } - }); - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(self.sleep_duration)); - } + let conn = lock_onto_mutex!(self.engine); + let mut stmt = conn.prepare(command)?; + return stmt.query_row(args, |row| { + match row.get::(0) { + Ok(val) => Ok(val.to_string()), + Err(_) => row.get(0) } - } + }); } pub fn lock_and_select_all(&self, command: &str, args: &[&dyn ToSql]) -> Result { - loop { - match self.engine.lock() { - Ok(conn) => { - let mut stmt = conn.prepare(command)?; - let map = stmt.query_map(args, |row| { - match row.get::(0) { - Ok(val) => Ok(val.to_string()), - Err(_) => row.get(0) - } - })?; - let mut rv = array![]; - for val in map { - let res = val?; - match res.clone().parse::() { - Ok(v) => rv.push(v).unwrap(), - Err(_) => rv.push(res).unwrap() - }; - } - return Ok(rv); - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(self.sleep_duration)); - } + let conn = lock_onto_mutex!(self.engine); + let mut stmt = conn.prepare(command)?; + let map = stmt.query_map(args, |row| { + match row.get::(0) { + Ok(val) => Ok(val.to_string()), + Err(_) => row.get(0) } + })?; + let mut rv = array![]; + for val in map { + let res = val?; + match res.clone().parse::() { + Ok(v) => rv.push(v).unwrap(), + Err(_) => rv.push(res).unwrap() + }; } + return Ok(rv); } pub fn get_live_data(&self, id: i64) -> Result { - loop { - match self.engine.lock() { - Ok(conn) => { - let mut stmt = conn.prepare("SELECT * FROM lives WHERE live_id=?1")?; - return stmt.query_row(params!(id), |row| { - Ok(Live { - live_id: row.get(0)?, - normal_failed: row.get(1)?, - normal_pass: row.get(2)?, - hard_failed: row.get(3)?, - hard_pass: row.get(4)?, - expert_failed: row.get(5)?, - expert_pass: row.get(6)?, - master_failed: row.get(7)?, - master_pass: row.get(8)?, - }) - }); - } - Err(_) => { - std::thread::sleep(std::time::Duration::from_millis(self.sleep_duration)); - } - } - } + let conn = lock_onto_mutex!(self.engine); + let mut stmt = conn.prepare("SELECT * FROM lives WHERE live_id=?1")?; + return stmt.query_row(params!(id), |row| { + Ok(Live { + live_id: row.get(0)?, + normal_failed: row.get(1)?, + normal_pass: row.get(2)?, + hard_failed: row.get(3)?, + hard_pass: row.get(4)?, + expert_failed: row.get(5)?, + expert_pass: row.get(6)?, + master_failed: row.get(7)?, + master_pass: row.get(8)?, + }) + }); } pub fn create_store_v2(&self, table: &str) { self.lock_and_exec(table, params!());