Updated NCM to 9.0.0

This commit is contained in:
Adubbz 2019-10-02 18:44:15 +10:00
parent bb3d41b416
commit 1c19856fb0
8 changed files with 53 additions and 61 deletions

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "ncm_rights_cache.hpp"
namespace sts::ncm::impl {
namespace {
RightsIdCache g_rights_id_cache;
}
RightsIdCache* GetRightsIdCache() {
return &g_rights_id_cache;
}
}

View File

@ -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();
}

View File

@ -77,4 +77,8 @@ namespace sts::ncm {
return impl::InactivateContentMetaDatabase(storage_id);
}
Result ContentManagerService::InvalidateRightsIdCache() {
return impl::InvalidateRightsIdCache();
}
}

View File

@ -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),
};
};

View File

@ -14,7 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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<FsRightsId> out_rights_id, Out<u64> out_key_generation, ContentId content_id) {
R_TRY(this->EnsureEnabled());
impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache();
{
std::scoped_lock<HosMutex> lk(rights_id_cache->mutex);
std::scoped_lock<HosMutex> 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<HosMutex> lk(rights_id_cache->mutex);
impl::RightsIdCache::Entry* eviction_candidate = &rights_id_cache->entries[0];
std::scoped_lock<HosMutex> 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<FsRightsId> out_rights_id, Out<u64> out_key_generation, PlaceHolderId placeholder_id, ContentId cache_content_id) {
R_TRY(this->EnsureEnabled());
impl::RightsIdCache* rights_id_cache = impl::GetRightsIdCache();
{
std::scoped_lock<HosMutex> lk(rights_id_cache->mutex);
std::scoped_lock<HosMutex> 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<HosMutex> lk(rights_id_cache->mutex);
impl::RightsIdCache::Entry* eviction_candidate = &rights_id_cache->entries[0];
std::scoped_lock<HosMutex> 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);

View File

@ -19,6 +19,7 @@
#include <stratosphere.hpp>
#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();