From 9529b426c39b9c4a875079c6d5c2075d47ed7fd4 Mon Sep 17 00:00:00 2001 From: David Dykstal Date: Fri, 11 May 2007 04:05:14 +0000 Subject: [PATCH] [177329][api] API changes to add timeouts and better return indications for the persistence manager. --- .../rse/core/model/RSEModelOperation.java | 2 +- .../internal/core/model/SystemProfile.java | 6 +- .../core/model/SystemProfileManager.java | 4 +- .../persistence/RSEPersistenceManager.java | 118 +++++++++--------- .../persistence/IRSEPersistenceManager.java | 44 ++++--- .../ui/resources/SystemTempFileListener.java | 2 +- .../rse/ui/internal/model/SystemRegistry.java | 3 +- 7 files changed, 94 insertions(+), 85 deletions(-) diff --git a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/model/RSEModelOperation.java b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/model/RSEModelOperation.java index 0ba83f2ee02..8734c628476 100644 --- a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/model/RSEModelOperation.java +++ b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/core/model/RSEModelOperation.java @@ -76,7 +76,7 @@ public abstract class RSEModelOperation { */ private static void endTransaction() { IRSEPersistenceManager persistenceManager = RSECorePlugin.getThePersistenceManager(); - persistenceManager.commitProfiles(); + persistenceManager.commitProfiles(5000); } /** diff --git a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfile.java b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfile.java index 82df2e5d875..822d62c7ead 100644 --- a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfile.java +++ b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfile.java @@ -211,7 +211,11 @@ public class SystemProfile extends RSEModelObject implements ISystemProfile, IAd public boolean commit() { - return RSECorePlugin.getThePersistenceManager().commitProfile(this); + boolean result = false; + if (!RSECorePlugin.getThePersistenceManager().isBusy()) { + result = RSECorePlugin.getThePersistenceManager().commitProfile(this, 5000); + } + return result; } /** diff --git a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfileManager.java b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfileManager.java index 43ab921c3f4..5eb5a4b9eb8 100644 --- a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfileManager.java +++ b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/core/model/SystemProfileManager.java @@ -56,7 +56,7 @@ public class SystemProfileManager implements ISystemProfileManager { public static SystemProfileManager getDefault() { if (singleton == null) { singleton = new SystemProfileManager(); - RSECorePlugin.getThePersistenceManager().restoreProfiles(); + RSECorePlugin.getThePersistenceManager().restoreProfiles(5000); } return singleton; } @@ -403,7 +403,7 @@ public class SystemProfileManager implements ISystemProfileManager { public void setRestoring(boolean flag) { restoring = flag; } - + private ISystemProfile internalCreateSystemProfile(String name) { ISystemProfile newProfile = new SystemProfile(); newProfile.setName(name); diff --git a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/persistence/RSEPersistenceManager.java b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/persistence/RSEPersistenceManager.java index b361f97eace..9f6c796c400 100644 --- a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/persistence/RSEPersistenceManager.java +++ b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/internal/persistence/RSEPersistenceManager.java @@ -47,6 +47,7 @@ import org.eclipse.rse.logging.Logger; import org.eclipse.rse.persistence.IRSEPersistenceManager; import org.eclipse.rse.persistence.IRSEPersistenceProvider; import org.eclipse.rse.persistence.dom.RSEDOM; +import org.eclipse.rse.services.Mutex; /** * The persistence manager controls all aspects of persisting the RSE data model. It will both @@ -56,10 +57,6 @@ import org.eclipse.rse.persistence.dom.RSEDOM; */ public class RSEPersistenceManager implements IRSEPersistenceManager { - private static final int STATE_NONE = 0; - private static final int STATE_LOADING = 1; - private static final int STATE_SAVING = 2; - private class ProviderRecord { private String providerId = null; private IConfigurationElement configurationElement = null; @@ -75,9 +72,9 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { private Map knownProviders = new HashMap(10); private Map loadedProviders = new HashMap(10); - private int _currentState = STATE_NONE; private RSEDOMExporter _exporter; private RSEDOMImporter _importer; + private Mutex mutex = new Mutex(); public RSEPersistenceManager(ISystemRegistry registry) { _exporter = RSEDOMExporter.getInstance(); @@ -89,15 +86,8 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { /* (non-Javadoc) * @see org.eclipse.rse.persistence.IRSEPersistenceManager#isExporting() */ - public synchronized boolean isExporting() { - return _currentState == STATE_SAVING; - } - - /* (non-Javadoc) - * @see org.eclipse.rse.persistence.IRSEPersistenceManager#isImporting() - */ - public synchronized boolean isImporting() { - return _currentState == STATE_LOADING; + public synchronized boolean isBusy() { + return mutex.isLocked(); } /* (non-Javadoc) @@ -142,32 +132,36 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { /* (non-Javadoc) * @see org.eclipse.rse.persistence.IRSEPersistenceManager#commitProfile(org.eclipse.rse.core.model.ISystemProfile) */ - public boolean commitProfile(ISystemProfile profile) { + public boolean commitProfile(ISystemProfile profile, long timeout) { boolean result = false; - if (profile != null) { - result = save(profile, true); - } + result = save(profile, true, timeout); return result; } /* (non-Javadoc) * @see org.eclipse.rse.persistence.IRSEPersistenceManager#commitProfiles() */ - public boolean commitProfiles() { - boolean ok = true; + public ISystemProfile[] commitProfiles(long timeout) { + List failed = new ArrayList(10); ISystemProfile[] profiles = RSECorePlugin.getTheSystemRegistry().getAllSystemProfiles(); - for (int idx = 0; idx < profiles.length && ok; idx++) { + for (int idx = 0; idx < profiles.length; idx++) { + ISystemProfile profile = profiles[idx]; try { - ok = commitProfile(profiles[idx]); + boolean ok = commitProfile(profile, timeout); + if (!ok) { + failed.add(profile); + } } catch (Exception exc) { Logger logger = RSECorePlugin.getDefault().getLogger(); - String profileName = profiles[idx].getName(); + String profileName = profile.getName(); String message = "Error saving profile " + profileName; //$NON-NLS-1$ logger.logError(message, exc); - ok = false; + failed.add(profile); } } - return ok; + ISystemProfile[] result = new ISystemProfile[failed.size()]; + failed.toArray(result); + return result; } /* (non-Javadoc) @@ -203,14 +197,14 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { /* (non-Javadoc) * @see org.eclipse.rse.persistence.IRSEPersistenceManager#restoreProfiles() */ - public ISystemProfile[] restoreProfiles() { + public ISystemProfile[] restoreProfiles(long timeout) { List profiles = new ArrayList(10); String[] ids = getPersistenceProviderIds(); for (int i = 0; i < ids.length; i++) { String id = ids[i]; IRSEPersistenceProvider provider = getPersistenceProvider(id); if (provider != null) { - ISystemProfile[] providerProfiles = restoreProfiles(provider); + ISystemProfile[] providerProfiles = restoreProfiles(provider, timeout); profiles.addAll(Arrays.asList(providerProfiles)); } } @@ -222,10 +216,10 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { /* (non-Javadoc) * @see org.eclipse.rse.persistence.IRSEPersistenceManager#restoreProfiles(org.eclipse.rse.persistence.IRSEPersistenceProvider) */ - public ISystemProfile[] restoreProfiles(IRSEPersistenceProvider provider) { + public ISystemProfile[] restoreProfiles(IRSEPersistenceProvider provider, long timeout) { ProviderRecord pr = getProviderRecord(provider); pr.setRestored(false); - List profiles = loadProfiles(provider); + List profiles = loadProfiles(provider, timeout); pr.setRestored(true); ISystemProfile[] result = new ISystemProfile[profiles.size()]; profiles.toArray(result); @@ -313,12 +307,12 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { * @param persistenceProvider * @return a list of profiles */ - private List loadProfiles(IRSEPersistenceProvider persistenceProvider) { + private List loadProfiles(IRSEPersistenceProvider persistenceProvider, long timeout) { List profiles = new ArrayList(10); String[] profileNames = persistenceProvider.getSavedProfileNames(); for (int i = 0; i < profileNames.length; i++) { String profileName = profileNames[i]; - ISystemProfile profile = load(persistenceProvider, profileName); + ISystemProfile profile = load(persistenceProvider, profileName, timeout); profiles.add(profile); } return profiles; @@ -331,19 +325,21 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { * @param profileName the name of the profile to produce * @return the profile or null */ - private synchronized ISystemProfile load(IRSEPersistenceProvider provider, String profileName) { + private synchronized ISystemProfile load(IRSEPersistenceProvider provider, String profileName, long timeout) { ISystemProfile profile = null; - if (_currentState == STATE_NONE) { - _currentState = STATE_LOADING; - RSEDOM dom = provider.loadRSEDOM(profileName, new NullProgressMonitor()); - if (dom != null) { - SystemProfileManager.getDefault().setRestoring(true); - profile = _importer.restoreProfile(dom); - profile.setPersistenceProvider(provider); - cleanTree(profile); - SystemProfileManager.getDefault().setRestoring(false); + if (mutex.waitForLock(null, timeout)) { + try { + RSEDOM dom = provider.loadRSEDOM(profileName, new NullProgressMonitor()); + if (dom != null) { + SystemProfileManager.getDefault().setRestoring(true); + profile = _importer.restoreProfile(dom); + profile.setPersistenceProvider(provider); + cleanTree(profile); + SystemProfileManager.getDefault().setRestoring(false); + } + } finally { + mutex.release(); } - _currentState = STATE_NONE; } return profile; } @@ -354,27 +350,29 @@ public class RSEPersistenceManager implements IRSEPersistenceManager { * If in the process of importing, skip writing. * @return true if the profile is written to a DOM */ - private synchronized boolean save(ISystemProfile profile, boolean force) { + private boolean save(ISystemProfile profile, boolean force, long timeout) { boolean result = false; - if (_currentState == STATE_NONE) { - _currentState = STATE_SAVING; - IRSEPersistenceProvider provider = profile.getPersistenceProvider(); - if (provider == null) { - provider = getDefaultPersistenceProvider(); - profile.setPersistenceProvider(provider); - } - RSEDOM dom = _exporter.createRSEDOM(profile, force); - cleanTree(profile); - if (dom.needsSave()) { - Job job = provider.getSaveJob(dom); - if (job != null) { - job.schedule(3000); // three second delay - } else { - provider.saveRSEDOM(dom, new NullProgressMonitor()); + if (mutex.waitForLock(null, timeout)) { + try { + IRSEPersistenceProvider provider = profile.getPersistenceProvider(); + if (provider == null) { + provider = getDefaultPersistenceProvider(); + profile.setPersistenceProvider(provider); } + RSEDOM dom = _exporter.createRSEDOM(profile, force); + cleanTree(profile); + if (dom.needsSave()) { + Job job = provider.getSaveJob(dom); + if (job != null) { + job.schedule(3000); // three second delay + } else { + provider.saveRSEDOM(dom, new NullProgressMonitor()); + } + } + result = true; + } finally { + mutex.release(); } - result = true; - _currentState = STATE_NONE; } return result; } diff --git a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/persistence/IRSEPersistenceManager.java b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/persistence/IRSEPersistenceManager.java index 70346c15af4..6eb7a498989 100644 --- a/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/persistence/IRSEPersistenceManager.java +++ b/rse/plugins/org.eclipse.rse.core/src/org/eclipse/rse/persistence/IRSEPersistenceManager.java @@ -21,32 +21,42 @@ import org.eclipse.rse.core.model.ISystemProfile; public interface IRSEPersistenceManager { /** - * Save a particular profile. If the profile has an existing persistence provider + * Schedules a save of particular profile. If the profile has an existing persistence provider * it is saved by that persistence provider. If the profile has no persistence provider - * then the default persistence provider is used. + * then the default persistence provider is used. If the persistence manager is in a state where + * it is saving or restoring another profile on another thread this call will block for the + * timeout value specified. If the timeout expires this call will return false. * @param profile the profile to save - * @return true if successful + * @param timeout the timeout value in milliseconds. If the operation cannot be started in this time + * it will return false. + * @return true if the save was scheduled and false if the timeout expired without scheduling the save. */ - public boolean commitProfile(ISystemProfile profile); + public boolean commitProfile(ISystemProfile profile, long timeout); /** - * Save all profiles. - * @return true if successful + * Save all profiles. Will attempt to schedule a save of all profiles. Each attempt will time out after + * the number of milliseconds specified if the operation cannot be started. + * @param timeout the maximum number of milliseconds to wait until the persistence manager becomes available + * to schedule a save for an individual profile. + * @return the list of profiles that could not be scheduled for save. */ - public boolean commitProfiles(); + public ISystemProfile[] commitProfiles(long timeout); /** - * Restore all profiles + * Restore all profiles. + * @param timeout the maximum number of milliseconds to wait for the manager to become idle for each profile. * @return an array of restored profiles. */ - public ISystemProfile[] restoreProfiles(); + public ISystemProfile[] restoreProfiles(long timeout); /** * Restore the profiles for a particular provider. * @param provider a persistence provider - * @return an array of the restored profiles + * @param timeout the maximum number of milliseconds to wait for the manager to become idle before restoring this + * the each profile managed by this provider. + * @return an array of the restored profiles. */ - public ISystemProfile[] restoreProfiles(IRSEPersistenceProvider provider); + public ISystemProfile[] restoreProfiles(IRSEPersistenceProvider provider, long timeout); /** * Delete the persistent form of a profile. @@ -91,20 +101,16 @@ public interface IRSEPersistenceManager { public IRSEPersistenceProvider getPersistenceProvider(String id); /** - * @return true if this instance of the persistence manager is currently exporting a profile. + * @return true if this instance of the persistence manager is currently saving or restoring a profile. */ - public boolean isExporting(); + public boolean isBusy(); - /** - * @return true if this instance of the persistence manager is currently importing a profile. - */ - public boolean isImporting(); - /** * Indicate if all profiles for a particular persistence provider have been restored. * Profiles are typically restored when RSE is activated and when profiles * are reloaded by the user. This will not load the persistence provider. If the persistence - * provider is not loaded it will return false. + * provider has not yet been loaded it will return false. This can be used from a different thread + * than the one that requested the restore. * @param providerId the persistence providerId * @return true if the profiles have been fully restored */ diff --git a/rse/plugins/org.eclipse.rse.files.ui/src/org/eclipse/rse/files/ui/resources/SystemTempFileListener.java b/rse/plugins/org.eclipse.rse.files.ui/src/org/eclipse/rse/files/ui/resources/SystemTempFileListener.java index d371db572d1..d0c0efe1ae6 100644 --- a/rse/plugins/org.eclipse.rse.files.ui/src/org/eclipse/rse/files/ui/resources/SystemTempFileListener.java +++ b/rse/plugins/org.eclipse.rse.files.ui/src/org/eclipse/rse/files/ui/resources/SystemTempFileListener.java @@ -137,7 +137,7 @@ public abstract class SystemTempFileListener implements IResourceChangeListener } else { - if (!RSECorePlugin.getThePersistenceManager().isExporting()) + if (!RSECorePlugin.getThePersistenceManager().isBusy()) { List changes = new ArrayList(); checkLocalChanges(delta, changes); diff --git a/rse/plugins/org.eclipse.rse.ui/model/org/eclipse/rse/ui/internal/model/SystemRegistry.java b/rse/plugins/org.eclipse.rse.ui/model/org/eclipse/rse/ui/internal/model/SystemRegistry.java index 9afc1d866c3..5cb307249fc 100644 --- a/rse/plugins/org.eclipse.rse.ui/model/org/eclipse/rse/ui/internal/model/SystemRegistry.java +++ b/rse/plugins/org.eclipse.rse.ui/model/org/eclipse/rse/ui/internal/model/SystemRegistry.java @@ -3279,7 +3279,8 @@ public class SystemRegistry implements ISystemRegistryUI, ISystemViewInputProvid */ public boolean save() { - return RSECorePlugin.getThePersistenceManager().commitProfiles(); + ISystemProfile[] notSaved = RSECorePlugin.getThePersistenceManager().commitProfiles(5000); + return notSaved.length > 0; } /**