mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 732768 - Eliminate shared state and concurrency problems in tests. r=nalexander
This commit is contained in:
parent
4b3ef26701
commit
bb48da370c
@ -1,39 +1,6 @@
|
|||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Android Sync Client.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* the Mozilla Foundation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Richard Newman <rnewman@mozilla.com>
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
package org.mozilla.gecko.sync.middleware;
|
package org.mozilla.gecko.sync.middleware;
|
||||||
|
|
||||||
@ -43,16 +10,12 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import org.mozilla.gecko.sync.CryptoRecord;
|
import org.mozilla.gecko.sync.CryptoRecord;
|
||||||
import org.mozilla.gecko.sync.crypto.CryptoException;
|
import org.mozilla.gecko.sync.crypto.CryptoException;
|
||||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||||
|
import org.mozilla.gecko.sync.repositories.InactiveSessionException;
|
||||||
import org.mozilla.gecko.sync.repositories.NoStoreDelegateException;
|
import org.mozilla.gecko.sync.repositories.NoStoreDelegateException;
|
||||||
import org.mozilla.gecko.sync.repositories.RecordFactory;
|
import org.mozilla.gecko.sync.repositories.RecordFactory;
|
||||||
import org.mozilla.gecko.sync.repositories.RepositorySession;
|
import org.mozilla.gecko.sync.repositories.RepositorySession;
|
||||||
import org.mozilla.gecko.sync.repositories.RepositorySessionBundle;
|
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionBeginDelegate;
|
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate;
|
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate;
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate;
|
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionGuidsSinceDelegate;
|
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate;
|
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionStoreDelegate;
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelegate;
|
|
||||||
import org.mozilla.gecko.sync.repositories.domain.Record;
|
import org.mozilla.gecko.sync.repositories.domain.Record;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -94,14 +57,12 @@ import org.mozilla.gecko.sync.repositories.domain.Record;
|
|||||||
* @author rnewman
|
* @author rnewman
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Crypto5MiddlewareRepositorySession extends RepositorySession {
|
public class Crypto5MiddlewareRepositorySession extends MiddlewareRepositorySession {
|
||||||
private KeyBundle keyBundle;
|
private KeyBundle keyBundle;
|
||||||
private RepositorySession inner;
|
|
||||||
private RecordFactory recordFactory;
|
private RecordFactory recordFactory;
|
||||||
|
|
||||||
public Crypto5MiddlewareRepositorySession(RepositorySession session, Crypto5MiddlewareRepository repository, RecordFactory recordFactory) {
|
public Crypto5MiddlewareRepositorySession(RepositorySession session, Crypto5MiddlewareRepository repository, RecordFactory recordFactory) {
|
||||||
super(repository);
|
super(session, repository);
|
||||||
this.inner = session;
|
|
||||||
this.keyBundle = repository.keyBundle;
|
this.keyBundle = repository.keyBundle;
|
||||||
this.recordFactory = recordFactory;
|
this.recordFactory = recordFactory;
|
||||||
}
|
}
|
||||||
@ -180,13 +141,6 @@ public class Crypto5MiddlewareRepositorySession extends RepositorySession {
|
|||||||
return new DecryptingTransformingFetchDelegate(inner, this.keyBundle, this.recordFactory);
|
return new DecryptingTransformingFetchDelegate(inner, this.keyBundle, this.recordFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void guidsSince(long timestamp,
|
|
||||||
RepositorySessionGuidsSinceDelegate delegate) {
|
|
||||||
// TODO: need to do anything here?
|
|
||||||
inner.guidsSince(timestamp, delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fetchSince(long timestamp,
|
public void fetchSince(long timestamp,
|
||||||
RepositorySessionFetchRecordsDelegate delegate) {
|
RepositorySessionFetchRecordsDelegate delegate) {
|
||||||
@ -195,7 +149,7 @@ public class Crypto5MiddlewareRepositorySession extends RepositorySession {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fetch(String[] guids,
|
public void fetch(String[] guids,
|
||||||
RepositorySessionFetchRecordsDelegate delegate) {
|
RepositorySessionFetchRecordsDelegate delegate) throws InactiveSessionException {
|
||||||
inner.fetch(guids, makeUnwrappingDelegate(delegate));
|
inner.fetch(guids, makeUnwrappingDelegate(delegate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,92 +184,4 @@ public class Crypto5MiddlewareRepositorySession extends RepositorySession {
|
|||||||
// Allow the inner session to do delegate handling.
|
// Allow the inner session to do delegate handling.
|
||||||
inner.store(rec);
|
inner.store(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void wipe(RepositorySessionWipeDelegate delegate) {
|
|
||||||
inner.wipe(delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void storeDone() {
|
|
||||||
inner.storeDone();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void storeDone(long storeEnd) {
|
|
||||||
inner.storeDone(storeEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Crypto5MiddlewareRepositorySessionBeginDelegate implements RepositorySessionBeginDelegate {
|
|
||||||
private Crypto5MiddlewareRepositorySession outerSession;
|
|
||||||
private RepositorySessionBeginDelegate next;
|
|
||||||
|
|
||||||
public Crypto5MiddlewareRepositorySessionBeginDelegate(Crypto5MiddlewareRepositorySession outerSession, RepositorySessionBeginDelegate next) {
|
|
||||||
this.outerSession = outerSession;
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBeginFailed(Exception ex) {
|
|
||||||
next.onBeginFailed(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBeginSucceeded(RepositorySession session) {
|
|
||||||
outerSession.setStatus(SessionStatus.ACTIVE);
|
|
||||||
next.onBeginSucceeded(outerSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RepositorySessionBeginDelegate deferredBeginDelegate(ExecutorService executor) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void begin(RepositorySessionBeginDelegate delegate) {
|
|
||||||
inner.begin(new Crypto5MiddlewareRepositorySessionBeginDelegate(this, delegate));
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Crypto5MiddlewareRepositorySessionFinishDelegate implements RepositorySessionFinishDelegate {
|
|
||||||
private Crypto5MiddlewareRepositorySession outerSession;
|
|
||||||
private RepositorySessionFinishDelegate next;
|
|
||||||
|
|
||||||
public Crypto5MiddlewareRepositorySessionFinishDelegate(Crypto5MiddlewareRepositorySession outerSession, RepositorySessionFinishDelegate next) {
|
|
||||||
this.outerSession = outerSession;
|
|
||||||
this.next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinishFailed(Exception ex) {
|
|
||||||
next.onFinishFailed(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinishSucceeded(RepositorySession session, RepositorySessionBundle bundle) {
|
|
||||||
outerSession.setStatus(SessionStatus.DONE);
|
|
||||||
next.onFinishSucceeded(outerSession, bundle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RepositorySessionFinishDelegate deferredFinishDelegate(ExecutorService executor) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finish(RepositorySessionFinishDelegate delegate) {
|
|
||||||
inner.finish(new Crypto5MiddlewareRepositorySessionFinishDelegate(this, delegate));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort() {
|
|
||||||
setStatus(SessionStatus.ABORTED);
|
|
||||||
inner.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void abort(RepositorySessionFinishDelegate delegate) {
|
|
||||||
this.status = SessionStatus.DONE; // TODO: ABORTED?
|
|
||||||
inner.abort(new Crypto5MiddlewareRepositorySessionFinishDelegate(this, delegate));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,5 @@ public abstract class MiddlewareRepository extends Repository {
|
|||||||
public RepositorySessionCreationDelegate deferredCreationDelegate() {
|
public RepositorySessionCreationDelegate deferredCreationDelegate() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,164 @@
|
|||||||
|
/* 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.middleware;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.sync.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.RepositorySessionBeginDelegate;
|
||||||
|
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate;
|
||||||
|
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionGuidsSinceDelegate;
|
||||||
|
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelegate;
|
||||||
|
|
||||||
|
public abstract class MiddlewareRepositorySession extends RepositorySession {
|
||||||
|
private static final String LOG_TAG = "MiddlewareSession";
|
||||||
|
protected final RepositorySession inner;
|
||||||
|
|
||||||
|
public MiddlewareRepositorySession(RepositorySession innerSession, MiddlewareRepository repository) {
|
||||||
|
super(repository);
|
||||||
|
this.inner = innerSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wipe(RepositorySessionWipeDelegate delegate) {
|
||||||
|
inner.wipe(delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MiddlewareRepositorySessionBeginDelegate implements RepositorySessionBeginDelegate {
|
||||||
|
|
||||||
|
private MiddlewareRepositorySession outerSession;
|
||||||
|
private RepositorySessionBeginDelegate next;
|
||||||
|
|
||||||
|
public MiddlewareRepositorySessionBeginDelegate(MiddlewareRepositorySession outerSession, RepositorySessionBeginDelegate next) {
|
||||||
|
this.outerSession = outerSession;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBeginFailed(Exception ex) {
|
||||||
|
next.onBeginFailed(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBeginSucceeded(RepositorySession session) {
|
||||||
|
next.onBeginSucceeded(outerSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RepositorySessionBeginDelegate deferredBeginDelegate(ExecutorService executor) {
|
||||||
|
final RepositorySessionBeginDelegate deferred = next.deferredBeginDelegate(executor);
|
||||||
|
return new RepositorySessionBeginDelegate() {
|
||||||
|
@Override
|
||||||
|
public void onBeginSucceeded(RepositorySession session) {
|
||||||
|
if (inner != session) {
|
||||||
|
Logger.warn(LOG_TAG, "Got onBeginSucceeded for session " + session + ", not our inner session!");
|
||||||
|
}
|
||||||
|
deferred.onBeginSucceeded(outerSession);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBeginFailed(Exception ex) {
|
||||||
|
deferred.onBeginFailed(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RepositorySessionBeginDelegate deferredBeginDelegate(ExecutorService executor) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
|
||||||
|
inner.begin(new MiddlewareRepositorySessionBeginDelegate(this, delegate));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MiddlewareRepositorySessionFinishDelegate implements RepositorySessionFinishDelegate {
|
||||||
|
private final MiddlewareRepositorySession outerSession;
|
||||||
|
private final RepositorySessionFinishDelegate next;
|
||||||
|
|
||||||
|
public MiddlewareRepositorySessionFinishDelegate(MiddlewareRepositorySession outerSession, RepositorySessionFinishDelegate next) {
|
||||||
|
this.outerSession = outerSession;
|
||||||
|
this.next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinishFailed(Exception ex) {
|
||||||
|
next.onFinishFailed(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinishSucceeded(RepositorySession session, RepositorySessionBundle bundle) {
|
||||||
|
next.onFinishSucceeded(outerSession, bundle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RepositorySessionFinishDelegate deferredFinishDelegate(ExecutorService executor) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finish(RepositorySessionFinishDelegate delegate) throws InactiveSessionException {
|
||||||
|
inner.finish(new MiddlewareRepositorySessionFinishDelegate(this, delegate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void ensureActive() throws InactiveSessionException {
|
||||||
|
inner.ensureActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized boolean isActive() {
|
||||||
|
return inner.isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized SessionStatus getStatus() {
|
||||||
|
return inner.getStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setStatus(SessionStatus status) {
|
||||||
|
inner.setStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void transitionFrom(SessionStatus from, SessionStatus to)
|
||||||
|
throws InvalidSessionTransitionException {
|
||||||
|
inner.transitionFrom(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void abort() {
|
||||||
|
inner.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void abort(RepositorySessionFinishDelegate delegate) {
|
||||||
|
inner.abort(new MiddlewareRepositorySessionFinishDelegate(this, delegate));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void guidsSince(long timestamp, RepositorySessionGuidsSinceDelegate delegate) {
|
||||||
|
// TODO: need to do anything here?
|
||||||
|
inner.guidsSince(timestamp, delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeDone() {
|
||||||
|
inner.storeDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeDone(long storeEnd) {
|
||||||
|
inner.storeDone(storeEnd);
|
||||||
|
}
|
||||||
|
}
|
@ -80,7 +80,7 @@ public abstract class RepositorySession {
|
|||||||
Logger.trace(LOG_TAG, message);
|
Logger.trace(LOG_TAG, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SessionStatus status = SessionStatus.UNSTARTED;
|
private SessionStatus status = SessionStatus.UNSTARTED;
|
||||||
protected Repository repository;
|
protected Repository repository;
|
||||||
protected RepositorySessionStoreDelegate delegate;
|
protected RepositorySessionStoreDelegate delegate;
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ public abstract class RepositorySession {
|
|||||||
|
|
||||||
public abstract void guidsSince(long timestamp, RepositorySessionGuidsSinceDelegate delegate);
|
public abstract void guidsSince(long timestamp, RepositorySessionGuidsSinceDelegate delegate);
|
||||||
public abstract void fetchSince(long timestamp, RepositorySessionFetchRecordsDelegate delegate);
|
public abstract void fetchSince(long timestamp, RepositorySessionFetchRecordsDelegate delegate);
|
||||||
public abstract void fetch(String[] guids, RepositorySessionFetchRecordsDelegate delegate);
|
public abstract void fetch(String[] guids, RepositorySessionFetchRecordsDelegate delegate) throws InactiveSessionException;
|
||||||
public abstract void fetchAll(RepositorySessionFetchRecordsDelegate delegate);
|
public abstract void fetchAll(RepositorySessionFetchRecordsDelegate delegate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,21 +182,19 @@ public abstract class RepositorySession {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected void sharedBegin() throws InvalidSessionTransitionException {
|
protected void sharedBegin() throws InvalidSessionTransitionException {
|
||||||
if (this.status == SessionStatus.UNSTARTED) {
|
Logger.debug(LOG_TAG, "Shared begin.");
|
||||||
this.status = SessionStatus.ACTIVE;
|
if (delegateQueue.isShutdown()) {
|
||||||
} else {
|
|
||||||
Logger.error(LOG_TAG, "Tried to begin() an already active or finished session");
|
|
||||||
throw new InvalidSessionTransitionException(null);
|
throw new InvalidSessionTransitionException(null);
|
||||||
}
|
}
|
||||||
|
if (storeWorkQueue.isShutdown()) {
|
||||||
|
throw new InvalidSessionTransitionException(null);
|
||||||
|
}
|
||||||
|
this.transitionFrom(SessionStatus.UNSTARTED, SessionStatus.ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void begin(RepositorySessionBeginDelegate delegate) {
|
public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
|
||||||
try {
|
|
||||||
sharedBegin();
|
sharedBegin();
|
||||||
delegate.deferredBeginDelegate(delegateQueue).onBeginSucceeded(this);
|
delegate.deferredBeginDelegate(delegateQueue).onBeginSucceeded(this);
|
||||||
} catch (Exception e) {
|
|
||||||
delegate.deferredBeginDelegate(delegateQueue).onBeginFailed(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RepositorySessionBundle getBundle() {
|
protected RepositorySessionBundle getBundle() {
|
||||||
@ -231,43 +229,85 @@ public abstract class RepositorySession {
|
|||||||
* @param delegate
|
* @param delegate
|
||||||
*/
|
*/
|
||||||
public void abort(RepositorySessionFinishDelegate delegate) {
|
public void abort(RepositorySessionFinishDelegate delegate) {
|
||||||
this.status = SessionStatus.DONE; // TODO: ABORTED?
|
this.abort();
|
||||||
delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null));
|
delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish(final RepositorySessionFinishDelegate delegate) {
|
|
||||||
if (this.status == SessionStatus.ACTIVE) {
|
|
||||||
this.status = SessionStatus.DONE;
|
|
||||||
delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null));
|
|
||||||
} else {
|
|
||||||
Logger.error(LOG_TAG, "Tried to finish() an unstarted or already finished session");
|
|
||||||
Exception e = new InvalidSessionTransitionException(null);
|
|
||||||
delegate.deferredFinishDelegate(delegateQueue).onFinishFailed(e);
|
|
||||||
}
|
|
||||||
Logger.info(LOG_TAG, "Shutting down work queues.");
|
|
||||||
// storeWorkQueue.shutdown();
|
|
||||||
// delegateQueue.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isActive() {
|
|
||||||
return status == SessionStatus.ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SessionStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(SessionStatus status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void abort() {
|
public void abort() {
|
||||||
// TODO: do something here.
|
// TODO: do something here.
|
||||||
status = SessionStatus.ABORTED;
|
this.setStatus(SessionStatus.ABORTED);
|
||||||
|
try {
|
||||||
|
storeWorkQueue.shutdown();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error(LOG_TAG, "Caught exception shutting down store work queue.", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
delegateQueue.shutdown();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Logger.error(LOG_TAG, "Caught exception shutting down delegate queue.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finish(final RepositorySessionFinishDelegate delegate) throws InactiveSessionException {
|
||||||
|
try {
|
||||||
|
this.transitionFrom(SessionStatus.ACTIVE, SessionStatus.DONE);
|
||||||
|
delegate.deferredFinishDelegate(delegateQueue).onFinishSucceeded(this, this.getBundle(null));
|
||||||
|
} catch (InvalidSessionTransitionException e) {
|
||||||
|
Logger.error(LOG_TAG, "Tried to finish() an unstarted or already finished session");
|
||||||
|
InactiveSessionException ex = new InactiveSessionException(null);
|
||||||
|
ex.initCause(e);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.info(LOG_TAG, "Shutting down work queues.");
|
||||||
storeWorkQueue.shutdown();
|
storeWorkQueue.shutdown();
|
||||||
delegateQueue.shutdown();
|
delegateQueue.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the provided command if we're active and our delegate queue
|
||||||
|
* is not shut down.
|
||||||
|
*
|
||||||
|
* @param command
|
||||||
|
* @throws InactiveSessionException
|
||||||
|
*/
|
||||||
|
protected synchronized void executeDelegateCommand(Runnable command)
|
||||||
|
throws InactiveSessionException {
|
||||||
|
if (!isActive() || delegateQueue.isShutdown()) {
|
||||||
|
throw new InactiveSessionException(null);
|
||||||
|
}
|
||||||
|
delegateQueue.execute(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void ensureActive() throws InactiveSessionException {
|
||||||
|
if (!isActive()) {
|
||||||
|
throw new InactiveSessionException(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isActive() {
|
||||||
|
return status == SessionStatus.ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized SessionStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setStatus(SessionStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void transitionFrom(SessionStatus from, SessionStatus to) throws InvalidSessionTransitionException {
|
||||||
|
if (from == null || this.status == from) {
|
||||||
|
Logger.trace(LOG_TAG, "Successfully transitioning from " + this.status + " to " + to);
|
||||||
|
|
||||||
|
this.status = to;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Logger.warn(LOG_TAG, "Wanted to transition from " + from + " but in state " + this.status);
|
||||||
|
throw new InvalidSessionTransitionException(null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a record that is some combination of the remote and local records
|
* Produce a record that is some combination of the remote and local records
|
||||||
* provided.
|
* provided.
|
||||||
|
@ -24,7 +24,7 @@ public abstract class StoreTrackingRepositorySession extends RepositorySession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(RepositorySessionBeginDelegate delegate) {
|
public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
|
||||||
RepositorySessionBeginDelegate deferredDelegate = delegate.deferredBeginDelegate(delegateQueue);
|
RepositorySessionBeginDelegate deferredDelegate = delegate.deferredBeginDelegate(delegateQueue);
|
||||||
try {
|
try {
|
||||||
super.sharedBegin();
|
super.sharedBegin();
|
||||||
@ -74,7 +74,7 @@ public abstract class StoreTrackingRepositorySession extends RepositorySession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finish(RepositorySessionFinishDelegate delegate) {
|
public void finish(RepositorySessionFinishDelegate delegate) throws InactiveSessionException {
|
||||||
super.finish(delegate);
|
super.finish(delegate);
|
||||||
this.storeTracker = null;
|
this.storeTracker = null;
|
||||||
}
|
}
|
||||||
|
@ -1,40 +1,6 @@
|
|||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* 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/. */
|
||||||
* The contents of this file are subject to the Mozilla Public License Version
|
|
||||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
||||||
* the License. You may obtain a copy of the License at
|
|
||||||
* http://www.mozilla.org/MPL/
|
|
||||||
*
|
|
||||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
||||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
||||||
* for the specific language governing rights and limitations under the
|
|
||||||
* License.
|
|
||||||
*
|
|
||||||
* The Original Code is Android Sync Client.
|
|
||||||
*
|
|
||||||
* The Initial Developer of the Original Code is
|
|
||||||
* the Mozilla Foundation.
|
|
||||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
|
||||||
* the Initial Developer. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
* Jason Voll <jvoll@mozilla.com>
|
|
||||||
* Richard Newman <rnewman@mozilla.com>
|
|
||||||
*
|
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
||||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
||||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
||||||
* of those above. If you wish to allow use of your version of this file only
|
|
||||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
||||||
* use your version of this file under the terms of the MPL, indicate your
|
|
||||||
* decision by deleting the provisions above and replace them with the notice
|
|
||||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
||||||
* the provisions above, a recipient may use your version of this file under
|
|
||||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
||||||
*
|
|
||||||
* ***** END LICENSE BLOCK ***** */
|
|
||||||
|
|
||||||
package org.mozilla.gecko.sync.repositories.android;
|
package org.mozilla.gecko.sync.repositories.android;
|
||||||
|
|
||||||
@ -48,7 +14,8 @@ public class AndroidBrowserBookmarksRepository extends AndroidBrowserRepository
|
|||||||
@Override
|
@Override
|
||||||
protected void sessionCreator(RepositorySessionCreationDelegate delegate, Context context) {
|
protected void sessionCreator(RepositorySessionCreationDelegate delegate, Context context) {
|
||||||
AndroidBrowserBookmarksRepositorySession session = new AndroidBrowserBookmarksRepositorySession(AndroidBrowserBookmarksRepository.this, context);
|
AndroidBrowserBookmarksRepositorySession session = new AndroidBrowserBookmarksRepositorySession(AndroidBrowserBookmarksRepository.this, context);
|
||||||
delegate.onSessionCreated(session);
|
final RepositorySessionCreationDelegate deferredCreationDelegate = delegate.deferredCreationDelegate();
|
||||||
|
deferredCreationDelegate.onSessionCreated(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -16,6 +16,8 @@ import org.mozilla.gecko.R;
|
|||||||
import org.mozilla.gecko.db.BrowserContract;
|
import org.mozilla.gecko.db.BrowserContract;
|
||||||
import org.mozilla.gecko.sync.Logger;
|
import org.mozilla.gecko.sync.Logger;
|
||||||
import org.mozilla.gecko.sync.Utils;
|
import org.mozilla.gecko.sync.Utils;
|
||||||
|
import org.mozilla.gecko.sync.repositories.InactiveSessionException;
|
||||||
|
import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException;
|
||||||
import org.mozilla.gecko.sync.repositories.NoGuidForIdException;
|
import org.mozilla.gecko.sync.repositories.NoGuidForIdException;
|
||||||
import org.mozilla.gecko.sync.repositories.NullCursorException;
|
import org.mozilla.gecko.sync.repositories.NullCursorException;
|
||||||
import org.mozilla.gecko.sync.repositories.ParentNotFoundException;
|
import org.mozilla.gecko.sync.repositories.ParentNotFoundException;
|
||||||
@ -478,7 +480,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(RepositorySessionBeginDelegate delegate) {
|
public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
|
||||||
// Check for the existence of special folders
|
// Check for the existence of special folders
|
||||||
// and insert them if they don't exist.
|
// and insert them if they don't exist.
|
||||||
Cursor cur;
|
Cursor cur;
|
||||||
@ -526,7 +528,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finish(RepositorySessionFinishDelegate delegate) {
|
public void finish(RepositorySessionFinishDelegate delegate) throws InactiveSessionException {
|
||||||
// Override finish to do this check; make sure all records
|
// Override finish to do this check; make sure all records
|
||||||
// needing re-parenting have been re-parented.
|
// needing re-parenting have been re-parented.
|
||||||
if (needsReparenting != 0) {
|
if (needsReparenting != 0) {
|
||||||
|
@ -141,14 +141,9 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void begin(RepositorySessionBeginDelegate delegate) {
|
public void begin(RepositorySessionBeginDelegate delegate) throws InvalidSessionTransitionException {
|
||||||
RepositorySessionBeginDelegate deferredDelegate = delegate.deferredBeginDelegate(delegateQueue);
|
RepositorySessionBeginDelegate deferredDelegate = delegate.deferredBeginDelegate(delegateQueue);
|
||||||
try {
|
|
||||||
super.sharedBegin();
|
super.sharedBegin();
|
||||||
} catch (InvalidSessionTransitionException e) {
|
|
||||||
deferredDelegate.onBeginFailed(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// We do this check here even though it results in one extra call to the DB
|
// We do this check here even though it results in one extra call to the DB
|
||||||
@ -241,9 +236,9 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fetch(String[] guids,
|
public void fetch(String[] guids,
|
||||||
RepositorySessionFetchRecordsDelegate delegate) {
|
RepositorySessionFetchRecordsDelegate delegate) throws InactiveSessionException {
|
||||||
FetchRunnable command = new FetchRunnable(guids, now(), null, delegate);
|
FetchRunnable command = new FetchRunnable(guids, now(), null, delegate);
|
||||||
delegateQueue.execute(command);
|
executeDelegateCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class FetchingRunnable implements Runnable {
|
abstract class FetchingRunnable implements Runnable {
|
||||||
@ -289,7 +284,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FetchRunnable extends FetchingRunnable {
|
public class FetchRunnable extends FetchingRunnable {
|
||||||
private String[] guids;
|
private String[] guids;
|
||||||
private long end;
|
private long end;
|
||||||
private RecordFilter filter;
|
private RecordFilter filter;
|
||||||
@ -392,6 +387,7 @@ public abstract class AndroidBrowserRepositorySession extends StoreTrackingRepos
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
|
Logger.warn(LOG_TAG, "AndroidBrowserRepositorySession is inactive. Store failing.");
|
||||||
delegate.onRecordStoreFailed(new InactiveSessionException(null));
|
delegate.onRecordStoreFailed(new InactiveSessionException(null));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import java.util.concurrent.ExecutorService;
|
|||||||
|
|
||||||
import org.mozilla.gecko.sync.Logger;
|
import org.mozilla.gecko.sync.Logger;
|
||||||
import org.mozilla.gecko.sync.ThreadPool;
|
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.NoStoreDelegateException;
|
||||||
import org.mozilla.gecko.sync.repositories.RepositorySession;
|
import org.mozilla.gecko.sync.repositories.RepositorySession;
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionBeginDelegate;
|
import org.mozilla.gecko.sync.repositories.delegates.DeferredRepositorySessionBeginDelegate;
|
||||||
@ -166,8 +167,9 @@ class RecordsChannel implements
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin both sessions, invoking flow() when done.
|
* Begin both sessions, invoking flow() when done.
|
||||||
|
* @throws InvalidSessionTransitionException
|
||||||
*/
|
*/
|
||||||
public void beginAndFlow() {
|
public void beginAndFlow() throws InvalidSessionTransitionException {
|
||||||
Logger.info(LOG_TAG, "Beginning source.");
|
Logger.info(LOG_TAG, "Beginning source.");
|
||||||
source.begin(this);
|
source.begin(this);
|
||||||
}
|
}
|
||||||
@ -251,7 +253,11 @@ class RecordsChannel implements
|
|||||||
public void onBeginSucceeded(RepositorySession session) {
|
public void onBeginSucceeded(RepositorySession session) {
|
||||||
if (session == source) {
|
if (session == source) {
|
||||||
Logger.info(LOG_TAG, "Source session began. Beginning sink session.");
|
Logger.info(LOG_TAG, "Source session began. Beginning sink session.");
|
||||||
|
try {
|
||||||
sink.begin(this);
|
sink.begin(this);
|
||||||
|
} catch (InvalidSessionTransitionException e) {
|
||||||
|
onBeginFailed(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (session == sink) {
|
if (session == sink) {
|
||||||
Logger.info(LOG_TAG, "Sink session began. Beginning flow.");
|
Logger.info(LOG_TAG, "Sink session began. Beginning flow.");
|
||||||
|
@ -40,6 +40,8 @@ package org.mozilla.gecko.sync.synchronizer;
|
|||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
|
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.RepositorySession;
|
||||||
import org.mozilla.gecko.sync.repositories.RepositorySessionBundle;
|
import org.mozilla.gecko.sync.repositories.RepositorySessionBundle;
|
||||||
import org.mozilla.gecko.sync.repositories.delegates.DeferrableRepositorySessionCreationDelegate;
|
import org.mozilla.gecko.sync.repositories.delegates.DeferrableRepositorySessionCreationDelegate;
|
||||||
@ -170,7 +172,11 @@ implements RecordsChannelDelegate,
|
|||||||
};
|
};
|
||||||
final RecordsChannel channelAToB = new RecordsChannel(this.sessionA, this.sessionB, channelDelegate);
|
final RecordsChannel channelAToB = new RecordsChannel(this.sessionA, this.sessionB, channelDelegate);
|
||||||
info("Starting A to B flow. Channel is " + channelAToB);
|
info("Starting A to B flow. Channel is " + channelAToB);
|
||||||
|
try {
|
||||||
channelAToB.beginAndFlow();
|
channelAToB.beginAndFlow();
|
||||||
|
} catch (InvalidSessionTransitionException e) {
|
||||||
|
onFlowBeginFailed(channelAToB, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -183,7 +189,11 @@ implements RecordsChannelDelegate,
|
|||||||
flowBToACompleted = true;
|
flowBToACompleted = true;
|
||||||
|
|
||||||
// Finish the two sessions.
|
// Finish the two sessions.
|
||||||
|
try {
|
||||||
this.sessionA.finish(this);
|
this.sessionA.finish(this);
|
||||||
|
} catch (InactiveSessionException e) {
|
||||||
|
this.onFinishFailed(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -297,7 +307,11 @@ implements RecordsChannelDelegate,
|
|||||||
if (this.sessionB != null) {
|
if (this.sessionB != null) {
|
||||||
info("Finishing session B.");
|
info("Finishing session B.");
|
||||||
// On to the next.
|
// On to the next.
|
||||||
|
try {
|
||||||
this.sessionB.finish(this);
|
this.sessionB.finish(this);
|
||||||
|
} catch (InactiveSessionException e) {
|
||||||
|
this.onFinishFailed(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (session == sessionB) {
|
} else if (session == sessionB) {
|
||||||
if (flowBToACompleted) {
|
if (flowBToACompleted) {
|
||||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user