From 6498322c17f3d63314007641894e8b085318ca02 Mon Sep 17 00:00:00 2001 From: mynttt Date: Fri, 16 Jul 2021 21:39:37 +0200 Subject: [PATCH] 1.5.7 <=> Database Corruption Mitigation reworked for newer Plex versions --- CHANGELOG.md | 4 ++ VERSION | 2 +- build.gradle | 2 +- .../updatetool/imdb/ImdbDatabaseSupport.java | 72 ++++++++++--------- .../imdb/ImdbDockerImplementation.java | 12 ++++ src/main/resources/VERSION | 2 +- 6 files changed, 57 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d811ae..c3f4464 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.5.7 +- Database corruption mitigation reworked in order to support newer plex versions +- Added some library processing details for easier debugging of potential future issues + ## 1.5.6b - bugfix regarding support for 16 char TVDB v3 keys diff --git a/VERSION b/VERSION index 2b9fd67..f5a0d9d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.5.6b \ No newline at end of file +1.5.7 \ No newline at end of file diff --git a/build.gradle b/build.gradle index 5dcd35f..955eaac 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'com.github.spotbugs' version '2.0.1' } -version = '1.5.6b' +version = '1.5.7' sourceCompatibility = '11' new File(projectDir, "VERSION").text = version; diff --git a/src/main/java/updatetool/imdb/ImdbDatabaseSupport.java b/src/main/java/updatetool/imdb/ImdbDatabaseSupport.java index dc954d5..f7bc630 100644 --- a/src/main/java/updatetool/imdb/ImdbDatabaseSupport.java +++ b/src/main/java/updatetool/imdb/ImdbDatabaseSupport.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -164,53 +165,43 @@ public void requestBatchUpdateOf(List items) throws SQLiteEx } } - private static final String ICU_MIG_1 = "fts4_metadata_titles_after_update_icu"; - private static final String ICU_MIG_2 = "fts4_metadata_titles_before_update_icu"; - private static final String ICU_MIG_1_SQL = "CREATE TRIGGER fts4_metadata_titles_after_update_icu AFTER UPDATE ON metadata_items BEGIN INSERT INTO fts4_metadata_titles_icu(docid, title, title_sort, original_title) VALUES(new.rowid, new.title, new.title_sort, new.original_title); END"; - private static final String ICU_MIG_2_SQL = "CREATE TRIGGER fts4_metadata_titles_before_update_icu BEFORE UPDATE ON metadata_items BEGIN DELETE FROM fts4_metadata_titles_icu WHERE docid=old.rowid; END"; - @SuppressFBWarnings({"DM_EXIT", "REC_CATCH_EXCEPTION", "OBL_UNSATISFIED_OBLIGATION", "DE_MIGHT_IGNORE"}) private void internalBatchUpdate(List items, boolean isNewAgent) { boolean success = true; boolean mitigationIcuNeeded, mitigationIcuTriggersDisabled = false; List close = new ArrayList<>(); + Map disabledTriggers = new LinkedHashMap<>(); try { // Mitigation var mitigationIcu = provider.connection.createStatement(); close.add(mitigationIcu); - var rs = mitigationIcu.executeQuery("SELECT name, sql FROM sqlite_master WHERE type = 'trigger' AND name = '" + ICU_MIG_1 + "' OR name = '" + ICU_MIG_2 + "';"); + var rs = mitigationIcu.executeQuery("SELECT name, sql FROM sqlite_master WHERE type = 'trigger' AND sql LIKE \"%ON metadata_items%\";"); Map storedSql = new HashMap<>(); while(rs.next()) { storedSql.put(rs.getString(1), rs.getString(2)); } rs.close(); - int count = storedSql.size(); - if(!(count == 2 || count == 0)) { - throw new UnsupportedOperationException("@@!!! INCONSISTENT TRIGGER COUNT STATE !!!@@ - Parameters for ICU SQLite3 Mitigation have changed! Contact the author of this tool immediatly and create a github issue here and include the output of '.schema metadata_items' on your SQLite3 PlexDB: https://github.com/mynttt/UpdateTool/issues"); - } - - mitigationIcuNeeded = count == 2; + mitigationIcuNeeded = storedSql.size() > 0; Logger.info("PlexDB ICU Mitigation enabled: {}", mitigationIcuNeeded); if(mitigationIcuNeeded) { - if(!Objects.equals(ICU_MIG_1_SQL, storedSql.get(ICU_MIG_1)) || !Objects.equals(ICU_MIG_2_SQL, storedSql.get(ICU_MIG_2))) { - Logger.error("IS : {}",storedSql.get(ICU_MIG_1)); - Logger.error("MUST: {}",ICU_MIG_1_SQL); - Logger.error("IS : {}",storedSql.get(ICU_MIG_2)); - Logger.error("MUST: {}",ICU_MIG_2_SQL); - throw new UnsupportedOperationException("@@!!! INCONSISTENT TRIGGER STATE !!!@@ - Parameters for ICU SQLite3 Mitigation have changed! Contact the author of this tool immediatly and create a github issue here and include the output of '.schema metadata_items' on your SQLite3 PlexDB: https://github.com/mynttt/UpdateTool/issues"); + Logger.info("=== DATABASE CORRUPTION MITIGATION ==="); + Logger.info("Disabling the following metadata_items triggers temporarily:"); + + for(var s : storedSql.entrySet()) { + Logger.info("{} => {}", s.getKey(), s.getValue()); + var stmt = provider.connection.createStatement(); + close.add(stmt); + stmt.executeUpdate(String.format("DROP TRIGGER %s;", s.getKey())); + disabledTriggers.put(s.getKey(), s.getValue()); + Logger.info("Disabled Trigger: {}", s.getKey()); } - var s1 = provider.connection.createStatement(); - close.add(s1); - s1.executeUpdate("DROP TRIGGER fts4_metadata_titles_before_update_icu;"); - var s2 = provider.connection.createStatement(); - close.add(s2); - s2.executeUpdate("DROP TRIGGER fts4_metadata_titles_after_update_icu;"); mitigationIcuTriggersDisabled = true; + Logger.info("=== ALL metadata_items TRIGGERS DISABLED :: PROCEED UPDATE ==="); } try(var s = provider.connection.prepareStatement(isNewAgent ? "UPDATE metadata_items SET audience_rating = ?, extra_data = ?, rating = NULL WHERE id = ?" @@ -262,23 +253,36 @@ private void internalBatchUpdate(List items, boolean isNewAg close.clear(); if(mitigationIcuTriggersDisabled) { + Map uncompleted = new LinkedHashMap<>(disabledTriggers); try { - var s1 = provider.connection.createStatement(); - close.add(s1); - s1.executeUpdate(ICU_MIG_1_SQL); - var s2 = provider.connection.createStatement(); - close.add(s2); - s2.executeUpdate(ICU_MIG_2_SQL); + Logger.info("=== RESTORING metadata_items TRIGGERS AFTER UPDATE ==="); + for(var s : disabledTriggers.entrySet()) { + var stmt = provider.connection.createStatement(); + close.add(stmt); + stmt.executeUpdate(s.getValue()); + Logger.info("Restored Trigger: {}", s.getKey()); + uncompleted.remove(s.getKey()); + } + Logger.info("=== DATABASE CORRUPTION MITIGATION COMPLETED :: TRIGGERS RESTORED ==="); } catch (SQLException ex) { + + if(uncompleted.isEmpty()) { + Logger.error(ex); + Logger.error("Unknown error encountered. Please contact the author of this tool."); + System.exit(-1); + } + Logger.error(ex); Logger.error("======================================"); Logger.error("WARNING!!! COULD NOT RESTORE DISABLED TRIGGERS IN ICU MITIGATION!!!"); - Logger.error("RUN THE QUERIES BELOW ON YOUR PLEX DATABASE TO RESTORE TRIGGERS!"); + Logger.error("RUN THE TRIGGER CREATION QUERIES BELOW ON YOUR PLEX DATABASE MANUALLY TO RESTORE THE DISABLED TRIGGERS!"); Logger.error("======================================"); - Logger.error(ICU_MIG_1_SQL); - Logger.error(ICU_MIG_2_SQL); + for(var s : uncompleted.entrySet()) { + Logger.error(s.getValue()); + } Logger.error("======================================"); - Logger.error("TOOL WILL EXIT NOW! DON'T USE BEVORE HAVING EXECUTED THESE COMMANDS!"); + Logger.error("TOOL WILL EXIT NOW! DON'T USE BEFORE HAVING EXECUTED THESE COMMANDS!"); + Logger.error("CONTACT THE AUTHOR OF THIS TOOL IF YOU DON'T KNOW WHAT TO DO NOW!"); System.exit(-1); } finally { for(AutoCloseable a : close) { diff --git a/src/main/java/updatetool/imdb/ImdbDockerImplementation.java b/src/main/java/updatetool/imdb/ImdbDockerImplementation.java index 0c486a4..ed35547 100644 --- a/src/main/java/updatetool/imdb/ImdbDockerImplementation.java +++ b/src/main/java/updatetool/imdb/ImdbDockerImplementation.java @@ -211,6 +211,15 @@ public void run() { libraries.addAll(support.requestMovieLibraries(capabilities)); if(!capabilities.contains(Capabilities.NO_TV)) libraries.addAll(support.requestSeriesLibraries(capabilities)); + + if(libraries.isEmpty()) { + Logger.error("FATAL ERROR :: NO LIBRARIES EXIST IN DATABASE. EXITING NOW."); + System.exit(-1); + } + + Logger.info("LIBRARIES => PRE LIBRARY FILTERING"); + libraries.forEach(l -> Logger.info("Found library {} (ID={}) with agent: {} and {} item(s).", l.name, l.id, l.agent, l.items)); + libraries.removeIf(l -> IGNORE_LIBRARIES.contains(l.id)); libraries.removeIf(l -> { if(!l.agent.equals("tv.plex.agents.series")) @@ -221,6 +230,9 @@ public void run() { } return false; }); + + Logger.info("LIBRARIES => POST LIBRARY FILTERING"); + libraries.forEach(l -> Logger.info("Will process library {} (ID={}) with agent: {} and {} item(s).", l.name, l.id, l.agent, l.items)); metadata = ImdbLibraryMetadata.fetchAll(libraries, new ImdbDatabaseSupport(connection, caches.get("new-agent-mapping")), config); } catch(Exception e) { Logger.error(e.getClass().getSimpleName() + " exception encountered..."); diff --git a/src/main/resources/VERSION b/src/main/resources/VERSION index 2b9fd67..f5a0d9d 100644 --- a/src/main/resources/VERSION +++ b/src/main/resources/VERSION @@ -1 +1 @@ -1.5.6b \ No newline at end of file +1.5.7 \ No newline at end of file