| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.garbagecollector; |
| |
| import java.util.*; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.internal.p2.core.helpers.LogHelper; |
| import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository; |
| import org.eclipse.equinox.internal.provisional.p2.engine.IProfile; |
| import org.eclipse.equinox.internal.provisional.p2.engine.IProfileRegistry; |
| import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; |
| |
| /** |
| * The main control point for the p2 garbage collector. Takes a Profile and runs the CoreGarbageCollector with the |
| * appropriate MarkSets for the repositories used by that Profile. |
| * |
| * Takes the profile passed in and creates a set (markSet) that maps the artifact repositories it uses to the |
| * artifact keys its IUs hold. This is done by getting MarkSets from all registered IMarkSetProviders. |
| * |
| * Then, the MarkSets are obtained for every other registered Profile in a similar fashion. Each MarkSet is |
| * checked to see if its artifact repository is already a key in markSet. If so, that MarkSet's artifact keys |
| * are added to the list that is mapped to by the artifact repository. |
| */ |
| public class GarbageCollector { |
| private static final String ATTRIBUTE_CLASS = "class"; //$NON-NLS-1$ |
| private static final String PT_MARKSET = GCActivator.ID + ".marksetproviders"; //$NON-NLS-1$ |
| |
| /** |
| * Maps IArtifactRepository objects to their respective "marked set" of IArtifactKeys |
| */ |
| private Map markSet; |
| |
| public void runGC(IProfile profile) { |
| markSet = new HashMap(); |
| if (!traverseMainProfile(profile)) |
| return; |
| |
| //Complete each MarkSet with the MarkSets provided by all of the other registered Profiles |
| traverseRegisteredProfiles(); |
| |
| //Run the GC on each MarkSet |
| invokeCoreGC(); |
| } |
| |
| private boolean traverseMainProfile(IProfile profile) { |
| IExtensionRegistry registry = RegistryFactory.getRegistry(); |
| IConfigurationElement[] configElts = registry.getConfigurationElementsFor(PT_MARKSET); |
| |
| //First we collect all repos and keys for the profile being GC'ed |
| for (int i = 0; i < configElts.length; i++) { |
| if (!(configElts[i].getName().equals("run"))) { //$NON-NLS-1$ |
| continue; |
| } |
| IConfigurationElement runAttribute = configElts[i]; |
| if (runAttribute == null) { |
| continue; |
| } |
| |
| contributeMarkSets(runAttribute, profile, true); |
| } |
| return true; |
| } |
| |
| private void invokeCoreGC() { |
| Iterator keyIterator = markSet.keySet().iterator(); |
| while (keyIterator.hasNext()) { |
| IArtifactRepository nextRepo = (IArtifactRepository) keyIterator.next(); |
| IArtifactKey[] keys = (IArtifactKey[]) ((Collection) markSet.get(nextRepo)).toArray(new IArtifactKey[0]); |
| MarkSet aMarkSet = new MarkSet(keys, nextRepo); |
| new CoreGarbageCollector().clean(aMarkSet.getKeys(), aMarkSet.getRepo()); |
| } |
| } |
| |
| private void traverseRegisteredProfiles() { |
| IExtensionRegistry registry = RegistryFactory.getRegistry(); |
| IConfigurationElement[] configElts = registry.getConfigurationElementsFor(PT_MARKSET); |
| for (int i = 0; i < configElts.length; i++) { |
| if (!(configElts[i].getName().equals("run"))) { //$NON-NLS-1$ |
| continue; |
| } |
| IConfigurationElement runAttribute = configElts[i]; |
| if (runAttribute == null) { |
| continue; |
| } |
| |
| IProfileRegistry profileRegistry = (IProfileRegistry) GCActivator.getService(GCActivator.getContext(), IProfileRegistry.class.getName()); |
| if (profileRegistry == null) |
| return; |
| IProfile[] registeredProfiles = profileRegistry.getProfiles(); |
| |
| for (int j = 0; j < registeredProfiles.length; j++) { |
| contributeMarkSets(runAttribute, registeredProfiles[j], false); |
| } |
| } |
| } |
| |
| private class ParameterizedSafeRunnable implements ISafeRunnable { |
| IConfigurationElement cfg; |
| IProfile aProfile; |
| MarkSet[] aProfileMarkSets; |
| |
| public ParameterizedSafeRunnable(IConfigurationElement runtAttribute, IProfile profile) { |
| cfg = runtAttribute; |
| aProfile = profile; |
| } |
| |
| public void handleException(Throwable exception) { |
| LogHelper.log(new Status(IStatus.ERROR, GCActivator.ID, Messages.Error_in_extension, exception)); |
| } |
| |
| public void run() throws Exception { |
| IMarkSetProvider aMarkSetProvider = (IMarkSetProvider) cfg.createExecutableExtension(ATTRIBUTE_CLASS); |
| if (aMarkSetProvider == null) { |
| aProfileMarkSets = null; |
| return; |
| } |
| aProfileMarkSets = aMarkSetProvider.getMarkSets(aProfile); |
| } |
| |
| public MarkSet[] getResult() { |
| return aProfileMarkSets; |
| } |
| } |
| |
| private void contributeMarkSets(IConfigurationElement runAttribute, IProfile profile, boolean addRepositories) { |
| ParameterizedSafeRunnable providerExecutor = new ParameterizedSafeRunnable(runAttribute, profile); |
| SafeRunner.run(providerExecutor); |
| MarkSet[] aProfileMarkSets = providerExecutor.getResult(); |
| if (aProfileMarkSets[0] == null) |
| return; |
| |
| for (int i = 0; i < aProfileMarkSets.length; i++) { |
| if (aProfileMarkSets[i] == null) { |
| continue; |
| } |
| |
| for (int j = 0; j < aProfileMarkSets.length; j++) { |
| if (aProfileMarkSets[j] == null) { |
| continue; |
| } |
| Collection keys = (Collection) markSet.get(aProfileMarkSets[j].getRepo()); |
| if (keys == null) { |
| if (addRepositories) { |
| keys = new HashSet(); |
| markSet.put(aProfileMarkSets[j].getRepo(), keys); |
| addKeys(keys, aProfileMarkSets[j].getKeys()); |
| } |
| } else { |
| addKeys(keys, aProfileMarkSets[j].getKeys()); |
| } |
| } |
| } |
| } |
| |
| private void addKeys(Collection keyList, IArtifactKey[] keyArray) { |
| for (int i = 0; i < keyArray.length; i++) |
| keyList.add(keyArray[i]); |
| } |
| } |