3 Replies Latest reply on Nov 23, 2009 10:42 AM by brian.stansberry

    Question about lockParentForChildInsertRemove - when to use

      Hi there,

      The user guide/documentation doesn't clearly say in what scenario the configuration option lockParentForChildInsertRemove should be set to true. My assumption is jbosscache is thread safe by default. And, with mvcc (which is what we are using), reads dont acquire a lock anyway. So if I set this config value to false, what kind of "incorrectness" are we looking at? In the app that I am working on, the parent node is just a collection of similar objects, a logical grouping so to speak. It doesn't hold any state information (like info about number of nodes etc).

      We have a setup that uses jboss cache 3.1. The cache participates in transactions. Since multiple threads do reads and writes on this cache all the time, and some of the threads do some intense operations that take a long time before the transaction commits or rolls back (sometimes up to a minute or more, and our lock acquisition timeout is set to 20 seconds), we see a lot of lock acquire timeouts in other threads. I don't want to bump up the timeout just for this. I am considering turning lockParentForChildInsertRemove option to false, but I was just wondering if I am trivializing the effect of this change.

      Any input/clarifications are appreciated.

      Thanks
      P

        • 1. Re: Question about lockParentForChildInsertRemove - when to
          brian.stansberry

          Indirectly, the parent node *does* include state information like info about number of nodes. Not directly, i.e. in the node's attribute map. But indirectly, via the getChildren() and getChildrenNames() methods. If your application uses those methods and counts on transactional consistency in the results, that's when you'd set lockParentForChildInsertRemove to true.

          Personally I've never written an app where I needed to set lockParentFroChildInsertRemove to true.

          • 2. Re: Question about lockParentForChildInsertRemove - when to

            Thanks Brian. I think I kind of get the implication. However, arent getChildren or getChildrenNames methods considered read operations, and if so, with mvcc, the reads wouldnt need a write lock anyway. The read calls would return something that is based on isolation level (REPEATABLE_READ) in that case. So how would that affect the application.

            By the way, the only use case for which we need getChildren is to retrieve all objects of a certain type that are cached. In that case, if we get a snapshot from before any of the current running transaction started, that is good enough. The more I think about it, I am pretty sure we don't need this in our application. But I am just trying to understand if there is something obvious that I am ignoring, like nodes getting lost or overwritten by different threads etc. For eg. just because I didnt set this option to true, if two threads insert two nodes into this parent at the same time, we would never run into a situation where one of the node is lost or overwritten by the other or something of that nature, right? I wouldn't think so, but just confirming. Now, its totally ok if the read calls at around the same time don't include this/these node because of the transaction being not committed yet.

            • 3. Re: Question about lockParentForChildInsertRemove - when to
              brian.stansberry

              Thanks for the question; I didn't personally work on the MVCC code and the discussions I'd been on didn't specifically discuss handling of children. So, had to chat with Jason Greene and look into the code, both of which are always good. :-)

              As you said getChildren(Names) is a read operation, so with MVCC it won't block due to a concurrent write.

              If you need to avoid phantom reads with getChildren(Names), i.e. do two reads in the same tx and not have children appear/disappear, you need to use lockParentForChildInsertRemove. REPEATABLE_READ is implemented by making a copy of the node before writing and storing it in a context object associated with the transaction, and then only inserting that copy into the main tree on tx commit. But the addition/removal of a child is only considered to be a "write" if lockParentForChildInsertRemove=true. If lockParentForChildInsertRemove=false, no copy of the parent is made, so the inserts/removals become visible to other threads as soon as they commit.

              This behavior is consistent with the definition of REPEATABLE_READ in the java.sql.Connection javadocs, which says phantom reads can occur with R_R. Database notions never map exactly to a tree structure, but our interpretations have always treated new child nodes as being analogous to new db records returned by a query.

              If you do set lockParentForChildInsertRemove=true, concurrent insertions/removals won't occur, but only one will proceed at a time; any others will block until the first completes.