From 31f4f9871349eea1af5b4bb77be22be364fb3763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Kubitz?= Date: Tue, 25 Jun 2024 12:37:38 +0200 Subject: [PATCH] [performance] IFile.create: reduce 1 of 3 store.fetchInfo() Assume the file does not exist (normal case) - otherwise implementation fails later during actual write. https://github.com/eclipse-platform/eclipse.platform/issues/1443 --- .../localstore/FileSystemResourceManager.java | 45 ++++++++++++------- .../eclipse/core/internal/resources/File.java | 21 +++------ 2 files changed, 34 insertions(+), 32 deletions(-) diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java index 5cc21b19a76..27e2da6db1c 100644 --- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java +++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/localstore/FileSystemResourceManager.java @@ -23,6 +23,7 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -1213,32 +1214,42 @@ public void write(IFile target, InputStream content, IFileInfo fileInfo, int upd IFileStore store = getStore(target); prepareWrite(target, fileInfo, updateFlags, append, targetResource, store); - // On Windows an attempt to open an output stream on a hidden file results in FileNotFoundException. - // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=194216 - boolean restoreHiddenAttribute = false; - if (fileInfo.exists() && fileInfo.getAttribute(EFS.ATTRIBUTE_HIDDEN) && Platform.getOS().equals(Platform.OS_WIN32)) { - fileInfo.setAttribute(EFS.ATTRIBUTE_HIDDEN, false); - store.putInfo(fileInfo, EFS.SET_ATTRIBUTES, subMonitor.split(1)); - restoreHiddenAttribute = true; - } else { - subMonitor.split(1); - } int options = append ? EFS.APPEND : EFS.NONE; - try (OutputStream out = store.openOutputStream(options, subMonitor.split(1))) { - if (restoreHiddenAttribute) { - fileInfo.setAttribute(EFS.ATTRIBUTE_HIDDEN, true); + try { + boolean opened = false; + try (OutputStream out = store.openOutputStream(options, subMonitor.split(1))) { + opened = true; + FileUtil.transferStreams(content, out, store.toString(), subMonitor.split(1)); + } catch (CoreException e) { + // On Windows an attempt to open an output stream on a hidden file results in + // FileNotFoundException. + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=194216 + if (opened || !(e.getCause() instanceof FileNotFoundException) + || !Platform.getOS().equals(Platform.OS_WIN32)) { + throw e; + } + fileInfo = store.fetchInfo(); + if (!(fileInfo.exists() && fileInfo.getAttribute(EFS.ATTRIBUTE_HIDDEN))) { + throw e; + } + // set hidden=false and retry: + fileInfo.setAttribute(EFS.ATTRIBUTE_HIDDEN, false); store.putInfo(fileInfo, EFS.SET_ATTRIBUTES, subMonitor.split(1)); - } else { - subMonitor.split(1); + try (OutputStream out = store.openOutputStream(options, null)) { + // restore Hidden Attribute: + fileInfo.setAttribute(EFS.ATTRIBUTE_HIDDEN, true); + store.putInfo(fileInfo, EFS.SET_ATTRIBUTES, subMonitor.split(1)); + FileUtil.transferStreams(content, out, store.toString(), subMonitor.split(1)); + } } - FileUtil.transferStreams(content, out, store.toString(), subMonitor.split(1)); } catch (IOException e) { + // Exception on OutputStream.close() String msg = NLS.bind(Messages.localstore_couldNotWrite, store.toString()); throw new ResourceException(IResourceStatus.FAILED_WRITE_LOCAL, IPath.fromOSString(store.toString()), msg, e); } finishWrite(targetResource, store); } catch (IOException streamCloseIgnored) { - // ignore; + // ignore Exception on InputStream.close() } } diff --git a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/File.java b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/File.java index b5a2ed5cd22..76c0b56eeaa 100644 --- a/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/File.java +++ b/resources/bundles/org.eclipse.core.resources/src/org/eclipse/core/internal/resources/File.java @@ -24,6 +24,7 @@ import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileInfo; import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.filesystem.provider.FileInfo; import org.eclipse.core.internal.preferences.EclipsePreferences; import org.eclipse.core.internal.utils.BitMask; import org.eclipse.core.internal.utils.Messages; @@ -213,23 +214,13 @@ private void checkCreatable() throws CoreException { private IFileInfo create(int updateFlags, SubMonitor subMonitor, IFileStore store) throws CoreException, ResourceException { String message; - IFileInfo localInfo = store.fetchInfo(); + IFileInfo localInfo; if (BitMask.isSet(updateFlags, IResource.FORCE)) { - if (!Workspace.caseSensitive) { - if (localInfo.exists()) { - String name = getLocalManager().getLocalName(store); - if (name == null || localInfo.getName().equals(name)) { - delete(true, null); - } else { - // The file system is not case sensitive and there is already a file - // under this location. - message = NLS.bind(Messages.resources_existsLocalDifferentCase, - IPath.fromOSString(store.toString()).removeLastSegments(1).append(name).toOSString()); - throw new ResourceException(IResourceStatus.CASE_VARIANT_EXISTS, getFullPath(), message, null); - } - } - } + // Assume the file does not exist - otherwise implementation fails later + // during actual write + localInfo = new FileInfo(getName()); // with exists==false } else { + localInfo=store.fetchInfo(); if (localInfo.exists()) { // return an appropriate error message for case variant collisions if (!Workspace.caseSensitive) {