From 8c116142b89aa78f50fbf9dc08701428a6ea0b98 Mon Sep 17 00:00:00 2001 From: Simon Rutishauser Date: Thu, 2 Jan 2014 15:43:43 +0100 Subject: [PATCH] * directly update Feed/FeedItem FlattrStatus instead of writing back entire Feed/FeedItem to database * fix race condition when fetching FlattrStatus * fix missing copy of Flattr status in Feed.updateFromOther() * fix feed reading from db, was missing FlattrStatus followup on #331 --- .../asynctask/FlattrClickWorker.java | 17 +++++- src/de/danoeh/antennapod/feed/Feed.java | 3 + .../danoeh/antennapod/storage/DBReader.java | 2 +- src/de/danoeh/antennapod/storage/DBTasks.java | 12 ++-- .../danoeh/antennapod/storage/DBWriter.java | 57 +++++++++++++++---- .../antennapod/storage/PodDBAdapter.java | 26 +++++++++ .../antennapod/util/flattr/FlattrStatus.java | 1 + .../util/menuhandler/FeedItemMenuHandler.java | 17 +++++- .../util/menuhandler/FeedMenuHandler.java | 15 ++++- 9 files changed, 127 insertions(+), 23 deletions(-) diff --git a/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java b/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java index 1335e7bf7..fa0b0bb3d 100644 --- a/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java +++ b/src/de/danoeh/antennapod/asynctask/FlattrClickWorker.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ListIterator; +import java.util.concurrent.Executor; import org.shredzone.flattr4j.exception.FlattrException; import org.shredzone.flattr4j.model.Flattr; @@ -223,10 +224,10 @@ public class FlattrClickWorker extends AsyncTask { FlattrUtils.clickUrl(context, thing.getPaymentLink()); flattrd.add(thing.getTitle()); - + thing.getFlattrStatus().setFlattred(); } - catch (FlattrException e) { + catch (Exception e) { Log.d(TAG, "flattrQueue processing exception at item " + thing.getTitle() + " " + e.getMessage()); flattr_failed.ensureCapacity(flattrList.size()); flattr_failed.add(thing.getTitle()); @@ -256,4 +257,16 @@ public class FlattrClickWorker extends AsyncTask { } } + public void executeSync() { + class DirectExecutor implements Executor { + public void execute(Runnable r) { + r.run(); + } + } + FlattrUtils.hasToken(); + executeOnExecutor(new DirectExecutor()); + + } + + } diff --git a/src/de/danoeh/antennapod/feed/Feed.java b/src/de/danoeh/antennapod/feed/Feed.java index e577083e2..b45ae182a 100644 --- a/src/de/danoeh/antennapod/feed/Feed.java +++ b/src/de/danoeh/antennapod/feed/Feed.java @@ -245,6 +245,9 @@ public class Feed extends FeedFile implements FlattrThing { if (other.paymentLink != null) { paymentLink = other.paymentLink; } + if (other.flattrStatus != null) { + flattrStatus = other.flattrStatus; + } } public boolean compareWithOther(Feed other) { diff --git a/src/de/danoeh/antennapod/storage/DBReader.java b/src/de/danoeh/antennapod/storage/DBReader.java index 012c5f3e1..3ee3322bc 100644 --- a/src/de/danoeh/antennapod/storage/DBReader.java +++ b/src/de/danoeh/antennapod/storage/DBReader.java @@ -336,7 +336,7 @@ public final class DBReader { cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_FILE_URL), cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOAD_URL), cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOADED) > 0, - new FlattrStatus(cursor.getLong(PodDBAdapter.KEY_FEED_FLATTR_STATUS_INDEX))); + new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS))); if (image != null) { image.setFeed(feed); diff --git a/src/de/danoeh/antennapod/storage/DBTasks.java b/src/de/danoeh/antennapod/storage/DBTasks.java index b9190bbc4..6f48660db 100644 --- a/src/de/danoeh/antennapod/storage/DBTasks.java +++ b/src/de/danoeh/antennapod/storage/DBTasks.java @@ -153,16 +153,16 @@ public final class DBTasks { } isRefreshing.set(false); + if (AppConfig.DEBUG) Log.d(TAG, "Flattring all pending things."); + new FlattrClickWorker(context).executeSync(); // flattr pending things + + if (AppConfig.DEBUG) Log.d(TAG, "Fetching flattr status."); + new FlattrStatusFetcher(context).executeAsync(); + GpodnetSyncService.sendSyncIntent(context); autodownloadUndownloadedItems(context); } }.start(); - - if (AppConfig.DEBUG) Log.d(TAG, "Flattring all pending things."); - new FlattrClickWorker(context).executeAsync(); // flattr pending things - - if (AppConfig.DEBUG) Log.d(TAG, "Fetching flattr status."); - new FlattrStatusFetcher(context).executeAsync(); } else { if (AppConfig.DEBUG) Log.d(TAG, diff --git a/src/de/danoeh/antennapod/storage/DBWriter.java b/src/de/danoeh/antennapod/storage/DBWriter.java index 5976adf01..f356b88dd 100644 --- a/src/de/danoeh/antennapod/storage/DBWriter.java +++ b/src/de/danoeh/antennapod/storage/DBWriter.java @@ -213,6 +213,24 @@ public class DBWriter { }); } + /** + * Saves the FlattrStatus of a Feed object in the database. + */ + public static Future setFeedFlattrStatus(final Context context, + final Feed feed) { + return dbExec.submit(new Runnable() { + + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedFlattrStatus(feed); + adapter.close(); + } + }); + } + + /** * Adds a FeedMedia object to the playback history. A FeedMedia object is in the playback history if * its playback completion date is set to a non-null value. This method will set the playback completion date to the @@ -763,6 +781,23 @@ public class DBWriter { }); } + /** + * Saves the FlattrStatus of a FeedItem object in the database. + */ + public static Future setFeedItemFlattrStatus(final Context context, + final FeedItem item) { + return dbExec.submit(new Runnable() { + + @Override + public void run() { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedItemFlattrStatus(item); + adapter.close(); + } + }); + } + /** * Saves a FeedImage object in the database. This method will save all attributes of the FeedImage object. The * contents of FeedComponent-attributes (e.g. the FeedImages's 'feed'-attribute) will not be saved. @@ -847,23 +882,25 @@ public class DBWriter { // Set flattr status of the passed thing (either a FeedItem or a Feed) - public static void setFlattredStatus(Context context, FlattrThing thing) { + public static Future setFlattredStatus(Context context, FlattrThing thing) { // must propagate this to back db if (thing instanceof FeedItem) - DBWriter.setFeedItem(context, (FeedItem) thing); + return setFeedItemFlattrStatus(context, (FeedItem)thing); else if (thing instanceof Feed) - DBWriter.setCompleteFeed(context, (Feed) thing); + return setFeedFlattrStatus(context, (Feed)thing); else if (thing instanceof SimpleFlattrThing) {} // SimpleFlattrThings are generated on the fly and do not have DB backing else Log.e(TAG, "flattrQueue processing - thing is neither FeedItem nor Feed nor SimpleFlattrThing"); + + return null; } /* * Set flattr status of the feeds/feeditems in flattrList to flattred at the given timestamp, * where the information has been retrieved from the flattr API */ - public static void setFlattredStatus(Context context, List flattrList) { + public static void setFlattredStatus(final Context context, List flattrList) { class FlattrLinkTime { public String paymentLink; public long time; @@ -885,7 +922,7 @@ public class DBWriter { String paymentLink; List feeds = DBReader.getFeedList(context); - for (Feed feed: feeds) { + for (final Feed feed: feeds) { // check if the feed has been flattred paymentLink = feed.getPaymentLink(); if (paymentLink != null) { @@ -895,17 +932,17 @@ public class DBWriter { if (AppConfig.DEBUG) Log.d(TAG, "Feed: Trying to match " + feedThingUrl); - for (FlattrLinkTime flattr: flattrLinkTime) { + for (final FlattrLinkTime flattr: flattrLinkTime) { if (flattr.paymentLink.equals(feedThingUrl)) { feed.setFlattrStatus(new FlattrStatus(flattr.time)); - setCompleteFeed(context, feed); + setFeedFlattrStatus(context, feed); break; } } } // check if any of the feeditems have been flattred - for (FeedItem item: DBReader.getFeedItemList(context, feed)) { + for (final FeedItem item: DBReader.getFeedItemList(context, feed)) { paymentLink = item.getPaymentLink(); if (paymentLink != null) { @@ -915,10 +952,10 @@ public class DBWriter { if (AppConfig.DEBUG) Log.d(TAG, "FeedItem: Trying to match " + feedItemThingUrl); - for (FlattrLinkTime flattr: flattrLinkTime) { + for (final FlattrLinkTime flattr: flattrLinkTime) { if (flattr.paymentLink.equals(feedItemThingUrl)) { item.setFlattrStatus(new FlattrStatus(flattr.time)); - setFeedItem(context, item); + setFeedItemFlattrStatus(context, item); break; } } diff --git a/src/de/danoeh/antennapod/storage/PodDBAdapter.java b/src/de/danoeh/antennapod/storage/PodDBAdapter.java index 44a95ed62..70fff1f13 100644 --- a/src/de/danoeh/antennapod/storage/PodDBAdapter.java +++ b/src/de/danoeh/antennapod/storage/PodDBAdapter.java @@ -218,6 +218,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_TYPE, TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER, TABLE_NAME_FEEDS + "." + KEY_AUTO_DOWNLOAD, + TABLE_NAME_FEEDS + "." + KEY_FLATTR_STATUS }; // column indices for FEED_SEL_STD @@ -236,6 +237,7 @@ public class PodDBAdapter { public static final int IDX_FEED_SEL_STD_TYPE = 12; public static final int IDX_FEED_SEL_STD_FEED_IDENTIFIER = 13; public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD = 14; + public static final int IDX_FEED_SEL_STD_FLATTR_STATUS = 15; /** @@ -358,6 +360,9 @@ public class PodDBAdapter { values.put(KEY_LASTUPDATE, feed.getLastUpdate().getTime()); values.put(KEY_TYPE, feed.getType()); values.put(KEY_FEED_IDENTIFIER, feed.getFeedIdentifier()); + + Log.d(TAG, "Setting feed with flattr status " + feed.getTitle() + ": " + feed.getFlattrStatus().toLong()); + values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong()); if (feed.getId() == 0) { // Create new entry @@ -483,6 +488,16 @@ public class PodDBAdapter { db.endTransaction(); } + /** + * Update the flattr status of a feed + */ + public void setFeedFlattrStatus(Feed feed) + { + ContentValues values = new ContentValues(); + values.put(KEY_FLATTR_STATUS, feed.getFlattrStatus().toLong()); + db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feed.getId())}); + } + /** * Updates the download URL of a Feed. */ @@ -509,6 +524,17 @@ public class PodDBAdapter { return result; } + /** + * Update the flattr status of a FeedItem + */ + public void setFeedItemFlattrStatus(FeedItem feedItem) + { + ContentValues values = new ContentValues(); + values.put(KEY_FLATTR_STATUS, feedItem.getFlattrStatus().toLong()); + db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[] { String.valueOf(feedItem.getId()) } ); + } + + /** * Inserts or updates a feeditem entry * @param item The FeedItem diff --git a/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java b/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java index b00be9956..a1d6d3bc4 100644 --- a/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java +++ b/src/de/danoeh/antennapod/util/flattr/FlattrStatus.java @@ -11,6 +11,7 @@ public class FlattrStatus { private Calendar lastFlattred; public FlattrStatus() { + status = STATUS_UNFLATTERED; lastFlattred = Calendar.getInstance(); } diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java index 53316f9a4..3c662f794 100644 --- a/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java +++ b/src/de/danoeh/antennapod/util/menuhandler/FeedItemMenuHandler.java @@ -3,6 +3,8 @@ package de.danoeh.antennapod.util.menuhandler; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.util.Log; + import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.FlattrClickWorker; @@ -17,9 +19,13 @@ import de.danoeh.antennapod.util.ShareUtils; import de.danoeh.antennapod.util.flattr.FlattrStatus; import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; /** Handles interactions with the FeedItemMenu. */ public class FeedItemMenuHandler { + private static final String TAG = "FeedItemMenuHandler"; + private FeedItemMenuHandler() { } @@ -160,8 +166,15 @@ public class FeedItemMenuHandler { break; case R.id.support_item: selectedItem.getFlattrStatus().setFlattrQueue(); - DBWriter.setFlattredStatus(context, selectedItem); - new FlattrClickWorker(context).executeAsync(); + Future future = DBWriter.setFlattredStatus(context, selectedItem); + try { + synchronized (future) { + future.wait(10); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + new FlattrClickWorker(context).executeAsync(); break; case R.id.share_link_item: ShareUtils.shareFeedItemLink(context, selectedItem); diff --git a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java index 1559ae1c4..04620af49 100644 --- a/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java +++ b/src/de/danoeh/antennapod/util/menuhandler/FeedMenuHandler.java @@ -8,6 +8,10 @@ import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + import de.danoeh.antennapod.AppConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.FeedInfoActivity; @@ -81,8 +85,15 @@ public class FeedMenuHandler { break; case R.id.support_item: selectedFeed.getFlattrStatus().setFlattrQueue(); - DBWriter.setFlattredStatus(context, selectedFeed); - new FlattrClickWorker(context).executeAsync(); + Future future = DBWriter.setFlattredStatus(context, selectedFeed); + try { + synchronized (future) { + future.wait(10); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + new FlattrClickWorker(context).executeAsync(); break; case R.id.share_link_item: ShareUtils.shareFeedlink(context, selectedFeed);