Copyright (c) 2004, 2015 IBM Corporation and others.
This program and the accompanying materials
are made available under the terms of the Eclipse Public License 2.0
which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-2.0/
SPDX-License-Identifier: EPL-2.0
Contributors:
IBM - Initial API and implementation
James Blackburn (Broadcom Corp.) - ongoing development
/*******************************************************************************
* Copyright (c) 2004, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM - Initial API and implementation
* James Blackburn (Broadcom Corp.) - ongoing development
*******************************************************************************/
package org.eclipse.core.internal.utils;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
import org.osgi.framework.Bundle;
Performs string sharing passes on all string pool participants registered
with the platform.
/**
* Performs string sharing passes on all string pool participants registered
* with the platform.
*/
public class StringPoolJob extends Job {
private static final long INITIAL_DELAY = 300000; // five minutes
private static final long RESCHEDULE_DELAY = 900000; // fifteen minutes
private long lastDuration;
Stores all registered string pool participants, along with the scheduling
rule required when running it.
/**
* Stores all registered string pool participants, along with the scheduling
* rule required when running it.
*/
private Map<IStringPoolParticipant, ISchedulingRule> participants = Collections.synchronizedMap(new HashMap<IStringPoolParticipant, ISchedulingRule>(10));
private final Bundle systemBundle = Platform.getBundle("org.eclipse.osgi"); //$NON-NLS-1$
public StringPoolJob() {
super(Messages.utils_stringJobName);
setSystem(true);
setPriority(DECORATE);
}
Adds a string pool participant. The job periodically builds
a string pool and asks all registered participants to share their strings in
the pool. Once all participants have added their strings to the pool, the
pool is discarded to avoid additional memory overhead.
Adding a participant that is equal to a participant already registered will
replace the scheduling rule associated with the participant, but will otherwise
be ignored.
Params: - participant – The participant to add
- rule – The scheduling rule that must be owned at the time the
participant is called. This allows a participant to protect their data structures
against access at unsafe times.
See Also: Since: 3.1
/**
* Adds a string pool participant. The job periodically builds
* a string pool and asks all registered participants to share their strings in
* the pool. Once all participants have added their strings to the pool, the
* pool is discarded to avoid additional memory overhead.
*
* Adding a participant that is equal to a participant already registered will
* replace the scheduling rule associated with the participant, but will otherwise
* be ignored.
*
* @param participant The participant to add
* @param rule The scheduling rule that must be owned at the time the
* participant is called. This allows a participant to protect their data structures
* against access at unsafe times.
*
* @see #removeStringPoolParticipant(IStringPoolParticipant)
* @since 3.1
*/
public void addStringPoolParticipant(IStringPoolParticipant participant, ISchedulingRule rule) {
participants.put(participant, rule);
if (getState() == Job.SLEEPING)
wakeUp(INITIAL_DELAY);
else
schedule(INITIAL_DELAY);
}
Removes the indicated log listener from the set of registered string
pool participants. If no such participant is registered, no action is taken.
Params: - participant – the participant to deregister
See Also: Since: 3.1
/**
* Removes the indicated log listener from the set of registered string
* pool participants. If no such participant is registered, no action is taken.
*
* @param participant the participant to deregister
* @see #addStringPoolParticipant(IStringPoolParticipant, ISchedulingRule)
* @since 3.1
*/
public void removeStringPoolParticipant(IStringPoolParticipant participant) {
participants.remove(participant);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
//if the system is shutting down, don't build
if (systemBundle.getState() == Bundle.STOPPING)
return Status.OK_STATUS;
//copy current participants to handle concurrent additions and removals to map
Map.Entry<IStringPoolParticipant, ISchedulingRule>[] entries = participants.entrySet().toArray(new Map.Entry[participants.size()]);
ISchedulingRule[] rules = new ISchedulingRule[entries.length];
IStringPoolParticipant[] toRun = new IStringPoolParticipant[entries.length];
for (int i = 0; i < toRun.length; i++) {
toRun[i] = entries[i].getKey();
rules[i] = entries[i].getValue();
}
final ISchedulingRule rule = MultiRule.combine(rules);
long start = -1;
int savings = 0;
final IJobManager jobManager = Job.getJobManager();
try {
jobManager.beginRule(rule, monitor);
start = System.currentTimeMillis();
savings = shareStrings(toRun, monitor);
} finally {
jobManager.endRule(rule);
}
if (start > 0) {
lastDuration = System.currentTimeMillis() - start;
if (Policy.DEBUG_STRINGS)
Policy.debug("String sharing saved " + savings + " bytes in: " + lastDuration); //$NON-NLS-1$ //$NON-NLS-2$
}
//throttle frequency if it takes too long
long scheduleDelay = Math.max(RESCHEDULE_DELAY, lastDuration * 100);
if (Policy.DEBUG_STRINGS)
Policy.debug("Rescheduling string sharing job in: " + scheduleDelay); //$NON-NLS-1$
schedule(scheduleDelay);
return Status.OK_STATUS;
}
private int shareStrings(IStringPoolParticipant[] toRun, IProgressMonitor monitor) {
final StringPool pool = new StringPool();
for (final IStringPoolParticipant current : toRun) {
if (monitor.isCanceled())
break;
SafeRunner.run(new ISafeRunnable() {
@Override
public void handleException(Throwable exception) {
//exceptions are already logged, so nothing to do
}
@Override
public void run() {
current.shareStrings(pool);
}
});
}
return pool.getSavedStringCount();
}
}