Re: Transactional Queue

Jean Morissette <[email protected]> Sun, 05 Dec 2004 01:38:03 -0500
Newsgroups gmane.comp.java.seda.user
Message-ID <[email protected]>
Quartz wrote:
>>So, the user would just need to call 1 time commit() or, if an exception 
>>occur, 1 time abort().  But, who should create the Transaction object?
> 
> 
> I haven't used that yet. First guess, just pass the first key to an overloaded enqueue_prepare.
> If key is known by the sink, it just appends to whetever was prepared.
> Object key = queue1.enqueue_prepare(x); //or pass null key, but poor api.
> queue2.enqueue_prepare(key, x);
> queue3.enqueue_prepare(key, x);
> 
> And if you really want a txn object with .abort(), just give the key (txn) class the power to
> remove itself from its hosting weakhashmap of key-to-prepares. So, for txm object, it sure comes
> from the sink upon request (explicit, or collateral of first prepare).
> 

So, the solution could be to create a TransactionIF:

public interface TransactionIF {
   void commit();
   void abort();
   /**
    * Combine the given transaction to the current one. So, committing
    * the current transaction would also commit the given one, but
    * the not the inverse.
    * It's provided mainly for internal purpose.
    */
   void join(TransactionIF txn);
}


And modify SinkIF to remove enqueue_commit and enqueue_abort:

public interface SinkIF {
   ...
   /** Start a new transaction. */
   TransactionIF enqueue_prepare(QueueElement x);

   /** Continue a transaction */
   void enqueue_prepare(QueueElement x, TransactionIF txn);
}


And finally, an example of a SinkIF implementation:

class MyQueue implements QueueIF {
   ...

   public TransactionIF enqueue_prepare(QueueElementIF[] x) {
     // reserve space
     TxnImpl newTxn = new TxnImpl();
     txnMap.put(newTxn, x);
     return newTxn;
   }

   public void enqueue_prepare(QueueElementIF[] x, TransactionIF txn) {
     // reserve space
     TxnImpl newTxn = new TxnImpl();
     txnMap.put(newTxn, x);
     txn.join(newTxn);  // we combine the two transactions
   }

   // inner class
   class TxnImpl implements TransactionIF {

     TransactionIF joinedTxn;

     public void commit() {
       MyQueue.this.do_commit(this);
       joinedTxn.commit();
     }

     public void abort() {
       MyQueue.this.do_abort(this);
       joinedTxn.abort();
     }

     // Link the given transaction
     public void join(TransactionIF txn) {
       if (joinedTxn == null)
         joinedTxn = txn;
       else
         joinedTxn.join(txn);
     }

     // Protect "dangling prepares"
     protected void finalize() throws Throwable {
       abort();
     }

   }
}


Do do like what you see?  Me, I like it :-)



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now. 
http://productguide.itmanagersjournal.com/