Merge "Don't require sSyncLock for sync error map" into honeycomb

This commit is contained in:
Marc Blank 2011-01-23 15:04:30 -08:00 committed by Android (Google) Code Review
commit 5150d0e818
2 changed files with 40 additions and 51 deletions

View File

@ -93,6 +93,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* The ExchangeService handles all aspects of starting, maintaining, and stopping the various sync * The ExchangeService handles all aspects of starting, maintaining, and stopping the various sync
@ -193,7 +194,8 @@ public class ExchangeService extends Service implements Runnable {
private HashMap<Long, AbstractSyncService> mServiceMap = private HashMap<Long, AbstractSyncService> mServiceMap =
new HashMap<Long, AbstractSyncService>(); new HashMap<Long, AbstractSyncService>();
// Keeps track of services whose last sync ended with an error (by mailbox id) // Keeps track of services whose last sync ended with an error (by mailbox id)
/*package*/ HashMap<Long, SyncError> mSyncErrorMap = new HashMap<Long, SyncError>(); /*package*/ ConcurrentHashMap<Long, SyncError> mSyncErrorMap =
new ConcurrentHashMap<Long, SyncError>();
// Keeps track of which services require a wake lock (by mailbox id) // Keeps track of which services require a wake lock (by mailbox id)
private HashMap<Long, Boolean> mWakeLocks = new HashMap<Long, Boolean>(); private HashMap<Long, Boolean> mWakeLocks = new HashMap<Long, Boolean>();
// Keeps track of PendingIntents for mailbox alarms (by mailbox id) // Keeps track of PendingIntents for mailbox alarms (by mailbox id)
@ -394,25 +396,19 @@ public class ExchangeService extends Service implements Runnable {
public void hostChanged(long accountId) throws RemoteException { public void hostChanged(long accountId) throws RemoteException {
ExchangeService exchangeService = INSTANCE; ExchangeService exchangeService = INSTANCE;
if (exchangeService == null) return; if (exchangeService == null) return;
synchronized (sSyncLock) { ConcurrentHashMap<Long, SyncError> syncErrorMap = exchangeService.mSyncErrorMap;
HashMap<Long, SyncError> syncErrorMap = exchangeService.mSyncErrorMap; // Go through the various error mailboxes
ArrayList<Long> deletedMailboxes = new ArrayList<Long>(); for (long mailboxId: syncErrorMap.keySet()) {
// Go through the various error mailboxes SyncError error = syncErrorMap.get(mailboxId);
for (long mailboxId: syncErrorMap.keySet()) { // If it's a login failure, look a little harder
SyncError error = syncErrorMap.get(mailboxId); Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId);
// If it's a login failure, look a little harder // If it's for the account whose host has changed, clear the error
Mailbox m = Mailbox.restoreMailboxWithId(exchangeService, mailboxId); // If the mailbox is no longer around, remove the entry in the map
// If it's for the account whose host has changed, clear the error if (m == null) {
// If the mailbox is no longer around, remove the entry in the map
if (m == null) {
deletedMailboxes.add(mailboxId);
} else if (m.mAccountKey == accountId) {
error.fatal = false;
error.holdEndTime = 0;
}
}
for (long mailboxId: deletedMailboxes) {
syncErrorMap.remove(mailboxId); syncErrorMap.remove(mailboxId);
} else if (error != null && m.mAccountKey == accountId) {
error.fatal = false;
error.holdEndTime = 0;
} }
} }
// Stop any running syncs // Stop any running syncs
@ -967,16 +963,16 @@ public class ExchangeService extends Service implements Runnable {
} }
private void logSyncHolds() { private void logSyncHolds() {
if (Eas.USER_LOG && !mSyncErrorMap.isEmpty()) { if (Eas.USER_LOG) {
log("Sync holds:"); log("Sync holds:");
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
synchronized (sSyncLock) { for (long mailboxId : mSyncErrorMap.keySet()) {
for (long mailboxId : mSyncErrorMap.keySet()) { Mailbox m = Mailbox.restoreMailboxWithId(this, mailboxId);
Mailbox m = Mailbox.restoreMailboxWithId(this, mailboxId); if (m == null) {
if (m == null) { log("Mailbox " + mailboxId + " no longer exists");
log("Mailbox " + mailboxId + " no longer exists"); } else {
} else { SyncError error = mSyncErrorMap.get(mailboxId);
SyncError error = mSyncErrorMap.get(mailboxId); if (error != null) {
log("Mailbox " + m.mDisplayName + ", error = " + error.reason log("Mailbox " + m.mDisplayName + ", error = " + error.reason
+ ", fatal = " + error.fatal); + ", fatal = " + error.fatal);
if (error.holdEndTime > 0) { if (error.holdEndTime > 0) {
@ -1014,29 +1010,23 @@ public class ExchangeService extends Service implements Runnable {
} }
private boolean releaseSyncHoldsImpl(Context context, int reason, Account account) { private boolean releaseSyncHoldsImpl(Context context, int reason, Account account) {
synchronized(sSyncLock) { boolean holdWasReleased = false;
boolean holdWasReleased = false; for (long mailboxId: mSyncErrorMap.keySet()) {
ArrayList<Long> releaseList = new ArrayList<Long>(); if (account != null) {
for (long mailboxId: mSyncErrorMap.keySet()) { Mailbox m = Mailbox.restoreMailboxWithId(context, mailboxId);
if (account != null) { if (m == null) {
Mailbox m = Mailbox.restoreMailboxWithId(context, mailboxId); mSyncErrorMap.remove(mailboxId);
if (m == null) { } else if (m.mAccountKey != account.mId) {
releaseList.add(mailboxId); continue;
} else if (m.mAccountKey != account.mId) {
continue;
}
}
SyncError error = mSyncErrorMap.get(mailboxId);
if (error.reason == reason) {
releaseList.add(mailboxId);
} }
} }
for (long mailboxId: releaseList) { SyncError error = mSyncErrorMap.get(mailboxId);
if (error != null && error.reason == reason) {
mSyncErrorMap.remove(mailboxId); mSyncErrorMap.remove(mailboxId);
holdWasReleased = true; holdWasReleased = true;
} }
return holdWasReleased;
} }
return holdWasReleased;
} }
public class EasSyncStatusObserver implements SyncStatusObserver { public class EasSyncStatusObserver implements SyncStatusObserver {
@ -2371,8 +2361,7 @@ public class ExchangeService extends Service implements Runnable {
*/ */
static public void removeFromSyncErrorMap(long mailboxId) { static public void removeFromSyncErrorMap(long mailboxId) {
ExchangeService exchangeService = INSTANCE; ExchangeService exchangeService = INSTANCE;
if (exchangeService == null) return; if (exchangeService != null) {
synchronized(sSyncLock) {
exchangeService.mSyncErrorMap.remove(mailboxId); exchangeService.mSyncErrorMap.remove(mailboxId);
} }
} }
@ -2388,7 +2377,7 @@ public class ExchangeService extends Service implements Runnable {
if (exchangeService == null) return; if (exchangeService == null) return;
synchronized(sSyncLock) { synchronized(sSyncLock) {
long mailboxId = svc.mMailboxId; long mailboxId = svc.mMailboxId;
HashMap<Long, SyncError> errorMap = exchangeService.mSyncErrorMap; ConcurrentHashMap<Long, SyncError> errorMap = exchangeService.mSyncErrorMap;
SyncError syncError = errorMap.get(mailboxId); SyncError syncError = errorMap.get(mailboxId);
exchangeService.releaseMailbox(mailboxId); exchangeService.releaseMailbox(mailboxId);
int exitStatus = svc.mExitStatus; int exitStatus = svc.mExitStatus;

View File

@ -18,15 +18,15 @@
package com.android.exchange; package com.android.exchange;
import com.android.email.AccountTestCase; import com.android.email.AccountTestCase;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.ProviderTestUtils;
import com.android.email.provider.EmailContent.Account; import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Mailbox; import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailProvider;
import com.android.email.provider.ProviderTestUtils;
import com.android.exchange.ExchangeService.SyncError; import com.android.exchange.ExchangeService.SyncError;
import android.content.Context; import android.content.Context;
import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* You can run this entire test case with: * You can run this entire test case with:
@ -64,7 +64,7 @@ public class ExchangeServiceAccountTests extends AccountTestCase {
Mailbox box3 = ProviderTestUtils.setupMailbox("box3", acct2.mId, true, context); Mailbox box3 = ProviderTestUtils.setupMailbox("box3", acct2.mId, true, context);
Mailbox box4 = ProviderTestUtils.setupMailbox("box4", acct2.mId, true, context); Mailbox box4 = ProviderTestUtils.setupMailbox("box4", acct2.mId, true, context);
HashMap<Long, SyncError> errorMap = exchangeService.mSyncErrorMap; ConcurrentHashMap<Long, SyncError> errorMap = exchangeService.mSyncErrorMap;
// Add errors into the map // Add errors into the map
errorMap.put(box1.mId, securityErrorAccount1); errorMap.put(box1.mId, securityErrorAccount1);
errorMap.put(box2.mId, ioError); errorMap.put(box2.mId, ioError);