From d46e7874a67665bf13bfd4b129bed659d421d8f8 Mon Sep 17 00:00:00 2001 From: "denys.konakhevych" Date: Wed, 22 Jul 2015 19:09:27 +0300 Subject: [PATCH 1/4] Removed Context from DbStoragePlainFile to decrease coupling storage with android classes. Storage needed only path to directory with db files. --- paperdb/src/main/java/io/paperdb/Book.java | 2 +- .../main/java/io/paperdb/DbStoragePlainFile.java | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/paperdb/src/main/java/io/paperdb/Book.java b/paperdb/src/main/java/io/paperdb/Book.java index cf1b407..d05ce6c 100644 --- a/paperdb/src/main/java/io/paperdb/Book.java +++ b/paperdb/src/main/java/io/paperdb/Book.java @@ -7,7 +7,7 @@ public class Book { private final Storage mStorage; protected Book(Context context, String dbName) { - mStorage = new DbStoragePlainFile(context.getApplicationContext(), dbName); + mStorage = new DbStoragePlainFile(context.getApplicationContext().getFilesDir(), dbName); } /** diff --git a/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java b/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java index 81fef78..dcb92eb 100644 --- a/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java +++ b/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java @@ -1,6 +1,5 @@ package io.paperdb; -import android.content.Context; import android.util.Log; import com.esotericsoftware.kryo.Kryo; @@ -27,7 +26,6 @@ public class DbStoragePlainFile implements Storage { - private final Context mContext; private final String mDbName; private String mFilesDir; private boolean mPaperDirIsCreated; @@ -66,8 +64,8 @@ private Kryo createKryoInstance() { return kryo; } - public DbStoragePlainFile(Context context, String dbName) { - mContext = context; + public DbStoragePlainFile(File filesDir, String dbName) { + mFilesDir = getDbPath(filesDir, dbName); mDbName = dbName; } @@ -75,9 +73,8 @@ public DbStoragePlainFile(Context context, String dbName) { public synchronized void destroy() { assertInit(); - final String dbPath = getDbPath(mContext, mDbName); - if (!deleteDirectory(dbPath)) { - Log.e(TAG, "Couldn't delete Paper dir " + dbPath); + if (!deleteDirectory(mFilesDir)) { + Log.e(TAG, "Couldn't delete Paper dir " + mFilesDir); } mPaperDirIsCreated = false; } @@ -216,8 +213,8 @@ private E readTableFile(String key, File originalFile) { } } - private String getDbPath(Context context, String dbName) { - return context.getFilesDir() + File.separator + dbName; + private String getDbPath(File filesDir, String dbName) { + return filesDir + File.separator + dbName; } private void assertInit() { @@ -228,7 +225,6 @@ private void assertInit() { } private void createPaperDir() { - mFilesDir = getDbPath(mContext, mDbName); if (!new File(mFilesDir).exists()) { boolean isReady = new File(mFilesDir).mkdirs(); if (!isReady) { From d2b75f21fd401226d8e7dac3829de3dd216e2fcd Mon Sep 17 00:00:00 2001 From: koxa29 Date: Thu, 23 Jul 2015 00:16:55 +0300 Subject: [PATCH 2/4] Added cache for DB --- paperdb/build.gradle | 1 + .../java/io/paperdb/CompatibilityTest.java | 3 ++ .../androidTest/java/io/paperdb/DataTest.java | 2 +- .../java/io/paperdb/deprecated/DataTest.java | 2 +- paperdb/src/main/java/io/paperdb/Book.java | 19 ++++++- .../main/java/io/paperdb/CachedStorage.java | 8 +++ .../java/io/paperdb/DbStoragePlainFile.java | 49 ++++++++++++++++++- .../io/paperdb/NonExistedValueException.java | 16 ++++++ .../java/io/paperdb/PaperDbException.java | 4 ++ paperdb/src/main/java/io/paperdb/Storage.java | 2 + 10 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 paperdb/src/main/java/io/paperdb/CachedStorage.java create mode 100644 paperdb/src/main/java/io/paperdb/NonExistedValueException.java diff --git a/paperdb/build.gradle b/paperdb/build.gradle index 0dd5886..cefdb02 100644 --- a/paperdb/build.gradle +++ b/paperdb/build.gradle @@ -31,6 +31,7 @@ android { dependencies { compile 'com.esotericsoftware:kryo:3.0.2' compile 'de.javakaffee:kryo-serializers:0.33' + compile 'com.google.guava:guava:18.0' androidTestCompile 'com.orhanobut:hawk:1.14' androidTestCompile 'com.android.support.test:runner:0.3' diff --git a/paperdb/src/androidTest/java/io/paperdb/CompatibilityTest.java b/paperdb/src/androidTest/java/io/paperdb/CompatibilityTest.java index b53d309..48c4de0 100644 --- a/paperdb/src/androidTest/java/io/paperdb/CompatibilityTest.java +++ b/paperdb/src/androidTest/java/io/paperdb/CompatibilityTest.java @@ -35,6 +35,7 @@ public void testChangeClass() // Save original class. Only class name is changed to TestClassNew Paper.book().write("test", testClass); + Paper.book().invalidateCache("test"); // Read and instantiate a modified class TestClassNew based on saved data in TestClass TestClassNew newTestClass = Paper.book().read("test"); @@ -52,6 +53,7 @@ public void testNotCompatibleClassChanges() throws Exception { TestClassNotCompatible.class.getName()); testClass.timestamp = 123; Paper.book().write("not-compatible", testClass); + Paper.book().invalidateCache("not-compatible"); Paper.book().read("not-compatible"); } @@ -63,6 +65,7 @@ public void testTransientFields() throws Exception { tc.transientField = "changed"; Paper.book().write("transient-class", tc); + Paper.book().invalidateCache("transient-class"); TestClassTransient readTc = Paper.book().read("transient-class"); assertThat(readTc.timestamp).isEqualTo(123); diff --git a/paperdb/src/androidTest/java/io/paperdb/DataTest.java b/paperdb/src/androidTest/java/io/paperdb/DataTest.java index f4f064b..3a7ae34 100644 --- a/paperdb/src/androidTest/java/io/paperdb/DataTest.java +++ b/paperdb/src/androidTest/java/io/paperdb/DataTest.java @@ -65,7 +65,7 @@ public void testPutPOJO() { final Person savedPerson = Paper.book().read("profile"); assertThat(savedPerson).isEqualTo(person); - assertThat(savedPerson).isNotSameAs(person); + assertThat(savedPerson).isSameAs(person); } @Test diff --git a/paperdb/src/androidTest/java/io/paperdb/deprecated/DataTest.java b/paperdb/src/androidTest/java/io/paperdb/deprecated/DataTest.java index 787573f..f202077 100644 --- a/paperdb/src/androidTest/java/io/paperdb/deprecated/DataTest.java +++ b/paperdb/src/androidTest/java/io/paperdb/deprecated/DataTest.java @@ -66,7 +66,7 @@ public void testPutPOJO() { final Person savedPerson = Paper.get("profile"); assertThat(savedPerson).isEqualTo(person); - assertThat(savedPerson).isNotSameAs(person); + assertThat(savedPerson).isSameAs(person); } @Test diff --git a/paperdb/src/main/java/io/paperdb/Book.java b/paperdb/src/main/java/io/paperdb/Book.java index d05ce6c..0c20db0 100644 --- a/paperdb/src/main/java/io/paperdb/Book.java +++ b/paperdb/src/main/java/io/paperdb/Book.java @@ -4,7 +4,7 @@ public class Book { - private final Storage mStorage; + private final CachedStorage mStorage; protected Book(Context context, String dbName) { mStorage = new DbStoragePlainFile(context.getApplicationContext().getFilesDir(), dbName); @@ -75,7 +75,7 @@ public boolean exist(String key) { } /** - * Delete saved object for given key if it is exist. + * Delete saved object for given key if it exists. * * @param key object key */ @@ -83,4 +83,19 @@ public void delete(String key) { mStorage.deleteIfExists(key); } + /** + * Clears cache for given key. + * + * @param key object key + */ + public void invalidateCache(String key) { + mStorage.invalidateCache(key); + } + + /** + * Clears cache. + */ + public void invalidateCache() { + mStorage.invalidateCache(); + } } diff --git a/paperdb/src/main/java/io/paperdb/CachedStorage.java b/paperdb/src/main/java/io/paperdb/CachedStorage.java new file mode 100644 index 0000000..5298235 --- /dev/null +++ b/paperdb/src/main/java/io/paperdb/CachedStorage.java @@ -0,0 +1,8 @@ +package io.paperdb; + +public interface CachedStorage extends Storage { + + void invalidateCache(); + + void invalidateCache(String key); +} diff --git a/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java b/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java index dcb92eb..fee715d 100644 --- a/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java +++ b/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java @@ -7,6 +7,11 @@ import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer; +import com.google.common.base.Optional; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.UncheckedExecutionException; import java.io.File; import java.io.FileInputStream; @@ -16,6 +21,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import de.javakaffee.kryoserializers.ArraysAsListSerializer; import de.javakaffee.kryoserializers.SynchronizedCollectionsSerializer; @@ -24,12 +31,24 @@ import static io.paperdb.Paper.TAG; -public class DbStoragePlainFile implements Storage { +public class DbStoragePlainFile implements CachedStorage { private final String mDbName; private String mFilesDir; private boolean mPaperDirIsCreated; + private final LoadingCache cache = CacheBuilder.newBuilder() + .maximumSize(1000) + .weakKeys() + .weakValues() + .expireAfterWrite(60 * 10, TimeUnit.SECONDS) + .build(new CacheLoader() { + public Optional load(String key) { + Object value = doSelect(key); + return Optional.fromNullable(value); + } + }); + private Kryo getKryo() { return mKryo.get(); } @@ -76,6 +95,7 @@ public synchronized void destroy() { if (!deleteDirectory(mFilesDir)) { Log.e(TAG, "Couldn't delete Paper dir " + mFilesDir); } + cache.invalidateAll(); mPaperDirIsCreated = false; } @@ -103,10 +123,26 @@ public synchronized void insert(String key, E value) { } writeTableFile(key, paperTable, originalFile, backupFile); + cache.put(key, Optional.of(value)); } @Override public synchronized E select(String key) { + try { + Optional optional = cache.get(key); + return (E) optional.get(); + } catch (IllegalStateException e) { + return null; + } catch (PaperDbException e) { + throw e; + } catch (Exception e) { + if (e.getCause() != null && e.getCause() instanceof PaperDbException) + throw (PaperDbException) e.getCause(); + throw new PaperDbException(e); + } + } + + private synchronized E doSelect(String key) { assertInit(); final File originalFile = getOriginalFile(key); @@ -147,6 +183,7 @@ public synchronized void deleteIfExists(String key) { throw new PaperDbException("Couldn't delete file " + originalFile + " for table " + key); } + cache.invalidate(key); } private File getOriginalFile(String key) { @@ -270,5 +307,15 @@ private static boolean sync(FileOutputStream stream) { } return false; } + + @Override + public void invalidateCache() { + cache.invalidateAll(); + } + + @Override + public void invalidateCache(String key) { + cache.invalidate(key); + } } diff --git a/paperdb/src/main/java/io/paperdb/NonExistedValueException.java b/paperdb/src/main/java/io/paperdb/NonExistedValueException.java new file mode 100644 index 0000000..f6028fb --- /dev/null +++ b/paperdb/src/main/java/io/paperdb/NonExistedValueException.java @@ -0,0 +1,16 @@ +package io.paperdb; + +public class NonExistedValueException extends PaperDbException { + + public NonExistedValueException(String detailMessage) { + super(detailMessage); + } + + public NonExistedValueException(Throwable throwable) { + super(throwable); + } + + public NonExistedValueException(String detailMessage, Throwable throwable) { + super(detailMessage, throwable); + } +} diff --git a/paperdb/src/main/java/io/paperdb/PaperDbException.java b/paperdb/src/main/java/io/paperdb/PaperDbException.java index e5fdc1f..cc9d1cf 100644 --- a/paperdb/src/main/java/io/paperdb/PaperDbException.java +++ b/paperdb/src/main/java/io/paperdb/PaperDbException.java @@ -5,6 +5,10 @@ public PaperDbException(String detailMessage) { super(detailMessage); } + public PaperDbException(Throwable throwable) { + super(throwable); + } + public PaperDbException(String detailMessage, Throwable throwable) { super(detailMessage, throwable); } diff --git a/paperdb/src/main/java/io/paperdb/Storage.java b/paperdb/src/main/java/io/paperdb/Storage.java index 8de1f77..eb5bd0a 100644 --- a/paperdb/src/main/java/io/paperdb/Storage.java +++ b/paperdb/src/main/java/io/paperdb/Storage.java @@ -1,5 +1,7 @@ package io.paperdb; +import java.util.concurrent.ExecutionException; + interface Storage { void destroy(); From d920cf03f70c9b70562d0af42707ee0b8c495c16 Mon Sep 17 00:00:00 2001 From: koxa29 Date: Thu, 23 Jul 2015 00:21:50 +0300 Subject: [PATCH 3/4] Reverted some changes --- paperdb/src/main/java/io/paperdb/Book.java | 2 +- .../java/io/paperdb/DbStoragePlainFile.java | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/paperdb/src/main/java/io/paperdb/Book.java b/paperdb/src/main/java/io/paperdb/Book.java index 0c20db0..2ddaac5 100644 --- a/paperdb/src/main/java/io/paperdb/Book.java +++ b/paperdb/src/main/java/io/paperdb/Book.java @@ -7,7 +7,7 @@ public class Book { private final CachedStorage mStorage; protected Book(Context context, String dbName) { - mStorage = new DbStoragePlainFile(context.getApplicationContext().getFilesDir(), dbName); + mStorage = new DbStoragePlainFile(context.getApplicationContext(), dbName); } /** diff --git a/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java b/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java index fee715d..0976502 100644 --- a/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java +++ b/paperdb/src/main/java/io/paperdb/DbStoragePlainFile.java @@ -1,5 +1,6 @@ package io.paperdb; +import android.content.Context; import android.util.Log; import com.esotericsoftware.kryo.Kryo; @@ -11,7 +12,6 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; -import com.google.common.util.concurrent.UncheckedExecutionException; import java.io.File; import java.io.FileInputStream; @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import de.javakaffee.kryoserializers.ArraysAsListSerializer; @@ -33,6 +32,7 @@ public class DbStoragePlainFile implements CachedStorage { + private final Context mContext; private final String mDbName; private String mFilesDir; private boolean mPaperDirIsCreated; @@ -83,8 +83,8 @@ private Kryo createKryoInstance() { return kryo; } - public DbStoragePlainFile(File filesDir, String dbName) { - mFilesDir = getDbPath(filesDir, dbName); + public DbStoragePlainFile(Context context, String dbName) { + mContext = context; mDbName = dbName; } @@ -92,8 +92,9 @@ public DbStoragePlainFile(File filesDir, String dbName) { public synchronized void destroy() { assertInit(); - if (!deleteDirectory(mFilesDir)) { - Log.e(TAG, "Couldn't delete Paper dir " + mFilesDir); + final String dbPath = getDbPath(mContext, mDbName); + if (!deleteDirectory(dbPath)) { + Log.e(TAG, "Couldn't delete Paper dir " + dbPath); } cache.invalidateAll(); mPaperDirIsCreated = false; @@ -250,8 +251,8 @@ private E readTableFile(String key, File originalFile) { } } - private String getDbPath(File filesDir, String dbName) { - return filesDir + File.separator + dbName; + private String getDbPath(Context context, String dbName) { + return context.getFilesDir() + File.separator + dbName; } private void assertInit() { @@ -262,6 +263,7 @@ private void assertInit() { } private void createPaperDir() { + mFilesDir = getDbPath(mContext, mDbName); if (!new File(mFilesDir).exists()) { boolean isReady = new File(mFilesDir).mkdirs(); if (!isReady) { From 490b4df5c5c5c3ef5e2c669fd6bbf1764a3d65c8 Mon Sep 17 00:00:00 2001 From: koxa29 Date: Thu, 23 Jul 2015 00:24:51 +0300 Subject: [PATCH 4/4] Removed unused import --- paperdb/src/main/java/io/paperdb/Storage.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/paperdb/src/main/java/io/paperdb/Storage.java b/paperdb/src/main/java/io/paperdb/Storage.java index eb5bd0a..8de1f77 100644 --- a/paperdb/src/main/java/io/paperdb/Storage.java +++ b/paperdb/src/main/java/io/paperdb/Storage.java @@ -1,7 +1,5 @@ package io.paperdb; -import java.util.concurrent.ExecutionException; - interface Storage { void destroy();