summaryrefslogtreecommitdiffstats
path: root/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer')
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ConcurrentRecordConsumer.java122
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordConsumer.java26
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannel.java292
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannelDelegate.java13
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsConsumerDelegate.java23
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SerialRecordConsumer.java131
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizer.java18
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizerSession.java78
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SessionNotBegunException.java19
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/Synchronizer.java105
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerDelegate.java10
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSession.java425
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSessionDelegate.java13
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnbundleError.java19
-rw-r--r--mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnexpectedSessionException.java26
15 files changed, 0 insertions, 1320 deletions
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ConcurrentRecordConsumer.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ConcurrentRecordConsumer.java
deleted file mode 100644
index 9b1ef3e85..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ConcurrentRecordConsumer.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.repositories.domain.Record;
-
-/**
- * Consume records from a queue inside a RecordsChannel, as fast as we can.
- * TODO: rewrite this in terms of an ExecutorService and a CompletionService.
- * See Bug 713483.
- *
- * @author rnewman
- *
- */
-class ConcurrentRecordConsumer extends RecordConsumer {
- private static final String LOG_TAG = "CRecordConsumer";
-
- /**
- * When this is true and all records have been processed, the consumer
- * will notify its delegate.
- */
- protected boolean allRecordsQueued = false;
- private long counter = 0;
-
- public ConcurrentRecordConsumer(RecordsConsumerDelegate delegate) {
- this.delegate = delegate;
- }
-
- private final Object monitor = new Object();
- @Override
- public void doNotify() {
- synchronized (monitor) {
- monitor.notify();
- }
- }
-
- @Override
- public void queueFilled() {
- Logger.debug(LOG_TAG, "Queue filled.");
- synchronized (monitor) {
- this.allRecordsQueued = true;
- monitor.notify();
- }
- }
-
- @Override
- public void halt() {
- synchronized (monitor) {
- this.stopImmediately = true;
- monitor.notify();
- }
- }
-
- private final Object countMonitor = new Object();
- @Override
- public void stored() {
- Logger.trace(LOG_TAG, "Record stored. Notifying.");
- synchronized (countMonitor) {
- counter++;
- }
- }
-
- private void consumerIsDone() {
- Logger.debug(LOG_TAG, "Consumer is done. Processed " + counter + ((counter == 1) ? " record." : " records."));
- delegate.consumerIsDone(!allRecordsQueued);
- }
-
- @Override
- public void run() {
- Record record;
-
- while (true) {
- // The queue is concurrent-safe.
- while ((record = delegate.getQueue().poll()) != null) {
- synchronized (monitor) {
- Logger.trace(LOG_TAG, "run() took monitor.");
- if (stopImmediately) {
- Logger.debug(LOG_TAG, "Stopping immediately. Clearing queue.");
- delegate.getQueue().clear();
- Logger.debug(LOG_TAG, "Notifying consumer.");
- consumerIsDone();
- return;
- }
- Logger.debug(LOG_TAG, "run() dropped monitor.");
- }
-
- Logger.trace(LOG_TAG, "Storing record with guid " + record.guid + ".");
- try {
- delegate.store(record);
- } catch (Exception e) {
- // TODO: Bug 709371: track records that failed to apply.
- Logger.error(LOG_TAG, "Caught error in store.", e);
- }
- Logger.trace(LOG_TAG, "Done with record.");
- }
- synchronized (monitor) {
- Logger.trace(LOG_TAG, "run() took monitor.");
-
- if (allRecordsQueued) {
- Logger.debug(LOG_TAG, "Done with records and no more to come. Notifying consumerIsDone.");
- consumerIsDone();
- return;
- }
- if (stopImmediately) {
- Logger.debug(LOG_TAG, "Done with records and told to stop immediately. Notifying consumerIsDone.");
- consumerIsDone();
- return;
- }
- try {
- Logger.debug(LOG_TAG, "Not told to stop but no records. Waiting.");
- monitor.wait(10000);
- } catch (InterruptedException e) {
- // TODO
- }
- Logger.trace(LOG_TAG, "run() dropped monitor.");
- }
- }
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordConsumer.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordConsumer.java
deleted file mode 100644
index 35e57d9c2..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordConsumer.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-public abstract class RecordConsumer implements Runnable {
-
- public abstract void stored();
-
- /**
- * There are no more store items to arrive at the delegate.
- * When you're done, take care of finishing up.
- */
- public abstract void queueFilled();
- public abstract void halt();
-
- public abstract void doNotify();
-
- protected boolean stopImmediately = false;
- protected RecordsConsumerDelegate delegate;
-
- public RecordConsumer() {
- super();
- }
-} \ No newline at end of file
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannel.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannel.java
deleted file mode 100644
index f929cdc75..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannel.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.ThreadPool;
-import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException;
-import org.mozilla.gecko.sync.repositories.NoStoreDelegateException;
-import org.mozilla.gecko.sync.repositories.RepositorySession;
-import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionBeginDelegate;
-import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionStoreDelegate;
-import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionBeginDelegate;
-import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate;
-import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate;
-import org.mozilla.gecko.sync.repositories.domain.Record;
-
-/**
- * Pulls records from `source`, applying them to `sink`.
- * Notifies its delegate of errors and completion.
- *
- * All stores (initiated by a fetch) must have been completed before storeDone
- * is invoked on the sink. This is to avoid the existing stored items being
- * considered as the total set, with onStoreCompleted being called when they're
- * done:
- *
- * store(A) store(B)
- * store(C) storeDone()
- * store(A) finishes. Store job begins.
- * store(C) finishes. Store job begins.
- * storeDone() finishes.
- * Storing of A complete.
- * Storing of C complete.
- * We're done! Call onStoreCompleted.
- * store(B) finishes... uh oh.
- *
- * In other words, storeDone must be gated on the synchronous invocation of every store.
- *
- * Similarly, we require that every store callback have returned before onStoreCompleted is invoked.
- *
- * This whole set of guarantees should be achievable thusly:
- *
- * * The fetch process must run in a single thread, and invoke store()
- * synchronously. After processing every incoming record, storeDone is called,
- * setting a flag.
- * If the fetch cannot be implicitly queued, it must be explicitly queued.
- * In this implementation, we assume that fetch callbacks are strictly ordered in this way.
- *
- * * The store process must be (implicitly or explicitly) queued. When the
- * queue empties, the consumer checks the storeDone flag. If it's set, and the
- * queue is exhausted, invoke onStoreCompleted.
- *
- * RecordsChannel exists to enforce this ordering of operations.
- *
- * @author rnewman
- *
- */
-public class RecordsChannel implements
- RepositorySessionFetchRecordsDelegate,
- RepositorySessionStoreDelegate,
- RecordsConsumerDelegate,
- RepositorySessionBeginDelegate {
-
- private static final String LOG_TAG = "RecordsChannel";
- public RepositorySession source;
- public RepositorySession sink;
- private final RecordsChannelDelegate delegate;
- private long fetchEnd = -1;
-
- protected final AtomicInteger numFetched = new AtomicInteger();
- protected final AtomicInteger numFetchFailed = new AtomicInteger();
- protected final AtomicInteger numStored = new AtomicInteger();
- protected final AtomicInteger numStoreFailed = new AtomicInteger();
-
- public RecordsChannel(RepositorySession source, RepositorySession sink, RecordsChannelDelegate delegate) {
- this.source = source;
- this.sink = sink;
- this.delegate = delegate;
- }
-
- /*
- * We push fetched records into a queue.
- * A separate thread is waiting for us to notify it of work to do.
- * When we tell it to stop, it'll stop. We do that when the fetch
- * is completed.
- * When it stops, we tell the sink that there are no more records,
- * and wait for the sink to tell us that storing is done.
- * Then we notify our delegate of completion.
- */
- private RecordConsumer consumer;
- private boolean waitingForQueueDone = false;
- private final ConcurrentLinkedQueue<Record> toProcess = new ConcurrentLinkedQueue<Record>();
-
- @Override
- public ConcurrentLinkedQueue<Record> getQueue() {
- return toProcess;
- }
-
- protected boolean isReady() {
- return source.isActive() && sink.isActive();
- }
-
- /**
- * Get the number of records fetched so far.
- *
- * @return number of fetches.
- */
- public int getFetchCount() {
- return numFetched.get();
- }
-
- /**
- * Get the number of fetch failures recorded so far.
- *
- * @return number of fetch failures.
- */
- public int getFetchFailureCount() {
- return numFetchFailed.get();
- }
-
- /**
- * Get the number of store attempts (successful or not) so far.
- *
- * @return number of stores attempted.
- */
- public int getStoreCount() {
- return numStored.get();
- }
-
- /**
- * Get the number of store failures recorded so far.
- *
- * @return number of store failures.
- */
- public int getStoreFailureCount() {
- return numStoreFailed.get();
- }
-
- /**
- * Start records flowing through the channel.
- */
- public void flow() {
- if (!isReady()) {
- RepositorySession failed = source;
- if (source.isActive()) {
- failed = sink;
- }
- this.delegate.onFlowBeginFailed(this, new SessionNotBegunException(failed));
- return;
- }
-
- if (!source.dataAvailable()) {
- Logger.info(LOG_TAG, "No data available: short-circuiting flow from source " + source);
- long now = System.currentTimeMillis();
- this.delegate.onFlowCompleted(this, now, now);
- return;
- }
-
- sink.setStoreDelegate(this);
- numFetched.set(0);
- numFetchFailed.set(0);
- numStored.set(0);
- numStoreFailed.set(0);
- // Start a consumer thread.
- this.consumer = new ConcurrentRecordConsumer(this);
- ThreadPool.run(this.consumer);
- waitingForQueueDone = true;
- source.fetchSince(source.getLastSyncTimestamp(), this);
- }
-
- /**
- * Begin both sessions, invoking flow() when done.
- * @throws InvalidSessionTransitionException
- */
- public void beginAndFlow() throws InvalidSessionTransitionException {
- Logger.trace(LOG_TAG, "Beginning source.");
- source.begin(this);
- }
-
- @Override
- public void store(Record record) {
- numStored.incrementAndGet();
- try {
- sink.store(record);
- } catch (NoStoreDelegateException e) {
- Logger.error(LOG_TAG, "Got NoStoreDelegateException in RecordsChannel.store(). This should not occur. Aborting.", e);
- delegate.onFlowStoreFailed(this, e, record.guid);
- }
- }
-
- @Override
- public void onFetchFailed(Exception ex, Record record) {
- Logger.warn(LOG_TAG, "onFetchFailed. Calling for immediate stop.", ex);
- numFetchFailed.incrementAndGet();
- this.consumer.halt();
- delegate.onFlowFetchFailed(this, ex);
- }
-
- @Override
- public void onFetchedRecord(Record record) {
- numFetched.incrementAndGet();
- this.toProcess.add(record);
- this.consumer.doNotify();
- }
-
- @Override
- public void onFetchCompleted(final long fetchEnd) {
- Logger.trace(LOG_TAG, "onFetchCompleted. Stopping consumer once stores are done.");
- Logger.trace(LOG_TAG, "Fetch timestamp is " + fetchEnd);
- this.fetchEnd = fetchEnd;
- this.consumer.queueFilled();
- }
-
- @Override
- public void onRecordStoreFailed(Exception ex, String recordGuid) {
- Logger.trace(LOG_TAG, "Failed to store record with guid " + recordGuid);
- numStoreFailed.incrementAndGet();
- this.consumer.stored();
- delegate.onFlowStoreFailed(this, ex, recordGuid);
- // TODO: abort?
- }
-
- @Override
- public void onRecordStoreSucceeded(String guid) {
- Logger.trace(LOG_TAG, "Stored record with guid " + guid);
- this.consumer.stored();
- }
-
-
- @Override
- public void consumerIsDone(boolean allRecordsQueued) {
- Logger.trace(LOG_TAG, "Consumer is done. Are we waiting for it? " + waitingForQueueDone);
- if (waitingForQueueDone) {
- waitingForQueueDone = false;
- this.sink.storeDone(); // Now we'll be waiting for onStoreCompleted.
- }
- }
-
- @Override
- public void onStoreCompleted(long storeEnd) {
- Logger.trace(LOG_TAG, "onStoreCompleted. Notifying delegate of onFlowCompleted. " +
- "Fetch end is " + fetchEnd + ", store end is " + storeEnd);
- // TODO: synchronize on consumer callback?
- delegate.onFlowCompleted(this, fetchEnd, storeEnd);
- }
-
- @Override
- public void onBeginFailed(Exception ex) {
- delegate.onFlowBeginFailed(this, ex);
- }
-
- @Override
- public void onBeginSucceeded(RepositorySession session) {
- if (session == source) {
- Logger.trace(LOG_TAG, "Source session began. Beginning sink session.");
- try {
- sink.begin(this);
- } catch (InvalidSessionTransitionException e) {
- onBeginFailed(e);
- return;
- }
- }
- if (session == sink) {
- Logger.trace(LOG_TAG, "Sink session began. Beginning flow.");
- this.flow();
- return;
- }
-
- // TODO: error!
- }
-
- @Override
- public RepositorySessionStoreDelegate deferredStoreDelegate(final ExecutorService executor) {
- return new DeferredRepositorySessionStoreDelegate(this, executor);
- }
-
- @Override
- public RepositorySessionBeginDelegate deferredBeginDelegate(final ExecutorService executor) {
- return new DeferredRepositorySessionBeginDelegate(this, executor);
- }
-
- @Override
- public RepositorySessionFetchRecordsDelegate deferredFetchDelegate(ExecutorService executor) {
- // Lie outright. We know that all of our fetch methods are safe.
- return this;
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannelDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannelDelegate.java
deleted file mode 100644
index 8daeb7ad5..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsChannelDelegate.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-public interface RecordsChannelDelegate {
- public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd);
- public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex);
- public void onFlowFetchFailed(RecordsChannel recordsChannel, Exception ex);
- public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex, String recordGuid);
- public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex);
-} \ No newline at end of file
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsConsumerDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsConsumerDelegate.java
deleted file mode 100644
index a00abf848..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/RecordsConsumerDelegate.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import java.util.concurrent.ConcurrentLinkedQueue;
-
-import org.mozilla.gecko.sync.repositories.domain.Record;
-
-interface RecordsConsumerDelegate {
- public abstract ConcurrentLinkedQueue<Record> getQueue();
-
- /**
- * Called when no more items will be processed.
- * If forced is true, the consumer is terminating because it was told to halt;
- * not all items will necessarily have been processed.
- * If forced is false, the consumer has invoked store and received an onStoreCompleted callback.
- * @param forced
- */
- public abstract void consumerIsDone(boolean forced);
- public abstract void store(Record record);
-} \ No newline at end of file
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SerialRecordConsumer.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SerialRecordConsumer.java
deleted file mode 100644
index 6ee44ea2b..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SerialRecordConsumer.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.repositories.domain.Record;
-
-/**
- * Consume records from a queue inside a RecordsChannel, storing them serially.
- * @author rnewman
- *
- */
-class SerialRecordConsumer extends RecordConsumer {
- private static final String LOG_TAG = "SerialRecordConsumer";
- protected boolean stopEventually = false;
- private volatile long counter = 0;
-
- public SerialRecordConsumer(RecordsConsumerDelegate delegate) {
- this.delegate = delegate;
- }
-
- private final Object monitor = new Object();
- @Override
- public void doNotify() {
- synchronized (monitor) {
- monitor.notify();
- }
- }
-
- @Override
- public void queueFilled() {
- Logger.debug(LOG_TAG, "Queue filled.");
- synchronized (monitor) {
- this.stopEventually = true;
- monitor.notify();
- }
- }
-
- @Override
- public void halt() {
- Logger.debug(LOG_TAG, "Halting.");
- synchronized (monitor) {
- this.stopEventually = true;
- this.stopImmediately = true;
- monitor.notify();
- }
- }
-
- private final Object storeSerializer = new Object();
- @Override
- public void stored() {
- Logger.debug(LOG_TAG, "Record stored. Notifying.");
- synchronized (storeSerializer) {
- Logger.debug(LOG_TAG, "stored() took storeSerializer.");
- counter++;
- storeSerializer.notify();
- Logger.debug(LOG_TAG, "stored() dropped storeSerializer.");
- }
- }
- private void storeSerially(Record record) {
- Logger.debug(LOG_TAG, "New record to store.");
- synchronized (storeSerializer) {
- Logger.debug(LOG_TAG, "storeSerially() took storeSerializer.");
- Logger.debug(LOG_TAG, "Storing...");
- try {
- this.delegate.store(record);
- } catch (Exception e) {
- Logger.warn(LOG_TAG, "Got exception in store. Not waiting.", e);
- return; // So we don't block for a stored() that never comes.
- }
- try {
- Logger.debug(LOG_TAG, "Waiting...");
- storeSerializer.wait();
- } catch (InterruptedException e) {
- // TODO
- }
- Logger.debug(LOG_TAG, "storeSerially() dropped storeSerializer.");
- }
- }
-
- private void consumerIsDone() {
- long counterNow = this.counter;
- Logger.info(LOG_TAG, "Consumer is done. Processed " + counterNow + ((counterNow == 1) ? " record." : " records."));
- delegate.consumerIsDone(stopImmediately);
- }
-
- @Override
- public void run() {
- while (true) {
- synchronized (monitor) {
- Logger.debug(LOG_TAG, "run() took monitor.");
- if (stopImmediately) {
- Logger.debug(LOG_TAG, "Stopping immediately. Clearing queue.");
- delegate.getQueue().clear();
- Logger.debug(LOG_TAG, "Notifying consumer.");
- consumerIsDone();
- return;
- }
- Logger.debug(LOG_TAG, "run() dropped monitor.");
- }
- // The queue is concurrent-safe.
- while (!delegate.getQueue().isEmpty()) {
- Logger.debug(LOG_TAG, "Grabbing record...");
- Record record = delegate.getQueue().remove();
- // Block here, allowing us to process records
- // serially.
- Logger.debug(LOG_TAG, "Invoking storeSerially...");
- this.storeSerially(record);
- Logger.debug(LOG_TAG, "Done with record.");
- }
- synchronized (monitor) {
- Logger.debug(LOG_TAG, "run() took monitor.");
-
- if (stopEventually) {
- Logger.debug(LOG_TAG, "Done with records and told to stop. Notifying consumer.");
- consumerIsDone();
- return;
- }
- try {
- Logger.debug(LOG_TAG, "Not told to stop but no records. Waiting.");
- monitor.wait(10000);
- } catch (InterruptedException e) {
- // TODO
- }
- Logger.debug(LOG_TAG, "run() dropped monitor.");
- }
- }
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizer.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizer.java
deleted file mode 100644
index ac4f48789..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizer.java
+++ /dev/null
@@ -1,18 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-/**
- * A <code>SynchronizerSession</code> designed to be used between a remote
- * server and a local repository.
- * <p>
- * See <code>ServerLocalSynchronizerSession</code> for error handling details.
- */
-public class ServerLocalSynchronizer extends Synchronizer {
- @Override
- public SynchronizerSession newSynchronizerSession() {
- return new ServerLocalSynchronizerSession(this, this);
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizerSession.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizerSession.java
deleted file mode 100644
index dc9eb01a0..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/ServerLocalSynchronizerSession.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.repositories.FetchFailedException;
-import org.mozilla.gecko.sync.repositories.StoreFailedException;
-
-/**
- * A <code>SynchronizerSession</code> designed to be used between a remote
- * server and a local repository.
- * <p>
- * Handles failure cases as follows (in the order they will occur during a sync):
- * <ul>
- * <li>Remote fetch failures abort.</li>
- * <li>Local store failures are ignored.</li>
- * <li>Local fetch failures abort.</li>
- * <li>Remote store failures abort.</li>
- * </ul>
- */
-public class ServerLocalSynchronizerSession extends SynchronizerSession {
- protected static final String LOG_TAG = "ServLocSynchronizerSess";
-
- public ServerLocalSynchronizerSession(Synchronizer synchronizer, SynchronizerSessionDelegate delegate) {
- super(synchronizer, delegate);
- }
-
- @Override
- public void onFirstFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) {
- // Fetch failures always abort.
- int numRemoteFetchFailed = recordsChannel.getFetchFailureCount();
- if (numRemoteFetchFailed > 0) {
- final String message = "Got " + numRemoteFetchFailed + " failures fetching remote records!";
- Logger.warn(LOG_TAG, message + " Aborting session.");
- delegate.onSynchronizeFailed(this, new FetchFailedException(), message);
- return;
- }
- Logger.trace(LOG_TAG, "No failures fetching remote records.");
-
- // Local store failures are ignored.
- int numLocalStoreFailed = recordsChannel.getStoreFailureCount();
- if (numLocalStoreFailed > 0) {
- final String message = "Got " + numLocalStoreFailed + " failures storing local records!";
- Logger.warn(LOG_TAG, message + " Ignoring local store failures and continuing synchronizer session.");
- } else {
- Logger.trace(LOG_TAG, "No failures storing local records.");
- }
-
- super.onFirstFlowCompleted(recordsChannel, fetchEnd, storeEnd);
- }
-
- @Override
- public void onSecondFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) {
- // Fetch failures always abort.
- int numLocalFetchFailed = recordsChannel.getFetchFailureCount();
- if (numLocalFetchFailed > 0) {
- final String message = "Got " + numLocalFetchFailed + " failures fetching local records!";
- Logger.warn(LOG_TAG, message + " Aborting session.");
- delegate.onSynchronizeFailed(this, new FetchFailedException(), message);
- return;
- }
- Logger.trace(LOG_TAG, "No failures fetching local records.");
-
- // Remote store failures abort!
- int numRemoteStoreFailed = recordsChannel.getStoreFailureCount();
- if (numRemoteStoreFailed > 0) {
- final String message = "Got " + numRemoteStoreFailed + " failures storing remote records!";
- Logger.warn(LOG_TAG, message + " Aborting session.");
- delegate.onSynchronizeFailed(this, new StoreFailedException(), message);
- return;
- }
- Logger.trace(LOG_TAG, "No failures storing remote records.");
-
- super.onSecondFlowCompleted(recordsChannel, fetchEnd, storeEnd);
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SessionNotBegunException.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SessionNotBegunException.java
deleted file mode 100644
index 20c7fcd56..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SessionNotBegunException.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.sync.SyncException;
-import org.mozilla.gecko.sync.repositories.RepositorySession;
-
-public class SessionNotBegunException extends SyncException {
-
- public RepositorySession failed;
-
- public SessionNotBegunException(RepositorySession failed) {
- this.failed = failed;
- }
-
- private static final long serialVersionUID = -4565241449897072841L;
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/Synchronizer.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/Synchronizer.java
deleted file mode 100644
index cc15b35a9..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/Synchronizer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.SynchronizerConfiguration;
-import org.mozilla.gecko.sync.repositories.Repository;
-import org.mozilla.gecko.sync.repositories.RepositorySessionBundle;
-
-import android.content.Context;
-
-/**
- * I perform a sync.
- *
- * Initialize me by calling `load` with a SynchronizerConfiguration.
- *
- * Start synchronizing by calling `synchronize` with a SynchronizerDelegate. I
- * provide coarse-grained feedback by calling my delegate's callback methods.
- *
- * I always call exactly one of my delegate's `onSynchronized` or
- * `onSynchronizeFailed` callback methods. In addition, I call
- * `onSynchronizeAborted` before `onSynchronizeFailed` when I encounter a fetch,
- * store, or session error while synchronizing.
- *
- * After synchronizing, call `save` to get back a SynchronizerConfiguration with
- * updated bundle information.
- */
-public class Synchronizer implements SynchronizerSessionDelegate {
- public static final String LOG_TAG = "SyncDelSDelegate";
-
- protected String configSyncID; // Used to pass syncID from load() back into save().
-
- protected SynchronizerDelegate synchronizerDelegate;
-
- protected SynchronizerSession session = null;
-
- public SynchronizerSession getSynchronizerSession() {
- return session;
- }
-
- @Override
- public void onInitialized(SynchronizerSession session) {
- session.synchronize();
- }
-
- @Override
- public void onSynchronized(SynchronizerSession synchronizerSession) {
- Logger.debug(LOG_TAG, "Got onSynchronized.");
- Logger.debug(LOG_TAG, "Notifying SynchronizerDelegate.");
- this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer());
- }
-
- @Override
- public void onSynchronizeSkipped(SynchronizerSession synchronizerSession) {
- Logger.debug(LOG_TAG, "Got onSynchronizeSkipped.");
- Logger.debug(LOG_TAG, "Notifying SynchronizerDelegate as if on success.");
- this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer());
- }
-
- @Override
- public void onSynchronizeFailed(SynchronizerSession session,
- Exception lastException, String reason) {
- this.synchronizerDelegate.onSynchronizeFailed(session.getSynchronizer(), lastException, reason);
- }
-
- public Repository repositoryA;
- public Repository repositoryB;
- public RepositorySessionBundle bundleA;
- public RepositorySessionBundle bundleB;
-
- /**
- * Fetch a synchronizer session appropriate for this <code>Synchronizer</code>
- */
- protected SynchronizerSession newSynchronizerSession() {
- return new SynchronizerSession(this, this);
- }
-
- /**
- * Start synchronizing, calling delegate's callback methods.
- */
- public void synchronize(Context context, SynchronizerDelegate delegate) {
- this.synchronizerDelegate = delegate;
- this.session = newSynchronizerSession();
- this.session.init(context, bundleA, bundleB);
- }
-
- public SynchronizerConfiguration save() {
- return new SynchronizerConfiguration(configSyncID, bundleA, bundleB);
- }
-
- /**
- * Set my repository session bundles from a SynchronizerConfiguration.
- *
- * This method is not thread-safe.
- *
- * @param config
- */
- public void load(SynchronizerConfiguration config) {
- bundleA = config.remoteBundle;
- bundleB = config.localBundle;
- configSyncID = config.syncID;
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerDelegate.java
deleted file mode 100644
index a290188ab..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerDelegate.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-public interface SynchronizerDelegate {
- public void onSynchronized(Synchronizer synchronizer);
- public void onSynchronizeFailed(Synchronizer synchronizer, Exception lastException, String reason);
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSession.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSession.java
deleted file mode 100644
index c4d244b4c..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSession.java
+++ /dev/null
@@ -1,425 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.mozilla.gecko.background.common.log.Logger;
-import org.mozilla.gecko.sync.repositories.InactiveSessionException;
-import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException;
-import org.mozilla.gecko.sync.repositories.RepositorySession;
-import org.mozilla.gecko.sync.repositories.RepositorySessionBundle;
-import org.mozilla.gecko.sync.repositories.delegates.DeferrableRepositorySessionCreationDelegate;
-import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionFinishDelegate;
-import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate;
-
-import android.content.Context;
-
-/**
- * I coordinate the moving parts of a sync started by
- * {@link Synchronizer#synchronize}.
- *
- * I flow records twice: first from A to B, and then from B to A. I provide
- * fine-grained feedback by calling my delegate's callback methods.
- *
- * Initialize me by creating me with a Synchronizer and a
- * SynchronizerSessionDelegate. Kick things off by calling `init` with two
- * RepositorySessionBundles, and then call `synchronize` in your `onInitialized`
- * callback.
- *
- * I always call exactly one of my delegate's `onInitialized` or
- * `onSessionError` callback methods from `init`.
- *
- * I call my delegate's `onSynchronizeSkipped` callback method if there is no
- * data to be synchronized in `synchronize`.
- *
- * In addition, I call `onFetchError`, `onStoreError`, and `onSessionError` when
- * I encounter a fetch, store, or session error while synchronizing.
- *
- * Typically my delegate will call `abort` in its error callbacks, which will
- * call my delegate's `onSynchronizeAborted` method and halt the sync.
- *
- * I always call exactly one of my delegate's `onSynchronized` or
- * `onSynchronizeFailed` callback methods if I have not seen an error.
- */
-public class SynchronizerSession
-extends DeferrableRepositorySessionCreationDelegate
-implements RecordsChannelDelegate,
- RepositorySessionFinishDelegate {
-
- protected static final String LOG_TAG = "SynchronizerSession";
- protected Synchronizer synchronizer;
- protected SynchronizerSessionDelegate delegate;
- protected Context context;
-
- /*
- * Computed during init.
- */
- private RepositorySession sessionA;
- private RepositorySession sessionB;
- private RepositorySessionBundle bundleA;
- private RepositorySessionBundle bundleB;
-
- // Bug 726054: just like desktop, we track our last interaction with the server,
- // not the last record timestamp that we fetched. This ensures that we don't re-
- // download the records we just uploaded, at the cost of skipping any records
- // that a concurrently syncing client has uploaded.
- private long pendingATimestamp = -1;
- private long pendingBTimestamp = -1;
- private long storeEndATimestamp = -1;
- private long storeEndBTimestamp = -1;
- private boolean flowAToBCompleted = false;
- private boolean flowBToACompleted = false;
-
- protected final AtomicInteger numInboundRecords = new AtomicInteger(-1);
- protected final AtomicInteger numOutboundRecords = new AtomicInteger(-1);
-
- /*
- * Public API: constructor, init, synchronize.
- */
- public SynchronizerSession(Synchronizer synchronizer, SynchronizerSessionDelegate delegate) {
- this.setSynchronizer(synchronizer);
- this.delegate = delegate;
- }
-
- public Synchronizer getSynchronizer() {
- return synchronizer;
- }
-
- public void setSynchronizer(Synchronizer synchronizer) {
- this.synchronizer = synchronizer;
- }
-
- public void init(Context context, RepositorySessionBundle bundleA, RepositorySessionBundle bundleB) {
- this.context = context;
- this.bundleA = bundleA;
- this.bundleB = bundleB;
- // Begin sessionA and sessionB, call onInitialized in callbacks.
- this.getSynchronizer().repositoryA.createSession(this, context);
- }
-
- /**
- * Get the number of records fetched from the first repository (usually the
- * server, hence inbound).
- * <p>
- * Valid only after first flow has completed.
- *
- * @return number of records, or -1 if not valid.
- */
- public int getInboundCount() {
- return numInboundRecords.get();
- }
-
- /**
- * Get the number of records fetched from the second repository (usually the
- * local store, hence outbound).
- * <p>
- * Valid only after second flow has completed.
- *
- * @return number of records, or -1 if not valid.
- */
- public int getOutboundCount() {
- return numOutboundRecords.get();
- }
-
- // These are accessed by `abort` and `synchronize`, both of which are synchronized.
- // Guarded by `this`.
- protected RecordsChannel channelAToB;
- protected RecordsChannel channelBToA;
-
- /**
- * Please don't call this until you've been notified with onInitialized.
- */
- public synchronized void synchronize() {
- numInboundRecords.set(-1);
- numOutboundRecords.set(-1);
-
- // First thing: decide whether we should.
- if (sessionA.shouldSkip() ||
- sessionB.shouldSkip()) {
- Logger.info(LOG_TAG, "Session requested skip. Short-circuiting sync.");
- sessionA.abort();
- sessionB.abort();
- this.delegate.onSynchronizeSkipped(this);
- return;
- }
-
- final SynchronizerSession session = this;
-
- // TODO: failed record handling.
-
- // This is the *second* record channel to flow.
- // I, SynchronizerSession, am the delegate for the *second* flow.
- channelBToA = new RecordsChannel(this.sessionB, this.sessionA, this);
-
- // This is the delegate for the *first* flow.
- RecordsChannelDelegate channelAToBDelegate = new RecordsChannelDelegate() {
- @Override
- public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) {
- session.onFirstFlowCompleted(recordsChannel, fetchEnd, storeEnd);
- }
-
- @Override
- public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex) {
- Logger.warn(LOG_TAG, "First RecordsChannel onFlowBeginFailed. Logging session error.", ex);
- session.delegate.onSynchronizeFailed(session, ex, "Failed to begin first flow.");
- }
-
- @Override
- public void onFlowFetchFailed(RecordsChannel recordsChannel, Exception ex) {
- Logger.warn(LOG_TAG, "First RecordsChannel onFlowFetchFailed. Logging remote fetch error.", ex);
- }
-
- @Override
- public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex, String recordGuid) {
- Logger.warn(LOG_TAG, "First RecordsChannel onFlowStoreFailed. Logging local store error.", ex);
- }
-
- @Override
- public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex) {
- Logger.warn(LOG_TAG, "First RecordsChannel onFlowFinishedFailed. Logging session error.", ex);
- session.delegate.onSynchronizeFailed(session, ex, "Failed to finish first flow.");
- }
- };
-
- // This is the *first* channel to flow.
- channelAToB = new RecordsChannel(this.sessionA, this.sessionB, channelAToBDelegate);
-
- Logger.trace(LOG_TAG, "Starting A to B flow. Channel is " + channelAToB);
- try {
- channelAToB.beginAndFlow();
- } catch (InvalidSessionTransitionException e) {
- onFlowBeginFailed(channelAToB, e);
- }
- }
-
- /**
- * Called after the first flow completes.
- * <p>
- * By default, any fetch and store failures are ignored.
- * @param recordsChannel the <code>RecordsChannel</code> (for error testing).
- * @param fetchEnd timestamp when fetches completed.
- * @param storeEnd timestamp when stores completed.
- */
- public void onFirstFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) {
- Logger.trace(LOG_TAG, "First RecordsChannel onFlowCompleted.");
- Logger.debug(LOG_TAG, "Fetch end is " + fetchEnd + ". Store end is " + storeEnd + ". Starting next.");
- pendingATimestamp = fetchEnd;
- storeEndBTimestamp = storeEnd;
- numInboundRecords.set(recordsChannel.getFetchCount());
- flowAToBCompleted = true;
- channelBToA.flow();
- }
-
- /**
- * Called after the second flow completes.
- * <p>
- * By default, any fetch and store failures are ignored.
- * @param recordsChannel the <code>RecordsChannel</code> (for error testing).
- * @param fetchEnd timestamp when fetches completed.
- * @param storeEnd timestamp when stores completed.
- */
- public void onSecondFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) {
- Logger.trace(LOG_TAG, "Second RecordsChannel onFlowCompleted.");
- Logger.debug(LOG_TAG, "Fetch end is " + fetchEnd + ". Store end is " + storeEnd + ". Finishing.");
-
- pendingBTimestamp = fetchEnd;
- storeEndATimestamp = storeEnd;
- numOutboundRecords.set(recordsChannel.getFetchCount());
- flowBToACompleted = true;
-
- // Finish the two sessions.
- try {
- this.sessionA.finish(this);
- } catch (InactiveSessionException e) {
- this.onFinishFailed(e);
- return;
- }
- }
-
- @Override
- public void onFlowCompleted(RecordsChannel recordsChannel, long fetchEnd, long storeEnd) {
- onSecondFlowCompleted(recordsChannel, fetchEnd, storeEnd);
- }
-
- @Override
- public void onFlowBeginFailed(RecordsChannel recordsChannel, Exception ex) {
- Logger.warn(LOG_TAG, "Second RecordsChannel onFlowBeginFailed. Logging session error.", ex);
- this.delegate.onSynchronizeFailed(this, ex, "Failed to begin second flow.");
- }
-
- @Override
- public void onFlowFetchFailed(RecordsChannel recordsChannel, Exception ex) {
- Logger.warn(LOG_TAG, "Second RecordsChannel onFlowFetchFailed. Logging local fetch error.", ex);
- }
-
- @Override
- public void onFlowStoreFailed(RecordsChannel recordsChannel, Exception ex, String recordGuid) {
- Logger.warn(LOG_TAG, "Second RecordsChannel onFlowStoreFailed. Logging remote store error.", ex);
- }
-
- @Override
- public void onFlowFinishFailed(RecordsChannel recordsChannel, Exception ex) {
- Logger.warn(LOG_TAG, "Second RecordsChannel onFlowFinishedFailed. Logging session error.", ex);
- this.delegate.onSynchronizeFailed(this, ex, "Failed to finish second flow.");
- }
-
- /*
- * RepositorySessionCreationDelegate methods.
- */
-
- /**
- * I could be called twice: once for sessionA and once for sessionB.
- *
- * I try to clean up sessionA if it is not null, since the creation of
- * sessionB must have failed.
- */
- @Override
- public void onSessionCreateFailed(Exception ex) {
- // Attempt to finish the first session, if the second is the one that failed.
- if (this.sessionA != null) {
- try {
- // We no longer need a reference to our context.
- this.context = null;
- this.sessionA.finish(this);
- } catch (Exception e) {
- // Never mind; best-effort finish.
- }
- }
- // We no longer need a reference to our context.
- this.context = null;
- this.delegate.onSynchronizeFailed(this, ex, "Failed to create session");
- }
-
- /**
- * I should be called twice: first for sessionA and second for sessionB.
- *
- * If I am called for sessionB, I call my delegate's `onInitialized` callback
- * method because my repository sessions are correctly initialized.
- */
- // TODO: some of this "finish and clean up" code can be refactored out.
- @Override
- public void onSessionCreated(RepositorySession session) {
- if (session == null ||
- this.sessionA == session) {
- // TODO: clean up sessionA.
- this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(session), "Failed to create session.");
- return;
- }
- if (this.sessionA == null) {
- this.sessionA = session;
-
- // Unbundle.
- try {
- this.sessionA.unbundle(this.bundleA);
- } catch (Exception e) {
- this.delegate.onSynchronizeFailed(this, new UnbundleError(e, sessionA), "Failed to unbundle first session.");
- // TODO: abort
- return;
- }
- this.getSynchronizer().repositoryB.createSession(this, this.context);
- return;
- }
- if (this.sessionB == null) {
- this.sessionB = session;
- // We no longer need a reference to our context.
- this.context = null;
-
- // Unbundle. We unbundled sessionA when that session was created.
- try {
- this.sessionB.unbundle(this.bundleB);
- } catch (Exception e) {
- this.delegate.onSynchronizeFailed(this, new UnbundleError(e, sessionA), "Failed to unbundle second session.");
- return;
- }
-
- this.delegate.onInitialized(this);
- return;
- }
- // TODO: need a way to make sure we don't call any more delegate methods.
- this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(session), "Failed to create session.");
- }
-
- /*
- * RepositorySessionFinishDelegate methods.
- */
-
- /**
- * I could be called twice: once for sessionA and once for sessionB.
- *
- * If sessionB couldn't be created, I don't fail again.
- */
- @Override
- public void onFinishFailed(Exception ex) {
- if (this.sessionB == null) {
- // Ah, it was a problem cleaning up. Never mind.
- Logger.warn(LOG_TAG, "Got exception cleaning up first after second session creation failed.", ex);
- return;
- }
- String session = (this.sessionA == null) ? "B" : "A";
- this.delegate.onSynchronizeFailed(this, ex, "Finish of session " + session + " failed.");
- }
-
- /**
- * I should be called twice: first for sessionA and second for sessionB.
- *
- * If I am called for sessionA, I try to finish sessionB.
- *
- * If I am called for sessionB, I call my delegate's `onSynchronized` callback
- * method because my flows should have completed.
- */
- @Override
- public void onFinishSucceeded(RepositorySession session,
- RepositorySessionBundle bundle) {
- Logger.debug(LOG_TAG, "onFinishSucceeded. Flows? " + flowAToBCompleted + ", " + flowBToACompleted);
-
- if (session == sessionA) {
- if (flowAToBCompleted) {
- Logger.debug(LOG_TAG, "onFinishSucceeded: bumping session A's timestamp to " + pendingATimestamp + " or " + storeEndATimestamp);
- bundle.bumpTimestamp(Math.max(pendingATimestamp, storeEndATimestamp));
- this.synchronizer.bundleA = bundle;
- } else {
- // Should not happen!
- this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(sessionA), "Failed to finish first session.");
- return;
- }
- if (this.sessionB != null) {
- Logger.trace(LOG_TAG, "Finishing session B.");
- // On to the next.
- try {
- this.sessionB.finish(this);
- } catch (InactiveSessionException e) {
- this.onFinishFailed(e);
- return;
- }
- }
- } else if (session == sessionB) {
- if (flowBToACompleted) {
- Logger.debug(LOG_TAG, "onFinishSucceeded: bumping session B's timestamp to " + pendingBTimestamp + " or " + storeEndBTimestamp);
- bundle.bumpTimestamp(Math.max(pendingBTimestamp, storeEndBTimestamp));
- this.synchronizer.bundleB = bundle;
- Logger.trace(LOG_TAG, "Notifying delegate.onSynchronized.");
- this.delegate.onSynchronized(this);
- } else {
- // Should not happen!
- this.delegate.onSynchronizeFailed(this, new UnexpectedSessionException(sessionB), "Failed to finish second session.");
- return;
- }
- } else {
- // TODO: hurrrrrr...
- }
-
- if (this.sessionB == null) {
- this.sessionA = null; // We're done.
- }
- }
-
- @Override
- public RepositorySessionFinishDelegate deferredFinishDelegate(final ExecutorService executor) {
- return new DeferredRepositorySessionFinishDelegate(this, executor);
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSessionDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSessionDelegate.java
deleted file mode 100644
index 1d55274e8..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/SynchronizerSessionDelegate.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-public interface SynchronizerSessionDelegate {
- public void onInitialized(SynchronizerSession session);
-
- public void onSynchronized(SynchronizerSession session);
- public void onSynchronizeFailed(SynchronizerSession session, Exception lastException, String reason);
- public void onSynchronizeSkipped(SynchronizerSession synchronizerSession);
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnbundleError.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnbundleError.java
deleted file mode 100644
index fea779636..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnbundleError.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.sync.SyncException;
-import org.mozilla.gecko.sync.repositories.RepositorySession;
-
-public class UnbundleError extends SyncException {
- private static final long serialVersionUID = -8709503281041697522L;
-
- public RepositorySession failedSession;
-
- public UnbundleError(Exception e, RepositorySession session) {
- super(e);
- this.failedSession = session;
- }
-}
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnexpectedSessionException.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnexpectedSessionException.java
deleted file mode 100644
index 0237b884b..000000000
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/synchronizer/UnexpectedSessionException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.gecko.sync.synchronizer;
-
-import org.mozilla.gecko.sync.SyncException;
-import org.mozilla.gecko.sync.repositories.RepositorySession;
-
-/**
- * An exception class that indicates that a session was passed
- * to a begin callback and wasn't expected.
- *
- * This shouldn't occur.
- *
- * @author rnewman
- *
- */
-public class UnexpectedSessionException extends SyncException {
- private static final long serialVersionUID = 949010933527484721L;
- public RepositorySession session;
-
- public UnexpectedSessionException(RepositorySession session) {
- this.session = session;
- }
-}