Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MyPerf4J-90] Fix SysGenProfilingFile rename fail #90 #91

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -73,23 +77,29 @@ public static void buildSysGenProfilingFile() {

if (!neverInvokedMethods.isEmpty()) {
fileWriter.write("#The following methods have never been invoked!\n");
for (int i = 0; i < neverInvokedMethods.size(); i++) {
final Integer methodId = neverInvokedMethods.get(i);
for (final Integer methodId : neverInvokedMethods) {
writeProfilingInfo(tagMaintainer, fileWriter, methodId, 128);
}
fileWriter.flush();
}
} catch (Exception e) {
Logger.error("MethodMetricssHistogram.buildSysGenProfilingFile() error", e);
}

final File destFile = new File(filePath);
final boolean rename = tempFile.renameTo(destFile) && destFile.setReadOnly();
try {
JiaRG marked this conversation as resolved.
Show resolved Hide resolved
final Path tempPath = tempFile.toPath();
final Path moved = Files.move(tempPath, Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);
final File destFile = moved.toFile();
// 此处不能设置只读,否则在windows环境下次move的时候会报错 AccessDeniedException
final boolean rename = destFile.exists()/* && destFile.setReadOnly() */;
Logger.debug("MethodMetricsHistogram.buildSysGenProfilingFile(): rename " + tempFile.getName()
+ " to " + destFile.getName() + " " + (rename ? "success" : "fail"));
} catch (Exception e) {
Logger.error("MethodMetricsHistogram.buildSysGenProfilingFile()", e);
} finally {
Logger.debug("MethodMetricsHistogram.buildSysGenProfilingFile() finished, cost="
+ (System.currentTimeMillis() - startMills) + "ms");
Logger.error("MethodMetricsHistogram.buildSysGenProfilingFile() rename error", e);
}

Logger.debug("MethodMetricsHistogram.buildSysGenProfilingFile() finished, cost="
+ (System.currentTimeMillis() - startMills) + "ms");
}

private static void writeProfilingInfo(MethodTagMaintainer tagMaintainer,
Expand Down
161 changes: 161 additions & 0 deletions MyPerf4J-Core/src/test/java/cn/myperf4j/core/FileTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package cn.myperf4j.core;

import cn.myperf4j.base.util.Logger;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Objects;

/**
* 文件测试
*/
public class FileTest {

protected static final File baseDir = new File(System.getProperty("user.dir"));

protected static final File testDir = new File(baseDir, "temp");

@BeforeClass
public static void prepare() {
getDir(FileTest.class.getSimpleName());
}

@AfterClass
public static void cleanup() {
deleteDir(FileTest.class.getSimpleName());
}

LinShunKang marked this conversation as resolved.
Show resolved Hide resolved

@Test
public void testFileRename() {
String testFile = getDir().getPath() + "/testFileRename";
final Path testFilePath1 = Paths.get(testFile + 1);
final Path testFilePath2 = Paths.get(testFile + 2);
final Path tmpFilePath = Paths.get(testFile + "_tmp");

boolean firstRenameTo = false;
boolean firstReadOnly = false;

boolean renameToResult = false;
boolean readOnlyResult = false;

for (int i = 0; i < 2; i++) {
try (BufferedWriter fileWriter = new BufferedWriter(new FileWriter(tmpFilePath.toFile(), false), 8192)) {
fileWriter.write("#This is a file automatically generated by MyPerf4J, please do not edit!\n");
fileWriter.flush();
final boolean renameTo = tmpFilePath.toFile().renameTo(testFilePath1.toFile());
final boolean readOnly = testFilePath1.toFile().setReadOnly();
// 流还没释放导致
Assert.assertFalse(renameTo);
JiaRG marked this conversation as resolved.
Show resolved Hide resolved
Assert.assertFalse(readOnly);
} catch (Exception e) {
Logger.error("testFileRename error", e);
}

if (i == 0) {
firstRenameTo = tmpFilePath.toFile().renameTo(testFilePath2.toFile());
JiaRG marked this conversation as resolved.
Show resolved Hide resolved
firstReadOnly = testFilePath2.toFile().setReadOnly();
} else {
renameToResult = tmpFilePath.toFile().renameTo(testFilePath2.toFile());
readOnlyResult = testFilePath2.toFile().setReadOnly();
}
}
// tmp文件存在
Assert.assertTrue(tmpFilePath.toFile().exists());
// BufferedWriter没释放时rename的文件不存在
Assert.assertFalse(testFilePath1.toFile().exists());
// BufferedWriter释放后rename的文件存在
Assert.assertTrue(testFilePath2.toFile().exists());

// 第一次rename能成功 文件存在的情况setReadOnly始终能成功
Assert.assertTrue(firstRenameTo);
Assert.assertTrue(firstReadOnly);
Assert.assertTrue(readOnlyResult);

// 第一次rename能成功,后续就失败
Assert.assertFalse(renameToResult);
}

@Test
public void testFilesMove() throws IOException {
String testFile = getDir().getPath() + "/testFilesMove";
final Path testFilePath = Paths.get(testFile);
final Path tmpFilePath = Paths.get(testFile + "_tmp");
if (!tmpFilePath.toFile().exists()) {
Files.createFile(tmpFilePath);
tmpFilePath.toFile().setReadOnly();
}

Assert.assertFalse(tmpFilePath.toFile().canWrite());
LinShunKang marked this conversation as resolved.
Show resolved Hide resolved

final Path moved = Files.move(tmpFilePath, testFilePath, StandardCopyOption.REPLACE_EXISTING);

moved.toFile().setReadOnly();

Assert.assertFalse(moved.toFile().canWrite());

Files.move(moved, tmpFilePath, StandardCopyOption.REPLACE_EXISTING);

Assert.assertFalse(tmpFilePath.toFile().canWrite());
}

public File getDir() {
JiaRG marked this conversation as resolved.
Show resolved Hide resolved
return getDir(getName());
}

public String getName() {
return getClass().getSimpleName();
}

public static File getDir(String dir) {
return getDir(testDir, dir);
}

public static File getDir(File parent, String dir) {
File file = new File(parent, dir);
if (!file.isDirectory()) {
if (!file.mkdirs()) {
throw new IllegalStateException("Can't create dir: " + file);
}
}
return file;
}

public static void deleteDir(String dir) {
deleteDir(testDir, dir);
}

public static void deleteDir(final File parent, String dir) {
final File dirFile = new File(parent, dir);
if (dirFile.isDirectory()) {
for (final File f: Objects.requireNonNull(dirFile.listFiles())) {
if (f.isDirectory()) {
deleteDir(dirFile, f.getName());
continue;
}
LinShunKang marked this conversation as resolved.
Show resolved Hide resolved
if (f.isFile()){
if (!f.delete()) {
throw new IllegalStateException("Can't delete file: " + f);
}
Logger.info("Delete file: " + f);
}
}
if (!dirFile.delete()) {
throw new IllegalStateException("Can't delete directory: " + dirFile);
}
Logger.info("Delete directory: " + dirFile);
}
testDir.deleteOnExit();
Logger.info("Delete testDir: " + testDir);
}
}