Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Unified Diff: components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java

Issue 2844803002: [Cronet] Make metrics reporting happen after terminal callbacks. (Closed)
Patch Set: self Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
index eb2abaf83195efa16810c38ae43f3583407dbae8..ef6dca70ef1a0510efea34e80640912c645f6c0e 100644
--- a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
+++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
@@ -51,13 +51,11 @@ public final class CronetUrlRequest extends UrlRequestBase {
private long mUrlRequestAdapter;
@GuardedBy("mUrlRequestAdapterLock")
- private boolean mStarted = false;
+ private boolean mStarted;
@GuardedBy("mUrlRequestAdapterLock")
- private boolean mWaitingOnRedirect = false;
+ private boolean mWaitingOnRedirect;
@GuardedBy("mUrlRequestAdapterLock")
- private boolean mWaitingOnRead = false;
- @GuardedBy("mUrlRequestAdapterLock")
- private RequestFinishedInfo.Metrics mMetrics;
+ private boolean mWaitingOnRead;
/*
* Synchronize access to mUrlRequestAdapter, mStarted, mWaitingOnRedirect,
@@ -81,9 +79,6 @@ public final class CronetUrlRequest extends UrlRequestBase {
private String mInitialMethod;
private final HeadersList mRequestHeaders = new HeadersList();
private final Collection<Object> mRequestAnnotations;
- @RequestFinishedInfoImpl.FinishedReason
- private int mFinishedReason;
- private CronetException mException;
private final boolean mDisableCache;
private final boolean mDisableConnectionMigration;
@@ -91,12 +86,20 @@ public final class CronetUrlRequest extends UrlRequestBase {
private UrlResponseInfoImpl mResponseInfo;
+ // These three should only be updated once with mUrlRequestAdapterLock held.
+ // They are read on executor's thread after the last update.
mef 2017/04/28 21:16:54 Should they be @GuardedBy("mUrlRequestAdapterLock"
mgersh 2017/05/01 15:29:22 this could clarify which executor
xunjieli 2017/05/01 19:17:16 Done.
xunjieli 2017/05/01 19:17:16 These three are not guarded by the lock because th
+ @RequestFinishedInfoImpl.FinishedReason
+ private int mFinishedReason;
+ private CronetException mException;
+ private CronetMetrics mMetrics;
+
/*
* Listener callback is repeatedly invoked when each read is completed, so it
* is cached as a member variable.
*/
private OnReadCompletedRunnable mOnReadCompletedTask;
+ @GuardedBy("mUrlRequestAdapterLock")
private Runnable mOnDestroyedCallbackForTesting;
private static final class HeadersList extends ArrayList<Map.Entry<String, String>> {}
@@ -234,9 +237,11 @@ public final class CronetUrlRequest extends UrlRequestBase {
return;
}
} catch (RuntimeException e) {
- // If there's an exception, cleanup and then throw the
- // exception to the caller.
- destroyRequestAdapter(false);
+ // If there's an exception, cleanup and then throw the exception to the caller. Use
+ // null to avoid rethrowing in onDestroy().
+ synchronized (mUrlRequestAdapterLock) {
mef 2017/04/28 21:16:54 This whole method is synchronized() at line 191, s
xunjieli 2017/05/01 19:17:16 Done.
+ setIsDoneLocked(null, RequestFinishedInfo.FAILED);
+ }
throw e;
}
mStarted = true;
@@ -298,7 +303,7 @@ public final class CronetUrlRequest extends UrlRequestBase {
if (isDoneLocked() || !mStarted) {
return;
}
- destroyRequestAdapter(true);
+ setIsDoneLocked(null, RequestFinishedInfo.CANCELED);
}
}
@@ -309,6 +314,26 @@ public final class CronetUrlRequest extends UrlRequestBase {
}
}
+ /**
+ * Helper method to set final status of CronetUrlRequest and clean up the
+ * native request adapter.
+ */
+ @GuardedBy("mUrlRequestAdapterLock")
+ private void setIsDoneLocked(
mef 2017/04/28 21:16:55 I really think it should still be called destroyRe
xunjieli 2017/05/01 19:17:16 Done. Partly yes, but now it also updates |mExcept
+ CronetException exception, @RequestFinishedInfoImpl.FinishedReason int finishedReason) {
+ assert mException == null;
+ assert exception == null || finishedReason == RequestFinishedInfo.FAILED;
+ mException = exception;
+ mFinishedReason = finishedReason;
+ if (mUrlRequestAdapter == 0) {
+ return;
+ }
+ mRequestContext.onRequestDestroyed();
+ // Posts a task to destroy the native adapter.
+ nativeDestroy(mUrlRequestAdapter, finishedReason == RequestFinishedInfo.CANCELED);
+ mUrlRequestAdapter = 0;
+ }
+
@GuardedBy("mUrlRequestAdapterLock")
private boolean isDoneLocked() {
return mStarted && mUrlRequestAdapter == 0;
@@ -335,7 +360,9 @@ public final class CronetUrlRequest extends UrlRequestBase {
@VisibleForTesting
public void setOnDestroyedCallbackForTesting(Runnable onDestroyedCallbackForTesting) {
- mOnDestroyedCallbackForTesting = onDestroyedCallbackForTesting;
+ synchronized (mUrlRequestAdapterLock) {
+ mOnDestroyedCallbackForTesting = onDestroyedCallbackForTesting;
+ }
}
@VisibleForTesting
@@ -410,20 +437,6 @@ public final class CronetUrlRequest extends UrlRequestBase {
}
}
- private void destroyRequestAdapter(boolean sendOnCanceled) {
- synchronized (mUrlRequestAdapterLock) {
- if (mUrlRequestAdapter == 0) {
- return;
- }
- nativeDestroy(mUrlRequestAdapter, sendOnCanceled);
- mRequestContext.onRequestDestroyed();
- mUrlRequestAdapter = 0;
- if (mOnDestroyedCallbackForTesting != null) {
- mOnDestroyedCallbackForTesting.run();
- }
- }
- }
-
/**
* If callback method throws an exception, request gets canceled
* and exception is reported via onFailed listener callback.
@@ -447,31 +460,17 @@ public final class CronetUrlRequest extends UrlRequestBase {
}
/**
- * Fails the request with an exception. Can be called on any thread.
+ * Fails the request with an exception on any thread.
*/
private void failWithException(final CronetException exception) {
- mException = exception;
synchronized (mUrlRequestAdapterLock) {
if (isDoneLocked()) {
return;
}
- destroyRequestAdapter(false);
- }
- Runnable task = new Runnable() {
- @Override
- public void run() {
- try {
- mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, exception);
- } catch (Exception e) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFailed method", e);
- }
- }
- };
- try {
- mExecutor.execute(task);
- } catch (RejectedExecutionException e) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to executor", e);
+ setIsDoneLocked(exception, RequestFinishedInfo.FAILED);
mef 2017/04/28 21:16:54 Can we set mException = exception; here and just p
xunjieli 2017/05/01 19:17:16 Done.
}
+ // Wait until onDestroy() is called to propagate the error to caller to
mef 2017/04/28 21:16:54 I would rephrase this like 'The onFailed callback
xunjieli 2017/05/01 19:17:16 Done.
+ // gather metrics.
}
////////////////////////////////////////////////
@@ -600,7 +599,6 @@ public final class CronetUrlRequest extends UrlRequestBase {
@SuppressWarnings("unused")
@CalledByNative
private void onSucceeded(long receivedByteCount) {
- mFinishedReason = RequestFinishedInfo.SUCCEEDED;
mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + receivedByteCount);
Runnable task = new Runnable() {
@Override
@@ -611,12 +609,17 @@ public final class CronetUrlRequest extends UrlRequestBase {
}
// Destroy adapter first, so request context could be shut
// down from the listener.
- destroyRequestAdapter(false);
+ setIsDoneLocked(null, RequestFinishedInfo.SUCCEEDED);
}
try {
mCallback.onSucceeded(CronetUrlRequest.this, mResponseInfo);
+ if (mMetrics != null) {
+ mRequestContext.reportFinished(
+ new RequestFinishedInfoImpl(mInitialUrl, mRequestAnnotations,
+ mMetrics, mFinishedReason, mResponseInfo, mException));
+ }
} catch (Exception e) {
- Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onComplete method", e);
+ Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onSucceeded method", e);
}
}
};
@@ -637,18 +640,19 @@ public final class CronetUrlRequest extends UrlRequestBase {
@CalledByNative
private void onError(int errorCode, int nativeError, int nativeQuicError, String errorString,
long receivedByteCount) {
- mFinishedReason = RequestFinishedInfo.FAILED;
if (mResponseInfo != null) {
mResponseInfo.setReceivedByteCount(mReceivedByteCountFromRedirects + receivedByteCount);
}
+ CronetException exception;
mef 2017/04/28 21:16:54 Why do we need local |exception| here?
xunjieli 2017/05/01 19:17:16 Done. Because we can acquire mUrlRequestAdapterLoc
if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED) {
- failWithException(new QuicExceptionImpl(
- "Exception in CronetUrlRequest: " + errorString, nativeError, nativeQuicError));
+ exception = new QuicExceptionImpl(
+ "Exception in CronetUrlRequest: " + errorString, nativeError, nativeQuicError);
} else {
int javaError = mapUrlRequestErrorToApiErrorCode(errorCode);
- failWithException(new NetworkExceptionImpl(
- "Exception in CronetUrlRequest: " + errorString, javaError, nativeError));
+ exception = new NetworkExceptionImpl(
+ "Exception in CronetUrlRequest: " + errorString, javaError, nativeError);
}
+ failWithException(exception);
}
/**
@@ -657,12 +661,16 @@ public final class CronetUrlRequest extends UrlRequestBase {
@SuppressWarnings("unused")
@CalledByNative
private void onCanceled() {
- mFinishedReason = RequestFinishedInfo.CANCELED;
Runnable task = new Runnable() {
@Override
public void run() {
try {
mCallback.onCanceled(CronetUrlRequest.this, mResponseInfo);
+ if (mMetrics != null) {
mef 2017/04/28 21:16:54 Does it make sense to extract this into maybeRepor
xunjieli 2017/05/01 19:17:16 Done.
+ mRequestContext.reportFinished(
+ new RequestFinishedInfoImpl(mInitialUrl, mRequestAnnotations,
+ mMetrics, mFinishedReason, mResponseInfo, mException));
+ }
} catch (Exception e) {
Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onCanceled method", e);
}
@@ -689,7 +697,8 @@ public final class CronetUrlRequest extends UrlRequestBase {
}
/**
- * Called by the native code to report metrics.
+ * Called by the native code on the network thread to report metrics. Happens before
+ * onSucceeded, onError and onCanceled.
*/
@SuppressWarnings("unused")
@CalledByNative
@@ -707,12 +716,42 @@ public final class CronetUrlRequest extends UrlRequestBase {
pushEndMs, responseStartMs, requestEndMs, socketReused, sentByteCount,
receivedByteCount);
}
mef 2017/04/28 21:16:54 Maybe add comment that metrics will be reported af
xunjieli 2017/05/01 19:17:16 Done.
- mRequestContext.reportFinished(getRequestFinishedInfo());
}
- private RequestFinishedInfo getRequestFinishedInfo() {
- return new RequestFinishedInfoImpl(mInitialUrl, mRequestAnnotations, mMetrics,
- mFinishedReason, mResponseInfo, mException);
+ /**
+ * Called when the native adapter is destroyed.
+ */
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void onDestroyed() {
mef 2017/04/28 21:16:55 Maybe (not strongly) call it onNativeAdapterDestro
xunjieli 2017/05/01 19:17:16 Done.
+ synchronized (mUrlRequestAdapterLock) {
+ if (mOnDestroyedCallbackForTesting != null) {
+ mOnDestroyedCallbackForTesting.run();
+ }
+ if (mException == null) {
mef 2017/04/28 21:16:55 Need a comment as to why we check mException and
xunjieli 2017/05/01 19:17:16 Done.
+ return;
+ }
+ }
+ Runnable task = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mCallback.onFailed(CronetUrlRequest.this, mResponseInfo, mException);
+ if (mMetrics != null) {
+ mRequestContext.reportFinished(
+ new RequestFinishedInfoImpl(mInitialUrl, mRequestAnnotations,
+ mMetrics, mFinishedReason, mResponseInfo, mException));
+ }
+ } catch (Exception e) {
+ Log.e(CronetUrlRequestContext.LOG_TAG, "Exception in onFailed method", e);
+ }
+ }
+ };
+ try {
+ mExecutor.execute(task);
+ } catch (RejectedExecutionException e) {
+ Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to executor", e);
+ }
}
/** Enforces prohibition of direct execution. */

Powered by Google App Engine
This is Rietveld 408576698