diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.cpp b/stratosphere/ncm/source/impl/ncm_content_manager.cpp
index 01ec3f94e..27b5e0b7a 100644
--- a/stratosphere/ncm/source/impl/ncm_content_manager.cpp
+++ b/stratosphere/ncm/source/impl/ncm_content_manager.cpp
@@ -25,6 +25,7 @@
#include "../ncm_make_path.hpp"
#include "../ncm_readonlycontentstorage.hpp"
#include "ncm_content_manager.hpp"
+#include "ncm_rights_cache.hpp"
namespace sts::ncm::impl {
@@ -115,6 +116,7 @@ namespace sts::ncm::impl {
ContentMetaDBEntry g_content_meta_entries[MaxContentMetaDBEntries];
u32 g_num_content_storage_entries;
u32 g_num_content_meta_entries;
+ RightsIdCache g_rights_id_cache;
ContentStorageEntry* FindContentStorageEntry(StorageId storage_id) {
for (size_t i = 0; i < MaxContentStorageEntries; i++) {
@@ -449,7 +451,7 @@ namespace sts::ncm::impl {
break;
}
- R_TRY(content_storage->Initialize(entry->root_path, content_path_func, placeholder_path_func, delay_flush));
+ R_TRY(content_storage->Initialize(entry->root_path, content_path_func, placeholder_path_func, delay_flush, &g_rights_id_cache));
entry->content_storage = std::move(content_storage);
mount_guard.Cancel();
}
@@ -706,4 +708,10 @@ namespace sts::ncm::impl {
return ResultSuccess;
}
+
+ Result InvalidateRightsIdCache() {
+ g_rights_id_cache.Invalidate();
+ return ResultSuccess;
+ }
+
}
diff --git a/stratosphere/ncm/source/impl/ncm_content_manager.hpp b/stratosphere/ncm/source/impl/ncm_content_manager.hpp
index 7cfe4254e..3fdaf9d99 100644
--- a/stratosphere/ncm/source/impl/ncm_content_manager.hpp
+++ b/stratosphere/ncm/source/impl/ncm_content_manager.hpp
@@ -43,5 +43,6 @@ namespace sts::ncm::impl {
Result CleanupContentMetaDatabase(StorageId storage_id);
Result ActivateContentMetaDatabase(StorageId storage_id);
Result InactivateContentMetaDatabase(StorageId storage_id);
+ Result InvalidateRightsIdCache();
}
diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.cpp b/stratosphere/ncm/source/impl/ncm_rights_cache.cpp
deleted file mode 100644
index 42b57da7c..000000000
--- a/stratosphere/ncm/source/impl/ncm_rights_cache.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2019 Adubbz
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "ncm_rights_cache.hpp"
-
-namespace sts::ncm::impl {
-
- namespace {
-
- RightsIdCache g_rights_id_cache;
-
- }
-
- RightsIdCache* GetRightsIdCache() {
- return &g_rights_id_cache;
- }
-
-}
diff --git a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp
index 1f1d74332..1e17437e4 100644
--- a/stratosphere/ncm/source/impl/ncm_rights_cache.hpp
+++ b/stratosphere/ncm/source/impl/ncm_rights_cache.hpp
@@ -29,14 +29,23 @@ namespace sts::ncm::impl {
util::Uuid uuid;
FsRightsId rights_id;
u64 key_generation;
- u64 last_accessed = 1;
+ u64 last_accessed;
};
Entry entries[MaxEntries];
- u64 counter = 2;
+ u64 counter;
HosMutex mutex;
+
+ RightsIdCache() {
+ this->Invalidate();
+ }
+
+ void Invalidate() {
+ this->counter = 2;
+ for (size_t i = 0; i < MaxEntries; i++) {
+ this->entries[i].last_accessed = 1;
+ }
+ }
};
- RightsIdCache* GetRightsIdCache();
-
}
diff --git a/stratosphere/ncm/source/ncm_content_manager_service.cpp b/stratosphere/ncm/source/ncm_content_manager_service.cpp
index 5a2d3c550..d0bcdffa6 100644
--- a/stratosphere/ncm/source/ncm_content_manager_service.cpp
+++ b/stratosphere/ncm/source/ncm_content_manager_service.cpp
@@ -77,4 +77,8 @@ namespace sts::ncm {
return impl::InactivateContentMetaDatabase(storage_id);
}
+ Result ContentManagerService::InvalidateRightsIdCache() {
+ return impl::InvalidateRightsIdCache();
+ }
+
}
diff --git a/stratosphere/ncm/source/ncm_content_manager_service.hpp b/stratosphere/ncm/source/ncm_content_manager_service.hpp
index 1d2c2fe31..48ddd1c65 100644
--- a/stratosphere/ncm/source/ncm_content_manager_service.hpp
+++ b/stratosphere/ncm/source/ncm_content_manager_service.hpp
@@ -39,6 +39,7 @@ namespace sts::ncm {
InactivateContentStorage = 10,
ActivateContentMetaDatabase = 11,
InactivateContentMetaDatabase = 12,
+ InvalidateRightsIdCache = 13,
};
public:
virtual Result CreateContentStorage(StorageId storage_id);
@@ -54,6 +55,7 @@ namespace sts::ncm {
virtual Result InactivateContentStorage(StorageId storage_id);
virtual Result ActivateContentMetaDatabase(StorageId storage_id);
virtual Result InactivateContentMetaDatabase(StorageId storage_id);
+ virtual Result InvalidateRightsIdCache();
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ContentManagerService, CreateContentStorage),
@@ -69,6 +71,7 @@ namespace sts::ncm {
MAKE_SERVICE_COMMAND_META(ContentManagerService, InactivateContentStorage, FirmwareVersion_200),
MAKE_SERVICE_COMMAND_META(ContentManagerService, ActivateContentMetaDatabase, FirmwareVersion_200),
MAKE_SERVICE_COMMAND_META(ContentManagerService, InactivateContentMetaDatabase, FirmwareVersion_200),
+ MAKE_SERVICE_COMMAND_META(ContentManagerService, InvalidateRightsIdCache, FirmwareVersion_900),
};
};
diff --git a/stratosphere/ncm/source/ncm_contentstorage.cpp b/stratosphere/ncm/source/ncm_contentstorage.cpp
index 01f177124..75e44ed4d 100644
--- a/stratosphere/ncm/source/ncm_contentstorage.cpp
+++ b/stratosphere/ncm/source/ncm_contentstorage.cpp
@@ -14,7 +14,6 @@
* along with this program. If not, see .
*/
-#include "impl/ncm_rights_cache.hpp"
#include "ncm_contentstorage.hpp"
#include "ncm_fs.hpp"
#include "ncm_make_path.hpp"
@@ -26,7 +25,7 @@ namespace sts::ncm {
this->Finalize();
}
- Result ContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush) {
+ Result ContentStorageInterface::Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache* rights_id_cache) {
R_TRY(this->EnsureEnabled());
R_TRY(fs::CheckContentStorageDirectoriesExist(root_path));
const size_t root_path_len = strnlen(root_path, FS_MAX_PATH-1);
@@ -38,6 +37,7 @@ namespace sts::ncm {
strncpy(this->root_path, root_path, FS_MAX_PATH-2);
this->make_content_path_func = *content_path_func;
this->placeholder_accessor.Initialize(this->root_path, *placeholder_path_func, delay_flush);
+ this->rights_id_cache = rights_id_cache;
return ResultSuccess;
}
@@ -428,18 +428,16 @@ namespace sts::ncm {
Result ContentStorageInterface::GetRightsIdFromContentId(Out out_rights_id, Out out_key_generation, ContentId content_id) {
R_TRY(this->EnsureEnabled());
- impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache();
-
{
- std::scoped_lock lk(rights_id_cache->mutex);
+ std::scoped_lock lk(this->rights_id_cache->mutex);
/* Attempt to locate the content id in the cache. */
for (size_t i = 0; i < impl::RightsIdCache::MaxEntries; i++) {
- impl::RightsIdCache::Entry* entry = &rights_id_cache->entries[i];
+ impl::RightsIdCache::Entry* entry = &this->rights_id_cache->entries[i];
if (entry->last_accessed != 1 && content_id == entry->uuid) {
- entry->last_accessed = rights_id_cache->counter;
- rights_id_cache->counter++;
+ entry->last_accessed = this->rights_id_cache->counter;
+ this->rights_id_cache->counter++;
out_rights_id.SetValue(entry->rights_id);
out_key_generation.SetValue(entry->key_generation);
return ResultSuccess;
@@ -456,12 +454,12 @@ namespace sts::ncm {
R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id));
{
- std::scoped_lock lk(rights_id_cache->mutex);
- impl::RightsIdCache::Entry* eviction_candidate = &rights_id_cache->entries[0];
+ std::scoped_lock lk(this->rights_id_cache->mutex);
+ impl::RightsIdCache::Entry* eviction_candidate = &this->rights_id_cache->entries[0];
/* Find a suitable existing entry to store our new one at. */
for (size_t i = 1; i < impl::RightsIdCache::MaxEntries; i++) {
- impl::RightsIdCache::Entry* entry = &rights_id_cache->entries[i];
+ impl::RightsIdCache::Entry* entry = &this->rights_id_cache->entries[i];
/* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */
if (content_id == entry->uuid || (content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) {
@@ -473,8 +471,8 @@ namespace sts::ncm {
eviction_candidate->uuid = content_id.uuid;
eviction_candidate->rights_id = rights_id;
eviction_candidate->key_generation = key_generation;
- eviction_candidate->last_accessed = rights_id_cache->counter;
- rights_id_cache->counter++;
+ eviction_candidate->last_accessed = this->rights_id_cache->counter;
+ this->rights_id_cache->counter++;
/* Set output. */
out_rights_id.SetValue(rights_id);
@@ -599,18 +597,16 @@ namespace sts::ncm {
Result ContentStorageInterface::GetRightsIdFromPlaceHolderIdWithCache(Out out_rights_id, Out out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) {
R_TRY(this->EnsureEnabled());
- impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache();
-
{
- std::scoped_lock lk(rights_id_cache->mutex);
+ std::scoped_lock lk(this->rights_id_cache->mutex);
/* Attempt to locate the content id in the cache. */
for (size_t i = 0; i < impl::RightsIdCache::MaxEntries; i++) {
- impl::RightsIdCache::Entry* entry = &rights_id_cache->entries[i];
+ impl::RightsIdCache::Entry* entry = &this->rights_id_cache->entries[i];
if (entry->last_accessed != 1 && cache_content_id == entry->uuid) {
- entry->last_accessed = rights_id_cache->counter;
- rights_id_cache->counter++;
+ entry->last_accessed = this->rights_id_cache->counter;
+ this->rights_id_cache->counter++;
out_rights_id.SetValue(entry->rights_id);
out_key_generation.SetValue(entry->key_generation);
return ResultSuccess;
@@ -627,12 +623,12 @@ namespace sts::ncm {
R_TRY(fsGetRightsIdAndKeyGenerationByPath(common_path, &key_generation, &rights_id));
{
- std::scoped_lock lk(rights_id_cache->mutex);
- impl::RightsIdCache::Entry* eviction_candidate = &rights_id_cache->entries[0];
+ std::scoped_lock lk(this->rights_id_cache->mutex);
+ impl::RightsIdCache::Entry* eviction_candidate = &this->rights_id_cache->entries[0];
/* Find a suitable existing entry to store our new one at. */
for (size_t i = 1; i < impl::RightsIdCache::MaxEntries; i++) {
- impl::RightsIdCache::Entry* entry = &rights_id_cache->entries[i];
+ impl::RightsIdCache::Entry* entry = &this->rights_id_cache->entries[i];
/* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */
if (cache_content_id == entry->uuid || (cache_content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) {
@@ -644,8 +640,8 @@ namespace sts::ncm {
eviction_candidate->uuid = cache_content_id.uuid;
eviction_candidate->rights_id = rights_id;
eviction_candidate->key_generation = key_generation;
- eviction_candidate->last_accessed = rights_id_cache->counter;
- rights_id_cache->counter++;
+ eviction_candidate->last_accessed = this->rights_id_cache->counter;
+ this->rights_id_cache->counter++;
/* Set output. */
out_rights_id.SetValue(rights_id);
diff --git a/stratosphere/ncm/source/ncm_contentstorage.hpp b/stratosphere/ncm/source/ncm_contentstorage.hpp
index 7f9f8b7de..bd0939187 100644
--- a/stratosphere/ncm/source/ncm_contentstorage.hpp
+++ b/stratosphere/ncm/source/ncm_contentstorage.hpp
@@ -19,6 +19,7 @@
#include
#include "impl/ncm_placeholder_accessor.hpp"
+#include "impl/ncm_rights_cache.hpp"
#include "ncm_icontentstorage.hpp"
#include "ncm_path_utils.hpp"
@@ -29,10 +30,11 @@ namespace sts::ncm {
impl::PlaceHolderAccessor placeholder_accessor;
ContentId cached_content_id;
FILE* content_cache_file_handle;
+ impl::RightsIdCache* rights_id_cache;
public:
~ContentStorageInterface();
- Result Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush);
+ Result Initialize(const char* root_path, MakeContentPathFunc content_path_func, MakePlaceHolderPathFunc placeholder_path_func, bool delay_flush, impl::RightsIdCache* rights_id_cache);
void Finalize();
private:
void ClearContentCache();