/*
* TV-Browser for Android
* Copyright (C) 2015 René Mach (rene@tvbrowser.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to use, copy, modify or merge the Software,
* furthermore to publish and distribute the Software free of charge without modifications and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.tvbrowser.tvbrowser;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import org.tvbrowser.content.TvBrowserContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.net.Uri;
import android.os.RemoteException;
import android.util.Log;
/**
* A class with bulk data base operations that takes the
* memory size on the system into consideration.
*
* @author René Mach
*/
public class MemorySizeConstrictedDatabaseOperation {
private static final int TABLE_OPERATION_MIN_SIZE = Math.max(100, (int)(Runtime.getRuntime().maxMemory()/1000000));
private Context mContext;
private ArrayList<ContentValues> mInsertList;
private ArrayList<ContentProviderOperation> mUpdateList;
private Uri mInsertUri;
private int mMinOperationDivider;
private int mOperationDivider;
private boolean mOperationsAvailable;
private boolean mOperationsAdded;
private AtomicBoolean mSuccess;
public MemorySizeConstrictedDatabaseOperation(Context context, Uri insertUri) {
this(context,insertUri,1);
}
/**
* @param context The Context to use.
* @param insertUri The content URI for the insert operations
* @param minOperationDivider The divider for the number of entries before starting database opertaion-
*/
public MemorySizeConstrictedDatabaseOperation(Context context, Uri insertUri, int minOperationDivider) {
mContext = context;
mInsertUri = insertUri;
mSuccess = new AtomicBoolean(true);
mOperationsAdded = false;
if(mMinOperationDivider > 0) {
mMinOperationDivider = minOperationDivider;
}
else {
mMinOperationDivider = 1;
}
mOperationDivider = TABLE_OPERATION_MIN_SIZE/mMinOperationDivider;
if(insertUri != null) {
mInsertList = new ArrayList<ContentValues>();
}
mUpdateList = new ArrayList<ContentProviderOperation>();
mOperationsAvailable = false;
}
public synchronized void cancel() {
if(mInsertList != null && !mInsertList.isEmpty()) {
mInsertList.clear();
}
if(mUpdateList != null && !mUpdateList.isEmpty()) {
mInsertList.clear();
}
mInsertList = null;
mUpdateList = null;
mContext = null;
}
public synchronized void finish() {
if(mInsertList != null && !mInsertList.isEmpty()) {
insert();
}
if(mUpdateList != null && !mUpdateList.isEmpty()) {
update();
}
mInsertList = null;
mUpdateList = null;
mContext = null;
}
public synchronized void addInsert(ContentValues insert) {
if(mInsertList != null) {
mOperationsAvailable = true;
mInsertList.add(insert);
mOperationsAdded = true;
if(mInsertList.size() > mOperationDivider) {
insert();
}
}
}
public synchronized void addUpdate(ContentProviderOperation update) {
if(mUpdateList != null) {
mOperationsAvailable = true;
mUpdateList.add(update);
mOperationsAdded = true;
if(mUpdateList.size() > mOperationDivider) {
update();
}
}
}
private synchronized void insert() {
if(mInsertUri != null && mInsertList != null && !mInsertList.isEmpty() && mContext != null) {
boolean success = mContext.getContentResolver().bulkInsert(mInsertUri, mInsertList.toArray(new ContentValues[mInsertList.size()])) >= mInsertList.size();
mSuccess.compareAndSet(true, success);
mInsertList.clear();
}
}
private synchronized void update() {
Log.d("info9", "update()");
if(mUpdateList != null && !mUpdateList.isEmpty() && mContext != null) {
boolean success = false;
Log.d("info9", " " + mUpdateList.size());
try {
success = mContext.getContentResolver().applyBatch(TvBrowserContentProvider.AUTHORITY, mUpdateList).length >= mUpdateList.size();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (OperationApplicationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mSuccess.compareAndSet(true, success);
mUpdateList.clear();
}
}
public boolean operationsAvailable() {
return mOperationsAvailable;
}
public boolean wasSuccessfull() {
return mSuccess.get() && mOperationsAdded;
}
}