Bug 742109 - Make Android Sync write to Android log with single tag "FxSync". r=rnewman,liuche

This commit is contained in:
Nick Alexander 2012-06-12 12:12:43 -07:00
parent a6c7f112d8
commit 6485671dfb
33 changed files with 665 additions and 320 deletions

File diff suppressed because one or more lines are too long

View File

@ -380,7 +380,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
return false;
}
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
Logger.trace(LOG_TAG, "Uploading updated meta/global record since there are engines requesting upload: " +
Utils.toCommaSeparatedString(enginesToUpdate.keySet()));
}
@ -648,7 +648,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
if (config.enabledEngineNames == null) {
Logger.warn(LOG_TAG, "meta/global reported no enabled engine names!");
} else {
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
Logger.trace(LOG_TAG, "Persisting enabled engine names '" +
Utils.toCommaSeparatedString(config.enabledEngineNames) + "' from meta/global.");
}

View File

@ -16,8 +16,6 @@ import org.mozilla.gecko.sync.net.SyncStorageRecordRequest;
import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate;
import org.mozilla.gecko.sync.net.SyncStorageResponse;
import android.util.Log;
public class InfoCollections implements SyncStorageRequestDelegate {
private static final String LOG_TAG = "InfoCollections";
protected String infoURL;
@ -108,7 +106,7 @@ public class InfoCollections implements SyncStorageRequestDelegate {
@SuppressWarnings("unchecked")
public void setFromRecord(ExtendedJSONObject record) throws IllegalStateException, IOException, ParseException, NonObjectJSONException {
Log.i(LOG_TAG, "info/collections is " + record.toJSONString());
Logger.info(LOG_TAG, "info/collections is " + record.toJSONString());
HashMap<String, Long> map = new HashMap<String, Long>();
Set<Entry<String, Object>> entrySet = record.object.entrySet();
@ -129,7 +127,7 @@ public class InfoCollections implements SyncStorageRequestDelegate {
map.put(key, Utils.decimalSecondsToMilliseconds((Integer) value));
continue;
}
Log.w(LOG_TAG, "Skipping info/collections entry for " + key);
Logger.warn(LOG_TAG, "Skipping info/collections entry for " + key);
}
this.timestamps = map;
}

View File

@ -4,157 +4,108 @@
package org.mozilla.gecko.sync;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import org.mozilla.gecko.sync.log.writers.AndroidLevelCachingLogWriter;
import org.mozilla.gecko.sync.log.writers.AndroidLogWriter;
import org.mozilla.gecko.sync.log.writers.LogWriter;
import org.mozilla.gecko.sync.log.writers.SingleTagLogWriter;
import android.util.Log;
/**
* Logging helper class. Serializes all log operations (by synchronizing),
* and caches log level settings.
*
* Ultimately this will also be a hook point for our own logging system.
*
* @author rnewman
*
* Logging helper class. Serializes all log operations (by synchronizing).
*/
public class Logger {
public static final String LOG_TAG = "Logger";
public static final String GLOBAL_LOG_TAG = "FxSync";
// For extra debugging.
public static boolean LOG_PERSONAL_INFORMATION = false;
// If true, log to System.out as well as using Android's Log.* calls.
public static boolean LOG_TO_STDOUT = false;
// I can't believe we have to implement this ourselves.
// These aren't synchronized (and neither are the setters) because
// the logging calls themselves are synchronized.
private static Map<String, Boolean> isErrorLoggable = new IdentityHashMap<String, Boolean>();
private static Map<String, Boolean> isWarnLoggable = new IdentityHashMap<String, Boolean>();
private static Map<String, Boolean> isInfoLoggable = new IdentityHashMap<String, Boolean>();
private static Map<String, Boolean> isDebugLoggable = new IdentityHashMap<String, Boolean>();
private static Map<String, Boolean> isVerboseLoggable = new IdentityHashMap<String, Boolean>();
/**
* Current set of writers logged to.
* <p>
* We want logging to be available while running tests, so we set initialize
* this set statically.
*/
protected final static Set<LogWriter> logWriters = new LinkedHashSet<LogWriter>(Logger.defaultLogWriters());
/**
* Empty the caches of log levels.
* Default set of log writers to log to.
*/
public static synchronized void refreshLogLevels() {
isErrorLoggable = new IdentityHashMap<String, Boolean>();
isWarnLoggable = new IdentityHashMap<String, Boolean>();
isInfoLoggable = new IdentityHashMap<String, Boolean>();
isDebugLoggable = new IdentityHashMap<String, Boolean>();
isVerboseLoggable = new IdentityHashMap<String, Boolean>();
protected final static Set<LogWriter> defaultLogWriters() {
final Set<LogWriter> defaultLogWriters = new LinkedHashSet<LogWriter>();
LogWriter log = new AndroidLogWriter();
LogWriter cache = new AndroidLevelCachingLogWriter(log);
LogWriter single = new SingleTagLogWriter(GLOBAL_LOG_TAG, cache);
defaultLogWriters.add(single);
return defaultLogWriters;
}
private static boolean shouldLogError(String logTag) {
Boolean out = isErrorLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.ERROR);
isErrorLoggable.put(logTag, out);
return out;
public static synchronized void startLoggingTo(LogWriter logWriter) {
logWriters.add(logWriter);
}
private static boolean shouldLogWarn(String logTag) {
Boolean out = isWarnLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
public static synchronized void stopLoggingTo(LogWriter logWriter) {
try {
logWriter.close();
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception closing and removing LogWriter " + logWriter + ".", e);
}
out = Log.isLoggable(logTag, Log.WARN);
isWarnLoggable.put(logTag, out);
return out;
logWriters.remove(logWriter);
}
private static boolean shouldLogInfo(String logTag) {
Boolean out = isInfoLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
public static synchronized void stopLoggingToAll() {
for (LogWriter logWriter : logWriters) {
try {
logWriter.close();
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception closing and removing LogWriter " + logWriter + ".", e);
}
}
out = Log.isLoggable(logTag, Log.INFO);
isInfoLoggable.put(logTag, out);
return out;
logWriters.clear();
}
private static boolean shouldLogDebug(String logTag) {
Boolean out = isDebugLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.DEBUG);
isDebugLoggable.put(logTag, out);
return out;
}
private static boolean shouldLogVerbose(String logTag) {
Boolean out = isVerboseLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.VERBOSE);
isVerboseLoggable.put(logTag, out);
return out;
/**
* Write to only the default log writers.
*/
public static synchronized void resetLogging() {
stopLoggingToAll();
logWriters.addAll(Logger.defaultLogWriters());
}
// Synchronized version for other classes to use.
public static synchronized boolean logVerbose(String logTag) {
return shouldLogVerbose(logTag);
}
private static void logToStdout(String... s) {
if (LOG_TO_STDOUT) {
for (String string : s) {
System.out.print(string);
public static synchronized boolean shouldLogVerbose(String logTag) {
for (LogWriter logWriter : logWriters) {
if (logWriter.shouldLogVerbose(logTag)) {
return true;
}
System.out.println("");
}
return false;
}
public static void error(String logTag, String message) {
Logger.error(logTag, message, null);
}
public static synchronized void error(String logTag, String message, Throwable error) {
logToStdout(logTag, " :: ERROR: ", message);
if (shouldLogError(logTag)) {
Log.e(logTag, message, error);
}
}
public static void warn(String logTag, String message) {
Logger.warn(logTag, message, null);
}
public static synchronized void warn(String logTag, String message, Throwable error) {
logToStdout(logTag, " :: WARN: ", message);
if (shouldLogWarn(logTag)) {
Log.w(logTag, message, error);
}
}
public static synchronized void info(String logTag, String message) {
logToStdout(logTag, " :: INFO: ", message);
if (shouldLogInfo(logTag)) {
Log.i(logTag, message);
}
public static void info(String logTag, String message) {
Logger.info(logTag, message, null);
}
public static void debug(String logTag, String message) {
Logger.debug(logTag, message, null);
}
public static synchronized void debug(String logTag, String message, Throwable error) {
logToStdout(logTag, " :: DEBUG: ", message);
if (shouldLogDebug(logTag)) {
Log.d(logTag, message, error);
}
}
public static synchronized void trace(String logTag, String message) {
logToStdout(logTag, " :: TRACE: ", message);
if (shouldLogVerbose(logTag)) {
Log.v(logTag, message);
}
public static void trace(String logTag, String message) {
Logger.trace(logTag, message, null);
}
public static void pii(String logTag, String message) {
@ -162,4 +113,69 @@ public class Logger {
Logger.debug(logTag, "$$PII$$: " + message);
}
}
public static synchronized void error(String logTag, String message, Throwable error) {
Iterator<LogWriter> it = logWriters.iterator();
while (it.hasNext()) {
LogWriter writer = it.next();
try {
writer.error(logTag, message, error);
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
it.remove();
}
}
}
public static synchronized void warn(String logTag, String message, Throwable error) {
Iterator<LogWriter> it = logWriters.iterator();
while (it.hasNext()) {
LogWriter writer = it.next();
try {
writer.warn(logTag, message, error);
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
it.remove();
}
}
}
public static synchronized void info(String logTag, String message, Throwable error) {
Iterator<LogWriter> it = logWriters.iterator();
while (it.hasNext()) {
LogWriter writer = it.next();
try {
writer.info(logTag, message, error);
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
it.remove();
}
}
}
public static synchronized void debug(String logTag, String message, Throwable error) {
Iterator<LogWriter> it = logWriters.iterator();
while (it.hasNext()) {
LogWriter writer = it.next();
try {
writer.debug(logTag, message, error);
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
it.remove();
}
}
}
public static synchronized void trace(String logTag, String message, Throwable error) {
Iterator<LogWriter> it = logWriters.iterator();
while (it.hasNext()) {
LogWriter writer = it.next();
try {
writer.trace(logTag, message, error);
} catch (Exception e) {
Log.e(LOG_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
it.remove();
}
}
}
}

View File

@ -8,20 +8,15 @@ import org.mozilla.gecko.R;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
/*
* Activity is just here for testing.
*/
public class StubActivity extends Activity {
private static final String LOG_TAG = "StubActivity";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(LOG_TAG, "In StubActivity onCreate.");
super.onCreate(savedInstanceState);
setContentView(R.layout.sync_stub);
Log.i(LOG_TAG, "Done with onCreate.");
}
}

View File

@ -7,18 +7,17 @@ package org.mozilla.gecko.sync.jpake;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.crypto.HKDF;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import android.util.Log;
import java.security.InvalidKeyException;
public class JPakeCrypto {
private static final String LOG_TAG = "JPakeCrypto";
@ -91,7 +90,7 @@ public class JPakeCrypto {
throws IncorrectZkpException, NoSuchAlgorithmException,
Gx3OrGx4IsZeroOrOneException, UnsupportedEncodingException {
Log.d(LOG_TAG, "round2 started.");
Logger.debug(LOG_TAG, "round2 started.");
// checkZkp does some additional checks, but we can throw a more informative exception here.
if (BigInteger.ZERO.compareTo(jp.gx3) == 0 || BigInteger.ONE.compareTo(jp.gx3) == 0 ||
@ -111,7 +110,7 @@ public class JPakeCrypto {
jp.thisZkpA = createZkp(y1, y2, a, jp.signerId, gen);
jp.thisA = a;
Log.d(LOG_TAG, "round2 finished.");
Logger.debug(LOG_TAG, "round2 finished.");
}
/**
@ -119,7 +118,7 @@ public class JPakeCrypto {
*/
public static KeyBundle finalRound(BigInteger secretValue, JPakeParty jp)
throws IncorrectZkpException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
Log.d(LOG_TAG, "Final round started.");
Logger.debug(LOG_TAG, "Final round started.");
BigInteger gb = jp.gx1.multiply(jp.gx2).mod(P).multiply(jp.gx3)
.mod(P);
checkZkp(gb, jp.otherA, jp.otherZkpA);
@ -133,7 +132,7 @@ public class JPakeCrypto {
byte[] hmac = new byte[32];
generateKeyAndHmac(k, enc, hmac);
Log.d(LOG_TAG, "Final round finished; returning key.");
Logger.debug(LOG_TAG, "Final round finished; returning key.");
return new KeyBundle(enc, hmac);
}
@ -147,7 +146,7 @@ public class JPakeCrypto {
hmacSha256.init(secret_key);
result = hmacSha256.doFinal(data);
} catch (GeneralSecurityException e) {
Log.d(LOG_TAG, e.toString());
Logger.debug(LOG_TAG, e.toString());
}
return result;
}
@ -168,7 +167,7 @@ public class JPakeCrypto {
// Calculate the ZKP b value = (r-x*h) % q.
BigInteger h = computeBHash(g, gr, gx, id);
Log.e(LOG_TAG, "myhash: " + h.toString(16));
Logger.error(LOG_TAG, "myhash: " + h.toString(16));
// ZKP value = b = r-x*h
BigInteger b = r.subtract(x.multiply(h)).mod(Q);
@ -187,31 +186,30 @@ public class JPakeCrypto {
// Check parameters of zkp, and compare to computed hash. These shouldn't
// fail.
if (gx.compareTo(BigInteger.ONE) < 1) { // g^x > 1.
Log.e(LOG_TAG, "g^x > 1 fails.");
Logger.error(LOG_TAG, "g^x > 1 fails.");
throw new IncorrectZkpException();
}
if (gx.compareTo(P.subtract(BigInteger.ONE)) > -1) { // g^x < p-1
Log.e(LOG_TAG, "g^x < p-1 fails.");
Logger.error(LOG_TAG, "g^x < p-1 fails.");
throw new IncorrectZkpException();
}
if (gx.modPow(Q, P).compareTo(BigInteger.ONE) != 0) {
Log.e(LOG_TAG, "g^x^q % p = 1 fails.");
Logger.error(LOG_TAG, "g^x^q % p = 1 fails.");
throw new IncorrectZkpException();
}
if (zkp.gr.compareTo(g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P)) != 0) {
// b = r-h*x ==> g^r = g^b*g^x^(h)
Log.i(LOG_TAG, "gb*g(xh) = "
+ g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P).toString(16));
Log.d(LOG_TAG, "gr = " + zkp.gr.toString(16));
Log.d(LOG_TAG, "b = " + zkp.b.toString(16));
Log.d(LOG_TAG, "g^b = " + g.modPow(zkp.b, P).toString(16));
Log.d(LOG_TAG, "g^(xh) = " + gx.modPow(h, P).toString(16));
Log.d(LOG_TAG, "gx = " + gx.toString(16));
Log.d(LOG_TAG, "h = " + h.toString(16));
Log.e(LOG_TAG, "zkp calculation incorrect.");
Logger.debug(LOG_TAG, "gb*g(xh) = " + g.modPow(zkp.b, P).multiply(gx.modPow(h, P)).mod(P).toString(16));
Logger.debug(LOG_TAG, "gr = " + zkp.gr.toString(16));
Logger.debug(LOG_TAG, "b = " + zkp.b.toString(16));
Logger.debug(LOG_TAG, "g^b = " + g.modPow(zkp.b, P).toString(16));
Logger.debug(LOG_TAG, "g^(xh) = " + gx.modPow(h, P).toString(16));
Logger.debug(LOG_TAG, "gx = " + gx.toString(16));
Logger.debug(LOG_TAG, "h = " + h.toString(16));
Logger.error(LOG_TAG, "zkp calculation incorrect.");
throw new IncorrectZkpException();
}
Log.d(LOG_TAG, "*** ZKP SUCCESS ***");
Logger.debug(LOG_TAG, "*** ZKP SUCCESS ***");
}
/*

View File

@ -11,12 +11,9 @@ import org.mozilla.gecko.sync.net.BaseResource;
import org.mozilla.gecko.sync.net.Resource;
import org.mozilla.gecko.sync.net.ResourceDelegate;
import android.util.Log;
import ch.boye.httpclientandroidlib.HttpEntity;
public class JPakeRequest implements Resource {
private static String LOG_TAG = "JPakeRequest";
private BaseResource resource;
public JPakeRequestDelegate delegate;
@ -27,7 +24,6 @@ public class JPakeRequest implements Resource {
public JPakeRequest(URI uri, ResourceDelegate delegate) {
this.resource = new BaseResource(uri);
this.resource.delegate = delegate;
Log.d(LOG_TAG, "new URI: " + uri);
}
@Override

View File

@ -0,0 +1,126 @@
/* 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.log.writers;
import java.util.IdentityHashMap;
import java.util.Map;
import android.util.Log;
/**
* Make a <code>LogWriter</code> only log when the Android log system says to.
*/
public class AndroidLevelCachingLogWriter extends LogWriter {
protected final LogWriter inner;
public AndroidLevelCachingLogWriter(LogWriter inner) {
this.inner = inner;
}
// I can't believe we have to implement this ourselves.
// These aren't synchronized (and neither are the setters) because
// the logging calls themselves are synchronized.
private Map<String, Boolean> isErrorLoggable = new IdentityHashMap<String, Boolean>();
private Map<String, Boolean> isWarnLoggable = new IdentityHashMap<String, Boolean>();
private Map<String, Boolean> isInfoLoggable = new IdentityHashMap<String, Boolean>();
private Map<String, Boolean> isDebugLoggable = new IdentityHashMap<String, Boolean>();
private Map<String, Boolean> isVerboseLoggable = new IdentityHashMap<String, Boolean>();
/**
* Empty the caches of log levels.
*/
public void refreshLogLevels() {
isErrorLoggable = new IdentityHashMap<String, Boolean>();
isWarnLoggable = new IdentityHashMap<String, Boolean>();
isInfoLoggable = new IdentityHashMap<String, Boolean>();
isDebugLoggable = new IdentityHashMap<String, Boolean>();
isVerboseLoggable = new IdentityHashMap<String, Boolean>();
}
private boolean shouldLogError(String logTag) {
Boolean out = isErrorLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.ERROR);
isErrorLoggable.put(logTag, out);
return out;
}
private boolean shouldLogWarn(String logTag) {
Boolean out = isWarnLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.WARN);
isWarnLoggable.put(logTag, out);
return out;
}
private boolean shouldLogInfo(String logTag) {
Boolean out = isInfoLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.INFO);
isInfoLoggable.put(logTag, out);
return out;
}
private boolean shouldLogDebug(String logTag) {
Boolean out = isDebugLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.DEBUG);
isDebugLoggable.put(logTag, out);
return out;
}
@Override
public boolean shouldLogVerbose(String logTag) {
Boolean out = isVerboseLoggable.get(logTag);
if (out != null) {
return out.booleanValue();
}
out = Log.isLoggable(logTag, Log.VERBOSE);
isVerboseLoggable.put(logTag, out);
return out;
}
public void error(String tag, String message, Throwable error) {
if (shouldLogError(tag)) {
inner.error(tag, message, error);
}
}
public void warn(String tag, String message, Throwable error) {
if (shouldLogWarn(tag)) {
inner.warn(tag, message, error);
}
}
public void info(String tag, String message, Throwable error) {
if (shouldLogInfo(tag)) {
inner.info(tag, message, error);
}
}
public void debug(String tag, String message, Throwable error) {
if (shouldLogDebug(tag)) {
inner.debug(tag, message, error);
}
}
public void trace(String tag, String message, Throwable error) {
if (shouldLogVerbose(tag)) {
inner.trace(tag, message, error);
}
}
public void close() {
inner.close();
}
}

View File

@ -0,0 +1,40 @@
/* 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.log.writers;
import android.util.Log;
/**
* Log to the Android log.
*/
public class AndroidLogWriter extends LogWriter {
@Override
public boolean shouldLogVerbose(String logTag) {
return true;
}
public void error(String tag, String message, Throwable error) {
Log.e(tag, message, error);
}
public void warn(String tag, String message, Throwable error) {
Log.w(tag, message, error);
}
public void info(String tag, String message, Throwable error) {
Log.i(tag, message, error);
}
public void debug(String tag, String message, Throwable error) {
Log.d(tag, message, error);
}
public void trace(String tag, String message, Throwable error) {
Log.v(tag, message, error);
}
public void close() {
}
}

View File

@ -0,0 +1,66 @@
/* 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.log.writers;
import android.util.Log;
/**
* A LogWriter that logs only if the message is as important as the specified
* level. For example, if the specified level is <code>Log.WARN</code>, only
* <code>warn</code> and <code>error</code> will log.
*/
public class LevelFilteringLogWriter extends LogWriter {
protected final LogWriter inner;
protected final int logLevel;
public LevelFilteringLogWriter(int logLevel, LogWriter inner) {
this.inner = inner;
this.logLevel = logLevel;
}
public void close() {
inner.close();
}
@Override
public void error(String tag, String message, Throwable error) {
if (logLevel <= Log.ERROR) {
inner.error(tag, message, error);
}
}
@Override
public void warn(String tag, String message, Throwable error) {
if (logLevel <= Log.WARN) {
inner.warn(tag, message, error);
}
}
@Override
public void info(String tag, String message, Throwable error) {
if (logLevel <= Log.INFO) {
inner.info(tag, message, error);
}
}
@Override
public void debug(String tag, String message, Throwable error) {
if (logLevel <= Log.DEBUG) {
inner.debug(tag, message, error);
}
}
@Override
public void trace(String tag, String message, Throwable error) {
if (logLevel <= Log.VERBOSE) {
inner.trace(tag, message, error);
}
}
@Override
public boolean shouldLogVerbose(String tag) {
return logLevel <= Log.VERBOSE;
}
}

View File

@ -0,0 +1,29 @@
/* 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.log.writers;
/**
* An abstract object that logs information in some way.
* <p>
* Intended to be composed with other log writers, for example a log
* writer could make all log entries have the same single log tag, or
* could ignore certain log levels, before delegating to an inner log
* writer.
*/
public abstract class LogWriter {
public abstract void error(String tag, String message, Throwable error);
public abstract void warn(String tag, String message, Throwable error);
public abstract void info(String tag, String message, Throwable error);
public abstract void debug(String tag, String message, Throwable error);
public abstract void trace(String tag, String message, Throwable error);
/**
* We expect <code>close</code> to be called only by static
* synchronized methods in class <code>Logger</code>.
*/
public abstract void close();
public abstract boolean shouldLogVerbose(String tag);
}

View File

@ -0,0 +1,76 @@
/* 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.log.writers;
import java.io.PrintWriter;
/**
* Log to a <code>PrintWriter</code>.
*/
public class PrintLogWriter extends LogWriter {
protected final PrintWriter pw;
protected boolean closed = false;
public static final String ERROR = " :: E :: ";
public static final String WARN = " :: W :: ";
public static final String INFO = " :: I :: ";
public static final String DEBUG = " :: D :: ";
public static final String VERBOSE = " :: V :: ";
public PrintLogWriter(PrintWriter pw) {
this.pw = pw;
}
protected void log(String tag, String message, Throwable error) {
if (closed) {
return;
}
pw.println(tag + message);
if (error != null) {
error.printStackTrace(pw);
}
}
@Override
public void error(String tag, String message, Throwable error) {
log(tag, ERROR + message, error);
}
@Override
public void warn(String tag, String message, Throwable error) {
log(tag, WARN + message, error);
}
@Override
public void info(String tag, String message, Throwable error) {
log(tag, INFO + message, error);
}
@Override
public void debug(String tag, String message, Throwable error) {
log(tag, DEBUG + message, error);
}
@Override
public void trace(String tag, String message, Throwable error) {
log(tag, VERBOSE + message, error);
}
@Override
public boolean shouldLogVerbose(String tag) {
return true;
}
public void close() {
if (closed) {
return;
}
if (pw != null) {
pw.close();
}
closed = true;
}
}

View File

@ -0,0 +1,53 @@
/* 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.log.writers;
/**
* Make a <code>LogWriter</code> only log with a single tag.
*/
public class SingleTagLogWriter extends LogWriter {
protected final String tag;
protected final LogWriter inner;
public SingleTagLogWriter(String tag, LogWriter inner) {
this.tag = tag;
this.inner = inner;
}
@Override
public void error(String tag, String message, Throwable error) {
inner.error(this.tag, tag + " :: " + message, error);
}
@Override
public void warn(String tag, String message, Throwable error) {
inner.warn(this.tag, tag + " :: " + message, error);
}
@Override
public void info(String tag, String message, Throwable error) {
inner.info(this.tag, tag + " :: " + message, error);
}
@Override
public void debug(String tag, String message, Throwable error) {
inner.debug(this.tag, tag + " :: " + message, error);
}
@Override
public void trace(String tag, String message, Throwable error) {
inner.trace(this.tag, tag + " :: " + message, error);
}
@Override
public boolean shouldLogVerbose(String tag) {
return inner.shouldLogVerbose(this.tag);
}
@Override
public void close() {
inner.close();
}
}

View File

@ -0,0 +1,51 @@
/* 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.log.writers;
import java.io.PrintWriter;
import java.io.StringWriter;
public class StringLogWriter extends LogWriter {
protected final StringWriter sw;
protected final PrintLogWriter inner;
public StringLogWriter() {
sw = new StringWriter();
inner = new PrintLogWriter(new PrintWriter(sw));
}
public String toString() {
return sw.toString();
}
@Override
public boolean shouldLogVerbose(String tag) {
return true;
}
public void error(String tag, String message, Throwable error) {
inner.error(tag, message, error);
}
public void warn(String tag, String message, Throwable error) {
inner.warn(tag, message, error);
}
public void info(String tag, String message, Throwable error) {
inner.info(tag, message, error);
}
public void debug(String tag, String message, Throwable error) {
inner.debug(tag, message, error);
}
public void trace(String tag, String message, Throwable error) {
inner.trace(tag, message, error);
}
public void close() {
inner.close();
}
}

View File

@ -1,71 +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.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
/**
* It's an entity without a body.
* @author rnewman
*
*/
public class CompletedEntity implements HttpEntity {
protected HttpEntity innerEntity;
public CompletedEntity(HttpEntity entity) {
innerEntity = entity;
}
@Override
public void consumeContent() throws IOException {
throw new IOException("Already processed.");
}
@Override
public InputStream getContent() throws IOException, IllegalStateException {
return null;
}
@Override
public Header getContentEncoding() {
return innerEntity.getContentEncoding();
}
@Override
public long getContentLength() {
return innerEntity.getContentLength();
}
@Override
public Header getContentType() {
return innerEntity.getContentType();
}
@Override
public boolean isChunked() {
return innerEntity.isChunked();
}
@Override
public boolean isRepeatable() {
return false;
}
@Override
public boolean isStreaming() {
return false;
}
@Override
public void writeTo(OutputStream arg0) throws IOException {
throw new IOException("Already processed.");
}
}

View File

@ -11,10 +11,10 @@ import java.util.Scanner;
import org.json.simple.parser.ParseException;
import org.mozilla.gecko.sync.ExtendedJSONObject;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.Utils;
import android.util.Log;
import ch.boye.httpclientandroidlib.Header;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
@ -120,7 +120,7 @@ public class SyncResponse {
Header header = this.response.getFirstHeader(h);
String value = header.getValue();
if (missingHeader(value)) {
Log.w(LOG_TAG, h + " header present but empty.");
Logger.warn(LOG_TAG, h + " header present but empty.");
return -1;
}
return Integer.parseInt(value, 10);
@ -139,7 +139,7 @@ public class SyncResponse {
Header header = this.response.getFirstHeader(HEADER_RETRY_AFTER);
String retryAfter = header.getValue();
if (missingHeader(retryAfter)) {
Log.w(LOG_TAG, "Retry-After header present but empty.");
Logger.warn(LOG_TAG, "Retry-After header present but empty.");
return -1;
}
@ -154,7 +154,7 @@ public class SyncResponse {
final long now = System.currentTimeMillis();
return (int)((then - now) / 1000); // Convert milliseconds to seconds.
} catch (DateParseException e) {
Log.w(LOG_TAG, "Retry-After header neither integer nor date: " + retryAfter);
Logger.warn(LOG_TAG, "Retry-After header neither integer nor date: " + retryAfter);
return -1;
}
}

View File

@ -10,7 +10,7 @@ import java.net.Socket;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import android.util.Log;
import org.mozilla.gecko.sync.Logger;
import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory;
import ch.boye.httpclientandroidlib.params.HttpParams;
@ -52,8 +52,8 @@ public class TLSSocketFactory extends SSLSocketFactory {
socket.setEnabledCipherSuites(cipherSuites);
} catch (IllegalArgumentException e) {
cipherSuites = socket.getSupportedCipherSuites();
Log.d(LOG_TAG, "Setting enabled cipher suites failed: " + e.getMessage());
Log.d(LOG_TAG, "Using " + cipherSuites.length + " supported suites.");
Logger.warn(LOG_TAG, "Setting enabled cipher suites failed: " + e.getMessage());
Logger.warn(LOG_TAG, "Using " + cipherSuites.length + " supported suites.");
socket.setEnabledCipherSuites(cipherSuites);
}
}
@ -65,4 +65,4 @@ public class TLSSocketFactory extends SSLSocketFactory {
setEnabledCipherSuites(socket);
return socket;
}
}
}

View File

@ -11,8 +11,6 @@ import org.mozilla.gecko.sync.ExtendedJSONObject;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.NonObjectJSONException;
import android.util.Log;
public class RepositorySessionBundle extends ExtendedJSONObject {
private static final String LOG_TAG = "RepositorySessionBundle";
@ -38,7 +36,7 @@ public class RepositorySessionBundle extends ExtendedJSONObject {
}
public void setTimestamp(long timestamp) {
Log.d(LOG_TAG, "Setting timestamp on RepositorySessionBundle to " + timestamp);
Logger.debug(LOG_TAG, "Setting timestamp on RepositorySessionBundle to " + timestamp);
this.put("timestamp", new Long(timestamp));
}

View File

@ -355,7 +355,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
}
}
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
// Don't JSON-encode unless we're logging.
Logger.trace(LOG_TAG, "Output child array: " + childArray.toJSONString());
}
@ -709,7 +709,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
if (parentName == null) {
return;
}
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
Logger.trace(LOG_TAG, "Replacing parent name \"" + r.parentName + "\" with \"" + parentName + "\".");
}
r.parentName = parentName;
@ -815,7 +815,7 @@ public class AndroidBrowserBookmarksRepositorySession extends AndroidBrowserRepo
JSONArray childArray = bmk.children;
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
Logger.trace(LOG_TAG, bmk.guid + " has children " + childArray.toJSONString());
}
parentToChildArray.put(bmk.guid, childArray);

View File

@ -23,7 +23,6 @@ import org.mozilla.gecko.sync.repositories.domain.Record;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;
public class AndroidBrowserHistoryRepositorySession extends AndroidBrowserRepositorySession {
public static final String LOG_TAG = "ABHistoryRepoSess";
@ -104,7 +103,7 @@ public class AndroidBrowserHistoryRepositorySession extends AndroidBrowserReposi
}
private Record addVisitsToRecord(Record record) throws NullCursorException {
Log.d(LOG_TAG, "Adding visits for GUID " + record.guid);
Logger.debug(LOG_TAG, "Adding visits for GUID " + record.guid);
HistoryRecord hist = (HistoryRecord) record;
JSONArray visitsArray = getDataExtender().visitsForGUID(hist.guid);
long missingRecords = hist.fennecVisitCount - visitsArray.size();

View File

@ -214,7 +214,7 @@ public class RepoUtils {
}
public static void logClient(ClientRecord rec) {
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
Logger.trace(LOG_TAG, "Returning client record " + rec.guid + " (" + rec.androidID + ")");
Logger.trace(LOG_TAG, "Client Name: " + rec.name);
Logger.trace(LOG_TAG, "Client Type: " + rec.type);

View File

@ -15,8 +15,6 @@ import org.mozilla.gecko.sync.NonArrayJSONException;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.repositories.android.RepoUtils;
import android.util.Log;
/**
* Covers the fields used by all bookmark objects.
* @author rnewman
@ -180,7 +178,7 @@ public class BookmarkRecord extends Record {
try {
this.children = payload.getArray("children");
} catch (NonArrayJSONException e) {
Log.e(LOG_TAG, "Got non-array children in bookmark record " + this.guid, e);
Logger.error(LOG_TAG, "Got non-array children in bookmark record " + this.guid, e);
// Let's see if we can recover later by using the parentid pointers.
this.children = new JSONArray();
}

View File

@ -146,7 +146,7 @@ public class HistoryRecord extends Record {
private boolean checkVisitsEquals(HistoryRecord other) {
Logger.debug(LOG_TAG, "Checking visits.");
if (Logger.logVerbose(LOG_TAG)) {
if (Logger.shouldLogVerbose(LOG_TAG)) {
// Don't JSON-encode unless we're logging.
Logger.trace(LOG_TAG, ">> Mine: " + ((this.visits == null) ? "null" : this.visits.toJSONString()));
Logger.trace(LOG_TAG, ">> Theirs: " + ((other.visits == null) ? "null" : other.visits.toJSONString()));

View File

@ -30,7 +30,6 @@ public class SyncAccounts {
public final static String DEFAULT_SERVER = "https://auth.services.mozilla.com/";
private static final String LOG_TAG = "SyncAccounts";
private static final String GLOBAL_LOG_TAG = "FxSync";
/**
* Returns true if a Sync account is set up.
@ -146,7 +145,7 @@ public class SyncAccounts {
try {
return createSyncAccount(syncAccount);
} catch (Exception e) {
Log.e(GLOBAL_LOG_TAG, "Unable to create account.", e);
Log.e(Logger.GLOBAL_LOG_TAG, "Unable to create account.", e);
return null;
}
}
@ -191,13 +190,13 @@ public class SyncAccounts {
// We use Log rather than Logger here to avoid possibly hiding these errors.
final String message = e.getMessage();
if (message != null && (message.indexOf("is different than the authenticator's uid") > 0)) {
Log.wtf(GLOBAL_LOG_TAG,
Log.wtf(Logger.GLOBAL_LOG_TAG,
"Unable to create account. " +
"If you have more than one version of " +
"Firefox/Beta/Aurora/Nightly/Fennec installed, that's why.",
e);
} else {
Log.e(GLOBAL_LOG_TAG, "Unable to create account.", e);
Log.e(Logger.GLOBAL_LOG_TAG, "Unable to create account.", e);
}
}

View File

@ -1,6 +1,6 @@
/* 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/. */
* 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.setup.auth;
@ -12,8 +12,6 @@ import org.mozilla.gecko.sync.ThreadPool;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.setup.activities.AccountActivity;
import android.util.Log;
public class AccountAuthenticator {
private final String LOG_TAG = "AccountAuthenticator";
@ -59,7 +57,7 @@ public class AccountAuthenticator {
}
Logger.debug(LOG_TAG, "username:" + username);
Log.d(LOG_TAG, "running first stage.");
Logger.debug(LOG_TAG, "running first stage.");
// Start first stage of authentication.
runNextStage();
}

View File

@ -1,6 +1,6 @@
/* 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/. */
* 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.setup.auth;
@ -17,7 +17,6 @@ import org.mozilla.gecko.sync.net.BaseResource;
import org.mozilla.gecko.sync.net.SyncResourceDelegate;
import org.mozilla.gecko.sync.setup.Constants;
import android.util.Log;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
@ -37,7 +36,7 @@ public class EnsureUserExistenceStage implements AuthenticatorStage {
@Override
public void handleSuccess() {
// User exists; now determine auth node.
Log.d(LOG_TAG, "handleSuccess()");
Logger.debug(LOG_TAG, "handleSuccess()");
aa.runNextStage();
}

View File

@ -13,13 +13,13 @@ import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import org.mozilla.gecko.sync.GlobalSession;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.NodeAuthenticationException;
import org.mozilla.gecko.sync.NullClusterURLException;
import org.mozilla.gecko.sync.ThreadPool;
import org.mozilla.gecko.sync.net.BaseResource;
import org.mozilla.gecko.sync.net.SyncResourceDelegate;
import android.util.Log;
import ch.boye.httpclientandroidlib.HttpEntity;
import ch.boye.httpclientandroidlib.HttpResponse;
import ch.boye.httpclientandroidlib.client.ClientProtocolException;
@ -69,7 +69,7 @@ public class EnsureClusterURLStage extends AbstractNonRepositorySyncStage {
*/
public static void fetchClusterURL(final String nodeWeaveURL,
final ClusterURLFetchDelegate delegate) throws URISyntaxException {
Log.d(LOG_TAG, "In fetchClusterURL: node/weave is " + nodeWeaveURL);
Logger.info(LOG_TAG, "In fetchClusterURL: node/weave is " + nodeWeaveURL);
BaseResource resource = new BaseResource(nodeWeaveURL);
resource.delegate = new SyncResourceDelegate(resource) {
@ -101,7 +101,7 @@ public class EnsureClusterURLStage extends AbstractNonRepositorySyncStage {
int status = response.getStatusLine().getStatusCode();
switch (status) {
case 200:
Log.i(LOG_TAG, "Got 200 for node/weave cluster URL request (user found; succeeding).");
Logger.info(LOG_TAG, "Got 200 for node/weave cluster URL request (user found; succeeding).");
HttpEntity entity = response.getEntity();
if (entity == null) {
delegate.handleThrottled();
@ -139,15 +139,15 @@ public class EnsureClusterURLStage extends AbstractNonRepositorySyncStage {
break;
case 400:
case 404:
Log.i(LOG_TAG, "Got " + status + " for node/weave cluster URL request (user not found; failing).");
Logger.info(LOG_TAG, "Got " + status + " for node/weave cluster URL request (user not found; failing).");
delegate.handleFailure(response);
break;
case 503:
Log.i(LOG_TAG, "Got 503 for node/weave cluster URL request (error fetching node; failing).");
Logger.info(LOG_TAG, "Got 503 for node/weave cluster URL request (error fetching node; failing).");
delegate.handleFailure(response);
break;
default:
Log.w(LOG_TAG, "Got " + status + " for node/weave cluster URL request (unexpected HTTP status; failing).");
Logger.warn(LOG_TAG, "Got " + status + " for node/weave cluster URL request (unexpected HTTP status; failing).");
delegate.handleFailure(response);
}
} finally {
@ -181,17 +181,17 @@ public class EnsureClusterURLStage extends AbstractNonRepositorySyncStage {
final boolean wantNodeAssignment = session.callback.wantNodeAssignment();
if (!wantNodeAssignment && oldClusterURL != null) {
Log.i(LOG_TAG, "Cluster URL is already set and not stale. Continuing with sync.");
Logger.info(LOG_TAG, "Cluster URL is already set and not stale. Continuing with sync.");
session.advance();
return;
}
Log.i(LOG_TAG, "Fetching cluster URL.");
Logger.info(LOG_TAG, "Fetching cluster URL.");
final ClusterURLFetchDelegate delegate = new ClusterURLFetchDelegate() {
@Override
public void handleSuccess(final URI url) {
Log.i(LOG_TAG, "Node assignment pointed us to " + url);
Logger.info(LOG_TAG, "Node assignment pointed us to " + url);
if (oldClusterURL != null && oldClusterURL.equals(url)) {
// Our cluster URL is marked as stale and the fresh cluster URL is the same -- this is the user's problem.
@ -219,16 +219,16 @@ public class EnsureClusterURLStage extends AbstractNonRepositorySyncStage {
@Override
public void handleFailure(HttpResponse response) {
int statusCode = response.getStatusLine().getStatusCode();
Log.w(LOG_TAG, "Got HTTP failure fetching node assignment: " + statusCode);
Logger.warn(LOG_TAG, "Got HTTP failure fetching node assignment: " + statusCode);
if (statusCode == 404) {
URI serverURL = session.config.serverURL;
if (serverURL != null) {
Log.i(LOG_TAG, "Using serverURL <" + serverURL.toASCIIString() + "> as clusterURL.");
Logger.info(LOG_TAG, "Using serverURL <" + serverURL.toASCIIString() + "> as clusterURL.");
session.config.setClusterURL(serverURL);
session.advance();
return;
}
Log.w(LOG_TAG, "No serverURL set to use as fallback cluster URL. Aborting sync.");
Logger.warn(LOG_TAG, "No serverURL set to use as fallback cluster URL. Aborting sync.");
// Fallthrough to abort.
} else {
session.interpretHTTPFailure(response);

View File

@ -11,11 +11,7 @@ import org.mozilla.gecko.sync.InfoCollections;
import org.mozilla.gecko.sync.delegates.InfoCollectionsDelegate;
import org.mozilla.gecko.sync.net.SyncStorageResponse;
import android.util.Log;
public class FetchInfoCollectionsStage extends AbstractNonRepositorySyncStage {
private static final String LOG_TAG = "FetchInfoCollStage";
public FetchInfoCollectionsStage(GlobalSession session) {
super(session);
}
@ -24,9 +20,6 @@ public class FetchInfoCollectionsStage extends AbstractNonRepositorySyncStage {
@Override
public void handleSuccess(InfoCollections global) {
Log.i(LOG_TAG, "Got timestamps: ");
// TODO: decide whether more work needs to be done?
session.advance();
}

View File

@ -249,7 +249,7 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
// Pick up log level changes. Do this here so that we don't do extra work
// if we're not going to be syncing.
Logger.refreshLogLevels();
Logger.resetLogging();
// TODO: don't clear the auth token unless we have a sync error.
Log.i(LOG_TAG, "Got onPerformSync. Extras bundle is " + extras);

View File

@ -7,8 +7,6 @@ package org.mozilla.gecko.sync.synchronizer;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.repositories.domain.Record;
import android.util.Log;
/**
* Consume records from a queue inside a RecordsChannel, as fast as we can.
* TODO: rewrite this in terms of an ExecutorService and a CompletionService.
@ -106,7 +104,7 @@ class ConcurrentRecordConsumer extends RecordConsumer {
delegate.store(record);
} catch (Exception e) {
// TODO: Bug 709371: track records that failed to apply.
Log.e(LOG_TAG, "Caught error in store.", e);
Logger.error(LOG_TAG, "Caught error in store.", e);
}
trace("Done with record.");
}

View File

@ -4,10 +4,9 @@
package org.mozilla.gecko.sync.synchronizer;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.repositories.domain.Record;
import android.util.Log;
/**
* Consume records from a queue inside a RecordsChannel, storing them serially.
* @author rnewman
@ -22,21 +21,6 @@ class SerialRecordConsumer extends RecordConsumer {
this.delegate = delegate;
}
private static void info(String message) {
System.out.println("INFO: " + message);
Log.i(LOG_TAG, message);
}
private static void warn(String message, Exception ex) {
System.out.println("WARN: " + message);
Log.w(LOG_TAG, message, ex);
}
private static void debug(String message) {
System.out.println("DEBUG: " + message);
Log.d(LOG_TAG, message);
}
private Object monitor = new Object();
@Override
public void doNotify() {
@ -47,7 +31,7 @@ class SerialRecordConsumer extends RecordConsumer {
@Override
public void queueFilled() {
debug("Queue filled.");
Logger.debug(LOG_TAG, "Queue filled.");
synchronized (monitor) {
this.stopEventually = true;
monitor.notify();
@ -56,7 +40,7 @@ class SerialRecordConsumer extends RecordConsumer {
@Override
public void halt() {
debug("Halting.");
Logger.debug(LOG_TAG, "Halting.");
synchronized (monitor) {
this.stopEventually = true;
this.stopImmediately = true;
@ -67,38 +51,38 @@ class SerialRecordConsumer extends RecordConsumer {
private Object storeSerializer = new Object();
@Override
public void stored() {
debug("Record stored. Notifying.");
Logger.debug(LOG_TAG, "Record stored. Notifying.");
synchronized (storeSerializer) {
debug("stored() took storeSerializer.");
Logger.debug(LOG_TAG, "stored() took storeSerializer.");
counter++;
storeSerializer.notify();
debug("stored() dropped storeSerializer.");
Logger.debug(LOG_TAG, "stored() dropped storeSerializer.");
}
}
private void storeSerially(Record record) {
debug("New record to store.");
Logger.debug(LOG_TAG, "New record to store.");
synchronized (storeSerializer) {
debug("storeSerially() took storeSerializer.");
debug("Storing...");
Logger.debug(LOG_TAG, "storeSerially() took storeSerializer.");
Logger.debug(LOG_TAG, "Storing...");
try {
this.delegate.store(record);
} catch (Exception e) {
warn("Got exception in store. Not waiting.", 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 {
debug("Waiting...");
Logger.debug(LOG_TAG, "Waiting...");
storeSerializer.wait();
} catch (InterruptedException e) {
// TODO
}
debug("storeSerially() dropped storeSerializer.");
Logger.debug(LOG_TAG, "storeSerially() dropped storeSerializer.");
}
}
private void consumerIsDone() {
long counterNow = this.counter;
info("Consumer is done. Processed " + counterNow + ((counterNow == 1) ? " record." : " records."));
Logger.info(LOG_TAG, "Consumer is done. Processed " + counterNow + ((counterNow == 1) ? " record." : " records."));
delegate.consumerIsDone(stopImmediately);
}
@ -106,42 +90,42 @@ class SerialRecordConsumer extends RecordConsumer {
public void run() {
while (true) {
synchronized (monitor) {
debug("run() took monitor.");
Logger.debug(LOG_TAG, "run() took monitor.");
if (stopImmediately) {
debug("Stopping immediately. Clearing queue.");
Logger.debug(LOG_TAG, "Stopping immediately. Clearing queue.");
delegate.getQueue().clear();
debug("Notifying consumer.");
Logger.debug(LOG_TAG, "Notifying consumer.");
consumerIsDone();
return;
}
debug("run() dropped monitor.");
Logger.debug(LOG_TAG, "run() dropped monitor.");
}
// The queue is concurrent-safe.
while (!delegate.getQueue().isEmpty()) {
debug("Grabbing record...");
Logger.debug(LOG_TAG, "Grabbing record...");
Record record = delegate.getQueue().remove();
// Block here, allowing us to process records
// serially.
debug("Invoking storeSerially...");
Logger.debug(LOG_TAG, "Invoking storeSerially...");
this.storeSerially(record);
debug("Done with record.");
Logger.debug(LOG_TAG, "Done with record.");
}
synchronized (monitor) {
debug("run() took monitor.");
Logger.debug(LOG_TAG, "run() took monitor.");
if (stopEventually) {
debug("Done with records and told to stop. Notifying consumer.");
Logger.debug(LOG_TAG, "Done with records and told to stop. Notifying consumer.");
consumerIsDone();
return;
}
try {
debug("Not told to stop but no records. Waiting.");
Logger.debug(LOG_TAG, "Not told to stop but no records. Waiting.");
monitor.wait(10000);
} catch (InterruptedException e) {
// TODO
}
debug("run() dropped monitor.");
Logger.debug(LOG_TAG, "run() dropped monitor.");
}
}
}
}
}

View File

@ -4,12 +4,12 @@
package org.mozilla.gecko.sync.synchronizer;
import org.mozilla.gecko.sync.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;
import android.util.Log;
/**
* I perform a sync.
@ -41,15 +41,15 @@ public class Synchronizer implements SynchronizerSessionDelegate {
@Override
public void onSynchronized(SynchronizerSession synchronizerSession) {
Log.d(LOG_TAG, "Got onSynchronized.");
Log.d(LOG_TAG, "Notifying SynchronizerDelegate.");
Logger.debug(LOG_TAG, "Got onSynchronized.");
Logger.debug(LOG_TAG, "Notifying SynchronizerDelegate.");
this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer());
}
@Override
public void onSynchronizeSkipped(SynchronizerSession synchronizerSession) {
Log.d(LOG_TAG, "Got onSynchronizeSkipped.");
Log.d(LOG_TAG, "Notifying SynchronizerDelegate as if on success.");
Logger.debug(LOG_TAG, "Got onSynchronizeSkipped.");
Logger.debug(LOG_TAG, "Notifying SynchronizerDelegate as if on success.");
this.synchronizerDelegate.onSynchronized(synchronizerSession.getSynchronizer());
}

View File

@ -52,6 +52,13 @@ sync/jpake/stage/PutRequestStage.java
sync/jpake/stage/VerifyPairingStage.java
sync/jpake/Zkp.java
sync/KeyBundleProvider.java
sync/log/writers/AndroidLevelCachingLogWriter.java
sync/log/writers/AndroidLogWriter.java
sync/log/writers/LevelFilteringLogWriter.java
sync/log/writers/LogWriter.java
sync/log/writers/PrintLogWriter.java
sync/log/writers/SingleTagLogWriter.java
sync/log/writers/StringLogWriter.java
sync/Logger.java
sync/MetaGlobal.java
sync/MetaGlobalException.java
@ -62,7 +69,6 @@ sync/middleware/Crypto5MiddlewareRepositorySession.java
sync/middleware/MiddlewareRepository.java
sync/middleware/MiddlewareRepositorySession.java
sync/net/BaseResource.java
sync/net/CompletedEntity.java
sync/net/ConnectionMonitorThread.java
sync/net/HandleProgressException.java
sync/net/HttpResponseObserver.java