Package org.hornetq.core.paging.impl

Source Code of org.hornetq.core.paging.impl.PageTransactionInfoImpl$UpdatePageTXOperation

/*
* Copyright 2009 Red Hat, Inc.
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*    http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.  See the License for the specific language governing
* permissions and limitations under the License.
*/

package org.hornetq.core.paging.impl;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

import org.hornetq.api.core.HornetQBuffer;
import org.hornetq.api.core.Pair;
import org.hornetq.core.journal.IOAsyncTask;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.paging.PageTransactionInfo;
import org.hornetq.core.paging.PagingManager;
import org.hornetq.core.paging.cursor.PagePosition;
import org.hornetq.core.paging.cursor.PageSubscription;
import org.hornetq.core.persistence.StorageManager;
import org.hornetq.core.server.MessageReference;
import org.hornetq.core.transaction.Transaction;
import org.hornetq.core.transaction.TransactionOperationAbstract;
import org.hornetq.core.transaction.TransactionPropertyIndexes;
import org.hornetq.utils.DataConstants;

/**
*
* @author <a href="mailto:clebert.suconic@jboss.com">Clebert Suconic</a>
*
*/
public class PageTransactionInfoImpl implements PageTransactionInfo
{
   // Constants -----------------------------------------------------

   private static final Logger log = Logger.getLogger(PageTransactionInfoImpl.class);

   // Attributes ----------------------------------------------------

   private long transactionID;

   private volatile long recordID = -1;

   private volatile boolean committed = false;
  
   private volatile boolean useRedelivery = false;

   private volatile boolean rolledback = false;

   private AtomicInteger numberOfMessages = new AtomicInteger(0);
  
   private AtomicInteger numberOfPersistentMessages = new AtomicInteger(0);
  
   private List<Pair<PageSubscription, PagePosition>> lateDeliveries;

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   public PageTransactionInfoImpl(final long transactionID)
   {
      this();
      this.transactionID = transactionID;
   }

   public PageTransactionInfoImpl()
   {
   }

   // Public --------------------------------------------------------

   public long getRecordID()
   {
      return recordID;
   }

   public void setRecordID(final long recordID)
   {
      this.recordID = recordID;
   }

   public long getTransactionID()
   {
      return transactionID;
   }

   public void onUpdate(final int update, final StorageManager storageManager, PagingManager pagingManager)
   {
      int sizeAfterUpdate = numberOfMessages.addAndGet(-update);
      if (sizeAfterUpdate == 0 && storageManager != null)
      {
         try
         {
            storageManager.deletePageTransactional(this.recordID);
         }
         catch (Exception e)
         {
            log.warn("Can't delete page transaction id=" + this.recordID);
         }

         pagingManager.removeTransaction(this.transactionID);
      }
   }

   public void increment(final boolean persistent)
   {
      if (persistent)
      {
         numberOfPersistentMessages.incrementAndGet();
      }
      numberOfMessages.incrementAndGet();
   }
  
   public void increment(final int durableSize, final int nonDurableSize)
   {
      numberOfPersistentMessages.addAndGet(durableSize);
      numberOfMessages.addAndGet(durableSize + nonDurableSize);
   }

   public int getNumberOfMessages()
   {
      return numberOfMessages.get();
   }

   // EncodingSupport implementation

   public synchronized void decode(final HornetQBuffer buffer)
   {
      transactionID = buffer.readLong();
      numberOfMessages.set(buffer.readInt());
      numberOfPersistentMessages.set(numberOfMessages.get());
      committed = true;
   }

   public synchronized void encode(final HornetQBuffer buffer)
   {
      buffer.writeLong(transactionID);
      buffer.writeInt(numberOfPersistentMessages.get());
   }

   public synchronized int getEncodeSize()
   {
      return DataConstants.SIZE_LONG + DataConstants.SIZE_INT;
   }

   public synchronized void commit()
   {
      if (lateDeliveries != null)
      {
         // This is to make sure deliveries that were touched before the commit arrived will be delivered
         for (Pair<PageSubscription, PagePosition> pos : lateDeliveries)
         {
            pos.a.redeliver(pos.b);
         }
         lateDeliveries.clear();
      }
      committed = true;
      lateDeliveries = null;
   }

   public void store(final StorageManager storageManager, PagingManager pagingManager, final Transaction tx) throws Exception
   {
      storageManager.storePageTransaction(tx.getID(), this);
   }

   /*
    * This is to be used after paging. We will update the PageTransactions until they get all the messages delivered. On that case we will delete the page TX
    * (non-Javadoc)
    * @see org.hornetq.core.paging.PageTransactionInfo#storeUpdate(org.hornetq.core.persistence.StorageManager, org.hornetq.core.transaction.Transaction, int)
    */
   public void storeUpdate(final StorageManager storageManager, final PagingManager pagingManager, final Transaction tx) throws Exception
   {
      internalUpdatePageManager(storageManager, pagingManager, tx, 1);
   }
  
   public void reloadUpdate(final StorageManager storageManager, final PagingManager pagingManager, final Transaction tx, final int increment) throws Exception
   {
      UpdatePageTXOperation updt = internalUpdatePageManager(storageManager, pagingManager, tx, increment);
      updt.setStored();
   }

   /**
    * @param storageManager
    * @param pagingManager
    * @param tx
    */
   protected UpdatePageTXOperation internalUpdatePageManager(final StorageManager storageManager,
                                            final PagingManager pagingManager,
                                            final Transaction tx,
                                            final int increment)
   {
      UpdatePageTXOperation pgtxUpdate = (UpdatePageTXOperation)tx.getProperty(TransactionPropertyIndexes.PAGE_TRANSACTION_UPDATE);
     
      if (pgtxUpdate == null)
      {
         pgtxUpdate = new UpdatePageTXOperation(storageManager, pagingManager);
         tx.putProperty(TransactionPropertyIndexes.PAGE_TRANSACTION_UPDATE, pgtxUpdate);
         tx.addOperation(pgtxUpdate);
      }
     
      tx.setContainsPersistent();
     
      pgtxUpdate.addUpdate(this, increment);
     
      return pgtxUpdate;
   }
  
   public void storeUpdate(final StorageManager storageManager, final PagingManager pagingManager) throws Exception
   {
      storageManager.updatePageTransaction(this, 1);
      storageManager.afterCompleteOperations(new IOAsyncTask()
      {
         public void onError(int errorCode, String errorMessage)
         {
         }
        
         public void done()
         {
            PageTransactionInfoImpl.this.onUpdate(1, storageManager, pagingManager);
         }

         public List<MessageReference> getRelatedMessageReferences()
         {
            return null;
         }
      });
   }
  
  

   public boolean isCommit()
   {
      return committed;
   }
  
   public void setCommitted(final boolean committed)
   {
      this.committed = committed;
   }

   public boolean isRollback()
   {
      return rolledback;
   }

   public synchronized void rollback()
   {
      rolledback = true;
      committed = false;

      if (lateDeliveries != null)
      {
         for (Pair<PageSubscription, PagePosition> pos : lateDeliveries)
         {
            pos.a.lateDeliveryRollback(pos.b);
         }
         lateDeliveries = null;
      }
   }

   public String toString()
   {
      return "PageTransactionInfoImpl(transactionID=" + transactionID +
             ",id=" +
             recordID +
             ",numberOfMessages=" +
             numberOfMessages +
             ")";
   }

   /* (non-Javadoc)
    * @see org.hornetq.core.paging.PageTransactionInfo#deliverAfterCommit(org.hornetq.core.paging.cursor.PageCursor, org.hornetq.core.paging.cursor.PagePosition)
    */
   public synchronized boolean deliverAfterCommit(PageSubscription cursor, PagePosition cursorPos)
   {
      if (committed && useRedelivery)
      {
         cursor.addPendingDelivery(cursorPos);
         cursor.redeliver(cursorPos);
         return true;
      }
      else
      if (committed)
      {
         return false;
      }
      else
      if (rolledback)
      {
         cursor.positionIgnored(cursorPos);
         return true;
      }
      else
      {
         useRedelivery = true;
         if (lateDeliveries == null)
         {
            lateDeliveries = new LinkedList<Pair<PageSubscription, PagePosition>>();
         }
         cursor.addPendingDelivery(cursorPos);
         lateDeliveries.add(new Pair<PageSubscription, PagePosition>(cursor, cursorPos));
         return true;
      }
   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
  
  
   static class UpdatePageTXOperation extends TransactionOperationAbstract
   {
      private HashMap<PageTransactionInfo, AtomicInteger> countsToUpdate = new HashMap<PageTransactionInfo, AtomicInteger>();
     
      private boolean stored = false;
     
      private final StorageManager storageManager;
     
      private final PagingManager pagingManager;
     
      public UpdatePageTXOperation(final StorageManager storageManager, final PagingManager pagingManager)
      {
         this.storageManager = storageManager;
         this.pagingManager = pagingManager;
      }
     
      public void setStored()
      {
         stored = true;
      }
     
      public void addUpdate(final PageTransactionInfo info, final int increment)
      {
         AtomicInteger counter = countsToUpdate.get(info);
        
         if (counter == null)
         {
            counter = new AtomicInteger(0);
            countsToUpdate.put(info, counter);
         }
        
         counter.addAndGet(increment);
      }
     
      public void beforePrepare(Transaction tx) throws Exception
      {
         storeUpdates(tx);
      }
     
      public void beforeCommit(Transaction tx) throws Exception
      {
         storeUpdates(tx);
      }
     
      public void afterCommit(Transaction tx)
      {
         for (Map.Entry<PageTransactionInfo, AtomicInteger> entry : countsToUpdate.entrySet())
         {
            entry.getKey().onUpdate(entry.getValue().intValue(), storageManager, pagingManager);
         }
      }
     
      private void storeUpdates(Transaction tx) throws Exception
      {
         if (!stored)
         {
            stored = true;
            for (Map.Entry<PageTransactionInfo, AtomicInteger> entry : countsToUpdate.entrySet())
            {
               storageManager.updatePageTransaction(tx.getID(), entry.getKey(), entry.getValue().get());
            }
         }
      }
     

     
   }
}
TOP

Related Classes of org.hornetq.core.paging.impl.PageTransactionInfoImpl$UpdatePageTXOperation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.