* 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
This commit is contained in:
Simon Rutishauser 2014-01-02 15:43:43 +01:00
parent 375aefb2bf
commit 8c116142b8
9 changed files with 127 additions and 23 deletions

View File

@ -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<Void, String, Void> {
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<Void, String, Void> {
}
}
public void executeSync() {
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run();
}
}
FlattrUtils.hasToken();
executeOnExecutor(new DirectExecutor());
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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,

View File

@ -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<Flattr> flattrList) {
public static void setFlattredStatus(final Context context, List<Flattr> flattrList) {
class FlattrLinkTime {
public String paymentLink;
public long time;
@ -885,7 +922,7 @@ public class DBWriter {
String paymentLink;
List<Feed> 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;
}
}

View File

@ -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

View File

@ -11,6 +11,7 @@ public class FlattrStatus {
private Calendar lastFlattred;
public FlattrStatus() {
status = STATUS_UNFLATTERED;
lastFlattred = Calendar.getInstance();
}

View File

@ -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);

View File

@ -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);