Handle unset size parameters, print # gc'd entries on startup.

This commit is contained in:
Bill Thiede 2020-02-19 21:19:40 -08:00
parent ab1a63da1e
commit f2f5279266

View File

@ -18,7 +18,7 @@ use rocksdb::IteratorMode;
use rocksdb::DB; use rocksdb::DB;
// Used to ensure DB is invalidated after schema changes. // Used to ensure DB is invalidated after schema changes.
const LIBRARY_GENERATION: &'static str = "5"; const LIBRARY_GENERATION: &'static str = "11";
#[derive(Clone)] #[derive(Clone)]
pub struct Library { pub struct Library {
@ -36,7 +36,10 @@ impl Library {
cache_db, cache_db,
root, root,
}; };
lib.clean_db()?; let cnt = lib.clean_db()?;
if cnt != 0 {
info!("Deleted {} entries", cnt);
}
if !lib.originals_dir.exists() { if !lib.originals_dir.exists() {
info!( info!(
"create originals dir {}", "create originals dir {}",
@ -47,27 +50,30 @@ impl Library {
Ok(lib) Ok(lib)
} }
// Removes all data in the database from older schema. // Removes all data in the database from older schema.
pub fn clean_db(&self) -> Result<(), rocksdb::Error> { pub fn clean_db(&self) -> Result<usize, rocksdb::Error> {
Library::gc(LIBRARY_GENERATION, &self.cache_db) Library::gc(LIBRARY_GENERATION, &self.cache_db)
} }
fn gc(generation: &str, db: &DB) -> Result<(), rocksdb::Error> { fn gc(generation: &str, db: &DB) -> Result<usize, rocksdb::Error> {
let gen = format!("{}/", generation); let gen = format!("{}/", generation);
// '0' is the next character after '/', so iterator's starting there would be after the // '0' is the next character after '/', so iterator's starting there would be after the
// last `gen` entry. // last `gen` entry.
let next_gen = format!("{}0", generation); let next_gen = format!("{}0", generation);
let mut del_cnt = 0;
for (k, _v) in db.iterator(IteratorMode::From(gen.as_bytes(), Direction::Reverse)) { for (k, _v) in db.iterator(IteratorMode::From(gen.as_bytes(), Direction::Reverse)) {
if !k.starts_with(gen.as_bytes()) { if !k.starts_with(gen.as_bytes()) {
info!("deleting stale key: {}", String::from_utf8_lossy(&k)); info!("deleting stale key: {}", String::from_utf8_lossy(&k));
db.delete(k)?; db.delete(k)?;
del_cnt += 1;
} }
} }
for (k, _v) in db.iterator(IteratorMode::From(next_gen.as_bytes(), Direction::Forward)) { for (k, _v) in db.iterator(IteratorMode::From(next_gen.as_bytes(), Direction::Forward)) {
if !k.starts_with(gen.as_bytes()) { if !k.starts_with(gen.as_bytes()) {
info!("deleting stale key: {}", String::from_utf8_lossy(&k)); info!("deleting stale key: {}", String::from_utf8_lossy(&k));
db.delete(k)?; db.delete(k)?;
del_cnt += 1;
} }
} }
Ok(()) Ok(del_cnt)
} }
pub fn create_album_index(&self, albums: &Vec<Album>) -> io::Result<()> { pub fn create_album_index(&self, albums: &Vec<Album>) -> io::Result<()> {
// Serialize it to a JSON string. // Serialize it to a JSON string.
@ -148,10 +154,10 @@ impl Library {
pub fn generate_thumbnail( pub fn generate_thumbnail(
&self, &self,
media_items_id: &str, media_items_id: &str,
dimensions: (u32, u32), w: Option<u32>,
h: Option<u32>,
filter: FilterType, filter: FilterType,
) -> Result<Vec<u8>, io::Error> { ) -> Result<Vec<u8>, io::Error> {
let (w, h) = dimensions;
match self.original(&media_items_id) { match self.original(&media_items_id) {
None => { None => {
warn!("Couldn't find original {}", &media_items_id); warn!("Couldn't find original {}", &media_items_id);
@ -165,6 +171,12 @@ impl Library {
.with_guessed_format()? .with_guessed_format()?
.decode() .decode()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
let (orig_w, orig_h) = orig_img.dimensions();
let (w, h) = match (w, h) {
(Some(w), Some(h)) => (w, h),
(Some(w), None) => (w, orig_h * w / orig_w),
(None, Some(h)) => (orig_w * h / orig_h, h),
};
let img = orig_img.resize_to_fill(w, h, filter); let img = orig_img.resize_to_fill(w, h, filter);
let mut buf = Vec::new(); let mut buf = Vec::new();
img.write_to(&mut buf, ImageFormat::Jpeg) img.write_to(&mut buf, ImageFormat::Jpeg)