!7552 create folder before file

Merge pull request !7552 from Lasting/fix/create-empty-file
This commit is contained in:
openharmony_ci 2024-05-31 10:41:28 +00:00 committed by Gitee
commit 30c657d5c0
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
12 changed files with 304 additions and 48 deletions

View File

@ -951,6 +951,7 @@ ecma_platform_source = []
ecma_platform_source += [
"ecmascript/platform/common/map.cpp",
"ecmascript/platform/common/mutex.cpp",
"ecmascript/platform/common/filesystem.cpp",
]
config("include_llvm") {

View File

@ -19,10 +19,10 @@
#include "ecmascript/base/string_helper.h"
#include "ecmascript/checkpoint/thread_state_transition.h"
#include "ecmascript/compiler/aot_compilation_env.h"
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
#include "ecmascript/compiler/aot_file/aot_file_manager.h"
#include "ecmascript/compiler/pass_manager.h"
#include "ecmascript/compiler/aot_compilation_env.h"
#include "ecmascript/ecma_string.h"
#include "ecmascript/js_runtime_options.h"
#include "ecmascript/log.h"
@ -31,6 +31,7 @@
#include "ecmascript/ohos/enable_aot_list_helper.h"
#include "ecmascript/ohos/ohos_pkg_args.h"
#include "ecmascript/platform/file.h"
#include "ecmascript/platform/filesystem.h"
#include "ecmascript/platform/os.h"
#include "ecmascript/compiler/aot_compiler_stats.h"
@ -42,6 +43,7 @@ enum ErrCode {
ERR_FAIL = (-1),
ERR_HELP = (1),
ERR_NO_AP = (2),
ERR_MERGE_AP = (3),
};
void CompileValidFiles(PassManager &passManager, AOTFileGenerator &generator, bool &ret,
@ -60,20 +62,19 @@ void CompileValidFiles(PassManager &passManager, AOTFileGenerator &generator, bo
}
} // namespace
std::pair<bool, int> CheckVersion(JSRuntimeOptions &runtimeOptions, bool result)
bool CheckVersion(JSRuntimeOptions& runtimeOptions, AotCompilerStats& compilerStats, bool isPgoMerged)
{
if (runtimeOptions.IsCheckPgoVersion()) {
if (result) {
return std::pair(true, 0);
} else {
LOG_COMPILER(ERROR) << "CheckVersion ap and abc do not match";
return std::pair(true, 1);
if (!isPgoMerged) {
LOG_COMPILER(ERROR) << "CheckVersion ap and abc may not match";
compilerStats.SetPgoFileLegal(false);
}
if (runtimeOptions.IsTargetCompilerMode()) {
compilerStats.PrintCompilerStatsLog();
}
return true;
}
if (!result) {
return std::pair(true, 1);
}
return std::pair(false, 0);
return false;
}
bool IsExistsPkgInfo(AotCompilerPreprocessor &cPreprocessor)
@ -134,7 +135,7 @@ int Main(const int argc, const char **argv)
return ERR_HELP;
}
if (IsExistsPkgInfo(cPreprocessor) && JSNApi::IsAotEscape(cPreprocessor.GetMainPkgArgs()->GetPgoDir())) {
LOG_COMPILER(ERROR) << " Stop compile AOT because there are more crashes";
LOG_COMPILER(ERROR) << "Stop compile AOT because there are multiple crashes";
return ERR_FAIL;
}
if (runtimeOptions.IsPartialCompilerMode() && cOptions.profilerIn_.empty()) {
@ -151,23 +152,20 @@ int Main(const int argc, const char **argv)
compilerStats.SetAotFilePath(cOptions.outputFileName_);
compilerStats.SetPgoPath(cOptions.profilerIn_);
compilerStats.StartCompiler();
cPreprocessor.CreateEmptyFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN);
cPreprocessor.CreateEmptyFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AI);
profilerDecoder.SetHotnessThreshold(cOptions.hotnessThreshold_);
profilerDecoder.SetInPath(cOptions.profilerIn_);
cPreprocessor.AOTInitialize();
uint32_t checksum = cPreprocessor.GenerateAbcFileInfos();
// Notice: lx move load pandaFileHead and verify before GeneralAbcFileInfos.
// need support muilt abc
auto result = CheckVersion(runtimeOptions, cPreprocessor.HandleMergedPgoFile(checksum));
if (result.first) {
if (result.second != 0) {
compilerStats.SetPgoFileLegal(false);
}
if (runtimeOptions.IsTargetCompilerMode()) {
compilerStats.PrintCompilerStatsLog();
}
return result.second;
// need support multiple abc
auto isPgoMerged = cPreprocessor.HandleMergedPgoFile(checksum);
if (CheckVersion(runtimeOptions, compilerStats, isPgoMerged)) {
return ERR_OK;
}
if (!isPgoMerged) {
filesystem::CreateEmptyFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AN);
filesystem::CreateEmptyFile(cOptions.outputFileName_ + AOTFileManager::FILE_EXTENSION_AI);
return ERR_MERGE_AP;
}
cPreprocessor.GeneratePGOTypes(cOptions);
cPreprocessor.SnapshotInitialize();

View File

@ -393,20 +393,4 @@ std::string AotCompilerPreprocessor::GetMainPkgArgsAppSignature() const
{
return GetMainPkgArgs() == nullptr ? "" : GetMainPkgArgs()->GetAppSignature();
}
void AotCompilerPreprocessor::CreateEmptyFile(const std::string& fileName)
{
std::string realPath;
if (!RealPath(fileName, realPath, false)) {
LOG_COMPILER(ERROR) << "failed to create empty file: " << fileName;
return;
}
const char* filePath = realPath.c_str();
if (FileExist(filePath)) {
LOG_COMPILER(DEBUG) << fileName << " file already exist, skip creating empty file";
return;
}
std::ofstream file(filePath);
file.close();
}
} // namespace panda::ecmascript::kungfu

View File

@ -186,8 +186,6 @@ public:
return str;
}
void CreateEmptyFile(const std::string& fileName);
private:
NO_COPY_SEMANTIC(AotCompilerPreprocessor);
NO_MOVE_SEMANTIC(AotCompilerPreprocessor);

View File

@ -578,7 +578,7 @@ bool AOTFileGenerator::CreateDirIfNotExist(const std::string &filename)
}
std::string path = realPath.substr(0, index);
if (!panda::ecmascript::ForceCreateDirectory(path)) {
LOG_COMPILER(ERROR) << "Fail to make dir:" << path;
LOG_COMPILER(ERROR) << "Fail to make dir: " << path;
return false;
}
return panda::ecmascript::SetDirModeAsDefault(path);
@ -591,7 +591,7 @@ void AOTFileGenerator::SaveAOTFile(const std::string &filename, const std::strin
return;
}
if (!CreateDirIfNotExist(filename)) {
LOG_COMPILER(ERROR) << "Fail to access dir:" << filename;
LOG_COMPILER(ERROR) << "Fail to access dir: " << filename;
return;
}
PrintMergedCodeComment();
@ -679,6 +679,10 @@ void AOTFileGenerator::SaveSnapshotFile()
ptManager->GetAOTSnapshot().ResolveSnapshotData(methodToEntryIndexMap);
CString aiPath = snapshotPath + AOTFileManager::FILE_EXTENSION_AI;
if (!CreateDirIfNotExist(aiPath.c_str())) {
LOG_COMPILER(ERROR) << "Fail to access dir: " << aiPath;
return;
}
snapshot.Serialize(aiPath);
if (!panda::ecmascript::SetFileModeAsDefault(aiPath.c_str())) {
LOG_COMPILER(ERROR) << "Fail to set ai file mode:" << aiPath;

View File

@ -155,6 +155,23 @@ host_unittest_action("InstructionCombineTest") {
external_deps = [ "zlib:libz" ]
}
host_unittest_action("CreateEmptyFileTest") {
module_out_path = module_output_path
sources = [
# test file
"create_empty_file_test.cpp",
]
deps = [
"$ark_root/libpandafile:libarkfile_static",
"$js_root:libark_jsruntime_test_set",
"$js_root/ecmascript/compiler:libark_jsoptimizer_set",
sdk_libc_secshared_dep,
]
external_deps = [ "zlib:libz" ]
}
group("host_unittest") {
testonly = true
@ -162,6 +179,7 @@ group("host_unittest") {
deps = [
":AssemblerTestAction",
":ConstantFoldingTestAction",
":CreateEmptyFileTestAction",
":GlobalValueNumberingTestAction",
":InstructionCombineTestAction",
":LoopOptimizationTestAction",

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/aot_compiler_preprocessor.h"
#include "ecmascript/platform/filesystem.h"
#include "ecmascript/tests/test_helper.h"
namespace panda::test {
using namespace panda;
using namespace panda::ecmascript;
using namespace panda::ecmascript::kungfu;
class CreateEmptyFileTest : public testing::Test {
public:
static void SetUpTestCase()
{
GTEST_LOG_(INFO) << "SetUpTestCase";
}
static void TearDownTestCase()
{
GTEST_LOG_(INFO) << "TearDownCase";
}
void SetUp() override
{
temp_dir = filesystem::TempDirectoryPath() + "/create_empty_file_test";
filesystem::CreateDirectory(temp_dir);
}
void TearDown() override
{
filesystem::RemoveAll(temp_dir);
}
protected:
std::string temp_dir;
};
HWTEST_F_L0(CreateEmptyFileTest, FileDoesNotExist)
{
std::string file_path = temp_dir + "/dir1/dir2/entry.an";
filesystem::CreateEmptyFile(file_path);
EXPECT_TRUE(filesystem::Exists(file_path));
}
HWTEST_F_L0(CreateEmptyFileTest, FileExists)
{
std::string file_path = temp_dir + "/entry.an";
std::ofstream ofs(file_path);
ofs << "test data";
ofs.close();
auto old_size = filesystem::FileSize(file_path);
EXPECT_GT(old_size, 0);
filesystem::CreateEmptyFile(file_path);
auto new_size = filesystem::FileSize(file_path);
EXPECT_TRUE(filesystem::Exists(file_path));
EXPECT_GT(old_size, 0);
EXPECT_GT(new_size, 0);
}
HWTEST_F_L0(CreateEmptyFileTest, DirectoryDoesNotExist)
{
std::string dir_path = temp_dir + "/dir4/com.hm.app";
std::string file_path = dir_path + "/entry.an";
filesystem::CreateEmptyFile(file_path);
EXPECT_TRUE(filesystem::Exists(dir_path));
EXPECT_TRUE(filesystem::Exists(file_path));
}
} // namespace panda::test

View File

@ -21,7 +21,7 @@
// NO_TAG means not print any tag
#define LOG_NO_TAG(level) ARK_LOG(level, Component::NO_TAG)
#define LOG_ECMA(level) ARK_LOG(level, Component::ECMASCRIPT)
#define LOG_FULL(level) ARK_LOG(level, Component::ALL) << __func__ << ":" << __LINE__ << " "
#define LOG_FULL(level) ARK_LOG(level, Component::ALL) << "[" << __func__ << ":" << __LINE__ << "] "
#define LOG_GC(level) ARK_LOG(level, Component::GC)
#define LOG_INTERPRETER(level) ARK_LOG(level, Component::INTERPRETER)
#define LOG_COMPILER(level) ARK_LOG(level, Component::COMPILER)

View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/platform/filesystem.h"
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "ecmascript/platform/directory.h"
#include "ecmascript/platform/file.h"
#include "os/filesystem.h"
namespace panda::ecmascript::filesystem {
bool CreateDirectory(const std::string& path)
{
if (path.empty()) {
return true;
}
auto pos = path.find_last_of('/');
if (pos != std::string::npos) {
if (!CreateDirectory(path.substr(0, pos))) {
return false;
}
}
panda::os::CreateDirectories(path);
if (!Exists(path)) {
return false;
}
return true;
}
bool Exists(const std::string& path)
{
return panda::ecmascript::FileExist(path.c_str());
}
std::string TempDirectoryPath()
{
const char* temp = getenv("TMPDIR");
if (temp) {
return std::string(temp);
}
return "/tmp";
}
std::size_t FileSize(const std::string& path)
{
struct stat info;
stat(path.c_str(), &info);
return info.st_size;
}
bool RemoveAll(const std::string& path)
{
struct stat info;
if (stat(path.c_str(), &info) != 0) {
return false;
}
if (S_ISDIR(info.st_mode)) {
DIR* dir = opendir(path.c_str());
if (!dir) {
return false;
}
struct dirent* entry;
while ((entry = readdir(dir)) != nullptr) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
std::string entryPath = path + "/" + entry->d_name;
if (!RemoveAll(entryPath)) {
closedir(dir);
return false;
}
}
closedir(dir);
return rmdir(path.c_str()) == 0;
} else {
return unlink(path.c_str()) == 0;
}
}
void CreateEmptyFile(const std::string& fileName)
{
std::string realPath;
if (!panda::ecmascript::RealPath(fileName, realPath, false)) {
LOG_FULL(ERROR) << "failed to create empty file: " << fileName << ", error: " << std::strerror(errno);
return;
}
if (Exists(realPath)) {
LOG_FULL(INFO) << realPath << " exists, skip creation";
return;
}
auto index = realPath.find_last_of('/');
if (index != std::string::npos) {
std::string dir = realPath.substr(0, index);
if (Exists(dir)) {
LOG_FULL(INFO) << dir << " exists, skip creation";
} else {
LOG_FULL(INFO) << "creating folder " << dir;
if (!CreateDirectory(dir)) {
LOG_FULL(ERROR) << "failed to create folder " << dir << ", error: " << std::strerror(errno);
return;
}
}
}
std::ofstream file(realPath);
if (!file.good()) {
LOG_FULL(ERROR) << "failed to create empty file: " << realPath << ", error: " << std::strerror(errno);
} else {
LOG_FULL(INFO) << "created empty file: " << realPath;
}
file.close();
}
} // namespace panda::ecmascript::kungfu::filesystem

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_BASE_FILESYSTEM_H
#define ECMASCRIPT_BASE_FILESYSTEM_H
#include <string>
#include <sys/types.h>
#include "ecmascript/common.h"
namespace panda::ecmascript::filesystem {
bool CreateDirectory(const std::string& path);
bool Exists(const std::string& path);
std::string TempDirectoryPath();
std::size_t FileSize(const std::string& path);
bool RemoveAll(const std::string& path);
PUBLIC_API void CreateEmptyFile(const std::string& fileName);
} // namespace panda::ecmascript::base
#endif // ECMASCRIPT_BASE_FILESYSTEM_H

View File

@ -41,7 +41,7 @@ std::string GetPathSeparator()
bool RealPath(const std::string &path, std::string &realPath, bool readOnly)
{
if (path.empty() || path.size() > PATH_MAX) {
LOG_ECMA(WARN) << "File path is illeage";
LOG_ECMA(WARN) << "File path is illegal";
return false;
}
char buffer[PATH_MAX] = { '\0' };
@ -51,7 +51,7 @@ bool RealPath(const std::string &path, std::string &realPath, bool readOnly)
realPath = path;
return true;
}
LOG_ECMA(ERROR) << "File path:" << path << " realpath failure. errno: " << errno;
LOG_ECMA(ERROR) << "File path: " << path << " realpath failure. errno: " << errno;
return false;
}
realPath = std::string(buffer);
@ -161,7 +161,7 @@ JSHandle<EcmaString> ResolveFilenameFromNative(JSThread *thread, JSTaggedValue d
bool FileExist(const char *filename)
{
return (access(filename, 0) != -1);
return (access(filename, F_OK) != -1);
}
int Unlink(const char *filename)

View File

@ -283,6 +283,7 @@
panda::ecmascript::SubtypingOperator::FillTSInheritInfo*;
panda::ecmascript::SubtypingOperator::MergeClassField*;
panda::ecmascript::Unlink*;
panda::ecmascript::filesystem::CreateEmptyFile*;
panda::ecmascript::base::ArrayHelper::GetLength*;
panda::ecmascript::base::utf_helper::ConvertRegionUtf16ToUtf8*;
panda::ecmascript::base::NumberHelper::DoubleInRangeInt32*;