Skip to content

Commit

Permalink
change all catalog-types to use dashmap
Browse files Browse the repository at this point in the history
  • Loading branch information
CommanderStorm committed Dec 15, 2024
1 parent 12e5167 commit 7ce7558
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 52 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ cargo-husky = { version = "1", features = ["user-hooks"], default-features = fal
clap = { version = "4", features = ["derive"] }
criterion = { version = "0.5", features = ["async_futures", "async_tokio", "html_reports"] }
ctor = "0.2"
dashmap = { version = "6.1.0", features = ["serde", "inline", "rayon"] }
deadpool-postgres = "0.14"
enum-display = "0.1"
env_logger = "0.11"
Expand Down
1 change: 1 addition & 0 deletions martin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ async-trait.workspace = true
bit-set = { workspace = true, optional = true }
brotli.workspace = true
clap.workspace = true
dashmap.workspace = true
deadpool-postgres = { workspace = true, optional = true }
enum-display.workspace = true
env_logger.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion martin/src/bin/martin-cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ fn parse_encoding(encoding: &str) -> MartinCpResult<AcceptEncoding> {
async fn init_schema(
mbt: &Mbtiles,
conn: &mut SqliteConnection,
sources: &[&dyn Source],
sources: &[TileInfoSource],
tile_info: TileInfo,
args: &CopyArgs,
) -> Result<MbtType, MartinError> {
Expand Down
15 changes: 7 additions & 8 deletions martin/src/fonts/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::collections::hash_map::Entry;
use std::collections::{BTreeMap, HashMap};
use std::ffi::OsStr;
use std::fmt::Debug;
use std::path::PathBuf;
use std::sync::OnceLock;

use bit_set::BitSet;
use dashmap::{DashMap, Entry};
use itertools::Itertools as _;
use log::{debug, info, warn};
use pbf_font_tools::freetype::{Face, Library};
Expand Down Expand Up @@ -103,11 +102,11 @@ fn get_available_codepoints(face: &mut Face) -> Option<GetGlyphInfo> {

#[derive(Debug, Clone, Default)]
pub struct FontSources {
fonts: HashMap<String, FontSource>,
fonts: DashMap<String, FontSource>,
masks: Vec<BitSet>,
}

pub type FontCatalog = BTreeMap<String, CatalogFontEntry>;
pub type FontCatalog = DashMap<String, CatalogFontEntry>;

#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
Expand All @@ -125,7 +124,7 @@ impl FontSources {
return Ok(Self::default());
}

let mut fonts = HashMap::new();
let mut fonts = DashMap::new();
let lib = Library::init()?;

for path in config.iter() {
Expand All @@ -150,7 +149,7 @@ impl FontSources {
pub fn get_catalog(&self) -> FontCatalog {
self.fonts
.iter()
.map(|(k, v)| (k.clone(), v.catalog_entry.clone()))
.map(|v| (v.key().clone(), v.catalog_entry.clone()))
.sorted_by(|(a, _), (b, _)| a.cmp(b))
.collect()
}
Expand Down Expand Up @@ -242,7 +241,7 @@ pub struct FontSource {
fn recurse_dirs(
lib: &Library,
path: PathBuf,
fonts: &mut HashMap<String, FontSource>,
fonts: &mut DashMap<String, FontSource>,
is_top_level: bool,
) -> FontResult<()> {
let start_count = fonts.len();
Expand Down Expand Up @@ -275,7 +274,7 @@ fn recurse_dirs(

fn parse_font(
lib: &Library,
fonts: &mut HashMap<String, FontSource>,
fonts: &mut DashMap<String, FontSource>,
path: PathBuf,
) -> FontResult<()> {
static RE_SPACES: OnceLock<Regex> = OnceLock::new();
Expand Down
18 changes: 10 additions & 8 deletions martin/src/source.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use std::collections::{BTreeMap, HashMap};
use std::collections::HashMap;
use std::fmt::Debug;

use actix_web::error::ErrorNotFound;
use async_trait::async_trait;
use dashmap::DashMap;
use log::debug;
use martin_tile_utils::{TileCoord, TileInfo};
use serde::{Deserialize, Serialize};
Expand All @@ -18,8 +19,8 @@ pub type TileInfoSource = Box<dyn Source>;
pub type TileInfoSources = Vec<TileInfoSource>;

#[derive(Default, Clone)]
pub struct TileSources(HashMap<String, TileInfoSource>);
pub type TileCatalog = BTreeMap<String, CatalogSourceEntry>;
pub struct TileSources(DashMap<String, TileInfoSource>);
pub type TileCatalog = DashMap<String, CatalogSourceEntry>;

impl TileSources {
#[must_use]
Expand All @@ -37,16 +38,17 @@ impl TileSources {
pub fn get_catalog(&self) -> TileCatalog {
self.0
.iter()
.map(|(id, src)| (id.to_string(), src.get_catalog_entry()))
.map(|v| (v.key().to_string(), v.get_catalog_entry()))
.collect()
}

pub fn get_source(&self, id: &str) -> actix_web::Result<&dyn Source> {
pub fn get_source(&self, id: &str) -> actix_web::Result<TileInfoSource> {
Ok(self
.0
.get(id)
.ok_or_else(|| ErrorNotFound(format!("Source {id} does not exist")))?
.as_ref())
.value()
.clone())
}

/// Get a list of sources, and the tile info for the merged sources.
Expand All @@ -56,7 +58,7 @@ impl TileSources {
&self,
source_ids: &str,
zoom: Option<u8>,
) -> actix_web::Result<(Vec<&dyn Source>, bool, TileInfo)> {
) -> actix_web::Result<(Vec<TileInfoSource>, bool, TileInfo)> {
let mut sources = Vec::new();
let mut info: Option<TileInfo> = None;
let mut use_url_query = false;
Expand All @@ -78,7 +80,7 @@ impl TileSources {

// TODO: Use chained-if-let once available
if match zoom {
Some(zoom) if Self::check_zoom(src, id, zoom) => true,
Some(zoom) if Self::check_zoom(&*src, id, zoom) => true,
None => true,
_ => false,
} {
Expand Down
65 changes: 39 additions & 26 deletions martin/src/sprites/mod.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use std::collections::hash_map::Entry;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Debug;
use std::path::PathBuf;

use dashmap::{DashMap, Entry};
use futures::future::try_join_all;
use log::{info, warn};
use serde::{Deserialize, Serialize};
use spreet::resvg::usvg::{Error as ResvgError, Options, Tree, TreeParsing};
use spreet::{
get_svg_input_paths, sprite_name, SpreetError, Sprite, Spritesheet, SpritesheetBuilder,
};
use std::collections::BTreeMap;
use std::fmt::Debug;
use std::path::PathBuf;
use tokio::io::AsyncReadExt;

use self::SpriteError::{SpriteInstError, SpriteParsingError, SpriteProcessingError};
Expand Down Expand Up @@ -56,7 +55,7 @@ pub struct CatalogSpriteEntry {
pub images: Vec<String>,
}

pub type SpriteCatalog = BTreeMap<String, CatalogSpriteEntry>;
pub type SpriteCatalog = DashMap<String, CatalogSpriteEntry>;

#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct SpriteConfig {
Expand All @@ -71,7 +70,7 @@ impl ConfigExtras for SpriteConfig {
}

#[derive(Debug, Clone, Default)]
pub struct SpriteSources(HashMap<String, SpriteSource>);
pub struct SpriteSources(DashMap<String, SpriteSource>);

impl SpriteSources {
pub fn resolve(config: &mut FileConfigEnum<SpriteConfig>) -> FileResult<Self> {
Expand Down Expand Up @@ -109,8 +108,8 @@ impl SpriteSources {

pub fn get_catalog(&self) -> SpriteResult<SpriteCatalog> {
// TODO: all sprite generation should be pre-cached
let mut entries = SpriteCatalog::new();
for (id, source) in &self.0 {
let entries = SpriteCatalog::new();
for source in &self.0 {
let paths = get_svg_input_paths(&source.path, true)
.map_err(|e| SpriteProcessingError(e, source.path.clone()))?;
let mut images = Vec::with_capacity(paths.len());
Expand All @@ -121,7 +120,7 @@ impl SpriteSources {
);
}
images.sort();
entries.insert(id.clone(), CatalogSpriteEntry { images });
entries.insert(source.key().clone(), CatalogSpriteEntry { images });
}
Ok(entries)
}
Expand All @@ -141,7 +140,7 @@ impl SpriteSources {
v.insert(SpriteSource { path });
}
}
};
}
}

/// Given a list of IDs in a format "id1,id2,id3", return a spritesheet with them all.
Expand All @@ -155,14 +154,17 @@ impl SpriteSources {

let sprite_ids = ids
.split(',')
.map(|id| {
self.0
.get(id)
.ok_or_else(|| SpriteError::SpriteNotFound(id.to_string()))
})
.map(|id| self.get(id))
.collect::<SpriteResult<Vec<_>>>()?;

get_spritesheet(sprite_ids.into_iter(), dpi, as_sdf).await
get_spritesheet(sprite_ids.iter(), dpi, as_sdf).await
}

fn get(&self, id: &str) -> SpriteResult<SpriteSource> {
match self.0.get(id) {
Some(v) => Ok(v.clone()),
None => Err(SpriteError::SpriteNotFound(id.to_string())),
}
}
}

Expand Down Expand Up @@ -247,19 +249,30 @@ mod tests {
//.sdf => generate sdf from png, add sdf == true
//- => does not generate sdf, omits sdf == true
for extension in ["_sdf", ""] {
test_src(sprites.values(), 1, "all_1", extension).await;
test_src(sprites.values(), 2, "all_2", extension).await;

test_src(sprites.get("src1").into_iter(), 1, "src1_1", extension).await;
test_src(sprites.get("src1").into_iter(), 2, "src1_2", extension).await;

test_src(sprites.get("src2").into_iter(), 1, "src2_1", extension).await;
test_src(sprites.get("src2").into_iter(), 2, "src2_2", extension).await;
let paths = sprites.iter().map(|v| v.path.clone()).collect::<Vec<_>>();
test_src(paths.iter(), 1, "all_1", extension).await;
test_src(paths.iter(), 2, "all_2", extension).await;

let src1_path = sprites
.get("src1")
.into_iter()
.map(|v| v.path.clone())
.collect::<Vec<_>>();
test_src(src1_path.iter(), 1, "src1_1", extension).await;
test_src(src1_path.iter(), 2, "src1_2", extension).await;

let src2_path = sprites
.get("src2")
.into_iter()
.map(|v| v.path.clone())
.collect::<Vec<_>>();
test_src(src2_path.iter(), 1, "src2_1", extension).await;
test_src(src2_path.iter(), 2, "src2_2", extension).await;
}
}

async fn test_src(
sources: impl Iterator<Item = &SpriteSource>,
sources: impl Iterator<Item = &PathBuf>,
pixel_ratio: u8,
filename: &str,
extension: &str,
Expand Down
4 changes: 2 additions & 2 deletions martin/src/srv/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub const RESERVED_KEYWORDS: &[&str] = &[
"reload", "sprite", "status",
];

#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct Catalog {
pub tiles: TileCatalog,
#[cfg(feature = "sprites")]
Expand Down Expand Up @@ -226,7 +226,7 @@ pub mod tests {
}

fn clone_source(&self) -> TileInfoSource {
unimplemented!()
Box::new(self.clone())
}

async fn get_tile(
Expand Down
4 changes: 2 additions & 2 deletions martin/src/srv/tiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use martin_tile_utils::{
use serde::Deserialize;

use crate::args::PreferredEncoding;
use crate::source::{Source, TileSources, UrlQuery};
use crate::source::{Source, TileInfoSource, TileInfoSources, TileSources, UrlQuery};
use crate::srv::server::map_internal_error;
use crate::srv::SrvConfig;
use crate::utils::cache::get_or_insert_cached_value;
Expand Down Expand Up @@ -62,7 +62,7 @@ async fn get_tile(
}

pub struct DynTileSource<'a> {
pub sources: Vec<&'a dyn Source>,
pub sources: TileInfoSources,
pub info: TileInfo,
pub query_str: Option<&'a str>,
pub query_obj: Option<UrlQuery>,
Expand Down
8 changes: 4 additions & 4 deletions martin/src/srv/tiles_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use itertools::Itertools as _;
use serde::Deserialize;
use tilejson::{tilejson, TileJSON};

use crate::source::{Source, TileSources};
use crate::source::{Source, TileInfoSource, TileSources};
use crate::srv::SrvConfig;

#[derive(Deserialize)]
Expand Down Expand Up @@ -62,7 +62,7 @@ async fn get_source_info(
}

#[must_use]
pub fn merge_tilejson(sources: &[&dyn Source], tiles_url: String) -> TileJSON {
pub fn merge_tilejson(sources: &[TileInfoSource], tiles_url: String) -> TileJSON {
if sources.len() == 1 {
let mut tj = sources[0].get_tilejson().clone();
tj.tiles = vec![tiles_url];
Expand Down Expand Up @@ -183,7 +183,7 @@ pub mod tests {
},
data: Vec::default(),
};
let tj = merge_tilejson(&[&src1], url.clone());
let tj = merge_tilejson(&[Box::new(src1.clone())], url.clone());
assert_eq!(
TileJSON {
tiles: vec![url.clone()],
Expand All @@ -210,7 +210,7 @@ pub mod tests {
data: Vec::default(),
};

let tj = merge_tilejson(&[&src1, &src2], url.clone());
let tj = merge_tilejson(&[Box::new(src1.clone()), Box::new(src2)], url.clone());
assert_eq!(tj.tiles, vec![url]);
assert_eq!(tj.name, Some("layer1,layer2".to_string()));
assert_eq!(tj.minzoom, Some(5));
Expand Down
2 changes: 1 addition & 1 deletion martin/tests/utils/pg_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn table<'a>(mock: &'a MockSource, name: &str) -> &'a martin::pg::TableInfo

#[allow(dead_code)]
#[must_use]
pub fn source<'a>(mock: &'a MockSource, name: &str) -> &'a dyn Source {
pub fn source(mock: &MockSource, name: &str) -> Box<dyn Source> {
let (sources, _) = mock;
sources.tiles.get_source(name).unwrap()
}

0 comments on commit 7ce7558

Please sign in to comment.