1 2 Previous Next 27 Replies Latest reply on Nov 15, 2005 11:59 AM by brian.stansberry

    ChainingCacheLoader initial designs

    manik

      Hi, all.

      JIRA task
      http://jira.jboss.com/jira/browse/JBCACHE-170

      Background
      Chaining cache loaders is a feature to be able to configure > 1 cache loader so that when the cache is queried, it would check in memory for the existence of the node, failing that it would check the first cache loader configured, then the second, etc etc until it finds what it is looking for.

      Ideal design
      * Ideally we would have a Cache interface which would front the TreeCache, and which could be extended by the CacheLoader interface (in the end a cache loader is just another cache).
      * All CacheLoader implementations would extend an AbstractCacheLoader class rather than the CacheLoader interface.
      * The AbstractCacheLoader class would support methods for retrieving the next cache loader in the chain, and for performing recursive gets, puts and removes which would affect every CacheLoader in the chain.
      * Similar to the Interceptor design (Interceptor.next(), Interceptor.add(), etc)

      Positives
      * Cache loader chaining is implicit in every cache loader implementation.
      * Easy to set up a hierarchical structure of caches.
      * A starting point for not exposing TreeCache directly - allows end users to use a generic Cache interface.
      * Compliant with the way JCACHE (JSR-107) is heading.

      Negatives
      * Will break all existing CacheLoader implementations.
      * Easy for us to fix the CacheLoaders we ship with JBossCache (make them all extend AbstractCacheLoader)
      * More of a hassle for customers to alter their custom CacheLoaders.
      * Will break current XML configuration. This will need re-thinking.

      See UML diagram http://wiki.jboss.org/wiki/attach?page=ChainedCacheLoader%2FIdealScenario.png

        • 1. Re: ChainingCacheLoader initial designs
          manik

          A 'minimal breakage' implementation

          * Create a ChainingCacheLoader class that implements the CacheLoader interface.
          * This class delegates calls to underlying CacheLoaders.
          * If a single CacheLoader is configured, the TreeCache uses it directly.
          * If more than one CacheLoader is configured, the TreeCache creates a ChainingCacheLoader, and adds all configured CacheLoaders to the ChainingCacheLoader.
          * The ChainingCacheLoader handles recursive calls down the chain of CacheLoaders implicitly and the TreeCache simplyy treats it as a standard CacheLoader.

          Positives
          * Quicker implementation
          * Doesn't break custom CacheLoaders.

          Negatives
          * Cache loader chaining isn't implicit in the CacheLoader design.
          * XML configuration will still break, and need changing.

          UML design:
          http://wiki.jboss.org/wiki/attach?page=ChainedCacheLoader%2FMinimalBreakageImplementation.png

          • 2. Re: ChainingCacheLoader initial designs
            manik

            What do people think? Feedback around this is greatly appreciated!

            Thanks,
            Manik

            • 3. Re: ChainingCacheLoader initial designs
              manik

              After more thought, I think my so-called 'Ideal design' above is rubbish! :) It will require that cache loaders have an understanding of the chain and will have to code for it accordingly (by calling superclass methods)

              Having a separate ChainingCacheLoader class may be a lot cleaner as individual CacheLoaders need not have any knowledge of whether it is in a chain or not. The more I think about it the more I lean towards this impl.

              • 4. Re: ChainingCacheLoader initial designs
                manik

                Configuration

                As mentioned above, both approaches would break the existing XML configuration regarding cache loaders, mainly so we could have multiple cache loader configs.

                What do people think of a configuration element a bit like this?

                Old:

                 <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">
                 <attribute name="CacheLoaderClass">org.jboss.cache.loader.bdbje.BdbjeCacheLoader</attribute>
                 <!-- attribute name="CacheLoaderClass">org.jboss.cache.loader.FileCacheLoader</attribute -->
                 <attribute name="CacheLoaderConfig" replace="false">
                 location=c:\\tmp\\bdbje
                 </attribute>
                 <attribute name="CacheLoaderShared">true</attribute>
                 <attribute name="CacheLoaderPreload">/</attribute>
                 <attribute name="CacheLoaderFetchTransientState">false</attribute>
                 <attribute name="CacheLoaderFetchPersistentState">true</attribute>
                 <attribute name="CacheLoaderAsynchronous">true</attribute>
                 </mbean>
                



                New:
                 <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">
                
                 <attribute name="CacheLoaderConfig">
                 <attribute name="CacheLoaderClass">org.jboss.cache.loader.bdbje.BdbjeCacheLoader</attribute>
                 <attribute name="CacheLoaderConfig" replace="false">
                 location=c:\\tmp\\bdbje
                 </attribute>
                 <attribute name="CacheLoaderShared">true</attribute>
                 <attribute name="CacheLoaderPreload">/</attribute>
                 <attribute name="CacheLoaderFetchTransientState">false</attribute>
                 <attribute name="CacheLoaderFetchPersistentState">true</attribute>
                 <attribute name="CacheLoaderAsynchronous">true</attribute>
                 <attribute name="CacheLoaderIgnoreMods">true</attribute>
                 </attribute>
                 </mbean>
                


                Basically this wraps the entire CacheLoader block into a single attribute, so like the EvictionPolicyConfig this can be passed into the TreeCache as a DOM Element.

                This way we could have multiple CacheLoader blocks like this, each one configured and added to the chain in the order which it appears in XML.

                The added element, CacheLoaderIgnoreMods, tells the ChainingCacheLoader whether to propagate CRUD methods to this particular cacheloader: useful if we have a delegating cache loader (using clustered get) backed by a JDBC cache loader where we'd want to write changes to the JDBC cache loader but not to the delegating cache loader.

                Would this have any adverse affects on JMX monitoring of the TreeCache? Thoughts?


                • 5. Re: ChainingCacheLoader initial designs
                  belaban

                  I agree that a ChainingCacheLoader is just another implementation of CacheLoader which delegates reads/writes to a list of real CacheLoaders. This is similar in design to AsyncCacheLoader.
                  To make it a Cache implementation is premature as we'll only go to interfaces in JBossCache 2.0.
                  Regarding configuration: can't we simply use CacheLoaderConfig, with an additional DOM tree inside, which is only parsed when we have a ChainingCacheLoader ?
                  In any case, we need to have a configuration for the list of CacheLoaders, and for each CacheLoader, we need to define:
                  - The classname
                  - Whether or not modifications (e.g. put()) should be applied: the philosophy should be that we return with the first non-null result for READS, but apply WRITES only to CacheLoaders that have that flag set.

                  Note that any CacheLoader in the list could be fronted by (e.g.) an AsyncCacheLoader, so this needs to be recursive !

                  • 6. Re: ChainingCacheLoader initial designs
                    manik

                    Yes, a similar 'delegating model' to the AsyncCacheLoader.

                    Re: config, what you are suggesting will work as well, I'm just concerned about making things too confusing in the configuration. I.e., we will have > 1 way to configure a cache loader then:

                    A single cache loader (E.g., BDBJE cache loader) may be configured as:

                     <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">
                     <attribute name="CacheLoaderClass">org.jboss.cache.loader.bdbje.BdbjeCacheLoader</attribute>
                     <attribute name="CacheLoaderConfig" replace="false">
                     location=c:\\tmp\\bdbje
                     </attribute>
                     <attribute name="CacheLoaderShared">true</attribute>
                     <attribute name="CacheLoaderPreload">/</attribute>
                     <attribute name="CacheLoaderFetchTransientState">false</attribute>
                     <attribute name="CacheLoaderFetchPersistentState">true</attribute>
                     <attribute name="CacheLoaderAsynchronous">true</attribute>
                     </mbean>
                    



                    or:

                     <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">
                     <attribute name="CacheLoaderClass">org.jboss.cache.loader.ChainingCacheLoader</attribute>
                     <attribute name="CacheLoaderConfig" replace="false">
                     <cacheloader>
                     <attribute name="CacheLoaderClass">org.jboss.cache.loader.bdbje.BdbjeCacheLoader</attribute>
                     <attribute name="CacheLoaderConfig" replace="false">
                     location=c:\\tmp\\bdbje
                     </attribute>
                     <attribute name="CacheLoaderShared">true</attribute>
                     <attribute name="CacheLoaderPreload">/</attribute>
                     <attribute name="CacheLoaderFetchTransientState">false</attribute>
                     <attribute name="CacheLoaderFetchPersistentState">true</attribute>
                     <attribute name="CacheLoaderAsynchronous">true</attribute>
                     </cacheloader>
                     </attribute>
                     <attribute name="CacheLoaderShared">true</attribute>
                     <attribute name="CacheLoaderPreload">/</attribute>
                     <attribute name="CacheLoaderFetchTransientState">false</attribute>
                     <attribute name="CacheLoaderFetchPersistentState">true</attribute>
                     <attribute name="CacheLoaderAsynchronous">true</attribute>
                     </mbean>
                    



                    I'd rather force the latter - given that it is a single config format that will work for 1 - n cache loaders (in fact the initial class declaration for the chaining cache loader can be skipped as this could be assumed if we force this config format).

                    The former would help prevent existing configs from breaking though.

                    What do we think?

                    • 7. Re: ChainingCacheLoader initial designs
                      belaban

                      Let's go for the cleaner design: let's make CacheLoader a DOM subtree, including all of the cacheloader-related attributes. Can you come up with a syntax (should also be in JBossCache/docs/design) ?
                      We need to document how to convert existing XML config files to the new version though.

                      • 8. Re: ChainingCacheLoader initial designs
                        manik

                        Off the cuff, I'd think something like this:

                         <attribute name="CacheLoaderConfig">
                        
                         <passivation>false</passivation>
                        
                         <cacheloader
                         class="org.jboss.cache.loader.FileCacheLoader" async="true"
                         shared="false" preload="/" fetchTransientState="true"
                         fetchPersistentState="true" ignoreMods="false">
                         # configuration elements
                         location=/tmp/file.cacheloader
                         </cacheloader>
                        
                         <cacheloader
                         class="org.jboss.cache.loader.bdbje.BdbjeCacheLoader" async="true"
                         shared="true" preload="/" fetchTransientState="true"
                         fetchPersistentState="true" ignoreMods="true">
                         # configuration elements
                         location=/mnt/shared_fs/bdbje.cacheloader
                         </cacheloader>
                        
                         </attribute>
                        


                        The TreeCache has a single setter/getter: CacheLoaderConfig, which gets a DOM tree.

                        In the DOM tree a single element (passivation) tells us if the cache loader is used as a passivation store or a standard cacheloader. Multiple cacheloader elements define each cache loader in the chain.

                        The code can be optimised such that if a single cacheloader element is present then it is used directly; otherwise a ChainingCacheLoader is used.

                        • 9. Re: ChainingCacheLoader initial designs
                          belaban

                          How does this look like for a ChainingCachaLoader ?

                          • 10. Re: ChainingCacheLoader initial designs
                            manik

                            And documenting how to convert between old and new configs will be done - we could even provide a short shell script consisting of a set of sed/awk commands to do the task...

                            Once we finalise on something I'll put it in docs/design...

                            • 11. Re: ChainingCacheLoader initial designs
                              manik

                              You would never explicitly specify a ChainingCacheLoader. If you only use a single cacheloader element, then we use it directly. If you specify > 1 cacheloader element, then we create a ChainingCacheLoader and add these to the chain.

                              • 12. Re: ChainingCacheLoader initial designs
                                belaban

                                I see. Can you spend a few more brain cycles on this before we finalize it ? :-)

                                • 13. Re: ChainingCacheLoader initial designs

                                  re:

                                  Would this have any adverse affects on JMX monitoring of the TreeCache?


                                  It wouldn't affect basic monitoring such as cache hits and misses since these are determined based upon whether the get operation ultimately returns something.

                                  It's been proposed that we capture cache loader nodes loaded and stored but I don't think anyone has investigated this yet.

                                  • 14. Re: ChainingCacheLoader initial designs
                                    manik

                                    Configuring the cache loader like this seems good to me - I'm pretty happy with it.

                                    1 2 Previous Next