[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: Is the graph cache thread-safe ?



On 07/12/2013 05:41 AM, Emmanuel LÃcharny wrote:
Hi Shawn,

yesterday, while stepping the code, I saw that we are using a cache to
handle the hierarchical relationship between roles. I'm afraid that the
'graph' object used to cache those elements is not thread-safe : we
protect it against concurrent modificatins, but that's not enough, as we
should also protect the graph against concurrent access. You may have
corner cases where one thread could fetch some data from this cache
while at the same time another thread is modifying the cache.

I'm just saying that from the code I have read yesterday in the train,
so I'm not 100% sure that this part of the code is at risk. I will
probably do some more investigation, but I'd like to know what are your
thoughts about it.

Thanks !


Emmanuel, share your concern. Ehcache is used to store the graphing object(s) which perhaps mitigates our risk to the corner case? If you want to see where all caching is being applied within fortress, check out the ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!--
Fortress CacheManager Configuration
==========================
This ehcache.xml corresponds to a single CacheManager.
-->
<ehcache name="fortress" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
         xsi:noNamespaceSchemaLocation="ehcache.xsd"
         updateCheck="true" monitoring="autodetect"
         dynamicConfig="true"
        >

    <cacheManagerEventListenerFactory class="" properties=""/>

    <!--
    Default Cache configuration. These settings will be applied to caches
    created programmatically using CacheManager.add(String cacheName).
This element is optional, and using CacheManager.add(String cacheName) when
    its not present will throw CacheException

The defaultCache has an implicit name "default" which is a reserved cache name.
    -->
    <defaultCache
           eternal="false"
           overflowToDisk="false"
           timeToIdleSeconds="120"
           timeToLiveSeconds="120"
           diskSpoolBufferSizeMB="30"
           maxElementsOnDisk="10"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"
           />

    <!--
Thic cache contains password policy entries. It is used to save a read on User password policy edits. There should be one element for every tenant.
    -->
    <cache name="fortress.policies"
           maxElementsInMemory="10"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="2"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

    <!--
Contains the value OrgUnits for User and Permissions. There should be two elements for every tenant.
    -->
    <cache name="fortress.ous"
           maxElementsInMemory="2"
           maxElementsOnDisk="2"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="2"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

    <!--
Contains the JGraphT hierarchies for RBAC roles. There should be one element for every tenant.
    -->
    <cache name="fortress.roles"
           maxElementsInMemory="10"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="2"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

    <!--
Contains the JGraphT hierarchies for ARBAC roles. There should be one element for every tenant.
    -->
    <cache name="fortress.admin.roles"
           maxElementsInMemory="10"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="2"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

    <!--
Contains the JGraphT hierarchies for Perm OUs. There should be one element for every tenant.
    -->
    <cache name="fortress.pso"
           maxElementsInMemory="10"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="2"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

    <!--
Contains the JGraphT hierarchies for User OUs. There should be one element for every tenant.
    -->
    <cache name="fortress.uso"
           maxElementsInMemory="10"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="2"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

    <!--
Searchable cache contains Role<->DSD mapping. This configuration sets a fairly long TTL of 1 hour.
    -->
    <cache name="fortress.dsd"
           maxElementsInMemory="1000"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="3600"
           memoryStoreEvictionPolicy="LFU">
           <searchable>
<searchAttribute name="member" expression="value.getMember()"/>
               <searchAttribute name="name" expression="value.getName()"/>
<searchAttribute name="contextId" expression="value.getContextId()"/>
           </searchable>
        </cache>

    <!--
        Cache contains Role<->SSD mapping.
    -->
    <cache name="fortress.ssd"
           maxElementsInMemory="1000"
           maxElementsOnDisk="10"
           eternal="false"
           overflowToDisk="false"
           diskSpoolBufferSizeMB="20"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           memoryStoreEvictionPolicy="LFU"
           />

</ehcache>


Shawn