1 11 package org.eclipse.core.internal.resources; 12 13 import java.io.*; 14 import java.util.*; 15 import org.eclipse.core.internal.events.*; 16 import org.eclipse.core.internal.localstore.*; 17 import org.eclipse.core.internal.utils.*; 18 import org.eclipse.core.internal.watson.*; 19 import org.eclipse.core.resources.*; 20 import org.eclipse.core.runtime.*; 21 import org.eclipse.core.runtime.jobs.ISchedulingRule; 22 import org.eclipse.core.runtime.jobs.Job; 23 import org.eclipse.osgi.util.NLS; 24 25 public class SaveManager implements IElementInfoFlattener, IManager, IStringPoolParticipant { 26 protected static final String CLEAR_DELTA_PREFIX = "clearDelta_"; protected static final String DELTA_EXPIRATION_PREFIX = "deltaExpiration_"; protected static final int DONE_SAVING = 3; 29 30 33 private static final long MIN_SNAPSHOT_DELAY = 1000 * 30L; 35 39 protected static final int NO_OP_THRESHOLD = 20; 40 41 42 protected static final int PREPARE_TO_SAVE = 1; 43 protected static final int ROLLBACK = 4; 44 protected static final String SAVE_NUMBER_PREFIX = "saveNumber_"; protected static final int SAVING = 2; 46 protected ElementTree lastSnap; 47 protected Properties masterTable; 48 49 54 private boolean isSaving = false; 55 56 59 protected int noopCount = 0; 60 63 protected int operationCount = 0; 64 65 protected long persistMarkers = 0l; 67 protected long persistSyncInfo = 0l; 68 69 75 protected Map savedStates; 76 77 83 protected Map saveParticipants; 84 85 protected final DelayedSnapshotJob snapshotJob; 86 87 protected boolean snapshotRequested; 88 protected Workspace workspace; 89 private static final String DEBUG_START = " starting..."; private static final String DEBUG_FULL_SAVE = "Full save on workspace: "; private static final String DEBUG_PROJECT_SAVE = "Save on project "; private static final String DEBUG_SNAPSHOT = "Snapshot: "; private static final int TREE_BUFFER_SIZE = 1024 * 64; 96 public SaveManager(Workspace workspace) { 97 this.workspace = workspace; 98 this.snapshotJob = new DelayedSnapshotJob(this); 99 snapshotRequested = false; 100 saveParticipants = Collections.synchronizedMap(new HashMap(10)); 101 } 102 103 public ISavedState addParticipant(Plugin plugin, ISaveParticipant participant) throws CoreException { 104 if (saveParticipants.put(plugin, participant) != null) 106 return null; 107 String id = plugin.getBundle().getSymbolicName(); 108 SavedState state = (SavedState) savedStates.get(id); 109 if (state != null) { 110 if (isDeltaCleared(id)) { 111 state.forgetTrees(); 113 removeClearDeltaMarks(id); 114 } else { 115 try { 116 workspace.prepareOperation(null, null); 119 workspace.beginOperation(true); 120 state.newTree = workspace.getElementTree(); 121 } finally { 122 workspace.endOperation(null, false, null); 123 } 124 return state; 125 } 126 } 127 if (getSaveNumber(id) > 0) 129 return new SavedState(workspace, id, null, null); 130 return null; 131 } 132 133 protected void broadcastLifecycle(final int lifecycle, Map contexts, final MultiStatus warnings, IProgressMonitor monitor) { 134 monitor = Policy.monitorFor(monitor); 135 try { 136 monitor.beginTask("", contexts.size()); for (final Iterator it = contexts.entrySet().iterator(); it.hasNext();) { 138 Map.Entry entry = (Map.Entry) it.next(); 139 Plugin plugin = (Plugin) entry.getKey(); 140 final ISaveParticipant participant = (ISaveParticipant) saveParticipants.get(plugin); 141 if (participant == null) { 143 monitor.worked(1); 144 continue; 145 } 146 final SaveContext context = (SaveContext) entry.getValue(); 147 148 ISafeRunnable code = new ISafeRunnable() { 149 150 public void handleException(Throwable e) { 151 String message = Messages.resources_saveProblem; 152 IStatus status = new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, message, e); 153 warnings.add(status); 154 155 156 it.remove(); 157 } 158 159 public void run() throws Exception { 160 executeLifecycle(lifecycle, participant, context); 161 } 162 }; 163 SafeRunner.run(code); 164 monitor.worked(1); 165 } 166 } finally { 167 monitor.done(); 168 } 169 } 170 171 175 protected void clearDeltaExpiration(String pluginId) { 176 masterTable.remove(DELTA_EXPIRATION_PREFIX + pluginId); 177 } 178 179 protected void cleanMasterTable() { 180 for (Iterator it = masterTable.keySet().iterator(); it.hasNext();) { 182 String key = (String ) it.next(); 183 if (!key.endsWith(LocalMetaArea.F_TREE)) 184 continue; 185 String prefix = key.substring(0, key.length() - LocalMetaArea.F_TREE.length()); 186 if (prefix.equals(Path.ROOT.toString())) 188 continue; 189 IProject project = workspace.getRoot().getProject(prefix); 190 if (!project.exists() || project.isOpen()) 191 it.remove(); 192 } 193 IPath location = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES); 194 IPath backup = workspace.getMetaArea().getBackupLocationFor(location); 195 try { 196 saveMasterTable(backup); 197 } catch (CoreException e) { 198 Policy.log(e.getStatus()); 199 backup.toFile().delete(); 200 return; 201 } 202 if (location.toFile().exists() && !location.toFile().delete()) 203 return; 204 try { 205 saveMasterTable(location); 206 } catch (CoreException e) { 207 Policy.log(e.getStatus()); 208 location.toFile().delete(); 209 return; 210 } 211 backup.toFile().delete(); 212 } 213 214 219 protected void clearSavedDelta() { 220 synchronized (saveParticipants) { 221 for (Iterator i = saveParticipants.keySet().iterator(); i.hasNext();) { 222 String pluginId = ((Plugin) i.next()).getBundle().getSymbolicName(); 223 masterTable.setProperty(CLEAR_DELTA_PREFIX + pluginId, "true"); } 225 } 226 } 227 228 232 protected void collapseTrees() throws CoreException { 233 235 ArrayList trees = new ArrayList(); 237 synchronized (savedStates) { 238 for (Iterator i = savedStates.values().iterator(); i.hasNext();) { 239 SavedState state = (SavedState) i.next(); 240 if (state.oldTree != null) { 241 trees.add(state.oldTree); 242 } 243 } 244 } 245 246 IProject[] projects = workspace.getRoot().getProjects(); 248 for (int i = 0; i < projects.length; i++) { 249 IProject project = projects[i]; 250 if (project.isOpen()) { 251 ArrayList builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project); 252 if (builderInfos != null) { 253 for (Iterator it = builderInfos.iterator(); it.hasNext();) { 254 BuilderPersistentInfo info = (BuilderPersistentInfo) it.next(); 255 trees.add(info.getLastBuiltTree()); 256 } 257 } 258 } 259 } 260 261 if (trees.isEmpty()) 263 return; 264 265 trees.add(workspace.getElementTree()); 267 268 ElementTree[] treeArray = new ElementTree[trees.size()]; 272 trees.toArray(treeArray); 273 ElementTree[] sorted = sortTrees(treeArray); 274 if (sorted == null) 277 return; 278 for (int i = 1; i < sorted.length; i++) 279 sorted[i].collapseTo(sorted[i - 1]); 280 } 281 282 protected void commit(Map contexts) throws CoreException { 283 for (Iterator i = contexts.values().iterator(); i.hasNext();) 284 ((SaveContext) i.next()).commit(); 285 } 286 287 292 protected Map computeSaveContexts(Plugin[] plugins, int kind, IProject project) { 293 HashMap result = new HashMap(plugins.length); 294 for (int i = 0; i < plugins.length; i++) { 295 Plugin plugin = plugins[i]; 296 try { 297 SaveContext context = new SaveContext(plugin, kind, project); 298 result.put(plugin, context); 299 } catch (CoreException e) { 300 Policy.log(e.getStatus()); 302 } 303 } 304 return result; 305 } 306 307 315 protected Map computeStatesToSave(Map contexts, ElementTree current) { 316 HashMap result = new HashMap(savedStates.size() * 2); 317 synchronized (savedStates) { 318 for (Iterator i = savedStates.values().iterator(); i.hasNext();) { 319 SavedState state = (SavedState) i.next(); 320 if (state.oldTree != null) 321 result.put(state.pluginId, state.oldTree); 322 } 323 } 324 for (Iterator i = contexts.values().iterator(); i.hasNext();) { 325 SaveContext context = (SaveContext) i.next(); 326 if (!context.isDeltaNeeded()) 327 continue; 328 String pluginId = context.getPlugin().getBundle().getSymbolicName(); 329 result.put(pluginId, current); 330 } 331 return result; 332 } 333 334 protected void executeLifecycle(int lifecycle, ISaveParticipant participant, SaveContext context) throws CoreException { 335 switch (lifecycle) { 336 case PREPARE_TO_SAVE : 337 participant.prepareToSave(context); 338 break; 339 case SAVING : 340 try { 341 if (ResourceStats.TRACE_SAVE_PARTICIPANTS) 342 ResourceStats.startSave(participant); 343 participant.saving(context); 344 } finally { 345 if (ResourceStats.TRACE_SAVE_PARTICIPANTS) 346 ResourceStats.endSave(); 347 } 348 break; 349 case DONE_SAVING : 350 participant.doneSaving(context); 351 break; 352 case ROLLBACK : 353 participant.rollback(context); 354 break; 355 default : 356 Assert.isTrue(false, "Invalid save lifecycle code"); } 358 } 359 360 public void forgetSavedTree(String pluginId) { 361 if (pluginId == null) { 362 synchronized (savedStates) { 363 for (Iterator i = savedStates.values().iterator(); i.hasNext();) 364 ((SavedState) i.next()).forgetTrees(); 365 } 366 } else { 367 SavedState state = (SavedState) savedStates.get(pluginId); 368 if (state != null) 369 state.forgetTrees(); 370 } 371 } 372 373 376 protected long getDeltaExpiration(String pluginId) { 377 String result = masterTable.getProperty(DELTA_EXPIRATION_PREFIX + pluginId); 378 return (result == null) ? System.currentTimeMillis() : new Long (result).longValue(); 379 } 380 381 protected Properties getMasterTable() { 382 return masterTable; 383 } 384 385 public int getSaveNumber(String pluginId) { 386 String value = masterTable.getProperty(SAVE_NUMBER_PREFIX + pluginId); 387 return (value == null) ? 0 : new Integer (value).intValue(); 388 } 389 390 protected Plugin[] getSaveParticipantPlugins() { 391 synchronized (saveParticipants) { 392 return (Plugin[]) saveParticipants.keySet().toArray(new Plugin[saveParticipants.size()]); 393 } 394 } 395 396 400 private void hookEndSave(int kind, IProject project, long start) { 401 if (ResourceStats.TRACE_SNAPSHOT && kind == ISaveContext.SNAPSHOT) 402 ResourceStats.endSnapshot(); 403 if (Policy.DEBUG_SAVE) { 404 String endMessage = null; 405 switch (kind) { 406 case ISaveContext.FULL_SAVE : 407 endMessage = DEBUG_FULL_SAVE; 408 break; 409 case ISaveContext.SNAPSHOT : 410 endMessage = DEBUG_SNAPSHOT; 411 break; 412 case ISaveContext.PROJECT_SAVE : 413 endMessage = DEBUG_PROJECT_SAVE + project.getFullPath() + ": "; break; 415 } 416 if (endMessage != null) 417 System.out.println(endMessage + (System.currentTimeMillis() - start) + "ms"); } 419 } 420 421 425 private void hookStartSave(int kind, Project project) { 426 if (ResourceStats.TRACE_SNAPSHOT && kind == ISaveContext.SNAPSHOT) 427 ResourceStats.startSnapshot(); 428 if (Policy.DEBUG_SAVE) { 429 switch (kind) { 430 case ISaveContext.FULL_SAVE : 431 System.out.println(DEBUG_FULL_SAVE + DEBUG_START); 432 break; 433 case ISaveContext.SNAPSHOT : 434 System.out.println(DEBUG_SNAPSHOT + DEBUG_START); 435 break; 436 case ISaveContext.PROJECT_SAVE : 437 System.out.println(DEBUG_PROJECT_SAVE + project.getFullPath() + DEBUG_START); 438 break; 439 } 440 } 441 } 442 443 446 protected void initSnap(IProgressMonitor monitor) throws CoreException { 447 snapshotJob.cancel(); 449 lastSnap = workspace.getElementTree(); 452 lastSnap.immutable(); 453 workspace.newWorkingTree(); 454 operationCount = 0; 455 IPath snapPath = workspace.getMetaArea().getSnapshotLocationFor(workspace.getRoot()); 457 java.io.File file = snapPath.toFile(); 458 if (file.exists()) 459 file.delete(); 460 if (file.exists()) { 461 String message = Messages.resources_snapInit; 462 throw new ResourceException(IResourceStatus.FAILED_DELETE_METADATA, null, message, null); 463 } 464 } 465 466 protected boolean isDeltaCleared(String pluginId) { 467 String clearDelta = masterTable.getProperty(CLEAR_DELTA_PREFIX + pluginId); 468 return clearDelta != null && clearDelta.equals("true"); } 470 471 protected boolean isOldPluginTree(String pluginId) { 472 if (isDeltaCleared(pluginId)) 474 return false; 475 if (Platform.getBundle(pluginId) == null) 477 return true; 478 479 long deltaAge = System.currentTimeMillis() - getDeltaExpiration(pluginId); 481 return deltaAge > workspace.internalGetDescription().getDeltaExpiration(); 482 } 483 484 487 public Object readElement(IPath path, DataInput input) throws IOException { 488 Assert.isNotNull(path); 489 Assert.isNotNull(input); 490 int flags = input.readInt(); 492 int type = (flags & ICoreConstants.M_TYPE) >> ICoreConstants.M_TYPE_START; 493 ResourceInfo info = workspace.newElement(type); 494 info.readFrom(flags, input); 495 return info; 496 } 497 498 502 protected void removeClearDeltaMarks() { 503 synchronized (saveParticipants) { 504 for (Iterator i = saveParticipants.keySet().iterator(); i.hasNext();) { 505 String pluginId = ((Plugin) i.next()).getBundle().getSymbolicName(); 506 removeClearDeltaMarks(pluginId); 507 } 508 } 509 } 510 511 protected void removeClearDeltaMarks(String pluginId) { 512 masterTable.setProperty(CLEAR_DELTA_PREFIX + pluginId, "false"); } 514 515 protected void removeFiles(java.io.File root, String [] candidates, List exclude) { 516 for (int i = 0; i < candidates.length; i++) { 517 boolean delete = true; 518 for (ListIterator it = exclude.listIterator(); it.hasNext();) { 519 String s = (String ) it.next(); 520 if (s.equals(candidates[i])) { 521 it.remove(); 522 delete = false; 523 break; 524 } 525 } 526 if (delete) 527 new java.io.File (root, candidates[i]).delete(); 528 } 529 } 530 531 private void removeGarbage(DataOutputStream output, IPath location, IPath tempLocation) throws IOException { 532 if (output.size() == 0) { 533 output.close(); 534 location.toFile().delete(); 535 tempLocation.toFile().delete(); 536 } 537 } 538 539 public void removeParticipant(Plugin plugin) { 540 saveParticipants.remove(plugin); 541 } 542 543 protected void removeUnusedSafeTables() { 544 List valuables = new ArrayList(10); 545 IPath location = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES); 546 valuables.add(location.lastSegment()); for (Enumeration e = masterTable.keys(); e.hasMoreElements();) { 548 String key = (String ) e.nextElement(); 549 if (key.startsWith(SAVE_NUMBER_PREFIX)) { 550 String pluginId = key.substring(SAVE_NUMBER_PREFIX.length()); 551 valuables.add(workspace.getMetaArea().getSafeTableLocationFor(pluginId).lastSegment()); 552 } 553 } 554 java.io.File target = location.toFile().getParentFile(); 555 String [] candidates = target.list(); 556 if (candidates == null) 557 return; 558 removeFiles(target, candidates, valuables); 559 } 560 561 protected void removeUnusedTreeFiles() { 562 List valuables = new ArrayList(10); 564 IPath location = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), false); 565 valuables.add(location.lastSegment()); 566 java.io.File target = location.toFile().getParentFile(); 567 FilenameFilter filter = new FilenameFilter() { 568 public boolean accept(java.io.File dir, String name) { 569 return name.endsWith(LocalMetaArea.F_TREE); 570 } 571 }; 572 String [] candidates = target.list(filter); 573 if (candidates != null) 574 removeFiles(target, candidates, valuables); 575 576 IProject[] projects = workspace.getRoot().getProjects(); 578 for (int i = 0; i < projects.length; i++) { 579 location = workspace.getMetaArea().getTreeLocationFor(projects[i], false); 580 valuables.add(location.lastSegment()); 581 target = location.toFile().getParentFile(); 582 candidates = target.list(filter); 583 if (candidates != null) 584 removeFiles(target, candidates, valuables); 585 } 586 } 587 588 public void requestSnapshot() { 589 snapshotRequested = true; 590 } 591 592 596 protected void resetSnapshots(IResource resource) throws CoreException { 597 Assert.isLegal(resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT); 598 String message; 599 600 java.io.File file = workspace.getMetaArea().getMarkersSnapshotLocationFor(resource).toFile(); 602 if (file.exists()) 603 file.delete(); 604 if (file.exists()) { 605 message = Messages.resources_resetMarkers; 606 throw new ResourceException(IResourceStatus.FAILED_DELETE_METADATA, resource.getFullPath(), message, null); 607 } 608 609 file = workspace.getMetaArea().getSyncInfoSnapshotLocationFor(resource).toFile(); 611 if (file.exists()) 612 file.delete(); 613 if (file.exists()) { 614 message = Messages.resources_resetSync; 615 throw new ResourceException(IResourceStatus.FAILED_DELETE_METADATA, resource.getFullPath(), message, null); 616 } 617 618 if (resource.getType() == IResource.PROJECT) 621 return; 622 IProject[] projects = ((IWorkspaceRoot) resource).getProjects(); 623 for (int i = 0; i < projects.length; i++) 624 resetSnapshots(projects[i]); 625 } 626 627 631 protected void restore(IProgressMonitor monitor) throws CoreException { 632 if (Policy.DEBUG_RESTORE) 633 System.out.println("Restore workspace: starting..."); long start = System.currentTimeMillis(); 635 monitor = Policy.monitorFor(monitor); 636 try { 637 monitor.beginTask("", 50); workspace.newWorkingTree(); 641 try { 642 String msg = Messages.resources_startupProblems; 643 MultiStatus problems = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.FAILED_READ_METADATA, msg, null); 644 645 restoreMasterTable(); 646 restoreTree(Policy.subMonitorFor(monitor, 10)); 648 restoreSnapshots(Policy.subMonitorFor(monitor, 10)); 649 650 try { 653 restoreMarkers(workspace.getRoot(), false, Policy.subMonitorFor(monitor, 10)); 654 } catch (CoreException e) { 655 problems.merge(e.getStatus()); 656 } 657 try { 658 restoreSyncInfo(workspace.getRoot(), Policy.subMonitorFor(monitor, 10)); 659 } catch (CoreException e) { 660 problems.merge(e.getStatus()); 661 } 662 restoreMetaInfo(problems, Policy.subMonitorFor(monitor, 10)); 664 IProject[] roots = workspace.getRoot().getProjects(); 665 for (int i = 0; i < roots.length; i++) 666 ((Project) roots[i]).startup(); 667 if (!problems.isOK()) 668 Policy.log(problems); 669 } finally { 670 workspace.getElementTree().immutable(); 671 } 672 } finally { 673 monitor.done(); 674 } 675 if (Policy.DEBUG_RESTORE) 676 System.out.println("Restore workspace: " + (System.currentTimeMillis() - start) + "ms"); } 678 679 683 protected void restore(Project project, IProgressMonitor monitor) throws CoreException { 684 if (Policy.DEBUG_RESTORE) 685 System.out.println("Restore project " + project.getFullPath() + ": starting..."); long start = System.currentTimeMillis(); 687 monitor = Policy.monitorFor(monitor); 688 try { 689 monitor.beginTask("", 40); if (project.isOpen()) { 691 restoreTree(project, Policy.subMonitorFor(monitor, 10)); 692 } else { 693 monitor.worked(10); 694 } 695 restoreMarkers(project, true, Policy.subMonitorFor(monitor, 10)); 696 restoreSyncInfo(project, Policy.subMonitorFor(monitor, 10)); 697 restoreMetaInfo(project, Policy.subMonitorFor(monitor, 10)); 699 } finally { 700 monitor.done(); 701 } 702 if (Policy.DEBUG_RESTORE) 703 System.out.println("Restore project " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); } 705 706 710 protected void restoreMarkers(IResource resource, boolean generateDeltas, IProgressMonitor monitor) throws CoreException { 711 Assert.isLegal(resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT); 712 long start = System.currentTimeMillis(); 713 MarkerManager markerManager = workspace.getMarkerManager(); 714 if (resource.isAccessible()) 716 markerManager.restore(resource, generateDeltas, monitor); 717 718 if (resource.getType() == IResource.PROJECT) { 720 if (Policy.DEBUG_RESTORE_MARKERS) { 721 System.out.println("Restore Markers for " + resource.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); } 723 return; 724 } 725 IProject[] projects = ((IWorkspaceRoot) resource).getProjects(); 726 for (int i = 0; i < projects.length; i++) 727 if (projects[i].isAccessible()) 728 markerManager.restore(projects[i], generateDeltas, monitor); 729 if (Policy.DEBUG_RESTORE_MARKERS) { 730 System.out.println("Restore Markers for workspace: " + (System.currentTimeMillis() - start) + "ms"); } 732 } 733 734 protected void restoreMasterTable() throws CoreException { 735 long start = System.currentTimeMillis(); 736 masterTable = new Properties(); 737 IPath location = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES); 738 java.io.File target = location.toFile(); 739 if (!target.exists()) { 740 location = workspace.getMetaArea().getBackupLocationFor(location); 741 target = location.toFile(); 742 if (!target.exists()) 743 return; 744 } 745 try { 746 SafeChunkyInputStream input = new SafeChunkyInputStream(target); 747 try { 748 masterTable.load(input); 749 } finally { 750 input.close(); 751 } 752 } catch (IOException e) { 753 String message = Messages.resources_exMasterTable; 754 throw new ResourceException(IResourceStatus.INTERNAL_ERROR, null, message, e); 755 } 756 if (Policy.DEBUG_RESTORE_MASTERTABLE) 757 System.out.println("Restore master table for " + location + ": " + (System.currentTimeMillis() - start) + "ms"); } 759 760 764 protected void restoreMetaInfo(MultiStatus problems, IProgressMonitor monitor) { 765 if (Policy.DEBUG_RESTORE_METAINFO) 766 System.out.println("Restore workspace metainfo: starting..."); long start = System.currentTimeMillis(); 768 IProject[] roots = workspace.getRoot().getProjects(); 769 for (int i = 0; i < roots.length; i++) { 770 try { 772 restoreMetaInfo((Project) roots[i], monitor); 773 } catch (CoreException e) { 774 String message = NLS.bind(Messages.resources_readMeta, roots[i].getName()); 775 problems.merge(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, roots[i].getFullPath(), message, e)); 776 } 777 } 778 if (Policy.DEBUG_RESTORE_METAINFO) 779 System.out.println("Restore workspace metainfo: " + (System.currentTimeMillis() - start) + "ms"); } 781 782 786 protected void restoreMetaInfo(Project project, IProgressMonitor monitor) throws CoreException { 787 long start = System.currentTimeMillis(); 788 ProjectDescription description = null; 789 CoreException failure = null; 790 try { 791 if (project.isOpen()) 792 description = workspace.getFileSystemManager().read(project, true); 793 else 794 description = workspace.getMetaArea().readOldDescription(project); 797 } catch (CoreException e) { 798 failure = e; 799 } 800 if (description == null) { 804 description = new ProjectDescription(); 805 description.setName(project.getName()); 806 workspace.getMetaArea().readPrivateDescription(project, description); 808 } 809 project.internalSetDescription(description, false); 810 if (failure != null) { 811 project.internalClose(); 813 throw failure; 814 } 815 if (Policy.DEBUG_RESTORE_METAINFO) 816 System.out.println("Restore metainfo for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); } 818 819 826 protected void restoreSnapshots(IProgressMonitor monitor) throws CoreException { 827 long start = System.currentTimeMillis(); 828 monitor = Policy.monitorFor(monitor); 829 String message; 830 try { 831 monitor.beginTask("", Policy.totalWork); IPath snapLocation = workspace.getMetaArea().getSnapshotLocationFor(workspace.getRoot()); 833 java.io.File localFile = snapLocation.toFile(); 834 835 if (!localFile.exists()) { 838 initSnap(Policy.subMonitorFor(monitor, Policy.totalWork / 2)); 839 return; 840 } 841 workspace.setCrashed(true); 843 try { 844 845 ElementTree complete = workspace.getElementTree(); 846 complete.immutable(); 847 DataInputStream input = new DataInputStream(new SafeChunkyInputStream(localFile)); 848 try { 849 WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt()); 850 complete = reader.readSnapshotTree(input, complete, monitor); 851 } finally { 852 FileUtil.safeClose(input); 853 lastSnap = complete; 856 complete = complete.newEmptyDelta(); 857 workspace.tree = complete; 858 } 859 } catch (Exception e) { 860 message = Messages.resources_snapRead; 862 Policy.log(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, null, message, e)); 863 } 864 } finally { 865 monitor.done(); 866 } 867 if (Policy.DEBUG_RESTORE_SNAPSHOTS) 868 System.out.println("Restore snapshots for workspace: " + (System.currentTimeMillis() - start) + "ms"); } 870 871 875 protected void restoreSyncInfo(IResource resource, IProgressMonitor monitor) throws CoreException { 876 Assert.isLegal(resource.getType() == IResource.ROOT || resource.getType() == IResource.PROJECT); 877 long start = System.currentTimeMillis(); 878 Synchronizer synchronizer = (Synchronizer) workspace.getSynchronizer(); 879 if (resource.isAccessible()) 881 synchronizer.restore(resource, monitor); 882 883 if (resource.getType() == IResource.PROJECT) { 885 if (Policy.DEBUG_RESTORE_SYNCINFO) { 886 System.out.println("Restore SyncInfo for " + resource.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); } 888 return; 889 } 890 IProject[] projects = ((IWorkspaceRoot) resource).getProjects(); 891 for (int i = 0; i < projects.length; i++) 892 if (projects[i].isAccessible()) 893 synchronizer.restore(projects[i], monitor); 894 if (Policy.DEBUG_RESTORE_SYNCINFO) { 895 System.out.println("Restore SyncInfo for workspace: " + (System.currentTimeMillis() - start) + "ms"); } 897 } 898 899 905 protected void restoreTree(IProgressMonitor monitor) throws CoreException { 906 long start = System.currentTimeMillis(); 907 IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), false); 908 IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation); 909 if (!treeLocation.toFile().exists() && !tempLocation.toFile().exists()) { 910 savedStates = Collections.synchronizedMap(new HashMap(10)); 911 return; 912 } 913 try { 914 DataInputStream input = new DataInputStream(new SafeFileInputStream(treeLocation.toOSString(), tempLocation.toOSString(), TREE_BUFFER_SIZE)); 915 try { 916 WorkspaceTreeReader.getReader(workspace, input.readInt()).readTree(input, monitor); 917 } finally { 918 input.close(); 919 } 920 } catch (IOException e) { 921 String msg = NLS.bind(Messages.resources_readMeta, treeLocation.toOSString()); 922 throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, treeLocation, msg, e); 923 } 924 if (Policy.DEBUG_RESTORE_TREE) { 925 System.out.println("Restore Tree for workspace: " + (System.currentTimeMillis() - start) + "ms"); } 927 } 928 929 937 protected void restoreTree(Project project, IProgressMonitor monitor) throws CoreException { 938 long start = System.currentTimeMillis(); 939 monitor = Policy.monitorFor(monitor); 940 String message; 941 try { 942 monitor.beginTask("", Policy.totalWork); IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(project, false); 944 IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation); 945 if (!treeLocation.toFile().exists() && !tempLocation.toFile().exists()) 946 return; 947 DataInputStream input = new DataInputStream(new SafeFileInputStream(treeLocation.toOSString(), tempLocation.toOSString())); 948 try { 949 WorkspaceTreeReader reader = WorkspaceTreeReader.getReader(workspace, input.readInt()); 950 reader.readTree(project, input, Policy.subMonitorFor(monitor, Policy.totalWork)); 951 } finally { 952 input.close(); 953 } 954 } catch (IOException e) { 955 message = NLS.bind(Messages.resources_readMeta, project.getFullPath()); 956 throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, project.getFullPath(), message, e); 957 } finally { 958 monitor.done(); 959 } 960 if (Policy.DEBUG_RESTORE_TREE) { 961 System.out.println("Restore Tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); } 963 } 964 965 public IStatus save(int kind, Project project, IProgressMonitor monitor) throws CoreException { 966 monitor = Policy.monitorFor(monitor); 967 try { 968 isSaving = true; 969 String message = Messages.resources_saving_0; 970 monitor.beginTask(message, 7); 971 message = Messages.resources_saveWarnings; 972 MultiStatus warnings = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IStatus.WARNING, message, null); 973 ISchedulingRule rule = project != null ? (IResource) project : workspace.getRoot(); 974 try { 975 workspace.prepareOperation(rule, monitor); 976 workspace.beginOperation(false); 977 hookStartSave(kind, project); 978 long start = System.currentTimeMillis(); 979 Map contexts = computeSaveContexts(getSaveParticipantPlugins(), kind, project); 980 broadcastLifecycle(PREPARE_TO_SAVE, contexts, warnings, Policy.subMonitorFor(monitor, 1)); 981 try { 982 broadcastLifecycle(SAVING, contexts, warnings, Policy.subMonitorFor(monitor, 1)); 983 switch (kind) { 984 case ISaveContext.FULL_SAVE : 985 saveTree(contexts, Policy.subMonitorFor(monitor, 1)); 987 initSnap(null); 989 cleanMasterTable(); 991 persistMarkers = 0l; 993 persistSyncInfo = 0l; 994 visitAndSave(workspace.getRoot()); 995 monitor.worked(1); 996 if (Policy.DEBUG_SAVE) { 997 Policy.debug("Total Save Markers: " + persistMarkers + "ms"); Policy.debug("Total Save Sync Info: " + persistSyncInfo + "ms"); } 1000 resetSnapshots(workspace.getRoot()); 1002 removeUnusedSafeTables(); 1004 removeUnusedTreeFiles(); 1005 workspace.getFileSystemManager().getHistoryStore().clean(Policy.subMonitorFor(monitor, 1)); 1006 saveMetaInfo(warnings, Policy.subMonitorFor(monitor, 1)); 1008 break; 1009 case ISaveContext.SNAPSHOT : 1010 snapTree(workspace.getElementTree(), Policy.subMonitorFor(monitor, 1)); 1011 persistMarkers = 0l; 1013 persistSyncInfo = 0l; 1014 visitAndSnap(workspace.getRoot()); 1015 monitor.worked(1); 1016 if (Policy.DEBUG_SAVE) { 1017 Policy.debug("Total Snap Markers: " + persistMarkers + "ms"); Policy.debug("Total Snap Sync Info: " + persistSyncInfo + "ms"); } 1020 collapseTrees(); 1021 clearSavedDelta(); 1022 saveMetaInfo(warnings, Policy.subMonitorFor(monitor, 1)); 1024 break; 1025 case ISaveContext.PROJECT_SAVE : 1026 writeTree(project, IResource.DEPTH_INFINITE); 1027 monitor.worked(1); 1028 visitAndSave(project); 1030 monitor.worked(1); 1031 resetSnapshots(project); 1033 IStatus result = saveMetaInfo(project, null); 1034 if (!result.isOK()) 1035 warnings.merge(result); 1036 monitor.worked(1); 1037 break; 1038 } 1039 commit(contexts); 1041 if (kind == ISaveContext.FULL_SAVE) 1042 removeClearDeltaMarks(); 1043 saveMasterTable(); 1045 broadcastLifecycle(DONE_SAVING, contexts, warnings, Policy.subMonitorFor(monitor, 1)); 1046 hookEndSave(kind, project, start); 1047 return warnings; 1048 } catch (CoreException e) { 1049 broadcastLifecycle(ROLLBACK, contexts, warnings, Policy.subMonitorFor(monitor, 1)); 1050 restoreMasterTable(); 1052 throw e; } 1054 } catch (OperationCanceledException e) { 1055 workspace.getWorkManager().operationCanceled(); 1056 throw e; 1057 } finally { 1058 workspace.endOperation(rule, false, Policy.monitorFor(null)); 1059 } 1060 } finally { 1061 isSaving = false; 1062 monitor.done(); 1063 } 1064 } 1065 1066 protected void saveMasterTable() throws CoreException { 1067 saveMasterTable(workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES)); 1068 } 1069 1070 protected void saveMasterTable(IPath location) throws CoreException { 1071 long start = System.currentTimeMillis(); 1072 java.io.File target = location.toFile(); 1073 try { 1074 SafeChunkyOutputStream output = new SafeChunkyOutputStream(target); 1075 try { 1076 masterTable.store(output, "master table"); output.succeed(); 1078 } finally { 1079 output.close(); 1080 } 1081 } catch (IOException e) { 1082 String message = Messages.resources_exSaveMaster; 1083 throw new ResourceException(IResourceStatus.INTERNAL_ERROR, null, message, e); 1084 } 1085 if (Policy.DEBUG_SAVE_MASTERTABLE) 1086 System.out.println("Save master table for " + location + ": " + (System.currentTimeMillis() - start) + "ms"); } 1088 1089 1093 protected void saveMetaInfo(MultiStatus problems, IProgressMonitor monitor) throws CoreException { 1094 if (Policy.DEBUG_SAVE_METAINFO) 1095 System.out.println("Save workspace metainfo: starting..."); long start = System.currentTimeMillis(); 1097 ResourcesPlugin.getPlugin().savePluginPreferences(); 1099 IProject[] roots = workspace.getRoot().getProjects(); 1101 for (int i = 0; i < roots.length; i++) 1102 if (roots[i].isAccessible()) { 1103 IStatus result = saveMetaInfo((Project) roots[i], null); 1104 if (!result.isOK()) 1105 problems.merge(result); 1106 } 1107 if (Policy.DEBUG_SAVE_METAINFO) 1108 System.out.println("Save workspace metainfo: " + (System.currentTimeMillis() - start) + "ms"); } 1110 1111 1118 protected IStatus saveMetaInfo(Project project, IProgressMonitor monitor) throws CoreException { 1119 long start = System.currentTimeMillis(); 1120 if (!workspace.getFileSystemManager().hasSavedDescription(project)) { 1122 workspace.getFileSystemManager().writeSilently(project); 1123 String msg = NLS.bind(Messages.resources_missingProjectMetaRepaired, project.getName()); 1124 return new ResourceStatus(IResourceStatus.MISSING_DESCRIPTION_REPAIRED, project.getFullPath(), msg); 1125 } 1126 if (Policy.DEBUG_SAVE_METAINFO) 1127 System.out.println("Save metainfo for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); return Status.OK_STATUS; 1129 } 1130 1131 1137 protected void saveTree(Map contexts, IProgressMonitor monitor) throws CoreException { 1138 long start = System.currentTimeMillis(); 1139 IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(workspace.getRoot(), true); 1140 try { 1141 IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation); 1142 DataOutputStream output = new DataOutputStream(new SafeFileOutputStream(treeLocation.toOSString(), tempLocation.toOSString())); 1143 try { 1144 output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2); 1145 writeTree(computeStatesToSave(contexts, workspace.getElementTree()), output, monitor); 1146 } finally { 1147 output.close(); 1148 } 1149 } catch (Exception e) { 1150 String msg = NLS.bind(Messages.resources_writeWorkspaceMeta, treeLocation); 1151 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, Path.ROOT, msg, e); 1152 } 1153 if (Policy.DEBUG_SAVE_TREE) 1154 System.out.println("Save Workspace Tree: " + (System.currentTimeMillis() - start) + "ms"); } 1156 1157 1160 void setPluginsSavedState(HashMap savedStates) { 1161 this.savedStates = Collections.synchronizedMap(savedStates); 1162 } 1163 1164 protected void setSaveNumber(String pluginId, int number) { 1165 masterTable.setProperty(SAVE_NUMBER_PREFIX + pluginId, new Integer (number).toString()); 1166 } 1167 1168 1171 public void shareStrings(StringPool pool) { 1172 lastSnap.shareStrings(pool); 1173 } 1174 1175 public void shutdown(final IProgressMonitor monitor) { 1176 int state = snapshotJob.getState(); 1180 if (state == Job.WAITING || state == Job.SLEEPING) 1181 snapshotJob.run(Policy.monitorFor(monitor)); 1183 snapshotJob.cancel(); 1185 } 1186 1187 1192 public void snapshotIfNeeded(boolean hasTreeChanges) { 1193 if (isSaving) 1195 return; 1196 if (snapshotRequested || operationCount >= workspace.internalGetDescription().getOperationsPerSnapshot()) { 1197 if (snapshotJob.getState() == Job.NONE) 1198 snapshotJob.schedule(); 1199 else 1200 snapshotJob.wakeUp(); 1201 } else { 1202 if (hasTreeChanges) { 1203 operationCount++; 1204 if (snapshotJob.getState() == Job.NONE) { 1205 if (Policy.DEBUG_SAVE) 1206 System.out.println("Scheduling workspace snapshot"); long interval = workspace.internalGetDescription().getSnapshotInterval(); 1208 snapshotJob.schedule(Math.max(interval, MIN_SNAPSHOT_DELAY)); 1209 } 1210 } else { 1211 if (++noopCount > NO_OP_THRESHOLD) { 1213 operationCount++; 1214 noopCount = 0; 1215 } 1216 } 1217 } 1218 } 1219 1220 1223 protected void snapTree(ElementTree tree, IProgressMonitor monitor) throws CoreException { 1224 long start = System.currentTimeMillis(); 1225 monitor = Policy.monitorFor(monitor); 1226 String message; 1227 try { 1228 monitor.beginTask("", Policy.totalWork); tree.immutable(); 1231 if (tree == lastSnap) 1233 return; 1234 operationCount = 0; 1235 IPath snapPath = workspace.getMetaArea().getSnapshotLocationFor(workspace.getRoot()); 1236 ElementTreeWriter writer = new ElementTreeWriter(this); 1237 java.io.File localFile = snapPath.toFile(); 1238 try { 1239 SafeChunkyOutputStream safeStream = new SafeChunkyOutputStream(localFile); 1240 DataOutputStream out = new DataOutputStream(safeStream); 1241 try { 1242 out.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2); 1243 writeWorkspaceFields(out, monitor); 1244 writer.writeDelta(tree, lastSnap, Path.ROOT, ElementTreeWriter.D_INFINITE, out, ResourceComparator.getSaveComparator()); 1245 safeStream.succeed(); 1246 } finally { 1247 out.close(); 1248 } 1249 } catch (IOException e) { 1250 message = NLS.bind(Messages.resources_writeWorkspaceMeta, localFile.getAbsolutePath()); 1251 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, Path.ROOT, message, e); 1252 } 1253 lastSnap = tree; 1254 } finally { 1255 monitor.done(); 1256 } 1257 if (Policy.DEBUG_SAVE_TREE) 1258 System.out.println("Snapshot Workspace Tree: " + (System.currentTimeMillis() - start) + "ms"); } 1260 1261 1269 protected ElementTree[] sortTrees(ElementTree[] trees) { 1270 1271 int numTrees = trees.length; 1272 ElementTree[] sorted = new ElementTree[numTrees]; 1273 1274 1275 Map table = new HashMap(numTrees * 2 + 1); 1276 for (int i = 0; i < trees.length; i++) { 1277 List indices = (List) table.get(trees[i]); 1278 if (indices == null) { 1279 indices = new ArrayList(10); 1280 table.put(trees[i], indices); 1281 } 1282 indices.add(new Integer (i)); 1283 } 1284 1285 1286 ElementTree oldest = trees[ElementTree.findOldest(trees)]; 1287 1288 1292 int i = numTrees - 1; 1293 while (i >= 0) { 1294 1295 List indices = (List) table.remove(oldest); 1296 for (Enumeration e = Collections.enumeration(indices); e.hasMoreElements();) { 1297 e.nextElement(); 1298 sorted[i] = oldest; 1299 i--; 1300 } 1301 if (i >= 0) { 1302 1303 ElementTree parent = oldest.getParent(); 1304 while (parent != null && table.get(parent) == null) { 1305 parent = parent.getParent(); 1306 } 1307 if (parent == null) { 1308 IStatus status = new Status(IStatus.WARNING, ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, "null parent found while collapsing trees", null); Policy.log(status); 1310 return null; 1311 } 1312 oldest = parent; 1313 } 1314 } 1315 return sorted; 1316 } 1317 1318 public void startup(IProgressMonitor monitor) throws CoreException { 1319 restore(monitor); 1320 java.io.File table = workspace.getMetaArea().getSafeTableLocationFor(ResourcesPlugin.PI_RESOURCES).toFile(); 1321 if (!table.exists()) 1322 table.getParentFile().mkdirs(); 1323 } 1324 1325 1333 protected void updateDeltaExpiration(String pluginId) { 1334 String key = DELTA_EXPIRATION_PREFIX + pluginId; 1335 if (!masterTable.containsKey(key)) 1336 masterTable.setProperty(key, Long.toString(System.currentTimeMillis())); 1337 } 1338 1339 1345 public void visitAndSave(final IResource root) throws CoreException { 1346 Assert.isLegal(root.getType() == IResource.ROOT || root.getType() == IResource.PROJECT); 1348 if (!root.isAccessible()) 1350 return; 1351 1352 final Synchronizer synchronizer = (Synchronizer) workspace.getSynchronizer(); 1354 final MarkerManager markerManager = workspace.getMarkerManager(); 1355 IPath markersLocation = workspace.getMetaArea().getMarkersLocationFor(root); 1356 IPath markersTempLocation = workspace.getMetaArea().getBackupLocationFor(markersLocation); 1357 IPath syncInfoLocation = workspace.getMetaArea().getSyncInfoLocationFor(root); 1358 IPath syncInfoTempLocation = workspace.getMetaArea().getBackupLocationFor(syncInfoLocation); 1359 final List writtenTypes = new ArrayList(5); 1360 final List writtenPartners = new ArrayList(synchronizer.registry.size()); 1361 DataOutputStream o1 = null; 1362 DataOutputStream o2 = null; 1363 String message; 1364 1365 try { 1367 o1 = new DataOutputStream(new SafeFileOutputStream(markersLocation.toOSString(), markersTempLocation.toOSString())); 1368 if (root.getType() != IResource.ROOT) 1371 o2 = new DataOutputStream(new SafeFileOutputStream(syncInfoLocation.toOSString(), syncInfoTempLocation.toOSString())); 1372 } catch (IOException e) { 1373 if (o1 != null) 1374 try { 1375 o1.close(); 1376 } catch (IOException e2) { 1377 } 1379 message = NLS.bind(Messages.resources_writeMeta, root.getFullPath()); 1380 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e); 1381 } 1382 1383 final DataOutputStream markersOutput = o1; 1384 final DataOutputStream syncInfoOutput = o2; 1385 final long[] saveTimes = new long[2]; 1390 1391 IElementContentVisitor visitor = new IElementContentVisitor() { 1393 public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { 1394 ResourceInfo info = (ResourceInfo) elementContents; 1395 if (info != null) { 1396 try { 1397 long start = System.currentTimeMillis(); 1399 markerManager.save(info, requestor, markersOutput, writtenTypes); 1400 long markerSaveTime = System.currentTimeMillis() - start; 1401 saveTimes[0] += markerSaveTime; 1402 persistMarkers += markerSaveTime; 1403 if (syncInfoOutput != null) { 1405 start = System.currentTimeMillis(); 1406 synchronizer.saveSyncInfo(info, requestor, syncInfoOutput, writtenPartners); 1407 long syncInfoSaveTime = System.currentTimeMillis() - start; 1408 saveTimes[1] += syncInfoSaveTime; 1409 persistSyncInfo += syncInfoSaveTime; 1410 } 1411 } catch (IOException e) { 1412 throw new WrappedRuntimeException(e); 1413 } 1414 } 1415 return root.getType() != IResource.ROOT; 1417 } 1418 }; 1419 1420 try { 1422 try { 1423 new ElementTreeIterator(workspace.getElementTree(), root.getFullPath()).iterate(visitor); 1424 } catch (WrappedRuntimeException e) { 1425 throw (IOException) e.getTargetException(); 1426 } 1427 if (Policy.DEBUG_SAVE_MARKERS) 1428 System.out.println("Save Markers for " + root.getFullPath() + ": " + saveTimes[0] + "ms"); if (Policy.DEBUG_SAVE_SYNCINFO) 1430 System.out.println("Save SyncInfo for " + root.getFullPath() + ": " + saveTimes[1] + "ms"); removeGarbage(markersOutput, markersLocation, markersTempLocation); 1432 if (syncInfoOutput != null) 1435 removeGarbage(syncInfoOutput, syncInfoLocation, syncInfoTempLocation); 1436 } catch (IOException e) { 1437 message = NLS.bind(Messages.resources_writeMeta, root.getFullPath()); 1438 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e); 1439 } finally { 1440 FileUtil.safeClose(markersOutput); 1441 FileUtil.safeClose(syncInfoOutput); 1442 } 1443 1444 if (root.getType() == IResource.PROJECT) 1446 return; 1447 IProject[] projects = ((IWorkspaceRoot) root).getProjects(); 1448 for (int i = 0; i < projects.length; i++) 1449 visitAndSave(projects[i]); 1450 } 1451 1452 1458 public void visitAndSnap(final IResource root) throws CoreException { 1459 Assert.isLegal(root.getType() == IResource.ROOT || root.getType() == IResource.PROJECT); 1461 if (!root.isAccessible()) 1463 return; 1464 1465 final Synchronizer synchronizer = (Synchronizer) workspace.getSynchronizer(); 1467 final MarkerManager markerManager = workspace.getMarkerManager(); 1468 IPath markersLocation = workspace.getMetaArea().getMarkersSnapshotLocationFor(root); 1469 IPath syncInfoLocation = workspace.getMetaArea().getSyncInfoSnapshotLocationFor(root); 1470 SafeChunkyOutputStream safeMarkerStream = null; 1471 SafeChunkyOutputStream safeSyncInfoStream = null; 1472 DataOutputStream o1 = null; 1473 DataOutputStream o2 = null; 1474 String message; 1475 1476 try { 1478 safeMarkerStream = new SafeChunkyOutputStream(markersLocation.toFile()); 1479 o1 = new DataOutputStream(safeMarkerStream); 1480 if (root.getType() != IResource.ROOT) { 1483 safeSyncInfoStream = new SafeChunkyOutputStream(syncInfoLocation.toFile()); 1484 o2 = new DataOutputStream(safeSyncInfoStream); 1485 } 1486 } catch (IOException e) { 1487 FileUtil.safeClose(o1); 1488 message = NLS.bind(Messages.resources_writeMeta, root.getFullPath()); 1489 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e); 1490 } 1491 1492 final DataOutputStream markersOutput = o1; 1493 final DataOutputStream syncInfoOutput = o2; 1494 int markerFileSize = markersOutput.size(); 1495 int syncInfoFileSize = safeSyncInfoStream == null ? -1 : syncInfoOutput.size(); 1496 final long[] snapTimes = new long[2]; 1501 1502 IElementContentVisitor visitor = new IElementContentVisitor() { 1503 public boolean visitElement(ElementTree tree, IPathRequestor requestor, Object elementContents) { 1504 ResourceInfo info = (ResourceInfo) elementContents; 1505 if (info != null) { 1506 try { 1507 long start = System.currentTimeMillis(); 1509 markerManager.snap(info, requestor, markersOutput); 1510 long markerSnapTime = System.currentTimeMillis() - start; 1511 snapTimes[0] += markerSnapTime; 1512 persistMarkers += markerSnapTime; 1513 if (syncInfoOutput != null) { 1515 start = System.currentTimeMillis(); 1516 synchronizer.snapSyncInfo(info, requestor, syncInfoOutput); 1517 long syncInfoSnapTime = System.currentTimeMillis() - start; 1518 snapTimes[1] += syncInfoSnapTime; 1519 persistSyncInfo += syncInfoSnapTime; 1520 } 1521 } catch (IOException e) { 1522 throw new WrappedRuntimeException(e); 1523 } 1524 } 1525 return root.getType() != IResource.ROOT; 1527 } 1528 }; 1529 1530 try { 1531 try { 1533 new ElementTreeIterator(workspace.getElementTree(), root.getFullPath()).iterate(visitor); 1534 } catch (WrappedRuntimeException e) { 1535 throw (IOException) e.getTargetException(); 1536 } 1537 if (Policy.DEBUG_SAVE_MARKERS) 1538 System.out.println("Snap Markers for " + root.getFullPath() + ": " + snapTimes[0] + "ms"); if (Policy.DEBUG_SAVE_SYNCINFO) 1540 System.out.println("Snap SyncInfo for " + root.getFullPath() + ": " + snapTimes[1] + "ms"); if (markerFileSize != markersOutput.size()) 1542 safeMarkerStream.succeed(); 1543 if (safeSyncInfoStream != null && syncInfoFileSize != syncInfoOutput.size()) 1544 safeSyncInfoStream.succeed(); 1545 } catch (IOException e) { 1546 message = NLS.bind(Messages.resources_writeMeta, root.getFullPath()); 1547 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, root.getFullPath(), message, e); 1548 } finally { 1549 FileUtil.safeClose(markersOutput); 1550 FileUtil.safeClose(syncInfoOutput); 1551 } 1552 1553 if (root.getType() == IResource.PROJECT) 1555 return; 1556 IProject[] projects = ((IWorkspaceRoot) root).getProjects(); 1557 for (int i = 0; i < projects.length; i++) 1558 visitAndSnap(projects[i]); 1559 } 1560 1561 1572 protected void writeBuilderPersistentInfo(DataOutputStream output, List builders, List trees, IProgressMonitor monitor) throws IOException { 1573 monitor = Policy.monitorFor(monitor); 1574 try { 1575 int numBuilders = builders.size(); 1577 output.writeInt(numBuilders); 1578 for (int i = 0; i < numBuilders; i++) { 1579 BuilderPersistentInfo info = (BuilderPersistentInfo) builders.get(i); 1580 output.writeUTF(info.getProjectName()); 1581 output.writeUTF(info.getBuilderName()); 1582 IProject[] interestingProjects = info.getInterestingProjects(); 1584 output.writeInt(interestingProjects.length); 1585 for (int j = 0; j < interestingProjects.length; j++) 1586 output.writeUTF(interestingProjects[j].getName()); 1587 ElementTree last = info.getLastBuiltTree(); 1588 if (last == null) 1590 last = workspace.getElementTree(); 1591 trees.add(last); 1592 } 1593 } finally { 1594 monitor.done(); 1595 } 1596 } 1597 1598 1601 public void writeElement(IPath path, Object element, DataOutput output) throws IOException { 1602 Assert.isNotNull(path); 1603 Assert.isNotNull(element); 1604 Assert.isNotNull(output); 1605 ResourceInfo info = (ResourceInfo) element; 1606 output.writeInt(info.getFlags()); 1607 info.writeTo(output); 1608 } 1609 1610 protected void writeTree(Map statesToSave, DataOutputStream output, IProgressMonitor monitor) throws IOException, CoreException { 1611 monitor = Policy.monitorFor(monitor); 1612 try { 1613 monitor.beginTask("", Policy.totalWork); boolean wasImmutable = false; 1615 try { 1616 ElementTree current = workspace.getElementTree(); 1618 wasImmutable = current.isImmutable(); 1619 current.immutable(); 1620 ArrayList trees = new ArrayList(statesToSave.size() * 2); monitor.worked(Policy.totalWork * 10 / 100); 1622 1623 writeWorkspaceFields(output, Policy.subMonitorFor(monitor, Policy.opWork * 20 / 100)); 1625 1626 output.writeInt(statesToSave.size()); for (Iterator i = statesToSave.entrySet().iterator(); i.hasNext();) { 1629 Map.Entry entry = (Map.Entry) i.next(); 1630 String pluginId = (String ) entry.getKey(); 1631 output.writeUTF(pluginId); 1632 trees.add(entry.getValue()); updateDeltaExpiration(pluginId); 1634 } 1635 monitor.worked(Policy.totalWork * 10 / 100); 1636 1637 IProject[] projects = workspace.getRoot().getProjects(); 1639 List builders = new ArrayList(projects.length * 2); 1640 for (int i = 0; i < projects.length; i++) { 1641 IProject project = projects[i]; 1642 if (project.isOpen()) { 1643 ArrayList infos = workspace.getBuildManager().createBuildersPersistentInfo(project); 1644 if (infos != null) 1645 builders.addAll(infos); 1646 } 1647 } 1648 writeBuilderPersistentInfo(output, builders, trees, Policy.subMonitorFor(monitor, Policy.totalWork * 10 / 100)); 1649 1650 trees.add(current); 1652 1653 1654 ElementTreeWriter writer = new ElementTreeWriter(this); 1655 ElementTree[] treesToSave = (ElementTree[]) trees.toArray(new ElementTree[trees.size()]); 1656 writer.writeDeltaChain(treesToSave, Path.ROOT, ElementTreeWriter.D_INFINITE, output, ResourceComparator.getSaveComparator()); 1657 monitor.worked(Policy.totalWork * 50 / 100); 1658 } finally { 1659 if (!wasImmutable) 1660 workspace.newWorkingTree(); 1661 } 1662 } finally { 1663 monitor.done(); 1664 } 1665 } 1666 1667 1673 protected void writeTree(Project project, DataOutputStream output, IProgressMonitor monitor) throws IOException, CoreException { 1674 monitor = Policy.monitorFor(monitor); 1675 try { 1676 monitor.beginTask("", 10); boolean wasImmutable = false; 1678 try { 1679 1684 ArrayList builderInfos = workspace.getBuildManager().createBuildersPersistentInfo(project); 1685 if (builderInfos == null) 1686 builderInfos = new ArrayList(5); 1687 List trees = new ArrayList(builderInfos.size() + 1); 1688 monitor.worked(1); 1689 1690 1691 ElementTree current = workspace.getElementTree(); 1692 wasImmutable = current.isImmutable(); 1693 current.immutable(); 1694 1695 1696 writeBuilderPersistentInfo(output, builderInfos, trees, Policy.subMonitorFor(monitor, 1)); 1697 trees.add(current); 1698 1699 1700 ElementTreeWriter writer = new ElementTreeWriter(this); 1701 ElementTree[] treesToSave = (ElementTree[]) trees.toArray(new ElementTree[trees.size()]); 1702 writer.writeDeltaChain(treesToSave, project.getFullPath(), ElementTreeWriter.D_INFINITE, output, ResourceComparator.getSaveComparator()); 1703 monitor.worked(8); 1704 } finally { 1705 if (output != null) 1706 output.close(); 1707 if (!wasImmutable) 1708 workspace.newWorkingTree(); 1709 } 1710 } finally { 1711 monitor.done(); 1712 } 1713 } 1714 1715 protected void writeTree(Project project, int depth) throws CoreException { 1716 long start = System.currentTimeMillis(); 1717 IPath treeLocation = workspace.getMetaArea().getTreeLocationFor(project, true); 1718 IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(treeLocation); 1719 try { 1720 SafeFileOutputStream safe = new SafeFileOutputStream(treeLocation.toOSString(), tempLocation.toOSString()); 1721 try { 1722 DataOutputStream output = new DataOutputStream(safe); 1723 output.writeInt(ICoreConstants.WORKSPACE_TREE_VERSION_2); 1724 writeTree(project, output, null); 1725 } finally { 1726 safe.close(); 1727 } 1728 } catch (IOException e) { 1729 String msg = NLS.bind(Messages.resources_writeMeta, project.getFullPath()); 1730 throw new ResourceException(IResourceStatus.FAILED_WRITE_METADATA, treeLocation, msg, e); 1731 } 1732 if (Policy.DEBUG_SAVE_TREE) 1733 System.out.println("Save tree for " + project.getFullPath() + ": " + (System.currentTimeMillis() - start) + "ms"); } 1735 1736 protected void writeWorkspaceFields(DataOutputStream output, IProgressMonitor monitor) throws IOException { 1737 monitor = Policy.monitorFor(monitor); 1738 try { 1739 output.writeLong(workspace.nextNodeId); 1741 output.writeLong(0L); 1743 output.writeLong(workspace.nextMarkerId); 1745 ((Synchronizer) workspace.getSynchronizer()).savePartners(output); 1747 } finally { 1748 monitor.done(); 1749 } 1750 } 1751} 1752 | Popular Tags |