123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "rcjoblistmodel.h"
- // uncomment this in order to add additional verbose log output for this class.
- // can drastically slow down function since this class is a hotspot
- // #define DEBUG_RCJOB_MODEL
- namespace AssetProcessor
- {
- RCJobListModel::RCJobListModel(QObject* parent)
- : QAbstractItemModel(parent)
- {
- }
- int RCJobListModel::rowCount(const QModelIndex& parent) const
- {
- if (parent.isValid())
- {
- return 0;
- }
- return itemCount();
- }
- QModelIndex RCJobListModel::parent(const QModelIndex& /*index*/) const
- {
- return QModelIndex();
- }
- QModelIndex RCJobListModel::index(int row, int column, const QModelIndex& parent) const
- {
- if (row >= rowCount(parent) || column >= columnCount(parent))
- {
- return QModelIndex();
- }
- return createIndex(row, column);
- }
- int RCJobListModel::columnCount(const QModelIndex& parent) const
- {
- return parent.isValid() ? 0 : Column::Max;
- }
- QVariant RCJobListModel::headerData(int section, Qt::Orientation orientation, int role) const
- {
- if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
- {
- switch (section)
- {
- case ColumnState:
- return tr("State");
- case ColumnJobId:
- return tr("Job Id");
- case ColumnCommand:
- return tr("Asset");
- case ColumnCompleted:
- return tr("Completed");
- case ColumnPlatform:
- return tr("Platform");
- default:
- break;
- }
- }
- return QAbstractItemModel::headerData(section, orientation, role);
- }
- unsigned int RCJobListModel::jobsInFlight() const
- {
- return m_jobsInFlight.size();
- }
- unsigned int RCJobListModel::jobsInQueueWithoutMissingDependencies() const
- {
- unsigned int jobsWithNoMissingDependencies = 0;
- for (const auto& job : m_jobsInQueueLookup)
- {
- if (!job->HasMissingSourceDependency())
- {
- ++jobsWithNoMissingDependencies;
- }
- }
- return jobsWithNoMissingDependencies;
- }
- unsigned int RCJobListModel::jobsPendingCatalog() const
- {
- return m_finishedJobsNotInCatalog.count();
- }
- void RCJobListModel::UpdateJobEscalation(const QueueElementID& toEscalate, int valueToEscalateTo)
- {
- for (auto foundInQueue = m_jobsInQueueLookup.find(toEscalate); foundInQueue != m_jobsInQueueLookup.end(); ++foundInQueue)
- {
- RCJob* job = foundInQueue.value();
- // this is a multi-map, so we have to keep going until it no longer matches.
- if (!job)
- {
- continue;
- }
- if (job->GetElementID() != toEscalate)
- {
- break;
- }
- if (job->JobEscalation() != valueToEscalateTo)
- {
- UpdateJobEscalation(job, valueToEscalateTo);
- }
- }
- }
- void RCJobListModel::UpdateJobEscalation(AssetProcessor::RCJob* rcJob, int valueToEscalateTo)
- {
- for (int idx = 0; idx < rowCount(); ++idx)
- {
- RCJob* job = getItem(idx);
- if (job == rcJob)
- {
- if (job->JobEscalation() != valueToEscalateTo)
- {
- job->SetJobEscalation(valueToEscalateTo);
- Q_EMIT dataChanged(index(idx, 0), index(idx, columnCount() - 1));
- }
- break;
- }
- }
- }
- void RCJobListModel::UpdateRow(int jobIndex)
- {
- Q_EMIT dataChanged(index(jobIndex, 0), index(jobIndex, columnCount() - 1));
- }
- QVariant RCJobListModel::data(const QModelIndex& index, int role) const
- {
- if (!index.isValid())
- {
- return QVariant();
- }
- if (index.row() >= itemCount())
- {
- return QVariant();
- }
- switch (role)
- {
- case jobIndexRole:
- return getItem(index.row())->GetJobEntry().m_jobRunKey;
- case stateRole:
- return RCJob::GetStateDescription(getItem(index.row())->GetState());
- case displayNameRole:
- return getItem(index.row())->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- case timeCreatedRole:
- return getItem(index.row())->GetTimeCreated().toString("hh:mm:ss.zzz");
- case timeLaunchedRole:
- return getItem(index.row())->GetTimeLaunched().toString("hh:mm:ss.zzz");
- case timeCompletedRole:
- return getItem(index.row())->GetTimeCompleted().toString("hh:mm:ss.zzz");
- case Qt::DisplayRole:
- switch (index.column())
- {
- case ColumnJobId:
- return getItem(index.row())->GetJobEntry().m_jobRunKey;
- case ColumnState:
- return RCJob::GetStateDescription(getItem(index.row())->GetState());
- case ColumnCommand:
- return getItem(index.row())->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- case ColumnCompleted:
- return getItem(index.row())->GetTimeCompleted().toString("hh:mm:ss.zzz");
- case ColumnPlatform:
- return QString::fromUtf8(getItem(index.row())->GetPlatformInfo().m_identifier.c_str());
- default:
- break;
- }
- default:
- break;
- }
- return QVariant();
- }
- int RCJobListModel::itemCount() const
- {
- return aznumeric_caster(m_jobs.size());
- }
- RCJob* RCJobListModel::getItem(int index) const
- {
- if (index >= 0 && index < m_jobs.size())
- {
- return m_jobs[index];
- }
- return nullptr; //invalid index
- }
- bool RCJobListModel::isEmpty()
- {
- return m_jobs.empty();
- }
- void RCJobListModel::addNewJob(RCJob* rcJob)
- {
- int posForInsert = aznumeric_caster(m_jobs.size());
- beginInsertRows(QModelIndex(), posForInsert, posForInsert);
- m_jobs.push_back(rcJob);
- #if defined(DEBUG_RCJOB_MODEL)
- AZ_TracePrintf(AssetProcessor::DebugChannel, "JobTrace AddNewJob(%i %s,%s,%s)\n", rcJob, rcJob->GetInputFileAbsolutePath().toUtf8().constData(), rcJob->GetPlatformInfo().m_identifier.c_str(), rcJob->GetJobKey().toUtf8().constData());
- #endif
- if (rcJob->GetState() == RCJob::pending)
- {
- m_jobsInQueueLookup.insert(rcJob->GetElementID(), rcJob);
- }
- endInsertRows();
- }
- void RCJobListModel::markAsProcessing(RCJob* rcJob)
- {
- #if defined(DEBUG_RCJOB_MODEL)
- AZ_TracePrintf(AssetProcessor::DebugChannel, "JobTrace markAsProcessing(%i %s,%s,%s)\n", rcJob, rcJob->GetJobEntry().m_databaseSourceName.toUtf8().constData(), rcJob->GetPlatformInfo().m_identifier.c_str(), rcJob->GetJobKey().toUtf8().constData());
- #endif
- rcJob->SetState(RCJob::processing);
- rcJob->SetTimeLaunched(QDateTime::currentDateTime());
- m_jobsInFlight.insert(rcJob);
- for(int jobIndex = static_cast<int>(m_jobs.size()) - 1; jobIndex >= 0; --jobIndex)
- {
- if(m_jobs[jobIndex] == rcJob)
- {
- Q_EMIT dataChanged(index(jobIndex, 0, QModelIndex()), index(jobIndex, 0, QModelIndex()));
- return;
- }
- }
- AZ_TracePrintf(AssetProcessor::DebugChannel, "JobTrace jobIndex == -1!!! (%i %s,%s,%s)\n",
- rcJob, rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- AZ_Assert(false, "Job not found!!!");
- }
- void RCJobListModel::markAsStarted(RCJob* rcJob)
- {
- #if defined(DEBUG_RCJOB_MODEL)
- AZ_TracePrintf(AssetProcessor::DebugChannel, "JobTrace markAsStarted(%i %s,%s,%s)\n", rcJob, rcJob->GetInputFileAbsolutePath().toUtf8().constData(), rcJob->GetPlatformInfo().m_identifier.c_str(), rcJob->GetJobKey().toUtf8().constData());
- #endif
- auto foundInQueue = m_jobsInQueueLookup.find(rcJob->GetElementID());
- while ((foundInQueue != m_jobsInQueueLookup.end()) && (foundInQueue.value() == rcJob))
- {
- foundInQueue = m_jobsInQueueLookup.erase(foundInQueue);
- }
- }
- void RCJobListModel::markAsCompleted(RCJob* rcJob)
- {
- #if defined(DEBUG_RCJOB_MODEL)
- AZ_TracePrintf(AssetProcessor::DebugChannel, "JobTrace markAsCompleted(%i %s,%s,%s)\n", rcJob, rcJob->GetInputFileAbsolutePath().toUtf8().constData(), rcJob->GetPlatformInfo().m_identifier.c_str(), rcJob->GetJobKey().toUtf8().constData());
- #endif
- rcJob->SetTimeCompleted(QDateTime::currentDateTime());
- auto foundInQueue = m_jobsInQueueLookup.find(rcJob->GetElementID());
- while ((foundInQueue != m_jobsInQueueLookup.end()) && (foundInQueue.value() == rcJob))
- {
- foundInQueue = m_jobsInQueueLookup.erase(foundInQueue);
- }
- for (int jobIndex = static_cast<int>(m_jobs.size()) - 1; jobIndex >= 0; --jobIndex)
- {
- if(m_jobs[jobIndex] == rcJob)
- {
- m_jobsInFlight.remove(rcJob);
- // remove it from the list and delete it - there is a separate model that keeps track for the GUI so no need to keep jobs around.
- {
- #if defined(DEBUG_RCJOB_MODEL)
- AZ_TracePrintf(AssetProcessor::DebugChannel, "JobTrace =>JobCompleted(%i %s,%s,%s)\n", rcJob, rcJob->GetJobEntry().m_databaseSourceName.toUtf8().constData(), rcJob->GetPlatformInfo().m_identifier.c_str(), rcJob->GetJobKey().toUtf8().constData());
- #endif
- beginRemoveRows(QModelIndex(), jobIndex, jobIndex);
- m_jobs.erase(m_jobs.begin() + jobIndex);
- endRemoveRows();
- // Only completed jobs need to wait on a catalog write
- if (rcJob->GetState() == RCJob::completed)
- {
- const auto& id = rcJob->GetElementID();
- auto itr = m_finishedJobsNotInCatalog.find(id);
- if (itr != m_finishedJobsNotInCatalog.end())
- {
- itr.value()++;
- }
- else
- {
- m_finishedJobsNotInCatalog.insert(id, 1);
- }
- }
- rcJob->deleteLater();
- }
- return;
- }
- }
- AZ_Error(
- AssetProcessor::ConsoleChannel,
- false,
- "Programmer Error: Could not mark job for file %s as completed, job was not tracked in the m_jobs container. It was either already finished, or never queued. (platform:%s, job key:%s)\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- }
- void RCJobListModel::markAsCataloged(const AssetProcessor::QueueElementID& check)
- {
- auto itr = m_finishedJobsNotInCatalog.find(check);
- if(itr == m_finishedJobsNotInCatalog.end())
- {
- AZ_Assert(false, "Attempting to mark a job as written to the catalog before the job has been put in the waiting queue! %s", check.GetSourceAssetReference().AbsolutePath().c_str());
- return;
- }
- itr.value()--;
- if (itr.value() == 0)
- {
- m_finishedJobsNotInCatalog.erase(itr);
- }
- }
- bool RCJobListModel::isInFlight(const AssetProcessor::QueueElementID& check) const
- {
- for (auto rcJob : m_jobsInFlight)
- {
- if (check == rcJob->GetElementID())
- {
- return true;
- }
- }
- return false;
- }
- int RCJobListModel::GetIndexOfJobByState(const QueueElementID& elementId, RCJob::JobState jobState)
- {
- for (int idx = 0; idx < rowCount(); ++idx)
- {
- RCJob* job = getItem(idx);
- if (job->GetState() == jobState && job->GetElementID() == elementId)
- {
- return idx;
- break;
- }
- }
- return -1; // invalid index
- }
- void RCJobListModel::EraseJobs(const SourceAssetReference& sourceAsset, AZStd::vector<RCJob*>& pendingJobs)
- {
- for (int jobIdx = 0; jobIdx < rowCount(); ++jobIdx)
- {
- RCJob* job = getItem(jobIdx);
- if (job->GetJobEntry().m_sourceAssetReference == sourceAsset)
- {
- const QueueElementID& target = job->GetElementID();
- if ((isInQueue(target)) || (isInFlight(target)))
- {
- // Its important that this still follows the 'cancelled' flow, so that other parts of the code can update their "in progress" and other maps.
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Cancelling Job [%s, %s, %s] because the source file no longer exists.\n",
- target.GetSourceAssetReference().AbsolutePath().c_str(),
- target.GetPlatform().toUtf8().data(),
- target.GetJobDescriptor().toUtf8().data());
- // if a job is pending, it was never started and thus will never enter Finished state,
- // so simply changing its state to cancelled is not enough, collect them and return to rccontroller to process manually
- if (job->GetState() == RCJob::JobState::pending)
- {
- pendingJobs.push_back(job);
- }
- job->SetState(RCJob::JobState::cancelled);
- AssetBuilderSDK::JobCommandBus::Event(job->GetJobEntry().m_jobRunKey, &AssetBuilderSDK::JobCommandBus::Events::Cancel);
- UpdateRow(jobIdx);
- }
- }
- }
- }
- bool RCJobListModel::isInQueue(const AssetProcessor::QueueElementID& check) const
- {
- return m_jobsInQueueLookup.contains(check);
- }
- bool RCJobListModel::isWaitingOnCatalog(const QueueElementID& check) const
- {
- return m_finishedJobsNotInCatalog.contains(check);
- }
- void RCJobListModel::PerformHeuristicSearch(QString searchTerm, QString platform, QSet<QueueElementID>& found, AssetProcessor::JobIdEscalationList& escalationList, bool isStatusRequest, int searchRules)
- {
- int escalationValue = 0;
- if (isStatusRequest)
- {
- escalationValue = AssetProcessor::JobEscalation::ProcessAssetRequestStatusEscalation;
- }
- else
- {
- escalationValue = AssetProcessor::JobEscalation::ProcessAssetRequestSyncEscalation;
- }
- // try to narrowly exact-match the search term in case the search term refers to a specific actual source file:
- for (const RCJob* rcJob : m_jobs)
- {
- if ((platform != rcJob->GetPlatformInfo().m_identifier.c_str()) || (rcJob->GetState() != RCJob::pending))
- {
- continue;
- }
- QString input = rcJob->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- if (input.endsWith(searchTerm, Qt::CaseInsensitive))
- {
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Job Queue: Heuristic search found exact match (%s,%s,%s).\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- escalationList.append(qMakePair(rcJob->GetJobEntry().m_jobRunKey, escalationValue));
- }
- }
- for (const RCJob* rcJob : m_jobsInFlight)
- {
- if (platform != rcJob->GetPlatformInfo().m_identifier.c_str())
- {
- continue;
- }
- QString input = rcJob->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- if (input.endsWith(searchTerm, Qt::CaseInsensitive))
- {
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Job Queue: Heuristic search found exact match (%s,%s,%s).\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- }
- }
- if (!found.isEmpty() || searchRules == AzFramework::AssetSystem::RequestAssetStatus::SearchType::Exact)
- {
- return;
- }
- // broaden the heuristic. Try without extensions - that is, ignore everything after the dot.
- // if there are dashes, ignore them also. This is how you match "blah.dds" to actually mean "blah.tif"
- // since we have no idea what products will be generated by a source still in the queue until it runs
- int dotIndex = searchTerm.lastIndexOf('.');
- QStringRef searchTermWithNoExtension = searchTerm.midRef(0, dotIndex);
- if (dotIndex != -1)
- {
- for (const auto& rcJob : m_jobs)
- {
- if ((platform != rcJob->GetPlatformInfo().m_identifier.c_str()) || (rcJob->GetState() != RCJob::pending))
- {
- continue;
- }
- QString input = rcJob->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- dotIndex = input.lastIndexOf('.');
- if (dotIndex != -1)
- {
- QStringRef testref = input.midRef(0, dotIndex);
- if (testref.endsWith(searchTermWithNoExtension, Qt::CaseInsensitive))
- {
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Job Queue: Heuristic search found broad match (%s,%s,%s).\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- escalationList.append(qMakePair(rcJob->GetJobEntry().m_jobRunKey, escalationValue));
- }
- }
- }
- for (const RCJob* rcJob : m_jobsInFlight)
- {
- if (platform != rcJob->GetPlatformInfo().m_identifier.c_str())
- {
- continue;
- }
- QString input = rcJob->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- dotIndex = input.lastIndexOf('.');
- if (dotIndex != -1)
- {
- QStringRef testref = input.midRef(0, dotIndex);
- if (testref.endsWith(searchTermWithNoExtension, Qt::CaseInsensitive))
- {
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Job Queue: Heuristic search found broad match (%s,%s,%s).\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- }
- }
- }
- }
- if (!found.isEmpty())
- {
- return;
- }
- // broaden the heuristic further. Eliminate anything after the last underscore in the file name
- // (so blahblah_diff.dds just becomes blahblah) and then allow anything which has that file somewhere in it.
- int slashIndex = searchTerm.lastIndexOf('/');
- int dashIndex = searchTerm.lastIndexOf('_');
- QStringRef searchTermWithNoSuffix = searchTermWithNoExtension;
- if ((dashIndex != -1) && (slashIndex == -1) || (dashIndex > slashIndex))
- {
- searchTermWithNoSuffix = searchTermWithNoSuffix.mid(0, dashIndex);
- }
- for (const auto& rcJob : m_jobs)
- {
- if ((platform != rcJob->GetPlatformInfo().m_identifier.c_str()) || (rcJob->GetState() != RCJob::pending))
- {
- continue;
- }
- QString input = rcJob->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- if (input.contains(searchTermWithNoSuffix, Qt::CaseInsensitive)) //notice here that we use simply CONTAINS instead of endswith - this can potentially be very broad!
- {
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Job Queue: Heuristic search found ultra-broad match (%s,%s,%s).\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- escalationList.append(qMakePair(rcJob->GetJobEntry().m_jobRunKey, escalationValue));
- }
- }
- for (const RCJob* rcJob : m_jobsInFlight)
- {
- if (platform != rcJob->GetPlatformInfo().m_identifier.c_str())
- {
- continue;
- }
- QString input = rcJob->GetJobEntry().m_sourceAssetReference.RelativePath().c_str();
- if (input.contains(searchTermWithNoSuffix, Qt::CaseInsensitive)) //notice here that we use simply CONTAINS instead of endswith - this can potentially be very broad!
- {
- AZ_TracePrintf(
- AssetProcessor::DebugChannel,
- "Job Queue: Heuristic search found ultra-broad match (%s,%s,%s).\n",
- rcJob->GetJobEntry().GetAbsoluteSourcePath().toUtf8().constData(),
- rcJob->GetPlatformInfo().m_identifier.c_str(),
- rcJob->GetJobKey().toUtf8().constData());
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- }
- }
- }
- void RCJobListModel::PerformUUIDSearch(AZ::Uuid searchUuid, QString platform, QSet<QueueElementID>& found, AssetProcessor::JobIdEscalationList& escalationList, bool isStatusRequest)
- {
- int escalationValue = 0;
- if (isStatusRequest)
- {
- escalationValue = AssetProcessor::JobEscalation::ProcessAssetRequestStatusEscalation;
- }
- else
- {
- escalationValue = AssetProcessor::JobEscalation::ProcessAssetRequestSyncEscalation;
- }
- for (const RCJob* rcJob : m_jobs)
- {
- if ((platform != rcJob->GetPlatformInfo().m_identifier.c_str()) || (rcJob->GetState() != RCJob::pending))
- {
- continue;
- }
- if (rcJob->GetJobEntry().m_sourceFileUUID == searchUuid)
- {
- found.insert(QueueElementID(rcJob->GetJobEntry().m_sourceAssetReference, platform, rcJob->GetJobKey()));
- escalationList.append(qMakePair(rcJob->GetJobEntry().m_jobRunKey, escalationValue));
- }
- }
- }
- }// namespace AssetProcessor
|