Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "resource_registry.h"
12 :
13 : #include <algorithm>
14 : #include <cerrno>
15 : #include <cstdlib>
16 : #include <cstring>
17 : #include <dlfcn.h>
18 : #include <fstream>
19 : #include <set>
20 : #include <utility>
21 : #include <vector>
22 :
23 : #include <boost/filesystem.hpp>
24 : #include <boost/system/error_code.hpp>
25 :
26 : #include "ascendc_manifest_abi.h"
27 : #include "ascendc_tool_log.h"
28 : #include "file_utils.h"
29 : #include "nlohmann/json.hpp"
30 :
31 : namespace ascendc {
32 : namespace specialization_compile {
33 :
34 : bool IsKernelMetaSavingEnabled() noexcept
35 : {
36 : const char* environmentValue = std::getenv("ASCEND_OP_COMPILE_SAVE_KERNEL_META");
37 : if (environmentValue == nullptr) {
38 : return false;
39 : }
40 :
41 : const auto isWhitespace = [](char value) {
42 : return value == ' ' || value == '\t' || value == '\n' || value == '\r' || value == '\f' || value == '\v';
43 : };
44 : const char* firstValueCharacter = environmentValue;
45 : while (*firstValueCharacter != '\0' && isWhitespace(*firstValueCharacter)) {
46 : ++firstValueCharacter;
47 : }
48 : const char* valueEnd = firstValueCharacter;
49 : while (*valueEnd != '\0') {
50 : ++valueEnd;
51 : }
52 : while (valueEnd != firstValueCharacter && isWhitespace(*(valueEnd - 1))) {
53 : --valueEnd;
54 : }
55 : return valueEnd == firstValueCharacter + 1 && *firstValueCharacter == '1';
56 : }
57 :
58 : void LibraryDeleter::operator()(void* handle) const noexcept
59 : {
60 : if (handle != nullptr && dlclose(handle) != 0) {
61 : ASCENDLOGW("Failed to close compile resource shared object: handle=%p reason=dlclose returned nonzero", handle);
62 : }
63 : }
64 :
65 : namespace {
66 :
67 : namespace fs = boost::filesystem;
68 : using Json = nlohmann::json;
69 :
70 : constexpr char RELATIVE_JIT_ROOT[] = "op_impl/ai_core/tbe/kernel/jit";
71 : constexpr char LIBRARY_NAME_SUFFIX[] = "_compile_database.so";
72 : constexpr uint64_t MAX_MANIFEST_SIZE = 8U * 1024U * 1024U;
73 : constexpr uint64_t MAX_PATH_SIZE = 4096U;
74 : constexpr uint64_t MAX_RESOURCE_FILE_SIZE = 256U * 1024U * 1024U;
75 : constexpr uint64_t MAX_MANIFEST_RESOURCE_SIZE = 512U * 1024U * 1024U;
76 : constexpr uint64_t MAX_REGISTRY_RESOURCE_SIZE = 1024U * 1024U * 1024U;
77 : constexpr uint64_t MAX_MANIFEST_COUNT = 4096U;
78 : constexpr uint64_t MAX_EXTENSION_COUNT = 4096U;
79 : constexpr uint64_t MAX_FILE_COUNT = 65536U;
80 : constexpr uint64_t MAX_REGISTRY_FILE_COUNT = 131072U;
81 :
82 : const char* SourceTypeName(ResourceSourceType sourceType) noexcept
83 : {
84 : switch (sourceType) {
85 : case ResourceSourceType::External:
86 : return "external";
87 : case ResourceSourceType::Custom:
88 : return "custom";
89 : case ResourceSourceType::BuiltIn:
90 : return "built-in";
91 : }
92 : return "unknown";
93 : }
94 :
95 : const char* ResourceStatusName(ResourceStatus status) noexcept
96 : {
97 : switch (status) {
98 : case ResourceStatus::Success:
99 : return "success";
100 : case ResourceStatus::NotFound:
101 : return "not_found";
102 : case ResourceStatus::Conflict:
103 : return "conflict";
104 : case ResourceStatus::InvalidResource:
105 : return "invalid_resource";
106 : case ResourceStatus::IoError:
107 : return "io_error";
108 : case ResourceStatus::LoadError:
109 : return "load_error";
110 : case ResourceStatus::InternalError:
111 : return "internal_error";
112 : }
113 : return "unknown";
114 : }
115 :
116 : void CleanupPath(const std::string& path) noexcept
117 : {
118 : if (path.empty()) {
119 : return;
120 : }
121 : if (!FileUtils::RemoveAll(path)) {
122 : ASCENDLOGW("Failed to remove compile resource path: path=%s reason=recursive removal failed", path.c_str());
123 : }
124 : }
125 :
126 : ResourceStatus CreateTemporaryRoot(std::string& temporaryRoot)
127 : {
128 : const char* environment = std::getenv("TMPDIR");
129 : const fs::path configured = environment == nullptr || *environment == '\0' ? "/tmp" : environment;
130 : boost::system::error_code error;
131 : const fs::path parent = fs::canonical(configured, error);
132 : if (error) {
133 : ASCENDLOGE(
134 : "Failed to resolve compile resource temporary parent: configured=%s error=%s", configured.c_str(),
135 : error.message().c_str());
136 : return ResourceStatus::IoError;
137 : }
138 : if (!fs::is_directory(parent, error)) {
139 : ASCENDLOGE(
140 : "Compile resource temporary parent is not a directory: configured=%s resolved=%s error=%s",
141 : configured.c_str(), parent.c_str(), error ? error.message().c_str() : "none");
142 : return ResourceStatus::IoError;
143 : }
144 : const std::string pattern = (parent / "aclrtc-resource-XXXXXX").string();
145 : std::vector<char> writable(pattern.begin(), pattern.end());
146 : writable.push_back('\0');
147 : char* created = mkdtemp(writable.data());
148 : if (created == nullptr) {
149 : ASCENDLOGE(
150 : "Failed to create compile resource temporary root: parent=%s error=%s", parent.c_str(),
151 : std::strerror(errno));
152 : return ResourceStatus::IoError;
153 : }
154 : const fs::path canonical = fs::canonical(created, error);
155 : if (error) {
156 : ASCENDLOGE(
157 : "Failed to resolve created compile resource temporary root: path=%s error=%s", created,
158 : error.message().c_str());
159 : CleanupPath(created);
160 : return ResourceStatus::IoError;
161 : }
162 : if (canonical != fs::path(created).lexically_normal()) {
163 : ASCENDLOGE(
164 : "Compile resource temporary root identity mismatch: expected=%s actual=%s", created, canonical.c_str());
165 : CleanupPath(created);
166 : return ResourceStatus::IoError;
167 : }
168 : temporaryRoot = canonical.string();
169 : ASCENDLOGI("Created compile resource temporary root: path=%s", temporaryRoot.c_str());
170 : return ResourceStatus::Success;
171 : }
172 :
173 : bool TryAddWithinLimit(uint64_t value, uint64_t limit, uint64_t& total) noexcept
174 : {
175 : if (total > limit || value > limit - total) {
176 : return false;
177 : }
178 : total += value;
179 : return true;
180 : }
181 :
182 : ResourceStatus CopyString(const AcString& value, const char* field, uint64_t limit, std::string& output)
183 : {
184 : if (value.size != 0U && value.data == nullptr) {
185 : ASCENDLOGE(
186 : "Compile resource string has null data: field=%s size=%" PRIu64 " expected=non-null data", field,
187 : value.size);
188 : return ResourceStatus::InvalidResource;
189 : }
190 : if (value.size > limit) {
191 : ASCENDLOGE(
192 : "Compile resource string exceeds size limit: field=%s actual=%" PRIu64 " limit=%" PRIu64, field, value.size,
193 : limit);
194 : return ResourceStatus::InvalidResource;
195 : }
196 : output.assign(value.size == 0U ? "" : value.data, value.size);
197 : return ResourceStatus::Success;
198 : }
199 :
200 : bool IsPlainName(const std::string& value)
201 : {
202 : return !value.empty() && FileUtils::IsSafeRelativePath(value) && FileUtils::FileName(value) == value;
203 : }
204 :
205 : std::string Trim(const std::string& value)
206 : {
207 : const size_t begin = value.find_first_not_of(" \t\r\n");
208 : if (begin == std::string::npos) {
209 : return {};
210 : }
211 : return value.substr(begin, value.find_last_not_of(" \t\r\n") - begin + 1U);
212 : }
213 :
214 : std::vector<std::string> SplitList(const char* value, char delimiter)
215 : {
216 : std::vector<std::string> result;
217 : const std::string text(value == nullptr ? "" : value);
218 : size_t begin = 0U;
219 : while (begin <= text.size()) {
220 : const size_t end = text.find(delimiter, begin);
221 : const std::string item = Trim(text.substr(begin, end - begin));
222 : if (!item.empty() && std::find(result.begin(), result.end(), item) == result.end()) {
223 : result.push_back(item);
224 : }
225 : if (end == std::string::npos) {
226 : break;
227 : }
228 : begin = end + 1U;
229 : }
230 : return result;
231 : }
232 :
233 : ResourceStatus ValidateBundleHeader(const AcCompileResourceBundleHeader* header, const LibrarySpec& spec)
234 : {
235 : if (header == nullptr) {
236 : ASCENDLOGE(
237 : "Compile resource bundle entry point returned null: source_type=%s so=%s", SourceTypeName(spec.sourceType),
238 : spec.path.c_str());
239 : return ResourceStatus::InvalidResource;
240 : }
241 : if (header->magic != AC_COMPILE_RESOURCE_MAGIC) {
242 : ASCENDLOGE(
243 : "Compile resource bundle magic mismatch: source_type=%s so=%s expected=0x%08x actual=0x%08x",
244 : SourceTypeName(spec.sourceType), spec.path.c_str(), AC_COMPILE_RESOURCE_MAGIC, header->magic);
245 : return ResourceStatus::InvalidResource;
246 : }
247 : if (header->abiVersion != AC_COMPILE_RESOURCE_ABI_VERSION) {
248 : ASCENDLOGE(
249 : "Compile resource bundle ABI version mismatch: source_type=%s so=%s expected=%u actual=%u",
250 : SourceTypeName(spec.sourceType), spec.path.c_str(), AC_COMPILE_RESOURCE_ABI_VERSION, header->abiVersion);
251 : return ResourceStatus::InvalidResource;
252 : }
253 : if (header->structSize != sizeof(AcCompileResourceBundle)) {
254 : ASCENDLOGE(
255 : "Compile resource bundle size mismatch: source_type=%s so=%s expected=%zu actual=%u",
256 : SourceTypeName(spec.sourceType), spec.path.c_str(), sizeof(AcCompileResourceBundle), header->structSize);
257 : return ResourceStatus::InvalidResource;
258 : }
259 : if (header->flags != 0U) {
260 : ASCENDLOGE(
261 : "Compile resource bundle has unsupported flags: source_type=%s so=%s expected=0 actual=0x%08x",
262 : SourceTypeName(spec.sourceType), spec.path.c_str(), header->flags);
263 : return ResourceStatus::InvalidResource;
264 : }
265 : return ResourceStatus::Success;
266 : }
267 :
268 : ResourceStatus ValidateManifestTable(const AcCompileResourceBundle& bundle, const LibrarySpec& spec)
269 : {
270 : if (bundle.manifestCount == 0U) {
271 : ASCENDLOGE(
272 : "Compile resource bundle has no manifests: source_type=%s so=%s expected_count=1..%" PRIu64,
273 : SourceTypeName(spec.sourceType), spec.path.c_str(), MAX_MANIFEST_COUNT);
274 : return ResourceStatus::InvalidResource;
275 : }
276 : if (bundle.manifestCount > MAX_MANIFEST_COUNT) {
277 : ASCENDLOGE(
278 : "Compile resource manifest count exceeds limit: source_type=%s so=%s actual=%" PRIu64 " limit=%" PRIu64,
279 : SourceTypeName(spec.sourceType), spec.path.c_str(), bundle.manifestCount, MAX_MANIFEST_COUNT);
280 : return ResourceStatus::InvalidResource;
281 : }
282 : if (bundle.manifests == nullptr) {
283 : ASCENDLOGE(
284 : "Compile resource manifest table is null: source_type=%s so=%s count=%" PRIu64,
285 : SourceTypeName(spec.sourceType), spec.path.c_str(), bundle.manifestCount);
286 : return ResourceStatus::InvalidResource;
287 : }
288 : return ResourceStatus::Success;
289 : }
290 :
291 : ResourceStatus ValidateExtensionTable(const AcCompileResourceBundle& bundle, const LibrarySpec& spec)
292 : {
293 : if (bundle.extensionCount == 0U) {
294 : if (bundle.extensions != nullptr) {
295 : ASCENDLOGE(
296 : "Compile resource extension table is inconsistent: source_type=%s so=%s count=0 pointer=%p "
297 : "expected=null",
298 : SourceTypeName(spec.sourceType), spec.path.c_str(), static_cast<const void*>(bundle.extensions));
299 : return ResourceStatus::InvalidResource;
300 : }
301 : return ResourceStatus::Success;
302 : }
303 : if (bundle.extensionCount > MAX_EXTENSION_COUNT) {
304 : ASCENDLOGE(
305 : "Compile resource extension count exceeds limit: source_type=%s so=%s actual=%" PRIu64 " limit=%" PRIu64,
306 : SourceTypeName(spec.sourceType), spec.path.c_str(), bundle.extensionCount, MAX_EXTENSION_COUNT);
307 : return ResourceStatus::InvalidResource;
308 : }
309 : if (bundle.extensions == nullptr) {
310 : ASCENDLOGE(
311 : "Compile resource extension table is null: source_type=%s so=%s count=%" PRIu64,
312 : SourceTypeName(spec.sourceType), spec.path.c_str(), bundle.extensionCount);
313 : return ResourceStatus::InvalidResource;
314 : }
315 : for (uint64_t index = 0U; index < bundle.extensionCount; ++index) {
316 : const AcCompileResourceExtension& extension = bundle.extensions[index];
317 : const uint64_t unsupportedFlags = extension.flags & ~AC_COMPILE_RESOURCE_EXTENSION_REQUIRED;
318 : if (unsupportedFlags != 0U) {
319 : ASCENDLOGE(
320 : "Compile resource extension has unsupported flags: source_type=%s so=%s extension=%" PRIu64
321 : " type=%u version=%u flags=0x%" PRIx64 " supported_mask=0x%" PRIx64,
322 : SourceTypeName(spec.sourceType), spec.path.c_str(), index, extension.type, extension.version,
323 : extension.flags, static_cast<uint64_t>(AC_COMPILE_RESOURCE_EXTENSION_REQUIRED));
324 : return ResourceStatus::InvalidResource;
325 : }
326 : if (extension.dataSize != 0U && extension.data == nullptr) {
327 : ASCENDLOGE(
328 : "Compile resource extension has null data: source_type=%s so=%s extension=%" PRIu64
329 : " type=%u version=%u size=%" PRIu64 " expected=non-null data",
330 : SourceTypeName(spec.sourceType), spec.path.c_str(), index, extension.type, extension.version,
331 : extension.dataSize);
332 : return ResourceStatus::InvalidResource;
333 : }
334 : if ((extension.flags & AC_COMPILE_RESOURCE_EXTENSION_REQUIRED) != 0U) {
335 : ASCENDLOGE(
336 : "Compile resource bundle requires an unsupported extension: source_type=%s so=%s extension=%" PRIu64
337 : " type=%u version=%u",
338 : SourceTypeName(spec.sourceType), spec.path.c_str(), index, extension.type, extension.version);
339 : return ResourceStatus::InvalidResource;
340 : }
341 : }
342 : return ResourceStatus::Success;
343 : }
344 :
345 : struct ManifestOwnership {
346 : Json document;
347 : std::string resourceId;
348 : std::string sourceFile;
349 : bool hasSourceFile = false;
350 : };
351 :
352 : ResourceStatus ParseResourceId(
353 : const Json& document, const LibrarySpec& spec, uint64_t manifestIndex, std::string& resourceId)
354 : {
355 : if (!document.contains("resource_id")) {
356 : ASCENDLOGE(
357 : "Compile resource manifest is missing required field: source_type=%s so=%s manifest=%" PRIu64
358 : " field=resource_id",
359 : SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex);
360 : return ResourceStatus::InvalidResource;
361 : }
362 : if (!document.at("resource_id").is_string()) {
363 : ASCENDLOGE(
364 : "Compile resource manifest field has invalid type: source_type=%s so=%s manifest=%" PRIu64
365 : " field=resource_id expected=string actual=%s",
366 : SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex, document.at("resource_id").type_name());
367 : return ResourceStatus::InvalidResource;
368 : }
369 : resourceId = document.at("resource_id").get<std::string>();
370 22 : if (resourceId.empty()) {
371 : ASCENDLOGE(
372 : "Compile resource manifest field is empty: source_type=%s so=%s manifest=%" PRIu64
373 : " field=resource_id expected=non-empty string",
374 2 : SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex);
375 2 : return ResourceStatus::InvalidResource;
376 : }
377 : return ResourceStatus::Success;
378 : }
379 :
380 : ResourceStatus ParseSourceFile(
381 : const Json& document, const LibrarySpec& spec, uint64_t manifestIndex, ManifestOwnership& ownership)
382 : {
383 : ownership.hasSourceFile = document.contains("source_file");
384 : if (!ownership.hasSourceFile) {
385 : return ResourceStatus::Success;
386 : }
387 : if (!document.at("source_file").is_string()) {
388 : ASCENDLOGE(
389 : "Compile resource manifest field has invalid type: resource_id=%s source_type=%s so=%s manifest=%" PRIu64
390 : " field=source_file expected=string actual=%s",
391 : ownership.resourceId.c_str(), SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex,
392 : document.at("source_file").type_name());
393 : return ResourceStatus::InvalidResource;
394 : }
395 : ownership.sourceFile = document.at("source_file").get<std::string>();
396 : if (!IsPlainName(ownership.sourceFile)) {
397 : ASCENDLOGE(
398 : "Compile resource manifest has unsafe source file name: resource_id=%s source_type=%s so=%s "
399 : "manifest=%" PRIu64 " source_file=%s expected=plain file name",
400 : ownership.resourceId.c_str(), SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex,
401 : ownership.sourceFile.c_str());
402 : return ResourceStatus::InvalidResource;
403 : }
404 : return ResourceStatus::Success;
405 : }
406 :
407 : ResourceStatus ParseManifestOwnership(
408 : const AcCompileResourceManifest& unit, const LibrarySpec& spec, uint64_t manifestIndex,
409 : ManifestOwnership& ownership)
410 : {
411 : std::string manifestText;
412 : ResourceStatus status = CopyString(unit.json, "manifest.json", MAX_MANIFEST_SIZE, manifestText);
413 : if (status != ResourceStatus::Success) {
414 : return status;
415 : }
416 : ownership.document = Json::parse(manifestText, nullptr, false);
417 : if (ownership.document.is_discarded()) {
418 : ASCENDLOGE(
419 : "Failed to parse compile resource manifest JSON: source_type=%s so=%s manifest=%" PRIu64
420 : " reason=malformed JSON",
421 : SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex);
422 : return ResourceStatus::InvalidResource;
423 : }
424 : if (!ownership.document.is_object()) {
425 : ASCENDLOGE(
426 : "Compile resource manifest root has invalid type: source_type=%s so=%s manifest=%" PRIu64
427 : " expected=object actual=%s",
428 : SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex, ownership.document.type_name());
429 : return ResourceStatus::InvalidResource;
430 : }
431 : status = ParseResourceId(ownership.document, spec, manifestIndex, ownership.resourceId);
432 : if (status != ResourceStatus::Success) {
433 : return status;
434 : }
435 : return ParseSourceFile(ownership.document, spec, manifestIndex, ownership);
436 : }
437 :
438 : ResourceStatus PrepareMaterializationRoot(
439 : const std::string& temporaryRoot, const std::string& resourceId, ResourceSourceType sourceType,
440 : std::string& categoryRoot, std::string& canonicalRoot)
441 : {
442 : boost::system::error_code error;
443 : const fs::path randomComponent = fs::unique_path("materialize-%%%%%%%%%%%%%%%%", error);
444 : if (error || randomComponent.empty() || randomComponent.has_parent_path()) {
445 : ASCENDLOGE(
446 : "Failed to generate compile resource materialization path: resource_id=%s source_type=%s error=%s",
447 : resourceId.c_str(), SourceTypeName(sourceType), error ? error.message().c_str() : "invalid random path");
448 : return ResourceStatus::IoError;
449 : }
450 : const std::string categoryParent = FileUtils::JoinPath(temporaryRoot, SourceTypeName(sourceType));
451 : categoryRoot = FileUtils::JoinPath(categoryParent, randomComponent.string());
452 : if (!FileUtils::CreateDirectories(categoryRoot)) {
453 : ASCENDLOGE(
454 : "Failed to create compile resource materialization directory: resource_id=%s source_type=%s path=%s",
455 : resourceId.c_str(), SourceTypeName(sourceType), categoryRoot.c_str());
456 : return ResourceStatus::IoError;
457 : }
458 : const fs::path canonical = fs::canonical(categoryRoot, error);
459 : if (error) {
460 : ASCENDLOGE(
461 : "Failed to resolve compile resource materialization directory: resource_id=%s source_type=%s path=%s "
462 : "error=%s",
463 : resourceId.c_str(), SourceTypeName(sourceType), categoryRoot.c_str(), error.message().c_str());
464 : return ResourceStatus::IoError;
465 : }
466 : if (canonical != fs::path(categoryRoot).lexically_normal()) {
467 : ASCENDLOGE(
468 : "Compile resource materialization directory identity mismatch: resource_id=%s source_type=%s expected=%s "
469 : "actual=%s",
470 : resourceId.c_str(), SourceTypeName(sourceType), categoryRoot.c_str(), canonical.c_str());
471 : return ResourceStatus::IoError;
472 : }
473 : canonicalRoot = canonical.string();
474 : return ResourceStatus::Success;
475 : }
476 :
477 : ResourceStatus ResolveExplicitDiscoveryPath(const char* path, std::string& canonical)
478 : {
479 : if (FileUtils::IsSymlink(path)) {
480 : ASCENDLOGE("Explicit compile resource SO must not be a symbolic link: path=%s expected=regular file", path);
481 : return ResourceStatus::InvalidResource;
482 : }
483 : if (!FileUtils::IsRegularFile(path)) {
484 : if (FileUtils::IsDirectory(path)) {
485 : ASCENDLOGE(
486 : "Explicit compile resource path must be a regular SO file; directory input is unsupported: path=%s",
487 : path);
488 : } else {
489 : ASCENDLOGE("Explicit compile resource path is not a regular SO file: path=%s", path);
490 : }
491 : return ResourceStatus::InvalidResource;
492 : }
493 : if (!FileUtils::ResolveCanonicalPath(path, canonical)) {
494 : ASCENDLOGE("Failed to resolve explicit compile resource SO: path=%s", path);
495 : return ResourceStatus::InvalidResource;
496 : }
497 : return ResourceStatus::Success;
498 : }
499 :
500 : ResourceStatus ValidateResourceFilePath(
501 : const std::string& resourceId, const std::string& fileName, const std::string& relativePath,
502 : std::set<std::string>& paths)
503 : {
504 : if (!IsPlainName(fileName)) {
505 : ASCENDLOGE(
506 : "Compile resource file name is unsafe: resource_id=%s file_name=%s expected=plain file name",
507 : resourceId.c_str(), fileName.c_str());
508 : return ResourceStatus::InvalidResource;
509 : }
510 : if (!FileUtils::IsSafeRelativePath(relativePath)) {
511 : ASCENDLOGE(
512 : "Compile resource file path is unsafe: resource_id=%s path=%s expected=relative path without traversal",
513 : resourceId.c_str(), relativePath.c_str());
514 : return ResourceStatus::InvalidResource;
515 : }
516 : const std::string pathFileName = FileUtils::FileName(relativePath);
517 : if (pathFileName != fileName) {
518 : ASCENDLOGE(
519 : "Compile resource file name does not match its path: resource_id=%s file_name=%s path=%s "
520 : "path_file_name=%s",
521 : resourceId.c_str(), fileName.c_str(), relativePath.c_str(), pathFileName.c_str());
522 : return ResourceStatus::InvalidResource;
523 : }
524 : if (!paths.insert(relativePath).second) {
525 : ASCENDLOGE(
526 : "Compile resource file path is duplicated in manifest: resource_id=%s path=%s", resourceId.c_str(),
527 : relativePath.c_str());
528 : return ResourceStatus::InvalidResource;
529 : }
530 : return ResourceStatus::Success;
531 : }
532 :
533 : ResourceStatus ValidateResourceFilePayload(
534 : const AcCompileResourceFile& file, const std::string& resourceId, const std::string& relativePath,
535 : uint64_t& manifestBytes, StagedResources& staged)
536 : {
537 : if (file.size > MAX_RESOURCE_FILE_SIZE) {
538 : ASCENDLOGE(
539 : "Compile resource file exceeds size limit: resource_id=%s path=%s actual=%" PRIu64 " limit=%" PRIu64,
540 : resourceId.c_str(), relativePath.c_str(), file.size, MAX_RESOURCE_FILE_SIZE);
541 : return ResourceStatus::InvalidResource;
542 : }
543 : if (file.size != 0U && file.data == nullptr) {
544 : ASCENDLOGE(
545 : "Compile resource file has null payload: resource_id=%s path=%s size=%" PRIu64 " expected=non-null data",
546 : resourceId.c_str(), relativePath.c_str(), file.size);
547 : return ResourceStatus::InvalidResource;
548 : }
549 : if (!TryAddWithinLimit(file.size, MAX_MANIFEST_RESOURCE_SIZE, manifestBytes)) {
550 : ASCENDLOGE(
551 : "Compile resource manifest payload exceeds size limit: resource_id=%s path=%s current=%" PRIu64
552 : " incoming=%" PRIu64 " limit=%" PRIu64,
553 : resourceId.c_str(), relativePath.c_str(), manifestBytes, file.size, MAX_MANIFEST_RESOURCE_SIZE);
554 : return ResourceStatus::InvalidResource;
555 : }
556 : if (!TryAddWithinLimit(file.size, MAX_REGISTRY_RESOURCE_SIZE, staged.bytes)) {
557 : ASCENDLOGE(
558 : "Staged compile resource payload exceeds registry size limit: resource_id=%s path=%s current=%" PRIu64
559 : " incoming=%" PRIu64 " limit=%" PRIu64,
560 : resourceId.c_str(), relativePath.c_str(), staged.bytes, file.size, MAX_REGISTRY_RESOURCE_SIZE);
561 : return ResourceStatus::InvalidResource;
562 : }
563 : return ResourceStatus::Success;
564 : }
565 :
566 : ResourceStatus ValidateManifestFileTable(
567 : const AcCompileResourceManifest& unit, const std::string& resourceId, const StagedResources& staged)
568 : {
569 : if (unit.fileCount > MAX_FILE_COUNT) {
570 : ASCENDLOGE(
571 : "Compile resource manifest file count exceeds limit: resource_id=%s actual=%" PRIu64 " limit=%" PRIu64,
572 : resourceId.c_str(), unit.fileCount, MAX_FILE_COUNT);
573 : return ResourceStatus::InvalidResource;
574 : }
575 : if (unit.fileCount == 0U && unit.files != nullptr) {
576 : ASCENDLOGE(
577 : "Compile resource manifest has inconsistent file table: resource_id=%s count=0 pointer=%p "
578 : "expected_pointer=null",
579 : resourceId.c_str(), static_cast<const void*>(unit.files));
580 : return ResourceStatus::InvalidResource;
581 : }
582 : if (unit.fileCount != 0U && unit.files == nullptr) {
583 : ASCENDLOGE(
584 : "Compile resource manifest has inconsistent file table: resource_id=%s count=%" PRIu64
585 : " pointer=null expected_pointer=non-null",
586 : resourceId.c_str(), unit.fileCount);
587 : return ResourceStatus::InvalidResource;
588 : }
589 : if (staged.files > MAX_REGISTRY_FILE_COUNT || unit.fileCount > MAX_REGISTRY_FILE_COUNT - staged.files) {
590 : ASCENDLOGE(
591 : "Staged compile resource file count exceeds registry limit: resource_id=%s staged=%" PRIu64
592 : " incoming=%" PRIu64 " limit=%" PRIu64,
593 : resourceId.c_str(), staged.files, unit.fileCount, MAX_REGISTRY_FILE_COUNT);
594 : return ResourceStatus::InvalidResource;
595 : }
596 : return ResourceStatus::Success;
597 : }
598 :
599 : bool CheckRegistryLimits(const StagedResources& staged, ResourceSourceType sourceType, uint64_t& bytes, uint64_t& files)
600 : {
601 : if (!staged.discovered || staged.conflict) {
602 : return true;
603 : }
604 : const uint64_t currentBytes = bytes;
605 : if (!TryAddWithinLimit(staged.bytes, MAX_REGISTRY_RESOURCE_SIZE, bytes)) {
606 : ASCENDLOGE(
607 : "Compile resource registry payload limit exceeded: source_type=%s current=%" PRIu64 " incoming=%" PRIu64
608 : " limit=%" PRIu64,
609 : SourceTypeName(sourceType), currentBytes, staged.bytes, MAX_REGISTRY_RESOURCE_SIZE);
610 : return false;
611 : }
612 : const uint64_t currentFiles = files;
613 : if (!TryAddWithinLimit(staged.files, MAX_REGISTRY_FILE_COUNT, files)) {
614 : ASCENDLOGE(
615 : "Compile resource registry file count limit exceeded: source_type=%s current=%" PRIu64 " incoming=%" PRIu64
616 : " limit=%" PRIu64,
617 : SourceTypeName(sourceType), currentFiles, staged.files, MAX_REGISTRY_FILE_COUNT);
618 : return false;
619 : }
620 : return true;
621 : }
622 :
623 : ResourceStatus MergeStagedLibrary(const LibrarySpec& spec, StagedResources& incoming, StagedResources& staged)
624 : {
625 : for (const auto& item : incoming.resources) {
626 : const auto existing = staged.resources.find(item.first);
627 : if (existing != staged.resources.end()) {
628 : ASCENDLOGW(
629 : "Skipping compile resource SO because its resource conflicts with an earlier SO: resource_id=%s "
630 : "source_type=%s incoming_so=%s existing_so=%s",
631 : item.first.c_str(), SourceTypeName(spec.sourceType), spec.path.c_str(),
632 : existing->second->sourceSoPath.c_str());
633 : return ResourceStatus::Conflict;
634 : }
635 : }
636 : uint64_t bytes = staged.bytes;
637 : uint64_t files = staged.files;
638 : if (!TryAddWithinLimit(incoming.bytes, MAX_REGISTRY_RESOURCE_SIZE, bytes) ||
639 : !TryAddWithinLimit(incoming.files, MAX_REGISTRY_FILE_COUNT, files)) {
640 : ASCENDLOGW(
641 : "Skipping compile resource SO because cumulative staged resources exceed the registry limit: "
642 : "source_type=%s so=%s current_bytes=%" PRIu64 " incoming_bytes=%" PRIu64 " current_files=%" PRIu64
643 : " incoming_files=%" PRIu64,
644 : SourceTypeName(spec.sourceType), spec.path.c_str(), staged.bytes, incoming.bytes, staged.files,
645 : incoming.files);
646 : return ResourceStatus::InvalidResource;
647 : }
648 : staged.resources.merge(incoming.resources);
649 : staged.bytes = bytes;
650 : staged.files = files;
651 : return ResourceStatus::Success;
652 : }
653 :
654 : } // namespace
655 :
656 : AutomaticRoots ResourceRegistry::AutomaticSearchRoots()
657 : {
658 : AutomaticRoots roots;
659 : for (const std::string& path : SplitList(std::getenv("ASCEND_CUSTOM_OPP_PATH"), ':')) {
660 : roots.custom.push_back(FileUtils::JoinPath(path, RELATIVE_JIT_ROOT));
661 : }
662 : const char* environment = std::getenv("ASCEND_OPP_PATH");
663 : if (environment == nullptr || *environment == '\0') {
664 : ASCENDLOGD(
665 : "Automatic compile resource roots collected without built-in OPP path: custom_roots=%zu "
666 : "reason=ASCEND_OPP_PATH is unset",
667 : roots.custom.size());
668 : return roots;
669 : }
670 : std::string oppRoot;
671 : if (!FileUtils::ResolveCanonicalPath(environment, oppRoot)) {
672 : ASCENDLOGW(
673 : "Unable to normalize configured OPP root: path=%s; vendor and built-in discovery will be skipped",
674 : environment);
675 : return roots;
676 : }
677 : const std::string vendorConfig = FileUtils::JoinPath(oppRoot, "vendors/config.ini");
678 : std::string canonicalVendorConfig;
679 : if (!FileUtils::ResolveCanonicalPath(vendorConfig, canonicalVendorConfig)) {
680 : ASCENDLOGW(
681 : "Unable to normalize optional compile resource vendor configuration: path=%s; "
682 : "built-in discovery will continue",
683 : vendorConfig.c_str());
684 : } else {
685 : std::ifstream input(canonicalVendorConfig);
686 : if (!input.is_open()) {
687 : ASCENDLOGW(
688 : "Unable to read optional compile resource vendor configuration: path=%s reason=open failed; "
689 : "built-in discovery will continue",
690 : canonicalVendorConfig.c_str());
691 : }
692 : std::string line;
693 : while (std::getline(input, line)) {
694 : const size_t separator = line.find('=');
695 : if (separator == std::string::npos || Trim(line.substr(0U, separator)) != "load_priority") {
696 : continue;
697 : }
698 : for (const std::string& vendor : SplitList(line.substr(separator + 1U).c_str(), ',')) {
699 : if (IsPlainName(vendor)) {
700 : roots.custom.push_back(
701 : FileUtils::JoinPath(FileUtils::JoinPath(oppRoot, "vendors/" + vendor), RELATIVE_JIT_ROOT));
702 : } else {
703 : ASCENDLOGW(
704 : "Ignoring unsafe compile resource vendor name: path=%s vendor=%s expected=plain directory name",
705 : canonicalVendorConfig.c_str(), vendor.c_str());
706 : }
707 : }
708 : break;
709 : }
710 : }
711 : roots.builtIn.push_back(FileUtils::JoinPath(FileUtils::JoinPath(oppRoot, "built-in"), RELATIVE_JIT_ROOT));
712 : ASCENDLOGD(
713 : "Automatic compile resource roots collected: custom_roots=%zu built_in_roots=%zu opp_root=%s",
714 : roots.custom.size(), roots.builtIn.size(), oppRoot.c_str());
715 : return roots;
716 : }
717 :
718 : bool ResourceRegistry::IsLibraryName(const std::string& path)
719 : {
720 : const std::string name = FileUtils::FileName(path);
721 : return name.size() > std::strlen("lib") + std::strlen(LIBRARY_NAME_SUFFIX) && name.rfind("lib", 0U) == 0U &&
722 : name.compare(
723 : name.size() - std::strlen(LIBRARY_NAME_SUFFIX), std::strlen(LIBRARY_NAME_SUFFIX), LIBRARY_NAME_SUFFIX) ==
724 : 0;
725 : }
726 :
727 : void ResourceRegistry::AddLibrary(const std::string& path, std::set<std::string>& found)
728 : {
729 : if (!IsLibraryName(path) || !FileUtils::IsRegularFile(path) || FileUtils::IsSymlink(path)) {
730 : return;
731 : }
732 : std::string canonical;
733 : if (!FileUtils::ResolveCanonicalPath(path, canonical)) {
734 : ASCENDLOGW("Ignoring compile resource SO with unresolved path: path=%s", path.c_str());
735 : return;
736 : }
737 : found.insert(canonical);
738 : }
739 :
740 : bool ResourceRegistry::CollectLibraries(
741 : const std::string& root, ResourceSourceType sourceType, bool recursive, std::set<std::string>& found)
742 : {
743 : const size_t initialCount = found.size();
744 : ASCENDLOGD(
745 : "Scanning compile resource directory: source_type=%s root=%s recursive=%s", SourceTypeName(sourceType),
746 : root.c_str(), recursive ? "true" : "false");
747 : std::vector<std::string> pending = {root};
748 : boost::system::error_code error;
749 : while (!pending.empty()) {
750 : const std::string currentRoot = std::move(pending.back());
751 : pending.pop_back();
752 : fs::directory_iterator current(currentRoot, fs::directory_options::none, error);
753 : const fs::directory_iterator end;
754 : if (error) {
755 : ASCENDLOGE(
756 : "Failed to scan compile resource directory: source_type=%s path=%s error=%s",
757 : SourceTypeName(sourceType), currentRoot.c_str(), error.message().c_str());
758 : return false;
759 : }
760 : while (current != end) {
761 : const std::string path = current->path().string();
762 : AddLibrary(path, found);
763 : const fs::file_status status = recursive ? current->symlink_status(error) : fs::file_status();
764 : if (error) {
765 : ASCENDLOGE(
766 : "Failed to inspect compile resource path: source_type=%s path=%s error=%s",
767 : SourceTypeName(sourceType), path.c_str(), error.message().c_str());
768 : return false;
769 : }
770 : if (recursive && fs::is_directory(status)) {
771 : pending.push_back(path);
772 : }
773 : current.increment(error);
774 : if (error) {
775 : ASCENDLOGE(
776 : "Failed to scan compile resource directory: source_type=%s path=%s error=%s",
777 : SourceTypeName(sourceType), currentRoot.c_str(), error.message().c_str());
778 : return false;
779 : }
780 : }
781 : }
782 : ASCENDLOGD(
783 : "Finished scanning compile resource directory: source_type=%s root=%s libraries_added=%zu",
784 : SourceTypeName(sourceType), root.c_str(), found.size() - initialCount);
785 : return true;
786 : }
787 :
788 : bool ResourceRegistry::CollectAutomaticLibraries(
789 : const std::vector<std::string>& roots, ResourceSourceType sourceType, std::set<std::string>& found)
790 : {
791 : for (const std::string& root : roots) {
792 : if (!FileUtils::IsDirectory(root)) {
793 : ASCENDLOGD(
794 : "Skipping missing automatic compile resource root: source_type=%s path=%s", SourceTypeName(sourceType),
795 : root.c_str());
796 : continue;
797 : }
798 : if (!CollectLibraries(root, sourceType, true, found)) {
799 : return false;
800 : }
801 : }
802 : return true;
803 : }
804 :
805 : ResourceStatus ResourceRegistry::DiscoverLibraries(const char* directory, std::vector<LibrarySpec>& libraries)
806 : {
807 : const bool automatic = directory == nullptr || *directory == '\0';
808 : ASCENDLOGI(
809 : "Discovering compile resource libraries: mode=%s path=%s", automatic ? "automatic" : "explicit",
810 : automatic ? "<environment>" : directory);
811 : if (!automatic) {
812 : std::string canonical;
813 : const ResourceStatus status = ResolveExplicitDiscoveryPath(directory, canonical);
814 : if (status != ResourceStatus::Success) {
815 : return status;
816 : }
817 : libraries.push_back({canonical, ResourceSourceType::External});
818 : ASCENDLOGI("Discovered explicit compile resource SO: path=%s", canonical.c_str());
819 : return ResourceStatus::Success;
820 : }
821 : const AutomaticRoots roots = AutomaticSearchRoots();
822 : std::set<std::string> custom;
823 : std::set<std::string> builtIn;
824 : if (!CollectAutomaticLibraries(roots.custom, ResourceSourceType::Custom, custom) ||
825 : !CollectAutomaticLibraries(roots.builtIn, ResourceSourceType::BuiltIn, builtIn)) {
826 : return ResourceStatus::IoError;
827 : }
828 : for (const std::string& path : custom) {
829 : libraries.push_back({path, ResourceSourceType::Custom});
830 : }
831 : for (const std::string& path : builtIn) {
832 : libraries.push_back({path, ResourceSourceType::BuiltIn});
833 : }
834 : if (libraries.empty()) {
835 : ASCENDLOGW(
836 : "No compile resource libraries found by automatic discovery: custom_roots=%zu built_in_roots=%zu "
837 : "pattern=lib*%s",
838 : roots.custom.size(), roots.builtIn.size(), LIBRARY_NAME_SUFFIX);
839 : return ResourceStatus::NotFound;
840 : }
841 : ASCENDLOGI(
842 : "Discovered compile resource libraries: mode=automatic custom=%zu built_in=%zu total=%zu", custom.size(),
843 : builtIn.size(), libraries.size());
844 : return ResourceStatus::Success;
845 : }
846 :
847 : ResourceStatus ResourceRegistry::GetBundle(
848 : const LibraryHandle& library, const LibrarySpec& spec, const AcCompileResourceBundle*& bundle)
849 : {
850 : dlerror();
851 : const auto getter =
852 : reinterpret_cast<AscendcGetCompileResourceBundleFn>(dlsym(library.get(), "AscendcGetCompileResourceBundle"));
853 : const char* symbolError = dlerror();
854 : if (symbolError != nullptr || getter == nullptr) {
855 : ASCENDLOGE(
856 : "Failed to resolve compile resource bundle entry point: source_type=%s so=%s "
857 : "symbol=AscendcGetCompileResourceBundle error=%s",
858 : SourceTypeName(spec.sourceType), spec.path.c_str(),
859 : symbolError == nullptr ? "symbol resolved to null" : symbolError);
860 : return ResourceStatus::LoadError;
861 : }
862 : const AcCompileResourceBundleHeader* header = getter();
863 : ResourceStatus status = ValidateBundleHeader(header, spec);
864 : if (status != ResourceStatus::Success) {
865 : return status;
866 : }
867 : bundle = reinterpret_cast<const AcCompileResourceBundle*>(header);
868 : status = ValidateManifestTable(*bundle, spec);
869 : if (status == ResourceStatus::Success) {
870 : status = ValidateExtensionTable(*bundle, spec);
871 : }
872 : if (status == ResourceStatus::Success) {
873 : ASCENDLOGD(
874 : "Validated compile resource bundle: source_type=%s so=%s manifests=%" PRIu64 " extensions=%" PRIu64,
875 : SourceTypeName(spec.sourceType), spec.path.c_str(), bundle->manifestCount, bundle->extensionCount);
876 : }
877 : return status;
878 : }
879 :
880 : ResourceStatus ResourceRegistry::ResolveSourceRoot(
881 : const fs::path& searchRoot, const std::string& resourceId, std::string& canonicalRoot)
882 : {
883 : boost::system::error_code error;
884 : const fs::file_status status = fs::symlink_status(searchRoot, error);
885 : if (error) {
886 : ASCENDLOGE(
887 : "Failed to inspect compile source root: resource_id=%s root=%s error=%s", resourceId.c_str(),
888 : searchRoot.c_str(), error.message().c_str());
889 : return error == boost::system::errc::no_such_file_or_directory ? ResourceStatus::InvalidResource :
890 : ResourceStatus::IoError;
891 : }
892 : if (fs::is_symlink(status)) {
893 : ASCENDLOGE(
894 : "Compile source root must not be a symbolic link: resource_id=%s root=%s", resourceId.c_str(),
895 : searchRoot.c_str());
896 : return ResourceStatus::InvalidResource;
897 : }
898 : if (!fs::is_directory(status)) {
899 : ASCENDLOGE(
900 : "Compile source root is not a directory: resource_id=%s root=%s", resourceId.c_str(), searchRoot.c_str());
901 : return ResourceStatus::InvalidResource;
902 : }
903 : const fs::path canonical = fs::canonical(searchRoot, error);
904 : if (error) {
905 : ASCENDLOGE(
906 : "Failed to resolve compile source root: resource_id=%s root=%s error=%s", resourceId.c_str(),
907 : searchRoot.c_str(), error.message().c_str());
908 : return ResourceStatus::IoError;
909 : }
910 : canonicalRoot = canonical.string();
911 : return ResourceStatus::Success;
912 : }
913 :
914 : ResourceStatus ResourceRegistry::AddSourceMatch(
915 : const fs::path& candidate, const std::string& sourceFile, const std::string& canonicalRoot,
916 : const std::string& resourceId, std::set<std::string>& matches)
917 : {
918 : if (candidate.filename() != sourceFile) {
919 : return ResourceStatus::Success;
920 : }
921 : boost::system::error_code error;
922 : const fs::file_status status = fs::symlink_status(candidate, error);
923 : if (error) {
924 : ASCENDLOGE(
925 : "Failed to inspect compile source candidate: resource_id=%s path=%s error=%s", resourceId.c_str(),
926 : candidate.c_str(), error.message().c_str());
927 : return ResourceStatus::IoError;
928 : }
929 : if (!fs::is_regular_file(status)) {
930 : return ResourceStatus::Success;
931 : }
932 : const fs::path canonical = fs::canonical(candidate, error);
933 : if (error) {
934 : ASCENDLOGE(
935 : "Failed to resolve compile source candidate: resource_id=%s path=%s error=%s", resourceId.c_str(),
936 : candidate.c_str(), error.message().c_str());
937 : return ResourceStatus::IoError;
938 : }
939 : if (!FileUtils::IsPathWithin(canonical.string(), canonicalRoot)) {
940 : ASCENDLOGE(
941 : "Compile source candidate escaped root: resource_id=%s candidate=%s canonical=%s root=%s",
942 : resourceId.c_str(), candidate.c_str(), canonical.c_str(), canonicalRoot.c_str());
943 : return ResourceStatus::InvalidResource;
944 : }
945 : matches.insert(canonical.parent_path().string());
946 : return ResourceStatus::Success;
947 : }
948 :
949 : ResourceStatus ResourceRegistry::LocateSourceFile(
950 : const LibrarySpec& spec, const std::string& resourceId, const std::string& sourceFile, std::string& located)
951 : {
952 : // Relative path example:
953 : // kernel/jit/ascend910b/libfoo_compile_database.so <- resource SO
954 : // kernel/ascend910b/impl/foo.cpp <- source file
955 : // Derive the SoC and kernel root from the SO path, then recursively search the sibling kernel/<soc> tree.
956 : // Exactly one regular-file match is required; located is set to that file's parent directory.
957 : const fs::path soPath(spec.path);
958 : const fs::path soc = soPath.parent_path().filename();
959 : const fs::path jitRoot = soPath.parent_path().parent_path();
960 : const fs::path kernelRoot = jitRoot.parent_path();
961 : if (soc.empty() || jitRoot.filename() != "jit" || kernelRoot.filename() != "kernel") {
962 : ASCENDLOGE(
963 : "Compile resource SO is outside kernel/jit/<soc>: resource_id=%s source_type=%s so=%s", resourceId.c_str(),
964 : SourceTypeName(spec.sourceType), spec.path.c_str());
965 : return ResourceStatus::InvalidResource;
966 : }
967 : const fs::path searchRoot = kernelRoot / soc;
968 : std::string canonicalRoot;
969 : ResourceStatus status = ResolveSourceRoot(searchRoot, resourceId, canonicalRoot);
970 : if (status != ResourceStatus::Success) {
971 : return status;
972 : }
973 : std::set<std::string> matches;
974 : boost::system::error_code error;
975 : fs::recursive_directory_iterator current(canonicalRoot, fs::directory_options::none, error);
976 : const fs::recursive_directory_iterator end;
977 : while (!error && current != end) {
978 : status = AddSourceMatch(current->path(), sourceFile, canonicalRoot, resourceId, matches);
979 : if (status != ResourceStatus::Success) {
980 : return status;
981 : }
982 : current.increment(error);
983 : }
984 : if (error) {
985 : ASCENDLOGE(
986 : "Failed to search compile source: resource_id=%s root=%s error=%s", resourceId.c_str(), searchRoot.c_str(),
987 : error.message().c_str());
988 : return ResourceStatus::IoError;
989 : }
990 : if (matches.size() != 1U) {
991 : ASCENDLOGE(
992 : "Compile source file must have exactly one match: resource_id=%s root=%s source_file=%s actual_matches=%zu "
993 : "expected_matches=1",
994 : resourceId.c_str(), searchRoot.c_str(), sourceFile.c_str(), matches.size());
995 : return ResourceStatus::InvalidResource;
996 : }
997 : located = *matches.begin();
998 : ASCENDLOGD(
999 : "Located compile source file: resource_id=%s source_file=%s directory=%s", resourceId.c_str(),
1000 : sourceFile.c_str(), located.c_str());
1001 : return ResourceStatus::Success;
1002 : }
1003 :
1004 : bool ResourceRegistry::FindPathConflict(const std::set<std::string>& paths)
1005 : {
1006 : for (const std::string& path : paths) {
1007 : size_t separator = path.find('/');
1008 : while (separator != std::string::npos) {
1009 : if (paths.count(path.substr(0U, separator)) != 0U) {
1010 : const std::string parent = path.substr(0U, separator);
1011 : ASCENDLOGE(
1012 : "Compile resource file path conflicts with another file: parent=%s child=%s "
1013 : "reason=a file cannot also be a directory",
1014 : parent.c_str(), path.c_str());
1015 : return true;
1016 : }
1017 : separator = path.find('/', separator + 1U);
1018 : }
1019 : }
1020 : return false;
1021 : }
1022 :
1023 : ResourceStatus ResourceRegistry::AppendFile(
1024 : const AcCompileResourceFile& file, const std::string& resourceId, ResourceEntry& entry,
1025 : std::set<std::string>& paths, uint64_t& manifestBytes, StagedResources& staged)
1026 : {
1027 : std::string fileName;
1028 : std::string relativePath;
1029 : ResourceStatus status = CopyString(file.fileName, "resource.fileName", MAX_PATH_SIZE, fileName);
1030 : if (status == ResourceStatus::Success) {
1031 : status = CopyString(file.filePath, "resource.filePath", MAX_PATH_SIZE, relativePath);
1032 : }
1033 : if (status != ResourceStatus::Success) {
1034 : return status;
1035 : }
1036 : status = ValidateResourceFilePath(resourceId, fileName, relativePath, paths);
1037 : if (status == ResourceStatus::Success) {
1038 : status = ValidateResourceFilePayload(file, resourceId, relativePath, manifestBytes, staged);
1039 : }
1040 : if (status != ResourceStatus::Success) {
1041 : return status;
1042 : }
1043 : std::vector<uint8_t> bytes;
1044 : if (file.size != 0U) {
1045 : bytes.assign(file.data, file.data + file.size);
1046 : }
1047 : entry.files.push_back({std::move(fileName), std::move(relativePath), std::move(bytes)});
1048 : return ResourceStatus::Success;
1049 : }
1050 :
1051 : ResourceStatus ResourceRegistry::CopyManifestFiles(
1052 : const AcCompileResourceManifest& unit, const std::string& resourceId, ResourceEntry& entry, StagedResources& staged)
1053 : {
1054 : const ResourceStatus tableStatus = ValidateManifestFileTable(unit, resourceId, staged);
1055 : if (tableStatus != ResourceStatus::Success) {
1056 : return tableStatus;
1057 : }
1058 : entry.files.reserve(static_cast<size_t>(unit.fileCount));
1059 : std::set<std::string> paths;
1060 : uint64_t manifestBytes = 0U;
1061 : for (uint64_t index = 0U; index < unit.fileCount; ++index) {
1062 : const ResourceStatus status = AppendFile(unit.files[index], resourceId, entry, paths, manifestBytes, staged);
1063 : if (status != ResourceStatus::Success) {
1064 : return status;
1065 : }
1066 : }
1067 : if (FindPathConflict(paths)) {
1068 : return ResourceStatus::InvalidResource;
1069 : }
1070 : staged.files += unit.fileCount;
1071 : std::sort(entry.files.begin(), entry.files.end(), [](const ResourceFileData& left, const ResourceFileData& right) {
1072 : return left.relativePath < right.relativePath;
1073 : });
1074 : ASCENDLOGD(
1075 : "Validated compile resource manifest files: resource_id=%s files=%" PRIu64 " bytes=%" PRIu64,
1076 : resourceId.c_str(), unit.fileCount, manifestBytes);
1077 : return ResourceStatus::Success;
1078 : }
1079 :
1080 : StagedResources& ResourceRegistry::SelectStagedResources(StageState& stage, ResourceSourceType sourceType)
1081 : {
1082 : if (sourceType == ResourceSourceType::Custom) {
1083 : return stage.custom;
1084 : }
1085 : return sourceType == ResourceSourceType::BuiltIn ? stage.builtIn : stage.external;
1086 : }
1087 :
1088 : ResourceStatus ResourceRegistry::LoadManifest(
1089 : const AcCompileResourceManifest& unit, const LibrarySpec& spec, uint64_t manifestIndex, StageState& stage)
1090 : {
1091 : ASCENDLOGI(
1092 : "Loading compile resource manifest: source_type=%s so=%s manifest=%" PRIu64, SourceTypeName(spec.sourceType),
1093 : spec.path.c_str(), manifestIndex);
1094 : ManifestOwnership ownership;
1095 : ResourceStatus status = ParseManifestOwnership(unit, spec, manifestIndex, ownership);
1096 : if (status != ResourceStatus::Success) {
1097 : return status;
1098 : }
1099 : std::unique_ptr<ResourceEntry> entry(new ResourceEntry());
1100 : if (ownership.hasSourceFile) {
1101 : status = LocateSourceFile(spec, ownership.resourceId, ownership.sourceFile, entry->data.sourceFilePath);
1102 : }
1103 : StagedResources& staged = SelectStagedResources(stage, spec.sourceType);
1104 : if (status == ResourceStatus::Success) {
1105 : status = CopyManifestFiles(unit, ownership.resourceId, *entry, staged);
1106 : }
1107 : if (status != ResourceStatus::Success) {
1108 : return status;
1109 : }
1110 : entry->data.json = std::move(ownership.document);
1111 : entry->sourceSoPath = spec.path;
1112 : entry->sourceType = spec.sourceType;
1113 : const auto existing = staged.resources.find(ownership.resourceId);
1114 : if (existing != staged.resources.end()) {
1115 : ASCENDLOGE(
1116 : "Duplicate resource_id in load transaction: resource_id=%s incoming_source_type=%s incoming_so=%s "
1117 : "existing_source_type=%s existing_so=%s",
1118 : ownership.resourceId.c_str(), SourceTypeName(entry->sourceType), entry->sourceSoPath.c_str(),
1119 : SourceTypeName(existing->second->sourceType), existing->second->sourceSoPath.c_str());
1120 : return ResourceStatus::Conflict;
1121 : }
1122 : const size_t fileCount = entry->files.size();
1123 : staged.resources.emplace(ownership.resourceId, std::move(entry));
1124 : ASCENDLOGI(
1125 : "Loaded compile resource manifest: resource_id=%s source_type=%s so=%s manifest=%" PRIu64 " files=%zu",
1126 : ownership.resourceId.c_str(), SourceTypeName(spec.sourceType), spec.path.c_str(), manifestIndex, fileCount);
1127 : return ResourceStatus::Success;
1128 : }
1129 :
1130 : ResourceStatus ResourceRegistry::LoadLibrary(const LibrarySpec& spec, StageState& stage)
1131 : {
1132 : LibrarySpec canonicalSpec = spec;
1133 : if (!FileUtils::ResolveCanonicalPath(spec.path, canonicalSpec.path)) {
1134 : ASCENDLOGE(
1135 : "Failed to normalize compile resource SO path before loading: source_type=%s so=%s",
1136 : SourceTypeName(spec.sourceType), spec.path.c_str());
1137 : return ResourceStatus::InvalidResource;
1138 : }
1139 : ASCENDLOGI(
1140 : "Loading compile resource SO: source_type=%s so=%s", SourceTypeName(canonicalSpec.sourceType),
1141 : canonicalSpec.path.c_str());
1142 : LibraryHandle library(dlopen(canonicalSpec.path.c_str(), RTLD_NOW | RTLD_LOCAL));
1143 : if (!library) {
1144 : const char* error = dlerror();
1145 : ASCENDLOGE(
1146 : "Failed to open compile resource SO: source_type=%s so=%s error=%s",
1147 : SourceTypeName(canonicalSpec.sourceType), canonicalSpec.path.c_str(), error == nullptr ? "unknown" : error);
1148 : return ResourceStatus::LoadError;
1149 : }
1150 : const AcCompileResourceBundle* bundle = nullptr;
1151 : ResourceStatus status = GetBundle(library, canonicalSpec, bundle);
1152 : if (status != ResourceStatus::Success) {
1153 : return status;
1154 : }
1155 : for (uint64_t manifestIndex = 0U; manifestIndex < bundle->manifestCount; ++manifestIndex) {
1156 : status = LoadManifest(bundle->manifests[manifestIndex], canonicalSpec, manifestIndex, stage);
1157 : if (status != ResourceStatus::Success) {
1158 : ASCENDLOGE(
1159 : "Stopped loading compile resource SO at manifest: source_type=%s so=%s manifest=%" PRIu64
1160 : " status=%s(%d)",
1161 : SourceTypeName(canonicalSpec.sourceType), canonicalSpec.path.c_str(), manifestIndex,
1162 : ResourceStatusName(status), static_cast<int>(status));
1163 : return status;
1164 : }
1165 : }
1166 : ASCENDLOGI(
1167 : "Loaded compile resource SO: source_type=%s so=%s manifests=%" PRIu64, SourceTypeName(canonicalSpec.sourceType),
1168 : canonicalSpec.path.c_str(), bundle->manifestCount);
1169 : return ResourceStatus::Success;
1170 : }
1171 :
1172 : ResourceStatus ResourceRegistry::LoadLibraries(const std::vector<LibrarySpec>& libraries, StageState& stage)
1173 : {
1174 : ASCENDLOGI("Loading compile resource SO list: count=%zu", libraries.size());
1175 : size_t loaded = 0U;
1176 : size_t skipped = 0U;
1177 : ResourceStatus firstFailure = ResourceStatus::Success;
1178 : for (const LibrarySpec& library : libraries) {
1179 : StagedResources& staged = SelectStagedResources(stage, library.sourceType);
1180 : staged.discovered = true;
1181 : StageState libraryStage;
1182 : StagedResources& incoming = SelectStagedResources(libraryStage, library.sourceType);
1183 : incoming.discovered = true;
1184 : ResourceStatus status = LoadLibrary(library, libraryStage);
1185 : if (status == ResourceStatus::Success) {
1186 : status = MergeStagedLibrary(library, incoming, staged);
1187 : }
1188 : if (status != ResourceStatus::Success) {
1189 : if (firstFailure == ResourceStatus::Success) {
1190 : firstFailure = status;
1191 : }
1192 : ++skipped;
1193 : ASCENDLOGW(
1194 : "Skipping failed compile resource SO and continuing with the next SO: source_type=%s so=%s "
1195 : "status=%s(%d)",
1196 : SourceTypeName(library.sourceType), library.path.c_str(), ResourceStatusName(status),
1197 : static_cast<int>(status));
1198 : continue;
1199 : }
1200 : ++loaded;
1201 : }
1202 : if (loaded == 0U && !libraries.empty()) {
1203 : ASCENDLOGW(
1204 : "No compile resource SO was loaded successfully: total=%zu skipped=%zu first_failure=%s(%d)",
1205 : libraries.size(), skipped, ResourceStatusName(firstFailure), static_cast<int>(firstFailure));
1206 : return firstFailure;
1207 : }
1208 : ASCENDLOGI("Loaded compile resource SO list: total=%zu loaded=%zu skipped=%zu", libraries.size(), loaded, skipped);
1209 : return ResourceStatus::Success;
1210 : }
1211 :
1212 : ResourceStatus ResourceRegistry::WriteMaterializedFiles(
1213 : const std::vector<ResourceFileData>& files, const std::string& root)
1214 : {
1215 : ASCENDLOGD("Writing materialized compile resource files: root=%s files=%zu", root.c_str(), files.size());
1216 : for (const ResourceFileData& file : files) {
1217 : const std::string path = FileUtils::JoinPath(root, file.relativePath);
1218 : const std::string parent = FileUtils::ParentPath(path);
1219 : if (!FileUtils::CreateDirectories(parent)) {
1220 : ASCENDLOGE(
1221 : "Failed to create materialized compile resource parent directory: root=%s relative_path=%s "
1222 : "parent=%s",
1223 : root.c_str(), file.relativePath.c_str(), parent.c_str());
1224 : return ResourceStatus::IoError;
1225 : }
1226 : std::string canonicalRoot;
1227 : std::string canonicalParent;
1228 : if (!FileUtils::ResolveCanonicalPath(root, canonicalRoot) ||
1229 : !FileUtils::ResolveCanonicalPath(parent, canonicalParent)) {
1230 : ASCENDLOGE(
1231 : "Failed to normalize materialized compile resource output path: root=%s relative_path=%s parent=%s",
1232 : root.c_str(), file.relativePath.c_str(), parent.c_str());
1233 : return ResourceStatus::IoError;
1234 : }
1235 : if (!FileUtils::IsPathWithin(canonicalParent, canonicalRoot)) {
1236 : ASCENDLOGE(
1237 : "Rejected materialized compile resource output outside its root: root=%s resolved_root=%s "
1238 : "relative_path=%s resolved_parent=%s",
1239 : root.c_str(), canonicalRoot.c_str(), file.relativePath.c_str(), canonicalParent.c_str());
1240 : return ResourceStatus::IoError;
1241 : }
1242 : const std::string canonicalPath = FileUtils::JoinPath(canonicalParent, FileUtils::FileName(file.relativePath));
1243 : errno = 0;
1244 : std::ofstream output(canonicalPath.c_str(), std::ios::binary | std::ios::trunc);
1245 : if (!output.is_open()) {
1246 : const int openError = errno;
1247 : ASCENDLOGE(
1248 : "Failed to open materialized compile resource file: root=%s relative_path=%s path=%s error=%s",
1249 : root.c_str(), file.relativePath.c_str(), canonicalPath.c_str(),
1250 : openError == 0 ? "stream open failed" : std::strerror(openError));
1251 : return ResourceStatus::IoError;
1252 : }
1253 : if (!file.bytes.empty()) {
1254 : output.write(
1255 : reinterpret_cast<const char*>(file.bytes.data()), static_cast<std::streamsize>(file.bytes.size()));
1256 : }
1257 : if (!FileUtils::FinalizeOutput(output)) {
1258 : ASCENDLOGE(
1259 : "Failed to finalize materialized compile resource file: root=%s relative_path=%s path=%s "
1260 : "reason=write, flush, or close failed",
1261 : root.c_str(), file.relativePath.c_str(), canonicalPath.c_str());
1262 : return ResourceStatus::IoError;
1263 : }
1264 : }
1265 : ASCENDLOGD("Wrote materialized compile resource files: root=%s files=%zu", root.c_str(), files.size());
1266 : return ResourceStatus::Success;
1267 : }
1268 :
1269 : ResourceRegistry& ResourceRegistry::Instance()
1270 : {
1271 : static ResourceRegistry registry;
1272 : return registry;
1273 : }
1274 :
1275 : ResourceRegistry::ResourceRegistry() = default;
1276 :
1277 : ResourceRegistry::~ResourceRegistry()
1278 : {
1279 : if (!keepTemporaryRoot_) {
1280 : CleanupPath(temporaryRoot_);
1281 : }
1282 : }
1283 :
1284 : ResourceEntry* ResourceRegistry::FindResource(const std::string& resourceId) noexcept
1285 : {
1286 : const auto external = externalResources_.find(resourceId);
1287 : if (external != externalResources_.end()) {
1288 : return external->second.get();
1289 : }
1290 : const auto custom = customResources_.find(resourceId);
1291 : if (custom != customResources_.end()) {
1292 : return custom->second.get();
1293 : }
1294 : const auto builtIn = builtInResources_.find(resourceId);
1295 : return builtIn == builtInResources_.end() ? nullptr : builtIn->second.get();
1296 : }
1297 :
1298 : bool ResourceRegistry::HasCommitConflict(const ResourceStore& incoming, const ResourceStore& committed) const
1299 : {
1300 : for (const auto& item : incoming) {
1301 : const auto existing = committed.find(item.first);
1302 : if (existing != committed.end()) {
1303 : ASCENDLOGW(
1304 : "Compile resource conflicts with an already registered resource and will not be added: "
1305 : "resource_id=%s incoming_source_type=%s incoming_so=%s "
1306 : "existing_source_type=%s existing_so=%s",
1307 : item.first.c_str(), SourceTypeName(item.second->sourceType), item.second->sourceSoPath.c_str(),
1308 : SourceTypeName(existing->second->sourceType), existing->second->sourceSoPath.c_str());
1309 : return true;
1310 : }
1311 : }
1312 : return false;
1313 : }
1314 :
1315 : ResourceStatus ResourceRegistry::Commit(StageState& stage)
1316 : {
1317 : std::lock_guard<std::mutex> lock(registryMutex_);
1318 : ASCENDLOGI(
1319 : "Committing compile resources: external=%zu custom=%zu built_in=%zu", stage.external.resources.size(),
1320 : stage.custom.resources.size(), stage.builtIn.resources.size());
1321 : ResourceStatus status = ResourceStatus::Success;
1322 : auto checkCategory = [this, &status](
1323 : StagedResources& staged, ResourceStore& committed, ResourceSourceType sourceType) {
1324 : if (!staged.discovered && !staged.conflict) {
1325 : return;
1326 : }
1327 : if (!staged.conflict && HasCommitConflict(staged.resources, committed)) {
1328 : staged.conflict = true;
1329 : }
1330 : if (staged.conflict) {
1331 : ASCENDLOGW(
1332 : "Compile resource category will not be committed because conflicts were detected: source_type=%s "
1333 : "resource_count=%zu",
1334 : SourceTypeName(sourceType), staged.resources.size());
1335 : status = ResourceStatus::Conflict;
1336 : return;
1337 : }
1338 : committed.reserve(committed.size() + staged.resources.size());
1339 : };
1340 : checkCategory(stage.external, externalResources_, ResourceSourceType::External);
1341 : checkCategory(stage.custom, customResources_, ResourceSourceType::Custom);
1342 : checkCategory(stage.builtIn, builtInResources_, ResourceSourceType::BuiltIn);
1343 : uint64_t bytes = resourceBytes_;
1344 : uint64_t files = resourceFileCount_;
1345 : if (!CheckRegistryLimits(stage.external, ResourceSourceType::External, bytes, files) ||
1346 : !CheckRegistryLimits(stage.custom, ResourceSourceType::Custom, bytes, files) ||
1347 : !CheckRegistryLimits(stage.builtIn, ResourceSourceType::BuiltIn, bytes, files)) {
1348 : return ResourceStatus::InvalidResource;
1349 : }
1350 : auto commitCategory = [](StagedResources& staged, ResourceStore& committed) {
1351 : if (!staged.discovered || staged.conflict) {
1352 : return;
1353 : }
1354 : committed.merge(staged.resources);
1355 : };
1356 : commitCategory(stage.external, externalResources_);
1357 : commitCategory(stage.custom, customResources_);
1358 : commitCategory(stage.builtIn, builtInResources_);
1359 : resourceBytes_ = bytes;
1360 : resourceFileCount_ = files;
1361 : ASCENDLOGI(
1362 : "Finished committing compile resources: status=%s(%d) registered_external=%zu registered_custom=%zu "
1363 : "registered_built_in=%zu total_files=%" PRIu64 " total_bytes=%" PRIu64,
1364 : ResourceStatusName(status), static_cast<int>(status), externalResources_.size(), customResources_.size(),
1365 : builtInResources_.size(), resourceFileCount_, resourceBytes_);
1366 : return status;
1367 : }
1368 :
1369 : ResourceStatus ResourceRegistry::Load(const char* directory)
1370 : {
1371 : const bool automatic = directory == nullptr || *directory == '\0';
1372 : std::lock_guard<std::mutex> loadLock(loadMutex_);
1373 : if (automatic && automaticLoadAttempted_) {
1374 : ASCENDLOGI(
1375 : "Returning cached automatic compile resource load result: status=%s(%d)",
1376 : ResourceStatusName(automaticLoadStatus_), static_cast<int>(automaticLoadStatus_));
1377 : return automaticLoadStatus_;
1378 : }
1379 : ASCENDLOGI(
1380 : "Loading compile resources: mode=%s directory=%s", automatic ? "automatic" : "explicit",
1381 : automatic ? "<environment>" : directory);
1382 : std::vector<LibrarySpec> libraries;
1383 : ResourceStatus status = DiscoverLibraries(directory, libraries);
1384 : if (status != ResourceStatus::Success) {
1385 : ASCENDLOGE(
1386 : "Compile resource load stopped during discovery: mode=%s path=%s status=%s(%d)",
1387 : automatic ? "automatic" : "explicit", automatic ? "<environment>" : directory, ResourceStatusName(status),
1388 : static_cast<int>(status));
1389 : } else {
1390 : ASCENDLOGI(
1391 : "Compile resource discovery completed: mode=%s libraries=%zu", automatic ? "automatic" : "explicit",
1392 : libraries.size());
1393 : StageState stage;
1394 : status = LoadLibraries(libraries, stage);
1395 : if (status == ResourceStatus::Success) {
1396 : status = Commit(stage);
1397 : }
1398 : }
1399 : if (automatic) {
1400 : automaticLoadAttempted_ = true;
1401 : automaticLoadStatus_ = status;
1402 : }
1403 : if (status == ResourceStatus::Success) {
1404 : ASCENDLOGI(
1405 : "Finished loading compile resources: mode=%s libraries=%zu status=%s(%d)",
1406 : automatic ? "automatic" : "explicit", libraries.size(), ResourceStatusName(status),
1407 : static_cast<int>(status));
1408 : }
1409 : return status;
1410 : }
1411 :
1412 : ResourceStatus ResourceRegistry::Materialize(
1413 : const std::string& resourceId, const ResourceEntry& entry, ResourceData& resource)
1414 : {
1415 : ASCENDLOGI(
1416 : "Materializing compile resource: resource_id=%s source_type=%s so=%s files=%zu", resourceId.c_str(),
1417 : SourceTypeName(entry.sourceType), entry.sourceSoPath.c_str(), entry.files.size());
1418 : std::string temporaryRoot;
1419 : {
1420 : std::lock_guard<std::mutex> lock(registryMutex_);
1421 : if (temporaryRoot_.empty()) {
1422 : keepTemporaryRoot_ = IsKernelMetaSavingEnabled();
1423 : const ResourceStatus status = CreateTemporaryRoot(temporaryRoot_);
1424 : if (status != ResourceStatus::Success) {
1425 : return status;
1426 : }
1427 : }
1428 : temporaryRoot = temporaryRoot_;
1429 : }
1430 : ASCENDLOGD(
1431 : "Compile resource temporary root is ready: resource_id=%s path=%s", resourceId.c_str(), temporaryRoot.c_str());
1432 : std::string categoryRoot;
1433 : std::string canonicalRoot;
1434 : ResourceStatus status =
1435 : PrepareMaterializationRoot(temporaryRoot, resourceId, entry.sourceType, categoryRoot, canonicalRoot);
1436 : if (status == ResourceStatus::Success) {
1437 : ASCENDLOGD(
1438 : "Compile resource materialization directory is ready: resource_id=%s path=%s", resourceId.c_str(),
1439 : canonicalRoot.c_str());
1440 : status = WriteMaterializedFiles(entry.files, canonicalRoot);
1441 : }
1442 : if (status != ResourceStatus::Success) {
1443 : if (!keepTemporaryRoot_) {
1444 : CleanupPath(categoryRoot);
1445 : }
1446 : resource.resourceDir.clear();
1447 : return status;
1448 : }
1449 : resource.resourceDir = canonicalRoot;
1450 : ASCENDLOGI(
1451 : "Compile resource materialized: resource_id=%s source_type=%s so=%s files=%zu directory=%s", resourceId.c_str(),
1452 : SourceTypeName(entry.sourceType), entry.sourceSoPath.c_str(), entry.files.size(), resource.resourceDir.c_str());
1453 : return ResourceStatus::Success;
1454 : }
1455 :
1456 : ResourceStatus ResourceRegistry::Lookup(const char* resourceId, ResourceData& resource)
1457 : {
1458 : resource = ResourceData{};
1459 : if (resourceId == nullptr) {
1460 : ASCENDLOGE("Compile resource lookup rejected: resource_id=<null> reason=identifier pointer is null");
1461 : return ResourceStatus::InvalidResource;
1462 : }
1463 : if (*resourceId == '\0') {
1464 : ASCENDLOGE("Compile resource lookup rejected: resource_id=<empty> reason=identifier is empty");
1465 : return ResourceStatus::InvalidResource;
1466 : }
1467 : ASCENDLOGD("Looking up compile resource: resource_id=%s", resourceId);
1468 : ResourceEntry* entry = nullptr;
1469 : {
1470 : std::lock_guard<std::mutex> lock(registryMutex_);
1471 : entry = FindResource(resourceId);
1472 : }
1473 : if (entry == nullptr) {
1474 : ASCENDLOGD("Compile resource lookup missed: resource_id=%s reason=not registered", resourceId);
1475 : return ResourceStatus::NotFound;
1476 : }
1477 : ASCENDLOGD(
1478 : "Compile resource lookup matched: resource_id=%s source_type=%s so=%s", resourceId,
1479 : SourceTypeName(entry->sourceType), entry->sourceSoPath.c_str());
1480 : std::lock_guard<std::mutex> materializeLock(entry->materializeMutex);
1481 : ResourceData materialized = entry->data;
1482 : materialized.resourceDir.clear();
1483 : const ResourceStatus status = Materialize(resourceId, *entry, materialized);
1484 : if (status == ResourceStatus::Success) {
1485 : resource = std::move(materialized);
1486 : ASCENDLOGD(
1487 : "Compile resource lookup completed: resource_id=%s directory=%s", resourceId, resource.resourceDir.c_str());
1488 : }
1489 : return status;
1490 : }
1491 :
1492 : } // namespace specialization_compile
1493 : } // namespace ascendc
|