9 Replies Latest reply on Jul 31, 2007 5:54 AM by supi

    RC1->RC3 problems

    supi

      We tried to migrage from RC1 to RC3 and are quite disappointed. IMO, there are a bunch of things that can happen in alpha or beta state, but really shouldn't happen between candidate releases.

      1) API changes
      There's already a thread about this regarding listener notification.

      2) Behavior changes
      - Cache data is removed when a cache is stopped. This has never been the case before. I know that it was written somewhere in the documentation since 1.2 or so but it was a concept that didn't make sense to begin with. Who would have thought that someone is actually going to implement this... Data can easily be removed manually if indeed necessary, doing it in stop is pointless: stop() should stop the cache, destroy() should destroy it. Now stop() partially destroys it and destroy contains some code that is even redundant. (you can tell me not to rely on undocumented features and you are right, but missing the point: somthing that has been there for 5 years shouldn't be removed between two candidate releases)

      - Cache restart (stop/start) is broken. When a cache is started in local mode first and then restarted in async mode, initial state transfer works, but updates at runtime don't because half the mode-dependent stuff is in create and half in start which renders a restarted cache unusable. This was not the case in RC1.

      I have a feeling that the cache life cycle has never really been thought through. I guess most people use create/start ... stop/destroy: in fact, start and destroy would be sufficient for them. But we use create/start ... stop/mode change/start ... stop/mode change/start ... etc. stop/destroy.

      3) New bugs introduced
      I admitt, I only ran a couple of our automated tests, but it didn't look pretty. Pojo cache can't even handle the following anymore:

       _cache.start();
      
       SystemW coreSystem = new SystemW();
       coreSystem.setDo(new SystemS(100, 123, "core system", "CORE")); // <- @Serializable
      
       _cache.attach("/systems/100", coreSystem);
       _cache.attach("/systems/100", new SystemW()); // <- throws
      


      whereas SystemW is advised and has a @org.jboss.cache.pojo.annotation.Serializable field _do. Something like this:
      public class SystemW {
       @org.jboss.cache.pojo.annotation.Serializable
       private SystemS _do;
      
       public void setDo(SystemS inDo) {
       _do = inDo;
       }
      }
      


      Stack trace:
      java.lang.ClassCastException: ch.steria.jbcache.aopobjects.SystemS
       at org.jboss.cache.pojo.impl.InternalHelper.getPojoReference(InternalHelper.java:46)
       at org.jboss.cache.pojo.impl.InternalHelper.getPojo(InternalHelper.java:181)
       at org.jboss.cache.pojo.impl.PojoCacheDelegate.getObject(PojoCacheDelegate.java:81)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.getObject(PojoCacheImpl.java:203)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.org$jboss$cache$pojo$impl$PojoCacheImpl$detach$aop(PojoCacheImpl.java:150)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.detach(PojoCacheImpl.java)
       at org.jboss.cache.pojo.impl.AdvisedPojoHandler.remove(AdvisedPojoHandler.java:215)
       at org.jboss.cache.pojo.impl.PojoCacheDelegate.removeObject(PojoCacheDelegate.java:276)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.removeObject(PojoCacheImpl.java:170)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.org$jboss$cache$pojo$impl$PojoCacheImpl$detach$aop(PojoCacheImpl.java:153)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.detach(PojoCacheImpl.java)
       at org.jboss.cache.pojo.impl.PojoCacheDelegate.putObjectII(PojoCacheDelegate.java:143)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.putObject(PojoCacheImpl.java:136)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.org$jboss$cache$pojo$impl$PojoCacheImpl$attach$aop(PojoCacheImpl.java:101)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.attach(PojoCacheImpl.java)
       at org.jboss.cache.pojo.impl.PojoCacheImpl.attach(PojoCacheImpl.java:93)
      


      This has never been a problem in RC1 or before.

      Regards,
      Basil


        • 1. Re: RC1->RC3 problems
          jason.greene

           

          "supi" wrote:

          3) New bugs introduced
          I admitt, I only ran a couple of our automated tests, but it didn't look pretty. Pojo cache can't even handle the following anymore:


          Thanks, I created an issue for this problem here:
          http://jira.jboss.com/jira/browse/JBCACHE-1150

          -Jason


          • 2. Re: RC1->RC3 problems
            jason.greene

             

            "jason.greene@jboss.com" wrote:
            "supi" wrote:

            3) New bugs introduced
            I admitt, I only ran a couple of our automated tests, but it didn't look pretty. Pojo cache can't even handle the following anymore:


            Thanks, I created an issue for this problem here:
            http://jira.jboss.com/jira/browse/JBCACHE-1150

            -Jason


            This problem has been fixed, try the latest cvs HEAD checkout if you want to verify it works for you.

            • 3. Re: RC1->RC3 problems
              manik

               

              "supi" wrote:

              1) API changes
              There's already a thread about this regarding listener notification.


              That selfsame thread contains explanations as to why this was done, along with links to other threads where this was publicly discussed beforehand.

              "supi" wrote:

              2) Behavior changes
              - Cache data is removed when a cache is stopped. This has never been the case before. I know that it was written somewhere in the documentation since 1.2 or so but it was a concept that didn't make sense to begin with. Who would have thought that someone is actually going to implement this... Data can easily be removed manually if indeed necessary, doing it in stop is pointless: stop() should stop the cache, destroy() should destroy it. Now stop() partially destroys it and destroy contains some code that is even redundant. (you can tell me not to rely on undocumented features and you are right, but missing the point: somthing that has been there for 5 years shouldn't be removed between two candidate releases)


              This was tagged for 2.0.0 as a part of the API change but wasn't properly unimplemented till pretty late.

              Caches are meant to me in-memory stores for data. When a cache stops, you are meant to lose this in-memory state. The fact that this state stuck around when you stopped and then restarted a cache was a bug.

              The definitions of the terms are:

              create() - sets up and configures the cache for use
              start() - starts the caching engine, and relevant services
              stop() - stops the engine and services - which typically includes the data store
              destroy() - releases resources and configuration elements

              You'd use a cache loader if you want a warm cache (even if it is a delegating cache loader that delegates to another in-memory cache that acts as your 'back-end' cache, while your 'front-end' cache adds behaviour), or configure the cache to fetch in-memory state from it's neighbours on startup.

              "supi" wrote:

              Cache restart (stop/start) is broken. When a cache is started in local mode first and then restarted in async mode, initial state transfer works, but updates at runtime don't because half the mode-dependent stuff is in create and half in start which renders a restarted cache unusable. This was not the case in RC1.


              This I can see as a bug. Will try and reproduce and create a JIRA accordingly.

              • 4. Re: RC1->RC3 problems
                manik

                Actually, the javadocs on stop() and destroy() are misleading - thanks for bringing this up, I've fixed this in CVS now.

                Please see http://lists.jboss.org/pipermail/jbosscache-dev/2007-May/001569.html for the discussion thread that led to the decisions around when the cache is emptied.

                • 5. Re: RC1->RC3 problems
                  supi

                   

                  "jason.greene@jboss.com" wrote:
                  "jason.greene@jboss.com" wrote:
                  This problem has been fixed, try the latest cvs HEAD checkout if you want to verify it works for you.


                  Thank a lot, Jason! Works perfectly so far.


                  • 6. Re: RC1->RC3 problems
                    supi

                     

                    When a cache stops, you are meant to lose this in-memory state.

                    I disagree. When a cache stops, you should lose the ability to operate on the data through the cache interface. I've never seen a database deleting tables when you stop the db server/agent. I would agree with you if a) a stopped cache was not meant to be restarted ever, b) there wasn't a destroy method perfectly suitable for releasing resources.


                    The definitions of the terms are:
                    ...
                    stop() - stops the engine and services - which typically includes the data store
                    ...

                    I agree. However, stopping a data store's services does not imply deleting the content.


                    The fact that this state stuck around when you stopped and then restarted a cache was a bug.

                    We need the ability to remove a cache from a cluster and add it to a cluster at runtime, so for us it's clearly a feature and not a bug. I can see your point, but what I don't understand is why you don't let the users make their own decision.


                    You'd use a cache loader if you want a warm cache (even if it is a delegating cache loader that delegates to another in-memory cache that acts as your 'back-end' cache, while your 'front-end' cache adds behaviour)

                    While we might use something like this eventually, it implies unnecessary code and performance overhead.


                    • 7. Re: RC1->RC3 problems
                      supi

                       

                      "Brian Stansberry in jbosscache-dev" wrote:

                      Basically, the state transfer semantics imply that the in-memory state
                      is "consistent" with the cluster when start returns. Either its
                      "consistent" because it's been transferred, or it's "consistent" because
                      it's empty and waiting to be populated from a trusted source (shared
                      cache loader or external source like db). Leaving the in-memory state
                      around after stop() breaks that.

                      The reasoning is flawed. If an empty state is considered "consistent" because it can externally be "populated from a trusted source", any state can be considered "consistent" as long as a process can be defined that yields a truly consistent state. For example: Leaving the in-memory state aound after stop() is also consistent: it's waiting to be synchronized "from a trusted source".

                      The definition of "consistent" is either too weak to be useful or does not hold for the start() method.


                      • 8. Re: RC1->RC3 problems
                        manik

                         

                        "supi" wrote:


                        I disagree. When a cache stops, you should lose the ability to operate on the data through the cache interface. I've never seen a database deleting tables when you stop the db server/agent.



                        A cache is not a database. A database is, by definition, persistent storage so such behaviour is nonsensical for a db. And this is why caches delegate persistence to dbs - in JBC's case using a cache loader.

                        • 9. Re: RC1->RC3 problems
                          supi

                           

                          "manik.surtani@jboss.com" wrote:

                          A cache is not a database. A database is, by definition, persistent storage so such behaviour is nonsensical for a db. And this is why caches delegate persistence to dbs - in JBC's case using a cache loader.


                          Umm, persistence is a relative term, valid within a certain scope. A local JB cache without cache loader indeed offers persistence within its operating environment, the JVM. The environment's execution entities, threads, can put objects into the cache, die, respawn and read them back from cache. Since the cache's storage environment, the heap, persists during the cache's life (even when the cache is stopped), there is no reason why the cache's own threads should be excluded from this mechanism and can't be restarted without losing data.