Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import org.eclipse.core.internal.localstore.SafeChunkyOutputStream;
import org.eclipse.core.internal.localstore.SafeFileInputStream;
import org.eclipse.core.internal.localstore.SafeFileOutputStream;
import org.eclipse.core.internal.runtime.StartupTrace;
import org.eclipse.core.internal.utils.IStringPoolParticipant;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.internal.utils.Policy;
Expand Down Expand Up @@ -790,6 +791,7 @@ protected void resetSnapshots(IResource resource) throws CoreException {
* which were open when it was last saved.
*/
protected void restore(IProgressMonitor monitor) throws CoreException {
long tRestore = StartupTrace.begin();
if (Policy.DEBUG_RESTORE) {
Policy.debug("Restore workspace: starting..."); //$NON-NLS-1$
}
Expand All @@ -804,29 +806,44 @@ protected void restore(IProgressMonitor monitor) throws CoreException {
String msg = Messages.resources_startupProblems;
MultiStatus problems = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_READ_METADATA, msg, null);

long t;
t = StartupTrace.begin();
restoreMasterTable();
StartupTrace.record("SaveManager.restore/restoreMasterTable", t); //$NON-NLS-1$
// restore the saved tree and overlay the snapshots if any
t = StartupTrace.begin();
restoreTree(Policy.subMonitorFor(monitor, 10));
StartupTrace.record("SaveManager.restore/restoreTree", t); //$NON-NLS-1$
t = StartupTrace.begin();
restoreSnapshots(Policy.subMonitorFor(monitor, 10));
StartupTrace.record("SaveManager.restore/restoreSnapshots", t); //$NON-NLS-1$

// tolerate failure for non-critical information
// if startup fails, the entire workspace is shot
t = StartupTrace.begin();
try {
restoreMarkers(workspace.getRoot(), false, Policy.subMonitorFor(monitor, 10));
} catch (CoreException e) {
problems.merge(e.getStatus());
}
StartupTrace.record("SaveManager.restore/restoreMarkers", t); //$NON-NLS-1$
t = StartupTrace.begin();
try {
restoreSyncInfo(workspace.getRoot(), Policy.subMonitorFor(monitor, 10));
} catch (CoreException e) {
problems.merge(e.getStatus());
}
StartupTrace.record("SaveManager.restore/restoreSyncInfo", t); //$NON-NLS-1$
// restore meta info last because it might close a project if its description is not readable
t = StartupTrace.begin();
restoreMetaInfo(problems, Policy.subMonitorFor(monitor, 10));
StartupTrace.record("SaveManager.restore/restoreMetaInfo", t); //$NON-NLS-1$
t = StartupTrace.begin();
IProject[] roots = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
for (IProject root : roots) {
((Project) root).startup();
}
StartupTrace.record("SaveManager.restore/project.startup(all)", t); //$NON-NLS-1$
if (!problems.isOK()) {
Policy.log(problems);
}
Expand All @@ -835,6 +852,7 @@ protected void restore(IProgressMonitor monitor) throws CoreException {
}
} finally {
monitor.done();
StartupTrace.record("SaveManager.restore(total)", tRestore); //$NON-NLS-1$
}
if (Policy.DEBUG_RESTORE) {
Policy.debug("Restore workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
Expand Down Expand Up @@ -923,7 +941,9 @@ protected void restoreMarkers(IResource resource, boolean generateDeltas, IProgr
MarkerManager markerManager = workspace.getMarkerManager();
// when restoring a project, only load markers if it is open
if (resource.isAccessible()) {
long tRoot = StartupTrace.begin();
markerManager.restore(resource, generateDeltas, monitor);
StartupTrace.record("SaveManager.restore/restoreMarkers/readSnapshot", tRoot); //$NON-NLS-1$
}

// if we have the workspace root then restore markers for its projects
Expand All @@ -934,11 +954,13 @@ protected void restoreMarkers(IResource resource, boolean generateDeltas, IProgr
return;
}
IProject[] projects = ((IWorkspaceRoot) resource).getProjects(IContainer.INCLUDE_HIDDEN);
long tLoop = StartupTrace.begin();
for (IProject project : projects) {
if (project.isAccessible()) {
markerManager.restore(project, generateDeltas, monitor);
}
}
StartupTrace.record("SaveManager.restore/restoreMarkers/readDelta(count=" + projects.length + ")", tLoop); //$NON-NLS-1$ //$NON-NLS-2$
if (Policy.DEBUG_RESTORE_MARKERS) {
Policy.debug("Restore Markers for workspace: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
}
Expand Down Expand Up @@ -977,6 +999,7 @@ protected void restoreMetaInfo(MultiStatus problems, IProgressMonitor monitor) {
}
long start = System.currentTimeMillis();
IProject[] roots = workspace.getRoot().getProjects(IContainer.INCLUDE_HIDDEN);
long tLoop = StartupTrace.begin();
for (IProject root : roots) {
//fatal to throw exceptions during startup
try {
Expand All @@ -986,6 +1009,7 @@ protected void restoreMetaInfo(MultiStatus problems, IProgressMonitor monitor) {
problems.merge(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, root.getFullPath(), message, e));
}
}
StartupTrace.record("SaveManager.restore/restoreMetaInfo/loadMetaInfo(count=" + roots.length + ")", tLoop); //$NON-NLS-1$ //$NON-NLS-2$
if (Policy.DEBUG_RESTORE_METAINFO) {
Policy.debug("Restore workspace metainfo: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
}
Expand Down Expand Up @@ -1160,8 +1184,12 @@ protected void restoreTree(IProgressMonitor monitor) throws CoreException {
savedStates = Collections.synchronizedMap(new HashMap<>(10));
return;
}
long tOpen = StartupTrace.begin();
try (DataInputStream input = new DataInputStream(new SafeFileInputStream(treeLocation.toOSString(), tempLocation.toOSString(), TREE_BUFFER_SIZE))) {
StartupTrace.record("SaveManager.restore/restoreTree/open DataInputStream", tOpen); //$NON-NLS-1$
long tRead = StartupTrace.begin();
WorkspaceTreeReader.getReader(workspace, input.readInt()).readTree(input, monitor);
StartupTrace.record("SaveManager.restore/restoreTree/readTree (ElementTreeReader)", tRead); //$NON-NLS-1$
} catch (Exception e) { // "Unknown format" is passed as ResourceException
String msg = NLS.bind(Messages.resources_readMeta, treeLocation.toOSString());
throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, treeLocation, msg, e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.eclipse.core.internal.refresh.RefreshManager;
import org.eclipse.core.internal.resources.ComputeProjectOrder.Digraph;
import org.eclipse.core.internal.resources.ComputeProjectOrder.VertexOrder;
import org.eclipse.core.internal.runtime.StartupTrace;
import org.eclipse.core.internal.utils.BitMask;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.internal.utils.Policy;
Expand Down Expand Up @@ -2342,6 +2343,7 @@ protected long nextNodeId() {
* @see ResourcesPlugin#getWorkspace()
*/
public IStatus open(IProgressMonitor monitor) throws CoreException {
long tOpen = StartupTrace.begin();
if (!localMetaArea.hasSavedWorkspace()) {
localMetaArea.createMetaArea();
}
Expand All @@ -2359,29 +2361,42 @@ public IStatus open(IProgressMonitor monitor) throws CoreException {

// Set explicit workspace encoding if no projects exist in the workspace
if (!localMetaArea.hasSavedProjects()) {
long tEnc = StartupTrace.begin();
setExplicitWorkspaceEncoding();
StartupTrace.record("Workspace.open/setExplicitWorkspaceEncoding", tEnc); //$NON-NLS-1$
}
long tPrefOrder = StartupTrace.begin();
initializePreferenceLookupOrder();
StartupTrace.record("Workspace.open/initializePreferenceLookupOrder", tPrefOrder); //$NON-NLS-1$

// create root location
localMetaArea.locationFor(getRoot()).toFile().mkdirs();

long tStartup = StartupTrace.begin();
startup(new NullProgressMonitor());
StartupTrace.record("Workspace.open/startup", tStartup); //$NON-NLS-1$
// restart the notification manager so it is initialized with the right tree
long tNotif = StartupTrace.begin();
notificationManager.startup(null);
StartupTrace.record("Workspace.open/notificationManager.startup(restart)", tNotif); //$NON-NLS-1$
openFlag = true;
if (crashed || refreshRequested()) {
long tRefresh = StartupTrace.begin();
try {
refreshManager.refresh(getRoot());
} catch (RuntimeException e) {
StartupTrace.record("Workspace.open/crashRecoveryRefresh", tRefresh); //$NON-NLS-1$
StartupTrace.record("Workspace.open", tOpen); //$NON-NLS-1$
//don't fail entire open if refresh failed, just report as warning
return new ResourceStatus(IResourceStatus.INTERNAL_ERROR, IPath.ROOT,
Messages.resources_errorMultiRefresh, e);
}
StartupTrace.record("Workspace.open/crashRecoveryRefresh", tRefresh); //$NON-NLS-1$
Comment on lines +2388 to +2394
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The recording of the Workspace.open and Workspace.open/crashRecoveryRefresh spans is inconsistent and contains duplication.

  1. tOpen is recorded manually in the RuntimeException catch block (line 2389) and at the end of the method (line 2399), but it is missed if a CoreException is thrown earlier (e.g., during startup() at line 2376).
  2. tRefresh is recorded twice: once in the catch block (line 2388) and once after the try block (line 2394).

Consider wrapping the method body in a try-finally block for tOpen, and using a try-finally for the refresh logic. This ensures all spans are recorded regardless of how the method exits, matching the robust pattern used in SaveManager.restore() and Workspace.startup().

}
//finally register a string pool participant
stringPoolJob = new StringPoolJob();
stringPoolJob.addStringPoolParticipant(saveManager, getRoot());
StartupTrace.record("Workspace.open", tOpen); //$NON-NLS-1$
return Status.OK_STATUS;
}

Expand Down Expand Up @@ -2654,45 +2669,76 @@ public String[] sortNatureSet(String[] natureIds) {
* Starts all the workspace manager classes.
*/
protected void startup(IProgressMonitor monitor) throws CoreException {
long tAll = StartupTrace.begin();
// ensure the tree is locked during the startup notification
try {
long t;
t = StartupTrace.begin();
_workManager = new WorkManager(this);
_workManager.startup(null);
StartupTrace.record("Workspace.startup/WorkManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
fileSystemManager = new FileSystemResourceManager(this);
fileSystemManager.startup(monitor);
StartupTrace.record("Workspace.startup/FileSystemResourceManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
pathVariableManager = new PathVariableManager();
pathVariableManager.startup(null);
StartupTrace.record("Workspace.startup/PathVariableManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
natureManager = new NatureManager(this);
natureManager.startup(null);
StartupTrace.record("Workspace.startup/NatureManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
filterManager = new FilterTypeManager();
filterManager.startup(null);
StartupTrace.record("Workspace.startup/FilterTypeManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
buildManager = new BuildManager(this, getWorkManager().getLock());
buildManager.startup(null);
StartupTrace.record("Workspace.startup/BuildManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
notificationManager = new NotificationManager(this);
notificationManager.startup(null);
StartupTrace.record("Workspace.startup/NotificationManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
markerManager = new MarkerManager(this);
markerManager.startup(null);
StartupTrace.record("Workspace.startup/MarkerManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
synchronizer = new Synchronizer(this);
saveManager = new SaveManager(this);
saveManager.startup(null);
StartupTrace.record("Workspace.startup/SaveManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
propertyManager = new PropertyManager2(this);
propertyManager.startup(monitor);
StartupTrace.record("Workspace.startup/PropertyManager2", t); //$NON-NLS-1$
t = StartupTrace.begin();
charsetManager = new CharsetManager(this);
charsetManager.startup(null);
StartupTrace.record("Workspace.startup/CharsetManager", t); //$NON-NLS-1$
t = StartupTrace.begin();
contentDescriptionManager = new ContentDescriptionManager(this);
contentDescriptionManager.startup(null);
StartupTrace.record("Workspace.startup/ContentDescriptionManager", t); //$NON-NLS-1$
//must start after save manager, because (read) access to tree is needed
//must start after other managers to avoid potential cyclic dependency on uninitialized managers (see bug 316182)
//must start before alias manager (see bug 94829)
t = StartupTrace.begin();
refreshManager = new RefreshManager(this);
refreshManager.startup(null);
StartupTrace.record("Workspace.startup/RefreshManager", t); //$NON-NLS-1$
//must start at the end to avoid potential cyclic dependency on other uninitialized managers (see bug 369177)
t = StartupTrace.begin();
aliasManager = new AliasManager(this);
aliasManager.startup(null);
StartupTrace.record("Workspace.startup/AliasManager", t); //$NON-NLS-1$
} finally {
//unlock tree even in case of failure, otherwise shutdown will also fail
treeLocked = null;
_workManager.postWorkspaceStartup();
StartupTrace.record("Workspace.startup(total)", tAll); //$NON-NLS-1$
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
/**
* Resource change events describe changes to resources.
* <p>
* There are currently five different types of resource change events:
* The following types of resource change events are reported:
* <ul>
* <li>
* Before-the-fact batch reports of arbitrary creations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Hashtable;
import java.util.List;
import org.eclipse.core.internal.resources.Workspace;
import org.eclipse.core.internal.runtime.StartupTrace;
import org.eclipse.core.internal.utils.Messages;
import org.eclipse.core.internal.utils.Policy;
import org.eclipse.core.runtime.CoreException;
Expand Down Expand Up @@ -549,20 +550,28 @@ public void stop(BundleContext context) throws Exception {
*/
@Override
public void start(BundleContext context) throws Exception {
long tTotal = StartupTrace.begin();
long tSuper = StartupTrace.begin();
super.start(context);
StartupTrace.record("ResourcesPlugin.start/super.start", tSuper); //$NON-NLS-1$
workspaceInitCustomizer = new WorkspaceInitCustomizer(context);
// register debug options listener
long tDbg = StartupTrace.begin();
Hashtable<String, String> properties = new Hashtable<>(2);
properties.put(DebugOptions.LISTENER_SYMBOLICNAME, PI_RESOURCES);
debugRegistration = context.registerService(DebugOptionsListener.class, Policy.RESOURCES_DEBUG_OPTIONS_LISTENER,
properties);
StartupTrace.record("ResourcesPlugin.start/registerDebugOptions", tDbg); //$NON-NLS-1$
instanceLocationTracker = new ServiceTracker<>(context,
context.createFilter(String.format("(&%s(%s=*))", Location.INSTANCE_FILTER, //$NON-NLS-1$
Location.SERVICE_PROPERTY_URL)),
workspaceInitCustomizer);
plugin = this; // must before open the tracker, as this can cause the registration of the
// workspace and this might trigger code that calls the static method then.
long tOpen = StartupTrace.begin();
instanceLocationTracker.open();
StartupTrace.record("ResourcesPlugin.start/openInstanceLocationTracker", tOpen); //$NON-NLS-1$
StartupTrace.record("ResourcesPlugin.start (total)", tTotal); //$NON-NLS-1$
}

private final class WorkspaceInitCustomizer implements ServiceTrackerCustomizer<Location, Workspace> {
Expand All @@ -579,20 +588,26 @@ public Workspace addingService(ServiceReference<Location> reference) {
if (workspace != null) {
return null; // there can only be one workspace right now...
}
long tLoc = StartupTrace.begin();
Location location = context.getService(reference);
StartupTrace.record("ResourcesPlugin.start/openInstanceLocationTracker/open instance Location", tLoc); //$NON-NLS-1$
if (location == null) {
return null; // we can't use that service...
}
// the workspace is accessible from now on, this is because some plugins require
// access to it in the early startup phase
long tCtor = StartupTrace.begin();
workspace = new Workspace();
StartupTrace.record("ResourcesPlugin.start/openInstanceLocationTracker/new Workspace", tCtor); //$NON-NLS-1$
IStatus result;
try {
result = workspace.open(null);
if (!result.isOK()) {
getLog().log(result);
}
long tReg = StartupTrace.begin();
workspaceRegistration = context.registerService(IWorkspace.class, workspace, null);
StartupTrace.record("ResourcesPlugin.start/openInstanceLocationTracker/register workspace with platform", tReg); //$NON-NLS-1$
return workspace;
} catch (CoreException e) {
getLog().log(e.getStatus());
Expand Down
Loading