/**
*
* Funf: Open Sensing Framework Copyright (C) 2010-2011 Nadav Aharony, Wei Pan, Alex Pentland.
* Acknowledgments: Alan Gardner Contact: nadav@media.mit.edu
*
* This file is part of Funf.
*
* Funf is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Funf is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with Funf. If not,
* see <http://www.gnu.org/licenses/>.
*
*/
package edu.mit.media.funf.storage;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import edu.mit.media.funf.config.Configurable;
import edu.mit.media.funf.util.LockUtil;
import edu.mit.media.funf.util.LogUtil;
public class UploadService {
@Configurable
private int maxRemoteRetries = 6;
@Configurable
private int maxFileRetries = 3;
private Context context;
private Map<String, Integer> fileFailures;
private Map<String, Integer> remoteArchiveFailures;
private Set<File> filesToUpload;
private WakeLock lock;
private Handler uploadHandler;
private Looper looper;
private Runnable endUploads = new Runnable() {
@Override
public void run() {
if (lock != null && lock.isHeld()) {
lock.release();
}
lock = null;
}
};
public UploadService() {
}
public UploadService(Context context) {
setContext(context);
}
public void setContext(Context context) {
this.context = context;
}
public void start() {
HandlerThread thread = new HandlerThread(getClass().getName());
thread.start();
looper = thread.getLooper();
uploadHandler = new Handler(looper);
fileFailures = new HashMap<String, Integer>();
remoteArchiveFailures = new HashMap<String, Integer>();
filesToUpload = Collections.synchronizedSet(new HashSet<File>());
}
public void stop() {
looper.quit();
endUploads.run();
}
public void run(final FileArchive archive, final RemoteFileArchive remoteArchive) {
Log.i(LogUtil.TAG, "Running upload...");
if (archive != null && remoteArchive != null) {
if (lock == null) {
lock = LockUtil.getWakeLock(context);
}
for (final File file : archive.getAll()) {
archive(archive, remoteArchive, file);
}
}
}
public void archive(final FileArchive archive, final RemoteFileArchive remoteArchive, final File file) {
if (!filesToUpload.contains(file)) {
filesToUpload.add(file);
uploadHandler.post(new Runnable() {
@Override
public void run() {
runArchive(archive, remoteArchive, file);
}
});
uploadHandler.removeCallbacks(endUploads);
uploadHandler.post(endUploads); // Add stop self to end
}
}
protected void runArchive(FileArchive archive, RemoteFileArchive remoteArchive, File file) {
Integer numRemoteFailures = remoteArchiveFailures.get(remoteArchive.getId());
numRemoteFailures = (numRemoteFailures == null) ? 0 : numRemoteFailures;
if (numRemoteFailures < maxRemoteRetries && remoteArchive.isAvailable()) {
Log.i(LogUtil.TAG, "Archiving..." + file.getName());
if (remoteArchive.add(file)) {
archive.remove(file);
filesToUpload.remove(file);
} else {
Integer numFileFailures = fileFailures.get(file.getName());
numFileFailures = (numFileFailures == null) ? 1 : numFileFailures + 1;
numRemoteFailures += 1;
fileFailures.put(file.getName(), numFileFailures);
remoteArchiveFailures.put(remoteArchive.getId(), numRemoteFailures);
// 3 Attempts
if (numFileFailures < maxFileRetries) {
filesToUpload.remove(file); // Remove so we can queue up again
archive(archive, remoteArchive, file);
} else {
Log.i(LogUtil.TAG, "Failed to upload '" + file.getAbsolutePath() + "' after 3 attempts.");
filesToUpload.remove(file);
}
}
} else {
Log.i(LogUtil.TAG, "Canceling upload. Remote archive '" + remoteArchive.getId()
+ "' is not currently available.");
filesToUpload.remove(file);
}
}
}