[Android] Handle DB corruption
Nicolas Pomepuy
git at videolan.org
Wed Sep 4 13:54:44 CEST 2019
vlc-android | branch: master | Nicolas Pomepuy <nicolas.pomepuy at gmail.com> | Fri Aug 30 06:53:34 2019 +0200| [ef6be71af96ea6623ff4b25242b47684da1c689b] | committer: Nicolas Pomepuy
Handle DB corruption
> https://code.videolan.org/videolan/vlc-android/commit/ef6be71af96ea6623ff4b25242b47684da1c689b
---
compile-medialibrary.sh | 4 ++--
medialibrary/jni/AndroidMediaLibrary.cpp | 6 ++++++
medialibrary/jni/AndroidMediaLibrary.h | 1 +
medialibrary/jni/medialibrary.cpp | 6 ++++++
.../org/videolan/medialibrary/Medialibrary.java | 25 ++++++++++++++++++++--
.../interfaces/AbstractMedialibrary.java | 4 ++--
.../src/org/videolan/vlc/MediaParsingService.kt | 11 +++++++---
7 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/compile-medialibrary.sh b/compile-medialibrary.sh
index 146ae38df..31db34122 100755
--- a/compile-medialibrary.sh
+++ b/compile-medialibrary.sh
@@ -4,7 +4,7 @@
# ARGUMENTS #
#############
-MEDIALIBRARY_HASH=862ceb5
+MEDIALIBRARY_HASH=f748def6
while [ $# -gt 0 ]; do
case $1 in
@@ -89,7 +89,7 @@ if [ ! -d "${MEDIALIBRARY_MODULE_DIR}/medialibrary" ]; then
git clone http://code.videolan.org/videolan/medialibrary.git "${SRC_DIR}/medialibrary/medialibrary"
avlc_checkfail "medialibrary source: git clone failed"
cd ${MEDIALIBRARY_MODULE_DIR}/medialibrary
- git checkout 0.5.x
+# git checkout 0.5.x
git submodule update --init libvlcpp
else
cd ${MEDIALIBRARY_MODULE_DIR}/medialibrary
diff --git a/medialibrary/jni/AndroidMediaLibrary.cpp b/medialibrary/jni/AndroidMediaLibrary.cpp
index 8b45eae63..28c4b272e 100644
--- a/medialibrary/jni/AndroidMediaLibrary.cpp
+++ b/medialibrary/jni/AndroidMediaLibrary.cpp
@@ -60,6 +60,12 @@ AndroidMediaLibrary::start()
m_started = true;
}
+
+void
+AndroidMediaLibrary::clearDatabase(bool restorePlaylists) {
+ p_ml->clearDatabase(restorePlaylists);
+}
+
bool
AndroidMediaLibrary::addDevice(const std::string& uuid, const std::string& path, bool removable)
{
diff --git a/medialibrary/jni/AndroidMediaLibrary.h b/medialibrary/jni/AndroidMediaLibrary.h
index 7eced7c62..0847d7d82 100644
--- a/medialibrary/jni/AndroidMediaLibrary.h
+++ b/medialibrary/jni/AndroidMediaLibrary.h
@@ -32,6 +32,7 @@ public:
medialibrary::InitializeResult initML(const std::string& dbPath, const std::string& thumbsPath);
void start();
bool addDevice(const std::string& uuid, const std::string& path, bool removable);
+ void clearDatabase(bool restorePlaylists);
std::vector<std::tuple<std::string, std::string, bool>> devices();
bool removeDevice(const std::string& uuid, const std::string& path);
void banFolder(const std::string& path);
diff --git a/medialibrary/jni/medialibrary.cpp b/medialibrary/jni/medialibrary.cpp
index 3e43cde13..943b4b5bf 100644
--- a/medialibrary/jni/medialibrary.cpp
+++ b/medialibrary/jni/medialibrary.cpp
@@ -54,6 +54,11 @@ release(JNIEnv* env, jobject thiz)
MediaLibrary_setInstance(env, thiz, NULL);
}
+void
+clearDatabase(JNIEnv* env, jobject thiz, jboolean restorePlaylists) {
+ MediaLibrary_getInstance(env, thiz)->clearDatabase(restorePlaylists);
+}
+
void
banFolder(JNIEnv* env, jobject thiz, jstring folderPath)
{
@@ -1729,6 +1734,7 @@ static JNINativeMethod methods[] = {
{"nativeInit", "(Ljava/lang/String;Ljava/lang/String;)I", (void*)init },
{"nativeStart", "()V", (void*)start },
{"nativeRelease", "()V", (void*)release },
+ {"nativeClearDatabase", "(Z)V", (void*)clearDatabase },
{"nativeAddDevice", "(Ljava/lang/String;Ljava/lang/String;Z)Z", (void*)addDevice },
{"nativeDevices", "()[Ljava/lang/String;", (void*)devices },
{"nativeDiscover", "(Ljava/lang/String;)V", (void*)discover },
diff --git a/medialibrary/src/org/videolan/medialibrary/Medialibrary.java b/medialibrary/src/org/videolan/medialibrary/Medialibrary.java
index 2d66f6451..ff7a33d9e 100644
--- a/medialibrary/src/org/videolan/medialibrary/Medialibrary.java
+++ b/medialibrary/src/org/videolan/medialibrary/Medialibrary.java
@@ -49,7 +49,7 @@ public class Medialibrary extends AbstractMedialibrary {
public int init(Context context) {
if (context == null) return ML_INIT_FAILED;
sContext = context;
- File extFilesDir = context.getExternalFilesDir(null);
+ final File extFilesDir = context.getExternalFilesDir(null);
File dbDirectory = context.getDir("db", Context.MODE_PRIVATE);
if (extFilesDir == null || !extFilesDir.exists()
|| dbDirectory == null || !dbDirectory.canWrite())
@@ -63,8 +63,27 @@ public class Medialibrary extends AbstractMedialibrary {
Log.e(TAG, "Can't load mla: " + ule);
return ML_INIT_FAILED;
}
- int initCode = nativeInit(dbDirectory+ VLC_MEDIA_DB_NAME, extFilesDir+ THUMBS_FOLDER_NAME);
+ //remove old thumbnails directory
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ final File oldDir = new File(extFilesDir + THUMBS_FOLDER_NAME);
+ if (oldDir.isDirectory()) {
+ String[] children = oldDir.list();
+ for (String child : children) {
+ new File(oldDir, child).delete();
+ }
+ oldDir.delete();
+ }
+ }
+ }).start();
+
+ int initCode = nativeInit(dbDirectory + VLC_MEDIA_DB_NAME, extFilesDir + MEDIALIB_FOLDER_NAME);
mIsInitiated = initCode != ML_INIT_FAILED;
+ if (initCode == ML_INIT_DB_CORRUPTED) {
+ Log.e(TAG, "Medialib database is corrupted. Clearing it and try to restore playlists");
+ nativeClearDatabase(true);
+ }
return initCode;
}
@@ -482,6 +501,8 @@ public class Medialibrary extends AbstractMedialibrary {
private native int nativeInit(String dbPath, String thumbsPath);
private native void nativeStart();
private native void nativeRelease();
+
+ private native void nativeClearDatabase(boolean keepPlaylist);
private native void nativeBanFolder(String path);
private native void nativeUnbanFolder(String path);
private native boolean nativeAddDevice(String uuid, String path, boolean removable);
diff --git a/medialibrary/src/org/videolan/medialibrary/interfaces/AbstractMedialibrary.java b/medialibrary/src/org/videolan/medialibrary/interfaces/AbstractMedialibrary.java
index 93bac0c4b..cbeae4fb8 100644
--- a/medialibrary/src/org/videolan/medialibrary/interfaces/AbstractMedialibrary.java
+++ b/medialibrary/src/org/videolan/medialibrary/interfaces/AbstractMedialibrary.java
@@ -2,7 +2,6 @@ package org.videolan.medialibrary.interfaces;
import android.Manifest;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
@@ -13,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
-import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.videolan.medialibrary.MLServiceLocator;
import org.videolan.medialibrary.SingleEvent;
@@ -60,10 +58,12 @@ abstract public class AbstractMedialibrary {
public static final int ML_INIT_ALREADY_INITIALIZED = 1;
public static final int ML_INIT_FAILED = 2;
public static final int ML_INIT_DB_RESET = 3;
+ public static final int ML_INIT_DB_CORRUPTED = 4;
public static final AbstractMediaWrapper[] EMPTY_COLLECTION = {};
public static final String VLC_MEDIA_DB_NAME = "/vlc_media.db";
public static final String THUMBS_FOLDER_NAME = "/thumbs";
+ public static final String MEDIALIB_FOLDER_NAME = "/medialib";
protected volatile boolean mIsInitiated = false;
protected volatile boolean mIsWorking = false;
diff --git a/vlc-android/src/org/videolan/vlc/MediaParsingService.kt b/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
index 487d8d8bd..ded84faaa 100644
--- a/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
+++ b/vlc-android/src/org/videolan/vlc/MediaParsingService.kt
@@ -243,9 +243,14 @@ class MediaParsingService : Service(), DevicesDiscoveryCb, CoroutineScope, Lifec
shouldInit -> {
for (folder in AbstractMedialibrary.getBlackList())
medialibrary.banFolder(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY + folder)
- if (preselectedStorages.isEmpty()) medialibrary.discover(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY)
+ if (preselectedStorages.isEmpty()) {
+ medialibrary.discover(AndroidDevices.EXTERNAL_PUBLIC_DIRECTORY)
+ }
else {
- for (folder in preselectedStorages) medialibrary.discover(folder)
+
+ for (folder in preselectedStorages) {
+ medialibrary.discover(folder)
+ }
preselectedStorages.clear()
}
}
@@ -395,7 +400,7 @@ class MediaParsingService : Service(), DevicesDiscoveryCb, CoroutineScope, Lifec
val context = this at MediaParsingService
var shouldInit = !dbExists()
val initCode = medialibrary.init(context)
- shouldInit = shouldInit or (initCode == AbstractMedialibrary.ML_INIT_DB_RESET)
+ shouldInit = shouldInit or (initCode == AbstractMedialibrary.ML_INIT_DB_RESET) or (initCode == AbstractMedialibrary.ML_INIT_DB_CORRUPTED)
if (initCode != AbstractMedialibrary.ML_INIT_FAILED) initMedialib(action.parse, context, shouldInit, action.upgrade)
else exitCommand()
}
More information about the Android
mailing list