Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

Commit

Permalink
Change cache invalidation method, by timestamping cached data and che…
Browse files Browse the repository at this point in the history
…cking a given key against other data stamps. To be tested extensively.
  • Loading branch information
cdujeu committed Sep 22, 2016
1 parent 6d429a9 commit 9a6a777
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 27 deletions.
6 changes: 6 additions & 0 deletions core/src/core/src/pydio/Core/Model/UserInterface.php
Expand Up @@ -281,4 +281,10 @@ public function updatePersonalRole(AJXP_Role $role);
* @throws \Exception
*/
public function reloadRolesIfRequired();

/**
* @return array
*/
public function getRolesKeys();

}
Expand Up @@ -430,7 +430,10 @@ public function getFilteredXMLRegistry($extendedVersion = true, $clone = false,
{
if ($useCache) {
$cacheKey = $this->getRegistryCacheKey($extendedVersion);
$cachedXml = CacheService::fetch(AJXP_CACHE_SERVICE_NS_SHARED, $cacheKey);
$tStamps = [];
if($this->context->hasUser()) $tStamps[] = "pydio:user:".$this->context->getUser()->getId();
if($this->context->hasRepository()) $tStamps[] = "pydio:repository:".$this->context->getRepositoryId();
$cachedXml = CacheService::fetchWithTimestamps(AJXP_CACHE_SERVICE_NS_SHARED, $cacheKey, $tStamps);
if ($cachedXml !== false) {
$registry = new \DOMDocument("1.0", "utf-8");
$registry->loadXML($cachedXml);
Expand All @@ -452,7 +455,7 @@ public function getFilteredXMLRegistry($extendedVersion = true, $clone = false,
}

if ($useCache && isSet($cacheKey)) {
CacheService::save(AJXP_CACHE_SERVICE_NS_SHARED, $cacheKey, $registry->saveXML());
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, $cacheKey, $registry->saveXML());
}

if ($clone) {
Expand Down
59 changes: 59 additions & 0 deletions core/src/core/src/pydio/Core/Services/CacheService.php
Expand Up @@ -56,12 +56,32 @@ public static function save($namespace, $id, $object, $timelimit = 0) {
$cacheDriver = ConfService::getCacheDriverImpl();

if ($cacheDriver) {
//if($namespace === AJXP_CACHE_SERVICE_NS_SHARED) error_log("Saving data for $id");
return $cacheDriver->save($namespace, $id, $object, $timelimit);
}

return false;
}

/**
* @param $namespace
* @param $id
* @param $object
* @param int $timelimit
* @return bool
*/
public static function saveWithTimestamp($namespace, $id, $object, $timelimit = 0){
$cacheDriver = ConfService::getCacheDriverImpl();

if ($cacheDriver) {
//if($namespace === AJXP_CACHE_SERVICE_NS_SHARED) error_log("Saving data for $id with timestamp");
return $cacheDriver->saveWithTimestamp($namespace, $id, $object, $timelimit);
}

return false;

}

/**
* @param $namespace
* @param $id
Expand All @@ -72,12 +92,51 @@ public static function fetch($namespace, $id) {

if ($cacheDriver) {
$data = $cacheDriver->fetch($namespace, $id);
if($data !== false && $namespace === AJXP_CACHE_SERVICE_NS_SHARED){
//error_log("Found data for $id");
}
return $data;
}

return false;
}

/**
* @param $namespace
* @param array $ids
* @return bool|mixed
*/
public static function fetchMultiple($namespace, $ids) {
$cacheDriver = ConfService::getCacheDriverImpl();

if ($cacheDriver) {
return $cacheDriver->fetchMultiple($namespace, $ids);
}

return false;
}

/**
* @param $namespace
* @param $id
* @param array $idsToCheck
* @return bool|false|mixed
*/
public static function fetchWithTimestamps($namespace, $id, $idsToCheck){
$cacheDriver = ConfService::getCacheDriverImpl();

if ($cacheDriver) {
$data = $cacheDriver->fetchWithTimestamps($namespace, $id, $idsToCheck);
if($data !== false && $namespace === AJXP_CACHE_SERVICE_NS_SHARED){
//error_log("Found data for $id after checking timestamps for ".implode(",", $idsToCheck));
}
return $data;
}

return false;

}

/**
* @param $namespace
* @param $id
Expand Down
18 changes: 6 additions & 12 deletions core/src/core/src/pydio/Core/Services/RepositoryService.php
Expand Up @@ -360,23 +360,23 @@ private function getRepositoryByIdInst($repoId)
if (isSet($this->cache["REPOSITORIES"]) && isSet($this->cache["REPOSITORIES"][$repoId])) {
return $this->cache["REPOSITORIES"][$repoId];
}
$test = CacheService::fetch(AJXP_CACHE_SERVICE_NS_SHARED, "repository:" . $repoId);
$test = CacheService::fetch(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:repository:" . $repoId);
if($test !== false){
$this->cache["REPOSITORIES"][$repoId] = $test;
return $test;
}
$test = ConfService::getConfStorageImpl()->getRepositoryById($repoId);
if($test != null) {
$this->cache["REPOSITORIES"][$repoId] = $test;
CacheService::save(AJXP_CACHE_SERVICE_NS_SHARED, "repository:" . $repoId, $test);
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:repository:" . $repoId, $test);
return $test;
}
// Finally try to search in default repositories
$statics = self::getStaticRepositories();
if (isSet($statics[$repoId])) {
$repo = $statics[$repoId];
$this->cache["REPOSITORIES"][$repoId] = $test;
CacheService::save(AJXP_CACHE_SERVICE_NS_SHARED, "repository:" . $repoId, $repo);
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:repository:" . $repoId, $repo);
return $repo;
}
$hookedRepo = null;
Expand Down Expand Up @@ -440,9 +440,7 @@ private function addRepositoryInst($oRepository)
}
Controller::applyHook("workspace.after_create", array(Context::fromGlobalServices(), $oRepository));
Logger::info(__CLASS__,"Create Repository", array("repo_name"=>$oRepository->getDisplay()));
CacheService::save(AJXP_CACHE_SERVICE_NS_SHARED, "repository:".$oRepository->getId(), $oRepository);
// TODO ?
//$this->invalidateLoadedRepositories();
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:repository:".$oRepository->getId(), $oRepository);
return null;
}

Expand Down Expand Up @@ -479,9 +477,7 @@ private function replaceRepositoryInst($oldId, $oRepositoryObject)
}
Controller::applyHook("workspace.after_update", array(Context::fromGlobalServices(), $oRepositoryObject));
Logger::info(__CLASS__,"Edit Repository", array("repo_name"=>$oRepositoryObject->getDisplay()));
// TODO ?
//$this->invalidateLoadedRepositories();
CacheService::save(AJXP_CACHE_SERVICE_NS_SHARED, "repository:" . $oRepositoryObject->getId(), $oRepositoryObject);
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:repository:" . $oRepositoryObject->getId(), $oRepositoryObject);
return 0;
}

Expand All @@ -508,9 +504,7 @@ private function deleteRepositoryInst($repoId)
}
Controller::applyHook("workspace.after_delete", array(Context::fromGlobalServices(), $repoId));
Logger::info(__CLASS__,"Delete Repository", array("repo_id"=>$repoId));
// TODO ?
//$this->invalidateLoadedRepositories();
CacheService::delete(AJXP_CACHE_SERVICE_NS_SHARED, "repository:".$repoId);
CacheService::delete(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:repository:".$repoId);
return 0;
}

Expand Down
31 changes: 29 additions & 2 deletions core/src/core/src/pydio/Core/Services/RolesService.php
Expand Up @@ -142,7 +142,7 @@ public static function getOrCreateRole($roleId, $groupPath = "/")
public static function updateRole($roleObject, $userObject = null)
{
ConfService::getConfStorageImpl()->updateRole($roleObject, $userObject);
//CacheService::deleteAll(AJXP_CACHE_SERVICE_NS_SHARED);
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:role:".$roleObject->getId(), $roleObject);
ConfService::getInstance()->invalidateLoadedRepositories();
}

Expand All @@ -155,7 +155,7 @@ public static function updateRole($roleObject, $userObject = null)
public static function deleteRole($roleId)
{
ConfService::getConfStorageImpl()->deleteRole($roleId);
//CacheService::deleteAll(AJXP_CACHE_SERVICE_NS_SHARED);
CacheService::delete(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:role:".$roleId);
ConfService::getInstance()->invalidateLoadedRepositories();
}

Expand Down Expand Up @@ -230,6 +230,26 @@ public static function getRolesList($roleIds = array(), $excludeReserved = false
if (self::$useCache && !count($roleIds) && $excludeReserved == true && self::$rolesCache != null) {
return self::$rolesCache;
}
$searches = array_map(function($k){return "pydio:role:".$k;}, $roleIds);
$fetches = CacheService::fetchMultiple(AJXP_CACHE_SERVICE_NS_SHARED, $searches);
$missing = [];
if(count($fetches)){
$found = [];
foreach($searches as $cacheKey){
$okKey = preg_replace('/^pydio:role:/', "", $cacheKey);
if(isSet($fetches[$cacheKey]) && $fetches[$cacheKey] instanceof AJXP_Role){
$found[$okKey] = $fetches[$cacheKey];
}else{
$missing[] = $okKey;
}
}
if(!count($missing)){
return $found;
}else{
$roleIds = $missing;
}
}

$confDriver = ConfService::getConfStorageImpl();
$roles = $confDriver->listRoles($roleIds, $excludeReserved);
$repoList = null;
Expand All @@ -241,6 +261,13 @@ public static function getRolesList($roleIds = array(), $excludeReserved = false
$roles[$roleId] = $newRole;
self::updateRole($newRole);
}
if(count($roleIds)){
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:role:".$roleId, $roleObject);
}
}
if(isSet($found) && count($found)){
// Add the ones loaded from cache
$roles = array_merge($roles, $found);
}
if (self::$useCache && !count($roleIds) && $excludeReserved == true) {
self::$rolesCache = $roles;
Expand Down
29 changes: 19 additions & 10 deletions core/src/core/src/pydio/Core/Services/UsersService.php
Expand Up @@ -82,14 +82,19 @@ public static function getUserById($userId, $checkExists = true){
return $self->usersCache[$userId];
}
// Try to get from cache
$test = CacheService::fetch("shared", "pydio:user:" . $userId);
$test = CacheService::fetch(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:user:" . $userId);
if($test !== false && $test instanceof UserInterface){
if($test->getPersonalRole() === null){
$test->updatePersonalRole($test->getRoles()["AJXP_USR_/".$userId]);
// Second check : if roles were updated in cache
$roleCacheIds = array_map(function($k){ return "pydio:role:".$k; }, $test->getRolesKeys());
$test = CacheService::fetchWithTimestamps(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:user:".$userId, $roleCacheIds);
if($test !== false){
if($test->getPersonalRole() === null){
$test->updatePersonalRole($test->getRoles()["AJXP_USR_/".$userId]);
}
$test->recomputeMergedRole();
$self->usersCache[$userId] = $test;
return $test;
}
$test->recomputeMergedRole();
$self->usersCache[$userId] = $test;
return $test;
}
if($checkExists && !self::userExists($userId)){
throw new UserNotFoundException($userId);
Expand All @@ -100,20 +105,25 @@ public static function getUserById($userId, $checkExists = true){
// Save in memory
$self->usersCache[$userId] = $userObject;
// Save in cache
CacheService::save("shared", "pydio:user:" . $userId, $userObject);
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:user:" . $userId, $userObject);
}
return $userObject;

}

/**
* @param $userObject UserInterface
* @param string $scope
*/
public static function updateUser($userObject){
public static function updateUser($userObject, $scope = "user"){
$self = self::instance();
$userId = $userObject->getId();
$self->usersCache[$userId] = $userObject;
CacheService::save("shared", "pydio:user:" . $userId, $userObject);
if($scope === "user"){
CacheService::save(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:user:" . $userId, $userObject);
}else{
CacheService::saveWithTimestamp(AJXP_CACHE_SERVICE_NS_SHARED, "pydio:user:" . $userId, $userObject);
}
}

/**
Expand Down Expand Up @@ -206,7 +216,6 @@ public static function invalidateCache(){

self::instance()->repositoriesCache = [];
self::instance()->usersCache = [];
CacheService::deleteAll(AJXP_CACHE_SERVICE_NS_SHARED);
SessionService::invalidateLoadedRepositories();

}
Expand Down

0 comments on commit 9a6a777

Please sign in to comment.