2 Replies Latest reply on Feb 12, 2008 8:45 AM by Adrian Brock

    JBAS-5229 - Feature request - Atomic redeploy of connection

    Adrian Brock Master

      While this is sounds trivial to do, it is a lot more complicated than it sounds.

      When you redeploy the datasource it has lost track of the transaction context.

      e.g.

      // Begin Transaction here

      // Before redeploy
      Connection c1 = dataSource.getConnection();
      // Use it
      c1.close();

      // Redeploy here

      // After redeploy
      Connection c2 = dataSource.getConnection();
      // etc.

      // End Transaction here

      Normally (without the redeploy) c2 would have the same underlying connection as c1
      and would share the same jdbc transaction.

      With the redeploy, it is two different real connections and unless it is XA two different jdbc transactions.
      So for at least a local-tx-datasource the semantics are broken.

      To be really "atomic" it would have to somehow pass-off both the real connections from one pool to another
      and the connection manager state for those connections as the redeploy occurs.

      This "passing off" of connections and state may not even be valid if you are redeploying
      the datasource to change a policy decision.

      But this could be dealt with by "immediately" closing those passed off connections
      when the application finishes with them (i.e. under the old policy)
      and creating new ones with the new policy.

        • 1. Re: JBAS-5229 - Feature request - Atomic redeploy of connect
          David Smiley Newbie

          Perhaps you could suspend new transactions from being acquired until the existing transactions complete, then switch the datasource, then resume the transactions?

          And when I mentioned closing down the datasource, then obviously that will entail closing any connections pooled therein.

          ~ David

          • 2. Re: JBAS-5229 - Feature request - Atomic redeploy of connect
            Adrian Brock Master

             

            "dsmiley" wrote:
            Perhaps you could suspend new transactions from being acquired until the existing transactions complete, then switch the datasource, then resume the transactions?


            Transactions can last a long time. e.g. the default timeout is 5 minutes.
            We aren't going to suspend all database activity on all threads for 5 minutes because
            of one long running transaction using the old datasource. ;-)


            And when I mentioned closing down the datasource, then obviously that will entail closing any connections pooled therein.


            We already do that. In fact, we do better. Although the previous datasource
            is shutdown, transactions can continue with the connections until they finish with them
            and then we close the real connection when the transaction commits.
            See the flushing part here:
            http://wiki.jboss.org/wiki/Wiki.jsp?page=HowDoIChangeThePoolingParameters
            What is not allowed is to make new getConection() requests from the shutdown
            datasource.

            In general, this "feature" would be best handled by the application retrying the request
            from the beginning of the transaciton.
            If you closed the connection and want to re-aquire one in the same jdbc transaction
            after the datasource is "gone", then your transaction is broken.
            The connection manager can't really satisfy your request (unless we add
            extra code to hand-off to the new connection manager described above).

            The solution is to rollback the transaction and restart with a new transaction and a
            new connection from the new datasource.
            In general only the application knows where the transaction starts,
            although the container can know for CMT if you tell it what
            exceptions are "retryable":
            http://wiki.jboss.org/wiki/Wiki.jsp?page=RetryingTransactions

            Of course, if the datasource is not transactional then this feature would make sense.
            There is no need for a correlation between two different getConnection() requests,
            there is not global transaction.

            But then again you don't really see the problem if you don't cache the datasource between
            the two getConnection() requests.