3 Replies Latest reply on Jun 12, 2008 3:22 AM by manik

    CacheLoader does not load a node if its parent has been dele

    kblanken

      In our application, we need to remove some nodes (FQNs) from the cache before reinserting them. We do not know which nodes must be removed exactly, so we just remove their nearest FQN parent. The nodes are loaded using a CacheLoader later in the same transaction.

      For simplicity, let's say we have a cache instance called "cache" that is configured to use a custom CacheLoader that always returns "value from CacheLoader". Starting with an empty cache we call:

      cache.remove(Fqn.fromString("/a"));
      String val = (String) cache.get("/a/b/c", "key");
      assertEquals("value from CacheLoader", val);


      The result will be null instead of "value from CacheLoader".

      This is because the parent node of the new key is put into the TransactionEntry's list of cache loader modifications when remove() is called. In the CacheLoaderInterceptor.invoke() method, the list is checked before loading the node:

      if (!initNode && !wasRemovedInTx(fqn))
      {
       n = loadNode(fqn, n, entry);
      }


      Here, wasRemovedInTx returns true although the node has never been loaded before. As a result, the node is not loaded by the cache loader.

      JBC version is 1.4.1 SP9.
      Are we doing something wrong here?

      Regards,

      Kai

        • 1. Re: CacheLoader does not load a node if its parent has been
          manik

          Looking at your scenario I think this is expected behaviour.

          cache.remove() will remove the node and all it's children. When you use a cache loader, this behaviour is passed on to the cache loader too.

          So when you do cache.remove("/a") this will remove /a and all its children both in memory and in the cache loader.

          So I'm not surprised that when you then to a cache.get("/a/b/c") you get null. :)

          • 2. Re: CacheLoader does not load a node if its parent has been
            kblanken

            Hi Manik,

            thank you for your response. This indeed makes sense, though I forgot to mention that our custom CacheLoader is one-way; it does not write any values back to the store.

            Is there a way I can configure JBC so it does not try to persist the data using the CacheLoader?

            Regarding locks, is there a difference between a CacheLoader's put() into the cache and an externally called put()? I could discard the CacheLoader and load and put the values outside of the cache.

            Regards,
            Kai

            • 3. Re: CacheLoader does not load a node if its parent has been
              manik

              Yes, you can suppress the cache loader from writing by setting ignoreModifications to true in your cache loader cfg.

              And yes, in this case wasRemovedInTx() will prevent the value from being loaded from the cache loader - this is an optimisation since in MOST cache loaders this would result in a null coming back anyway, after hitting the disk. But I see what you mean in that this does impair on the *correctness* of behaviour when ignoreModifications is true. Feel free to create a JIRA for this and vote for it.

              And regarding loading externally, you could use Cache.putForExternalRead() which is built for the purpose of doing a put which is a result of a read from an external data source (as opposed to a put() which is a write to the external data source as well, such as a new item in the cache and data source).