[jboss-cvs] JBoss Messaging SVN: r4939 - in trunk: src/main/org/jboss/messaging/core/client/impl and 9 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sat Sep 13 14:39:51 EDT 2008
Author: timfox
Date: 2008-09-13 14:39:51 -0400 (Sat, 13 Sep 2008)
New Revision: 4939
Added:
trunk/src/main/org/jboss/messaging/util/IDGenerator.java
Modified:
trunk/src/main/org/jboss/messaging/core/client/ClientBrowser.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientBrowserImpl.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerImpl.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerInternal.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerImpl.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerInternal.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionFactoryImpl.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java
trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionInternal.java
trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java
trunk/src/main/org/jboss/messaging/core/remoting/ConnectionRegistry.java
trunk/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/ConnectionRegistryImpl.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingServiceImpl.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMAcceptor.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnector.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMRegistry.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/BrowseMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionResponseMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ProducerFlowCreditMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionResponseMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReceiveMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SendMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserCloseMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserHasNextMessageMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserNextMessageMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserResetMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionConsumerCloseMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionFlowCreditMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionProducerCloseMessage.java
trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionReplicateDeliveryMessage.java
trunk/src/main/org/jboss/messaging/core/server/Delivery.java
trunk/src/main/org/jboss/messaging/core/server/MessagingServer.java
trunk/src/main/org/jboss/messaging/core/server/ServerConsumer.java
trunk/src/main/org/jboss/messaging/core/server/ServerProducer.java
trunk/src/main/org/jboss/messaging/core/server/ServerSession.java
trunk/src/main/org/jboss/messaging/core/server/impl/DeliveryImpl.java
trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java
trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java
trunk/src/main/org/jboss/messaging/core/server/impl/RoundRobinDistributionPolicy.java
trunk/src/main/org/jboss/messaging/core/server/impl/ServerBrowserImpl.java
trunk/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java
trunk/src/main/org/jboss/messaging/core/server/impl/ServerProducerImpl.java
trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java
trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java
trunk/tests/src/org/jboss/messaging/tests/integration/cluster/ReplicationTest.java
Log:
Failover
Modified: trunk/src/main/org/jboss/messaging/core/client/ClientBrowser.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/ClientBrowser.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/ClientBrowser.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -32,7 +32,7 @@
*/
public interface ClientBrowser
{
- int getID();
+ long getID();
void reset() throws MessagingException;
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientBrowserImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientBrowserImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientBrowserImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -49,7 +49,7 @@
// Attributes -----------------------------------------------------------------------------------
- private final int id;
+ private final long id;
private final ClientSessionInternal session;
@@ -62,7 +62,7 @@
// Constructors ---------------------------------------------------------------------------------
public ClientBrowserImpl(final ClientSessionInternal session,
- final int id,
+ final long id,
final Channel channel)
{
this.id = id;
@@ -74,7 +74,7 @@
// ClientBrowser implementation -----------------------------------------------------------------
- public int getID()
+ public long getID()
{
return id;
}
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -64,7 +64,7 @@
private final Channel channel;
- private final int id;
+ private final long id;
private final Executor sessionExecutor;
@@ -93,7 +93,7 @@
// ---------------------------------------------------------------------------------
public ClientConsumerImpl(final ClientSessionInternal session,
- final int id,
+ final long id,
final int clientWindowSize,
final boolean direct,
final Executor executor,
@@ -264,7 +264,7 @@
// ClientConsumerInternal implementation
// --------------------------------------------------------------
- public int getID()
+ public long getID()
{
return id;
}
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerInternal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerInternal.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientConsumerInternal.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -35,7 +35,7 @@
*/
public interface ClientConsumerInternal extends ClientConsumer
{
- int getID();
+ long getID();
void handleMessage(ClientMessage message) throws Exception;
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -57,7 +57,7 @@
private final SimpleString address;
- private final int id;
+ private final long id;
private final ClientSessionInternal session;
@@ -86,7 +86,7 @@
// Constructors ---------------------------------------------------------------------------------
public ClientProducerImpl(final ClientSessionInternal session,
- final int id,
+ final long id,
final SimpleString address,
final TokenBucketLimiter rateLimiter,
final boolean blockOnNonPersistentSend,
@@ -200,7 +200,7 @@
// ClientProducerInternal implementation --------------------------------------------------------
- public int getID()
+ public long getID()
{
return id;
}
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerInternal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerInternal.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientProducerInternal.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -33,7 +33,7 @@
*/
public interface ClientProducerInternal extends ClientProducer
{
- int getID();
+ long getID();
void receiveCredits(int credits) throws Exception;
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionFactoryImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionFactoryImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionFactoryImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -1,29 +1,30 @@
/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
+ * JBoss, Home of Professional Open Source Copyright 2005-2008, Red Hat
+ * Middleware LLC, and individual contributors by the @authors tag. See the
+ * copyright.txt in the distribution for a full listing of individual
+ * contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this software; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ */
package org.jboss.messaging.core.client.impl;
import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.EXCEPTION;
import java.util.Map;
+import java.util.Set;
import org.jboss.messaging.core.client.ClientSession;
import org.jboss.messaging.core.client.ClientSessionFactory;
@@ -42,9 +43,10 @@
import org.jboss.messaging.core.remoting.impl.wireformat.MessagingExceptionMessage;
import org.jboss.messaging.core.remoting.spi.ConnectorFactory;
import org.jboss.messaging.core.version.Version;
+import org.jboss.messaging.util.ConcurrentHashSet;
+import org.jboss.messaging.util.UUIDGenerator;
import org.jboss.messaging.util.VersionLoader;
-
/**
* @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
* @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
@@ -54,70 +56,77 @@
* @version <tt>$Revision: 3602 $</tt>
*
*/
-public class ClientSessionFactoryImpl implements ClientSessionFactory, FailureListener
+public class ClientSessionFactoryImpl implements ClientSessionFactoryInternal, FailureListener
{
- // Constants ------------------------------------------------------------------------------------
+ // Constants
+ // ------------------------------------------------------------------------------------
private static final long serialVersionUID = 2512460695662741413L;
-
+
private static final Logger log = Logger.getLogger(ClientSessionFactoryImpl.class);
-
+
public static final long DEFAULT_PING_PERIOD = 2000;
-
+
public static final long DEFAULT_CALL_TIMEOUT = 30000;
-
+
public static final int DEFAULT_CONSUMER_WINDOW_SIZE = 1024 * 1024;
-
+
public static final int DEFAULT_CONSUMER_MAX_RATE = -1;
-
+
public static final int DEFAULT_PRODUCER_WINDOW_SIZE = 1024 * 1024;
-
+
public static final int DEFAULT_PRODUCER_MAX_RATE = -1;
-
+
public static final boolean DEFAULT_BLOCK_ON_ACKNOWLEDGE = false;
-
+
public static final boolean DEFAULT_BLOCK_ON_PERSISTENT_SEND = false;
-
+
public static final boolean DEFAULT_BLOCK_ON_NON_PERSISTENT_SEND = false;
- // Attributes -----------------------------------------------------------------------------------
-
+ // Attributes
+ // -----------------------------------------------------------------------------------
+
private ConnectionRegistry connectionRegistry;
-
- //These attributes are mutable and can be updated by different threads so must be volatile
+ // These attributes are mutable and can be updated by different threads so
+ // must be volatile
+
private volatile ConnectorFactory connectorFactory;
-
+
private volatile Map<String, Object> transportParams;
-
+
private volatile ConnectorFactory backupConnectorFactory;
-
+
private volatile Map<String, Object> backupTransportParams;
-
+
private volatile long pingPeriod;
-
+
private volatile long callTimeout;
-
+
private volatile int consumerWindowSize;
-
+
private volatile int consumerMaxRate;
private volatile int producerWindowSize;
-
+
private volatile int producerMaxRate;
-
+
private volatile boolean blockOnAcknowledge;
-
+
private volatile boolean blockOnPersistentSend;
-
+
private volatile boolean blockOnNonPersistentSend;
-
+
private volatile boolean failedOver;
-
- // Static ---------------------------------------------------------------------------------------
+
+ private final Set<ClientSessionInternal> sessions = new ConcurrentHashSet<ClientSessionInternal>();
- // Constructors ---------------------------------------------------------------------------------
+ // Static
+ // ---------------------------------------------------------------------------------------
+ // Constructors
+ // ---------------------------------------------------------------------------------
+
/**
* Create a ClientSessionFactoryImpl specifying all attributes
*/
@@ -125,12 +134,14 @@
final TransportConfiguration backupConfig,
final long pingPeriod,
final long callTimeout,
- final int consumerWindowSize, final int consumerMaxRate,
- final int producerWindowSize, final int producerMaxRate,
+ final int consumerWindowSize,
+ final int consumerMaxRate,
+ final int producerWindowSize,
+ final int producerMaxRate,
final boolean blockOnAcknowledge,
final boolean blockOnNonPersistentSend,
final boolean blockOnPersistentSend)
- {
+ {
this.connectorFactory = instantiateConnectorFactory(connectorConfig.getFactoryClassName());
this.transportParams = connectorConfig.getParams();
if (backupConfig != null)
@@ -140,7 +151,7 @@
}
this.pingPeriod = pingPeriod;
this.callTimeout = callTimeout;
- this.consumerWindowSize = consumerWindowSize;
+ this.consumerWindowSize = consumerWindowSize;
this.consumerMaxRate = consumerMaxRate;
this.producerWindowSize = producerWindowSize;
this.producerMaxRate = producerMaxRate;
@@ -149,10 +160,10 @@
this.blockOnPersistentSend = blockOnPersistentSend;
this.connectionRegistry = ConnectionRegistryImpl.instance;
}
-
+
public ClientSessionFactoryImpl(final TransportConfiguration connectorConfig,
final TransportConfiguration backupConfig)
- {
+ {
this.connectorFactory = instantiateConnectorFactory(connectorConfig.getFactoryClassName());
this.transportParams = connectorConfig.getParams();
if (backupConfig != null)
@@ -168,13 +179,13 @@
producerMaxRate = DEFAULT_PRODUCER_MAX_RATE;
blockOnAcknowledge = DEFAULT_BLOCK_ON_ACKNOWLEDGE;
blockOnPersistentSend = DEFAULT_BLOCK_ON_PERSISTENT_SEND;
- blockOnNonPersistentSend = DEFAULT_BLOCK_ON_NON_PERSISTENT_SEND;
+ blockOnNonPersistentSend = DEFAULT_BLOCK_ON_NON_PERSISTENT_SEND;
this.connectionRegistry = ConnectionRegistryImpl.instance;
}
-
+
/**
* Create a ClientSessionFactoryImpl specify transport type and using defaults
- */
+ */
public ClientSessionFactoryImpl(final TransportConfiguration connectorConfig)
{
this.connectorFactory = instantiateConnectorFactory(connectorConfig.getFactoryClassName());
@@ -187,100 +198,109 @@
producerMaxRate = DEFAULT_PRODUCER_MAX_RATE;
blockOnAcknowledge = DEFAULT_BLOCK_ON_ACKNOWLEDGE;
blockOnPersistentSend = DEFAULT_BLOCK_ON_PERSISTENT_SEND;
- blockOnNonPersistentSend = DEFAULT_BLOCK_ON_NON_PERSISTENT_SEND;
+ blockOnNonPersistentSend = DEFAULT_BLOCK_ON_NON_PERSISTENT_SEND;
this.connectionRegistry = ConnectionRegistryImpl.instance;
}
-
- // ClientSessionFactory implementation ---------------------------------------------
- public ClientSession createSession(final String username, final String password, final boolean xa,
- final boolean autoCommitSends, final boolean autoCommitAcks,
- int lazyAckBatchSize, boolean cacheProducers)
- throws MessagingException
+ // ClientSessionFactory implementation
+ // ---------------------------------------------
+
+ public ClientSession createSession(final String username,
+ final String password,
+ final boolean xa,
+ final boolean autoCommitSends,
+ final boolean autoCommitAcks,
+ int lazyAckBatchSize,
+ boolean cacheProducers) throws MessagingException
{
- return createSessionInternal(username, password, xa, autoCommitSends, autoCommitAcks, lazyAckBatchSize,
+ return createSessionInternal(username,
+ password,
+ xa,
+ autoCommitSends,
+ autoCommitAcks,
+ lazyAckBatchSize,
cacheProducers);
}
-
+
public ClientSession createSession(final boolean xa,
- final boolean autoCommitSends, final boolean autoCommitAcks,
- int lazyAckBatchSize, boolean cacheProducers)
- throws MessagingException
+ final boolean autoCommitSends,
+ final boolean autoCommitAcks,
+ int lazyAckBatchSize,
+ boolean cacheProducers) throws MessagingException
{
- return createSessionInternal(null, null, xa, autoCommitSends, autoCommitAcks, lazyAckBatchSize,
- cacheProducers);
- }
-
- public int getConsumerWindowSize()
- {
- return consumerWindowSize;
- }
-
- public void setConsumerWindowSize(final int size)
+ return createSessionInternal(null, null, xa, autoCommitSends, autoCommitAcks, lazyAckBatchSize, cacheProducers);
+ }
+
+ public int getConsumerWindowSize()
{
+ return consumerWindowSize;
+ }
+
+ public void setConsumerWindowSize(final int size)
+ {
consumerWindowSize = size;
}
-
- public int getProducerWindowSize()
- {
- return producerWindowSize;
- }
-
- public void setProducerWindowSize(final int size)
+
+ public int getProducerWindowSize()
{
+ return producerWindowSize;
+ }
+
+ public void setProducerWindowSize(final int size)
+ {
producerWindowSize = size;
}
-
- public int getProducerMaxRate()
- {
- return producerMaxRate;
- }
-
- public void setProducerMaxRate(final int rate)
- {
- this.producerMaxRate = rate;
- }
-
- public int getConsumerMaxRate()
+
+ public int getProducerMaxRate()
{
+ return producerMaxRate;
+ }
+
+ public void setProducerMaxRate(final int rate)
+ {
+ this.producerMaxRate = rate;
+ }
+
+ public int getConsumerMaxRate()
+ {
return consumerMaxRate;
}
-
+
public void setConsumerMaxRate(final int rate)
{
this.consumerMaxRate = rate;
}
-
+
public boolean isBlockOnPersistentSend()
{
return blockOnPersistentSend;
}
-
+
public void setBlockOnPersistentSend(final boolean blocking)
{
blockOnPersistentSend = blocking;
}
-
+
public boolean isBlockOnNonPersistentSend()
{
return blockOnNonPersistentSend;
}
-
+
public void setBlockOnNonPersistentSend(final boolean blocking)
{
blockOnNonPersistentSend = blocking;
}
-
+
public boolean isBlockOnAcknowledge()
{
return this.blockOnAcknowledge;
}
-
+
public void setBlockOnAcknowledge(final boolean blocking)
{
blockOnAcknowledge = blocking;
}
-
+
public ConnectorFactory getConnectorFactory()
{
return connectorFactory;
@@ -300,7 +320,7 @@
{
this.transportParams = transportParams;
}
-
+
public ConnectorFactory getBackupConnectorFactory()
{
return backupConnectorFactory;
@@ -340,110 +360,161 @@
{
this.callTimeout = callTimeout;
}
-
+
public boolean isFailedOver()
{
return failedOver;
}
-
- // Public ---------------------------------------------------------------------------------------
-
+
+ // ClientSessionFactoryInternal implementation
+ // ------------------------------------------
+
+ public void removeSession(final ClientSessionInternal session)
+ {
+ sessions.remove(session);
+ }
+
+ // Public
+ // ---------------------------------------------------------------------------------------
+
public void setConnectionRegistry(final ConnectionRegistry registry)
{
this.connectionRegistry = registry;
}
-
- // Protected ------------------------------------------------------------------------------------
- // Package Private ------------------------------------------------------------------------------
+ // Protected
+ // ------------------------------------------------------------------------------------
- // Private --------------------------------------------------------------------------------------
-
+ // Package Private
+ // ------------------------------------------------------------------------------
+
+ // Private
+ // --------------------------------------------------------------------------------------
+
private void handleFailover(final MessagingException me)
{
- log.info(this + " Factory Failure has been detected, initiating failover");
+ log.info(this + " Connection failure has been detected, initiating failover");
+
if (backupConnectorFactory == null)
{
throw new IllegalStateException("Cannot fail-over if backup connector factory is null");
}
-
+
+ RemotingConnection liveConnection = connectionRegistry.getConnection(connectorFactory,
+ transportParams,
+ pingPeriod,
+ callTimeout);
+
this.connectorFactory = backupConnectorFactory;
this.transportParams = backupTransportParams;
+
+ this.backupConnectorFactory = null;
+ this.backupTransportParams = null;
+
+ RemotingConnection backupConnection = connectionRegistry.getConnection(connectorFactory,
+ transportParams,
+ pingPeriod,
+ callTimeout);
- this.backupConnectorFactory = null;
- this.backupTransportParams = null;
+ //log.info("*** Backup connection is " + System.identityHashCode(liveConnection));
+
+ for (ClientSessionInternal session : sessions)
+ {
+ session.handleFailover(backupConnection);
+ }
+
+ liveConnection.destroy();
}
-
+
private ConnectorFactory instantiateConnectorFactory(final String connectorFactoryClassName)
{
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try
{
Class<?> clazz = loader.loadClass(connectorFactoryClassName);
- return (ConnectorFactory)clazz.newInstance();
+ return (ConnectorFactory) clazz.newInstance();
}
catch (Exception e)
{
- throw new IllegalArgumentException("Error instantiating connector factory \"" + connectorFactoryClassName + "\"", e);
- }
+ throw new IllegalArgumentException("Error instantiating connector factory \"" + connectorFactoryClassName +
+ "\"", e);
+ }
}
-
- private ClientSession createSessionInternal(final String username, final String password, final boolean xa,
- final boolean autoCommitSends, final boolean autoCommitAcks,
- int lazyAckBatchSize, boolean cacheProducers)
- throws MessagingException
+
+ private ClientSession createSessionInternal(final String username,
+ final String password,
+ final boolean xa,
+ final boolean autoCommitSends,
+ final boolean autoCommitAcks,
+ int lazyAckBatchSize,
+ boolean cacheProducers) throws MessagingException
{
Version clientVersion = VersionLoader.load();
RemotingConnection remotingConnection = null;
- RemotingConnection backupConnection = null;
try
{
- remotingConnection = connectionRegistry.getConnection(connectorFactory, transportParams,
- pingPeriod, callTimeout);
-
+ remotingConnection = connectionRegistry.getConnection(connectorFactory,
+ transportParams,
+ pingPeriod,
+ callTimeout);
+
if (backupConnectorFactory != null)
{
remotingConnection.addFailureListener(this);
-
- backupConnection = connectionRegistry.getConnection(backupConnectorFactory, backupTransportParams,
- pingPeriod, callTimeout);
}
- Packet request =
- new CreateSessionMessage(clientVersion.getIncrementingVersion(),
- username, password,
- xa, autoCommitSends, autoCommitAcks);
-
+ String name = UUIDGenerator.getInstance().generateSimpleStringUUID().toString();
+
+ long sessionChannelID = remotingConnection.generateChannelID();
+
+ Packet request = new CreateSessionMessage(name,
+ sessionChannelID,
+ clientVersion.getIncrementingVersion(),
+ username,
+ password,
+ xa,
+ autoCommitSends,
+ autoCommitAcks);
+
Channel channel1 = remotingConnection.getChannel(1, false, -1);
-
+
Packet packet = channel1.sendBlocking(request);
-
+
if (packet.getType() == EXCEPTION)
{
- MessagingExceptionMessage mem = (MessagingExceptionMessage)packet;
-
+ MessagingExceptionMessage mem = (MessagingExceptionMessage) packet;
+
throw mem.getException();
}
-
- CreateSessionResponseMessage response = (CreateSessionResponseMessage)packet;
-
- long sessionID = response.getSessionID();
-
- Channel sessionChannel = remotingConnection.getChannel(sessionID, false, response.getPacketConfirmationBatchSize());
-
- ClientSessionInternal session = new ClientSessionImpl(xa, lazyAckBatchSize, cacheProducers,
- autoCommitSends, autoCommitAcks, blockOnAcknowledge,
- remotingConnection, this,
- response.getServerVersion(), sessionChannel,
- backupConnection);
-
+
+ CreateSessionResponseMessage response = (CreateSessionResponseMessage) packet;
+
+ Channel sessionChannel = remotingConnection.getChannel(sessionChannelID,
+ false,
+ response.getPacketConfirmationBatchSize());
+
+ ClientSessionInternal session = new ClientSessionImpl(this,
+ name,
+ xa,
+ lazyAckBatchSize,
+ cacheProducers,
+ autoCommitSends,
+ autoCommitAcks,
+ blockOnAcknowledge,
+ remotingConnection,
+ this,
+ response.getServerVersion(),
+ sessionChannel);
+
+ sessions.add(session);
+
ChannelHandler handler = new ClientSessionPacketHandler(session);
-
+
sessionChannel.setHandler(handler);
-
+
return session;
-
+
}
catch (Throwable t)
{
@@ -451,20 +522,21 @@
{
try
{
- connectionRegistry.returnConnection(remotingConnection.getID());
+ connectionRegistry.returnConnection(remotingConnection.getID());
}
catch (Throwable ignore)
- {
+ {
}
}
if (t instanceof MessagingException)
{
- throw (MessagingException)t;
+ throw (MessagingException) t;
}
else
{
- MessagingException me = new MessagingException(MessagingException.INTERNAL_ERROR, "Failed to start connection");
+ MessagingException me = new MessagingException(MessagingException.INTERNAL_ERROR,
+ "Failed to start connection");
me.initCause(t);
@@ -473,10 +545,9 @@
}
}
-
public void connectionFailed(final MessagingException me)
{
handleFailover(me);
}
-
+
}
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -83,6 +83,7 @@
import org.jboss.messaging.core.remoting.impl.wireformat.SessionXAStartMessage;
import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
import org.jboss.messaging.util.ExecutorFactory;
+import org.jboss.messaging.util.IDGenerator;
import org.jboss.messaging.util.JBMThreadFactory;
import org.jboss.messaging.util.OrderedExecutorFactory;
import org.jboss.messaging.util.SimpleString;
@@ -110,12 +111,15 @@
public static final int INITIAL_MESSAGE_BODY_SIZE = 1024;
- private static final ExecutorFactory executorFactory = new OrderedExecutorFactory(
- Executors.newCachedThreadPool(new JBMThreadFactory("jbm-client-session-threads")));
+ private static final ExecutorFactory executorFactory = new OrderedExecutorFactory(Executors.newCachedThreadPool(new JBMThreadFactory("jbm-client-session-threads")));
// Attributes
// -----------------------------------------------------------------------------------
+ private final ClientSessionFactoryInternal sessionFactory;
+
+ private final String name;
+
private final boolean xa;
private final int lazyAckBatchSize;
@@ -126,11 +130,11 @@
private volatile RemotingConnection remotingConnection;
- private final Map<Integer, ClientBrowser> browsers = new ConcurrentHashMap<Integer, ClientBrowser>();
+ private final Map<Long, ClientBrowser> browsers = new ConcurrentHashMap<Long, ClientBrowser>();
- private final Map<Integer, ClientProducerInternal> producers = new ConcurrentHashMap<Integer, ClientProducerInternal>();
+ private final Map<Long, ClientProducerInternal> producers = new ConcurrentHashMap<Long, ClientProducerInternal>();
- private final Map<Integer, ClientConsumerInternal> consumers = new ConcurrentHashMap<Integer, ClientConsumerInternal>();
+ private final Map<Long, ClientConsumerInternal> consumers = new ConcurrentHashMap<Long, ClientConsumerInternal>();
private final Map<SimpleString, ClientProducerInternal> producerCache;
@@ -159,39 +163,41 @@
private final boolean blockOnAcknowledge;
private final Channel channel;
-
+
private final int version;
-
+
private ConnectionRegistry connectionRegistry;
-
- private volatile int objectID;
-
+
// For testing only
private boolean forceNotSameRM;
-
- private final FailureListener failoverListener = new FailoverListener();
-
- private volatile RemotingConnection backupConnection;
-
+
+ private final IDGenerator idGenerator = new IDGenerator(0);
+
// Constructors
// ---------------------------------------------------------------------------------
-
- public ClientSessionImpl(
- final boolean xa, final int lazyAckBatchSize,
- final boolean cacheProducers, final boolean autoCommitSends,
- final boolean autoCommitAcks, final boolean blockOnAcknowledge,
- final RemotingConnection remotingConnection,
- final ClientSessionFactory connectionFactory,
- final int version,
- final Channel channel,
- final RemotingConnection backupConnection)
- throws MessagingException
+
+ public ClientSessionImpl(final ClientSessionFactoryInternal sessionFactory,
+ final String name,
+ final boolean xa,
+ final int lazyAckBatchSize,
+ final boolean cacheProducers,
+ final boolean autoCommitSends,
+ final boolean autoCommitAcks,
+ final boolean blockOnAcknowledge,
+ final RemotingConnection remotingConnection,
+ final ClientSessionFactory connectionFactory,
+ final int version,
+ final Channel channel) throws MessagingException
{
if (lazyAckBatchSize < -1 || lazyAckBatchSize == 0)
{
throw new IllegalArgumentException("Invalid lazyAckbatchSize, valid values are > 0 or -1 (infinite)");
}
+ this.sessionFactory = sessionFactory;
+
+ this.name = name;
+
this.remotingConnection = remotingConnection;
this.connectionFactory = connectionFactory;
@@ -220,45 +226,36 @@
this.blockOnAcknowledge = blockOnAcknowledge;
this.channel = channel;
-
+
this.version = version;
-
+
this.connectionRegistry = ConnectionRegistryImpl.instance;
-
- this.backupConnection = backupConnection;
-
- if (backupConnection != null)
- {
- this.remotingConnection.addFailureListener(failoverListener);
- }
}
// ClientSession implementation
// -----------------------------------------------------------------
public void createQueue(final SimpleString address,
- final SimpleString queueName, final SimpleString filterString,
- final boolean durable, final boolean temp)
- throws MessagingException
+ final SimpleString queueName,
+ final SimpleString filterString,
+ final boolean durable,
+ final boolean temp) throws MessagingException
{
checkClosed();
- SessionCreateQueueMessage request = new SessionCreateQueueMessage(
- address, queueName, filterString, durable, temp);
+ SessionCreateQueueMessage request = new SessionCreateQueueMessage(address, queueName, filterString, durable, temp);
channel.sendBlocking(request);
}
- public void deleteQueue(final SimpleString queueName)
- throws MessagingException
+ public void deleteQueue(final SimpleString queueName) throws MessagingException
{
checkClosed();
channel.sendBlocking(new SessionDeleteQueueMessage(queueName));
}
- public SessionQueueQueryResponseMessage queueQuery(
- final SimpleString queueName) throws MessagingException
+ public SessionQueueQueryResponseMessage queueQuery(final SimpleString queueName) throws MessagingException
{
checkClosed();
@@ -269,44 +266,36 @@
return response;
}
- public SessionBindingQueryResponseMessage bindingQuery(
- final SimpleString address) throws MessagingException
+ public SessionBindingQueryResponseMessage bindingQuery(final SimpleString address) throws MessagingException
{
checkClosed();
- SessionBindingQueryMessage request = new SessionBindingQueryMessage(
- address);
+ SessionBindingQueryMessage request = new SessionBindingQueryMessage(address);
SessionBindingQueryResponseMessage response = (SessionBindingQueryResponseMessage) channel.sendBlocking(request);
return response;
}
- public void addDestination(final SimpleString address,
- final boolean durable, final boolean temp)
- throws MessagingException
+ public void addDestination(final SimpleString address, final boolean durable, final boolean temp) throws MessagingException
{
checkClosed();
- SessionAddDestinationMessage request = new SessionAddDestinationMessage(
- address, durable, temp);
+ SessionAddDestinationMessage request = new SessionAddDestinationMessage(address, durable, temp);
channel.sendBlocking(request);
}
- public void removeDestination(final SimpleString address,
- final boolean durable) throws MessagingException
+ public void removeDestination(final SimpleString address, final boolean durable) throws MessagingException
{
checkClosed();
- SessionRemoveDestinationMessage request = new SessionRemoveDestinationMessage(
- address, durable);
+ SessionRemoveDestinationMessage request = new SessionRemoveDestinationMessage(address, durable);
channel.sendBlocking(request);
}
- public ClientConsumer createConsumer(final SimpleString queueName)
- throws MessagingException
+ public ClientConsumer createConsumer(final SimpleString queueName) throws MessagingException
{
checkClosed();
@@ -314,27 +303,32 @@
}
public ClientConsumer createConsumer(final SimpleString queueName,
- final SimpleString filterString, final boolean direct)
- throws MessagingException
+ final SimpleString filterString,
+ final boolean direct) throws MessagingException
{
checkClosed();
- return createConsumer(queueName, filterString, direct, connectionFactory
- .getConsumerWindowSize(), connectionFactory
- .getConsumerMaxRate());
+ return createConsumer(queueName,
+ filterString,
+ direct,
+ connectionFactory.getConsumerWindowSize(),
+ connectionFactory.getConsumerMaxRate());
}
public ClientConsumer createConsumer(final SimpleString queueName,
- final SimpleString filterString, final boolean direct,
- final int windowSize, final int maxRate) throws MessagingException
+ final SimpleString filterString,
+ final boolean direct,
+ final int windowSize,
+ final int maxRate) throws MessagingException
{
checkClosed();
- SessionCreateConsumerMessage request = new SessionCreateConsumerMessage(
- queueName, filterString, windowSize, maxRate);
+ SessionCreateConsumerMessage request = new SessionCreateConsumerMessage(queueName,
+ filterString,
+ windowSize,
+ maxRate);
- SessionCreateConsumerResponseMessage response = (SessionCreateConsumerResponseMessage) channel.sendBlocking(
- request);
+ SessionCreateConsumerResponseMessage response = (SessionCreateConsumerResponseMessage) channel.sendBlocking(request);
// The actual windows size that gets used is determined by the user since
// could be overridden on the queue settings
@@ -360,16 +354,18 @@
}
else
{
- throw new IllegalArgumentException("Invalid window size "
- + actualWindowSize);
+ throw new IllegalArgumentException("Invalid window size " + actualWindowSize);
}
-
- int consumerID = generateID();
- ClientConsumerInternal consumer = new ClientConsumerImpl(
- this, consumerID,
- clientWindowSize, direct, executor, channel);
+ long consumerID = idGenerator.generateID();
+ ClientConsumerInternal consumer = new ClientConsumerImpl(this,
+ consumerID,
+ clientWindowSize,
+ direct,
+ executor,
+ channel);
+
addConsumer(consumer);
// Now we send window size credits to start the consumption
@@ -381,8 +377,7 @@
return consumer;
}
- public ClientBrowser createBrowser(final SimpleString queueName)
- throws MessagingException
+ public ClientBrowser createBrowser(final SimpleString queueName) throws MessagingException
{
return createBrowser(queueName, null);
}
@@ -395,51 +390,48 @@
channel.sendBlocking(request);
- ClientBrowser browser = new ClientBrowserImpl(this, generateID(), channel);
+ ClientBrowser browser = new ClientBrowserImpl(this, idGenerator.generateID(), channel);
addBrowser(browser);
return browser;
}
-
- public ClientProducer createProducer(final SimpleString address)
- throws MessagingException
+
+ public ClientProducer createProducer(final SimpleString address) throws MessagingException
{
checkClosed();
- return createProducer(address, connectionFactory
- .getProducerWindowSize(), connectionFactory
- .getProducerMaxRate());
+ return createProducer(address, connectionFactory.getProducerWindowSize(), connectionFactory.getProducerMaxRate());
}
- public ClientProducer createRateLimitedProducer(SimpleString address,
- int rate) throws MessagingException
+ public ClientProducer createRateLimitedProducer(SimpleString address, int rate) throws MessagingException
{
checkClosed();
return createProducer(address, -1, rate);
}
- public ClientProducer createProducerWithWindowSize(SimpleString address,
- int windowSize) throws MessagingException
+ public ClientProducer createProducerWithWindowSize(SimpleString address, int windowSize) throws MessagingException
{
checkClosed();
return createProducer(address, windowSize, -1);
}
- private ClientProducer createProducer(final SimpleString address,
- final int windowSize, final int maxRate) throws MessagingException
+ private ClientProducer createProducer(final SimpleString address, final int windowSize, final int maxRate) throws MessagingException
{
- return createProducer(address, windowSize, maxRate, connectionFactory
- .isBlockOnNonPersistentSend(), connectionFactory
- .isBlockOnPersistentSend());
+ return createProducer(address,
+ windowSize,
+ maxRate,
+ connectionFactory.isBlockOnNonPersistentSend(),
+ connectionFactory.isBlockOnPersistentSend());
}
public ClientProducer createProducer(final SimpleString address,
- final int windowSize, final int maxRate,
- final boolean blockOnNonPersistentSend,
- final boolean blockOnPersistentSend) throws MessagingException
+ final int windowSize,
+ final int maxRate,
+ final boolean blockOnNonPersistentSend,
+ final boolean blockOnPersistentSend) throws MessagingException
{
checkClosed();
@@ -452,24 +444,26 @@
if (producer == null)
{
- SessionCreateProducerMessage request = new SessionCreateProducerMessage(
- address, windowSize, maxRate);
+ SessionCreateProducerMessage request = new SessionCreateProducerMessage(address, windowSize, maxRate);
- SessionCreateProducerResponseMessage response = (SessionCreateProducerResponseMessage) channel.sendBlocking(
- request);
+ SessionCreateProducerResponseMessage response = (SessionCreateProducerResponseMessage) channel.sendBlocking(request);
// maxRate and windowSize can be overridden by the server
// If the producer is not auto-commit sends then messages are never
// sent blocking - there is no point
// since commit, prepare or rollback will flush any messages sent.
-
- producer = new ClientProducerImpl(this, generateID(), address, response
- .getMaxRate() == -1 ? null : new TokenBucketLimiterImpl(
- response.getMaxRate(), false), autoCommitSends
- && blockOnNonPersistentSend, autoCommitSends
- && blockOnPersistentSend, response.getInitialCredits(),
- channel);
+
+ producer = new ClientProducerImpl(this,
+ idGenerator.generateID(),
+ address,
+ response.getMaxRate() == -1 ? null
+ : new TokenBucketLimiterImpl(response.getMaxRate(),
+ false),
+ autoCommitSends && blockOnNonPersistentSend,
+ autoCommitSends && blockOnPersistentSend,
+ response.getInitialCredits(),
+ channel);
}
addProducer(producer);
@@ -498,8 +492,9 @@
{
checkClosed();
- // We tell each consumer to clear it's buffers and ignore any repeated deliveries
-
+ // We tell each consumer to clear it's buffers and ignore any repeated
+ // deliveries
+
if (autoCommitAcks)
{
lastCommittedID = lastID;
@@ -575,14 +570,12 @@
doCleanup();
}
}
-
- public ClientMessage createClientMessage(byte type, boolean durable,
- long expiration, long timestamp, byte priority)
+
+ public ClientMessage createClientMessage(byte type, boolean durable, long expiration, long timestamp, byte priority)
{
MessagingBuffer body = remotingConnection.createBuffer(INITIAL_MESSAGE_BODY_SIZE);
- return new ClientMessageImpl(type, durable, expiration, timestamp,
- priority, body);
+ return new ClientMessageImpl(type, durable, expiration, timestamp, priority, body);
}
public ClientMessage createClientMessage(byte type, boolean durable)
@@ -662,7 +655,7 @@
{
return version;
}
-
+
// ClientSessionInternal implementation
// ------------------------------------------------------------
@@ -738,7 +731,10 @@
public synchronized void cleanUp() throws Exception
{
- if (closed) { return; }
+ if (closed)
+ {
+ return;
+ }
try
{
@@ -749,48 +745,75 @@
doCleanup();
}
}
-
- public void handleReceiveMessage(final int consumerID, final ClientMessage message) throws Exception
+
+ public void handleReceiveMessage(final long consumerID, final ClientMessage message) throws Exception
{
ClientConsumerInternal consumer = consumers.get(consumerID);
-
+
if (consumer == null)
{
throw new IllegalArgumentException("Cannot find consumer with id " + consumerID);
}
-
+
consumer.handleMessage(message);
}
- public void receiveProducerCredits(final int producerID, final int credits) throws Exception
+ public void receiveProducerCredits(final long producerID, final int credits) throws Exception
{
ClientProducerInternal producer = producers.get(producerID);
-
+
if (producer == null)
{
throw new IllegalArgumentException("Cannot find producer with id " + producerID);
}
-
- producer.receiveCredits(credits);
+
+ producer.receiveCredits(credits);
}
-
+
+ public void handleFailover(final RemotingConnection backupConnection)
+ {
+ channel.lock();
+
+ try
+ {
+ channel.transferConnection(backupConnection);
+
+ remotingConnection = backupConnection;
+
+ Packet request = new ReattachSessionMessage(name, channel.getLastReceivedCommandID());
+
+ Channel channel1 = backupConnection.getChannel(1, false, -1);
+
+ ReattachSessionResponseMessage response = (ReattachSessionResponseMessage) channel1.sendBlocking(request);
+
+ channel.replayCommands(response.getLastReceivedCommandID());
+ }
+ catch (Throwable t)
+ {
+ log.error("Failed to handle failover", t);
+ }
+ finally
+ {
+ channel.unlock();
+ }
+ }
+
// XAResource implementation
// --------------------------------------------------------------------
public void commit(final Xid xid, final boolean onePhase) throws XAException
{
checkXA();
-
+
// Note - don't need to flush acks since the previous end would have
// done this
-
- SessionXACommitMessage packet = new SessionXACommitMessage(xid,
- onePhase);
+ SessionXACommitMessage packet = new SessionXACommitMessage(xid, onePhase);
+
try
- {
+ {
SessionXAResponseMessage response = (SessionXAResponseMessage) channel.sendBlocking(packet);
-
+
if (response.isError())
{
throw new XAException(response.getResponseCode());
@@ -798,7 +821,7 @@
}
catch (MessagingException e)
{
- //This should never occur
+ // This should never occur
throw new XAException(XAException.XAER_RMERR);
}
}
@@ -870,17 +893,16 @@
public int getTransactionTimeout() throws XAException
{
checkXA();
-
+
try
{
- SessionXAGetTimeoutResponseMessage response =
- (SessionXAGetTimeoutResponseMessage)channel.sendBlocking(new PacketImpl(PacketImpl.SESS_XA_GET_TIMEOUT));
-
+ SessionXAGetTimeoutResponseMessage response = (SessionXAGetTimeoutResponseMessage) channel.sendBlocking(new PacketImpl(PacketImpl.SESS_XA_GET_TIMEOUT));
+
return response.getTimeoutSeconds();
}
catch (MessagingException e)
{
- //This should never occur
+ // This should never occur
throw new XAException(XAException.XAER_RMERR);
}
}
@@ -888,11 +910,17 @@
public boolean isSameRM(final XAResource xares) throws XAException
{
checkXA();
-
- if (!(xares instanceof ClientSessionImpl)) { return false; }
- if (forceNotSameRM) { return false; }
+ if (!(xares instanceof ClientSessionImpl))
+ {
+ return false;
+ }
+ if (forceNotSameRM)
+ {
+ return false;
+ }
+
ClientSessionImpl other = (ClientSessionImpl) xares;
return remotingConnection == other.remotingConnection;
@@ -910,7 +938,7 @@
try
{
SessionXAResponseMessage response = (SessionXAResponseMessage) channel.sendBlocking(packet);
-
+
if (response.isError())
{
throw new XAException(response.getResponseCode());
@@ -922,7 +950,7 @@
}
catch (MessagingException e)
{
- //This should never occur
+ // This should never occur
throw new XAException(XAException.XAER_RMERR);
}
}
@@ -935,18 +963,17 @@
{
try
{
- SessionXAGetInDoubtXidsResponseMessage response =
- (SessionXAGetInDoubtXidsResponseMessage) channel.sendBlocking(new PacketImpl(PacketImpl.SESS_XA_INDOUBT_XIDS));
-
+ SessionXAGetInDoubtXidsResponseMessage response = (SessionXAGetInDoubtXidsResponseMessage) channel.sendBlocking(new PacketImpl(PacketImpl.SESS_XA_INDOUBT_XIDS));
+
List<Xid> xids = response.getXids();
-
+
Xid[] xidArray = xids.toArray(new Xid[xids.size()]);
-
+
return xidArray;
}
catch (MessagingException e)
{
- //This should never occur
+ // This should never occur
throw new XAException(XAException.XAER_RMERR);
}
}
@@ -968,7 +995,7 @@
try
{
SessionXAResponseMessage response = (SessionXAResponseMessage) channel.sendBlocking(packet);
-
+
if (response.isError())
{
throw new XAException(response.getResponseCode());
@@ -976,7 +1003,7 @@
}
catch (MessagingException e)
{
- //This should never occur
+ // This should never occur
throw new XAException(XAException.XAER_RMERR);
}
}
@@ -984,17 +1011,16 @@
public boolean setTransactionTimeout(final int seconds) throws XAException
{
checkXA();
-
+
try
{
- SessionXASetTimeoutResponseMessage response =
- (SessionXASetTimeoutResponseMessage)channel.sendBlocking(new SessionXASetTimeoutMessage(seconds));
-
+ SessionXASetTimeoutResponseMessage response = (SessionXASetTimeoutResponseMessage) channel.sendBlocking(new SessionXASetTimeoutMessage(seconds));
+
return response.isOK();
}
catch (MessagingException e)
{
- //This should never occur
+ // This should never occur
throw new XAException(XAException.XAER_RMERR);
}
}
@@ -1034,8 +1060,7 @@
if (response.isError())
{
- log.error("XA operation failed " + response.getMessage() + " code:"
- + response.getResponseCode());
+ log.error("XA operation failed " + response.getMessage() + " code:" + response.getResponseCode());
throw new XAException(response.getResponseCode());
}
}
@@ -1059,62 +1084,21 @@
{
this.connectionRegistry = registry;
}
-
+
public RemotingConnection getConnection()
{
return remotingConnection;
}
-
+
// Protected
// ------------------------------------------------------------------------------------
-
+
// Package Private
// ------------------------------------------------------------------------------
// Private
// --------------------------------------------------------------------------------------
-
- private void handleFailover(final MessagingException me)
- {
- log.info("Session Failure has been detected, initiating failover");
-
- channel.lock();
-
- try
- {
- Packet request = new ReattachSessionMessage(channel.getID(), channel.getLastReceivedCommandID());
-
- //This is necessary for invm since the replicating connection will be the same connection
- //as the original replicating connection since the key is the same in the registry, and that connection
- //won't have any resend buffer etc
- backupConnection.setBackup(false);
-
- Channel channel1 = backupConnection.getChannel(1, false, -1);
-
- ReattachSessionResponseMessage response = (ReattachSessionResponseMessage)channel1.sendBlocking(request);
-
- channel.transferConnection(backupConnection);
-
- remotingConnection.removeFailureListener(failoverListener);
-
- remotingConnection = backupConnection;
-
- remotingConnection.addFailureListener(failoverListener);
-
- backupConnection = null;
-
- channel.replayCommands(response.getLastReceivedCommandID());
- }
- catch (Throwable t)
- {
- log.error("Failed to handle failover", t);
- }
- finally
- {
- channel.unlock();
- }
- }
-
+
private void checkXA() throws XAException
{
if (!xa)
@@ -1124,8 +1108,7 @@
}
}
- private void acknowledgeInternal(final boolean block)
- throws MessagingException
+ private void acknowledgeInternal(final boolean block) throws MessagingException
{
if (acked)
{
@@ -1210,31 +1193,15 @@
}
channel.close();
-
+
connectionRegistry.returnConnection(remotingConnection.getID());
-
- if (backupConnection != null)
- {
- remotingConnection.removeFailureListener(failoverListener);
- }
+ sessionFactory.removeSession(this);
+
closed = true;
}
-
- private int generateID()
- {
- return objectID++;
- }
// Inner Classes
// --------------------------------------------------------------------------------
-
- private class FailoverListener implements FailureListener
- {
- public void connectionFailed(final MessagingException me)
- {
- handleFailover(me);
- }
- }
}
Modified: trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionInternal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionInternal.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/client/impl/ClientSessionInternal.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -29,6 +29,7 @@
import org.jboss.messaging.core.client.ClientMessage;
import org.jboss.messaging.core.client.ClientSession;
import org.jboss.messaging.core.exception.MessagingException;
+import org.jboss.messaging.core.remoting.RemotingConnection;
import org.jboss.messaging.util.SimpleString;
/**
@@ -64,7 +65,9 @@
void cleanUp() throws Exception;
- void receiveProducerCredits(int producerID, int credits) throws Exception;
+ void receiveProducerCredits(long producerID, int credits) throws Exception;
- void handleReceiveMessage(int consumerID, ClientMessage message) throws Exception;
+ void handleReceiveMessage(long consumerID, ClientMessage message) throws Exception;
+
+ void handleFailover(final RemotingConnection backupConnection);
}
Modified: trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/journal/impl/JournalImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -1,24 +1,24 @@
/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
+ * JBoss, Home of Professional Open Source Copyright 2005-2008, Red Hat
+ * Middleware LLC, and individual contributors by the @authors tag. See the
+ * copyright.txt in the distribution for a full listing of individual
+ * contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 2.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this software; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
+ * site: http://www.fsf.org.
+ */
package org.jboss.messaging.core.journal.impl;
@@ -79,142 +79,153 @@
*/
public class JournalImpl implements TestableJournal
{
-
+
// Constants -----------------------------------------------------
private static final int STATE_STOPPED = 0;
-
+
private static final int STATE_STARTED = 1;
-
+
private static final int STATE_LOADED = 2;
-
+
// Static --------------------------------------------------------
-
+
private static final Logger log = Logger.getLogger(JournalImpl.class);
-
+
private static final boolean trace = log.isTraceEnabled();
-
+
// This method exists just to make debug easier.
- // I could replace log.trace by log.info temporarily while I was debugging Journal
+ // I could replace log.trace by log.info temporarily while I was debugging
+ // Journal
private static final void trace(String message)
- {
+ {
log.trace(message);
}
-
+
// The sizes of primitive types
-
+
private static final int SIZE_LONG = 8;
-
+
private static final int SIZE_INT = 4;
-
+
private static final int SIZE_BYTE = 1;
-
+
public static final int MIN_FILE_SIZE = 1024;
-
+
public static final int SIZE_HEADER = 4;
- //Record markers - they must be all unique
-
+ // Record markers - they must be all unique
+
public static final int BASIC_SIZE = SIZE_BYTE + SIZE_INT + SIZE_INT;
-
- public static final int SIZE_ADD_RECORD = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_INT; // + record.length
-
+
+ public static final int SIZE_ADD_RECORD = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_INT; // +
+ // record.length
+
public static final byte ADD_RECORD = 11;
-
- public static final byte SIZE_UPDATE_RECORD = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_INT; // + record.length;
-
+
+ public static final byte SIZE_UPDATE_RECORD = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_INT; // +
+ // record.length;
+
public static final byte UPDATE_RECORD = 12;
-
- public static final int SIZE_ADD_RECORD_TX = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_LONG + SIZE_INT; // + record.length
+ public static final int SIZE_ADD_RECORD_TX = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_LONG + SIZE_INT; // +
+ // record.length
+
public static final byte ADD_RECORD_TX = 13;
-
- public static final int SIZE_UPDATE_RECORD_TX = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_LONG + SIZE_INT; // + record.length
-
+
+ public static final int SIZE_UPDATE_RECORD_TX = BASIC_SIZE + SIZE_LONG + SIZE_BYTE + SIZE_LONG + SIZE_INT; // +
+ // record.length
+
public static final byte UPDATE_RECORD_TX = 14;
-
- public static final int SIZE_DELETE_RECORD_TX = BASIC_SIZE + SIZE_LONG + SIZE_LONG + SIZE_INT; // + record.length
-
+
+ public static final int SIZE_DELETE_RECORD_TX = BASIC_SIZE + SIZE_LONG + SIZE_LONG + SIZE_INT; // +
+ // record.length
+
public static final byte DELETE_RECORD_TX = 15;
-
+
public static final int SIZE_DELETE_RECORD = BASIC_SIZE + SIZE_LONG;
-
+
public static final byte DELETE_RECORD = 16;
-
- public static final int SIZE_COMPLETE_TRANSACTION_RECORD = BASIC_SIZE + SIZE_INT + SIZE_LONG; // + NumerOfElements*SIZE_INT*2
-
+
+ public static final int SIZE_COMPLETE_TRANSACTION_RECORD = BASIC_SIZE + SIZE_INT + SIZE_LONG; // +
+ // NumerOfElements*SIZE_INT*2
+
public static final int SIZE_PREPARE_RECORD = SIZE_COMPLETE_TRANSACTION_RECORD + SIZE_INT;
-
+
public static final byte PREPARE_RECORD = 17;
-
+
public static final int SIZE_COMMIT_RECORD = SIZE_COMPLETE_TRANSACTION_RECORD;
-
+
public static final byte COMMIT_RECORD = 18;
-
+
public static final int SIZE_ROLLBACK_RECORD = BASIC_SIZE + SIZE_LONG;
-
+
public static final byte ROLLBACK_RECORD = 19;
-
- public static final byte FILL_CHARACTER = 74; // Letter 'J'
-
+
+ public static final byte FILL_CHARACTER = 74; // Letter 'J'
+
// Attributes ----------------------------------------------------
-
+
private boolean autoReclaim = true;
-
+
private final AtomicInteger nextOrderingId = new AtomicInteger(0);
-
+
// used for Asynchronous IO only (ignored on NIO).
private final int maxAIO;
-
+
private final int fileSize;
-
+
private final int minFiles;
-
+
private final boolean syncTransactional;
-
+
private final boolean syncNonTransactional;
-
+
private final SequentialFileFactory fileFactory;
-
+
public final String filePrefix;
-
+
public final String fileExtension;
-
+
private final Queue<JournalFile> dataFiles = new ConcurrentLinkedQueue<JournalFile>();
-
+
private final Queue<JournalFile> freeFiles = new ConcurrentLinkedQueue<JournalFile>();
-
+
private final BlockingQueue<JournalFile> openedFiles = new LinkedBlockingQueue<JournalFile>();
-
+
private final Map<Long, PosFiles> posFilesMap = new ConcurrentHashMap<Long, PosFiles>();
-
+
private final ConcurrentMap<Long, JournalTransaction> transactionInfos = new ConcurrentHashMap<Long, JournalTransaction>();
-
+
private final ConcurrentMap<Long, TransactionCallback> transactionCallbacks = new ConcurrentHashMap<Long, TransactionCallback>();
-
+
private ExecutorService filesExecutor = null;
-
+
private final int reuseBufferSize;
-
+
/** Object that will control buffer's callback and getting buffers from the queue */
private final ReuseBuffersController buffersControl = new ReuseBuffersController();
-
- //TODO - improve concurrency by allowing concurrent accesses if doesn't change current file
+
+ // TODO - improve concurrency by allowing concurrent accesses if doesn't
+ // change current file
private final Semaphore lock = new Semaphore(1, true);
-
- private volatile JournalFile currentFile ;
-
+
+ private volatile JournalFile currentFile;
+
private volatile int state;
-
+
private final AtomicLong transactionIDSequence = new AtomicLong(0);
-
+
private final Reclaimer reclaimer = new Reclaimer();
-
+
// Constructors --------------------------------------------------
-
- public JournalImpl(final int fileSize, final int minFiles,
- final boolean syncTransactional, final boolean syncNonTransactional,
- final SequentialFileFactory fileFactory,
- final String filePrefix, final String fileExtension,
+
+ public JournalImpl(final int fileSize,
+ final int minFiles,
+ final boolean syncTransactional,
+ final boolean syncNonTransactional,
+ final SequentialFileFactory fileFactory,
+ final String filePrefix,
+ final String fileExtension,
final int maxAIO,
final int reuseBufferSize)
{
@@ -224,7 +235,9 @@
}
if (fileSize % fileFactory.getAlignment() != 0)
{
- throw new IllegalArgumentException("Invalid journal-file-size " + fileSize + ", It should be multiple of " + fileFactory.getAlignment());
+ throw new IllegalArgumentException("Invalid journal-file-size " + fileSize +
+ ", It should be multiple of " +
+ fileFactory.getAlignment());
}
if (minFiles < 2)
{
@@ -246,55 +259,56 @@
{
throw new IllegalStateException("maxAIO should aways be a positive number");
}
-
- this.reuseBufferSize = fileFactory.calculateBlockSize(reuseBufferSize);
-
+
+ this.reuseBufferSize = fileFactory.calculateBlockSize(reuseBufferSize);
+
this.fileSize = fileSize;
-
+
this.minFiles = minFiles;
-
+
this.syncTransactional = syncTransactional;
-
+
this.syncNonTransactional = syncNonTransactional;
-
+
this.fileFactory = fileFactory;
-
+
this.filePrefix = filePrefix;
-
+
this.fileExtension = fileExtension;
-
+
this.maxAIO = maxAIO;
}
-
- // Journal implementation ----------------------------------------------------------------
-
+
+ // Journal implementation
+ // ----------------------------------------------------------------
+
public void appendAddRecord(final long id, final byte recordType, final EncodingSupport record) throws Exception
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
int recordLength = record.getEncodeSize();
-
+
int size = SIZE_ADD_RECORD + recordLength;
-
+
ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
-
- bb.putByte(ADD_RECORD);
+
+ bb.putByte(ADD_RECORD);
bb.putInt(-1); // skip ID part
bb.putLong(id);
bb.putInt(recordLength);
bb.putByte(recordType);
record.encode(bb);
- bb.putInt(size);
-
+ bb.putInt(size);
+
try
- {
+ {
lock.acquire();
JournalFile usedFile = appendRecord(bb.getBuffer(), syncNonTransactional, null);
-
+
posFilesMap.put(id, new PosFiles(usedFile));
}
finally
@@ -302,39 +316,39 @@
lock.release();
}
}
-
+
public void appendUpdateRecord(final long id, final byte recordType, final EncodingSupport record) throws Exception
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
PosFiles posFiles = posFilesMap.get(id);
-
+
if (posFiles == null)
{
throw new IllegalStateException("Cannot find add info " + id);
}
-
+
int size = SIZE_UPDATE_RECORD + record.getEncodeSize();
-
+
ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
-
- bb.putByte(UPDATE_RECORD);
+
+ bb.putByte(UPDATE_RECORD);
bb.putInt(-1); // skip ID part
- bb.putLong(id);
+ bb.putLong(id);
bb.putInt(record.getEncodeSize());
bb.putByte(recordType);
record.encode(bb);
- bb.putInt(size);
-
+ bb.putInt(size);
+
lock.acquire();
try
- {
+ {
JournalFile usedFile = appendRecord(bb.getBuffer(), syncNonTransactional, null);
-
+
posFiles.addUpdateFile(usedFile);
}
finally
@@ -342,68 +356,70 @@
lock.release();
}
}
-
+
public void appendDeleteRecord(final long id) throws Exception
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
PosFiles posFiles = posFilesMap.remove(id);
-
+
if (posFiles == null)
{
throw new IllegalStateException("Cannot find add info " + id);
}
-
+
int size = SIZE_DELETE_RECORD;
-
- ByteBuffer bb = newBuffer(size);
-
- bb.put(DELETE_RECORD);
+
+ ByteBuffer bb = newBuffer(size);
+
+ bb.put(DELETE_RECORD);
bb.putInt(-1); // skip ID part
- bb.putLong(id);
- bb.putInt(size);
-
+ bb.putLong(id);
+ bb.putInt(size);
+
lock.acquire();
-
+
try
- {
+ {
JournalFile usedFile = appendRecord(bb, syncNonTransactional, null);
-
+
posFiles.addDelete(usedFile);
}
finally
{
lock.release();
}
- }
-
+ }
+
public long getTransactionID()
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
return transactionIDSequence.getAndIncrement();
}
-
- public void appendAddRecordTransactional(final long txID, final long id, final byte recordType,
+
+ public void appendAddRecordTransactional(final long txID,
+ final long id,
+ final byte recordType,
final EncodingSupport record) throws Exception
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
int recordLength = record.getEncodeSize();
-
+
int size = SIZE_ADD_RECORD_TX + recordLength;
-
- ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
-
+
+ ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
+
bb.putByte(ADD_RECORD_TX);
bb.putInt(-1); // skip ID part
bb.putLong(txID);
@@ -411,52 +427,55 @@
bb.putInt(recordLength);
bb.putByte(recordType);
record.encode(bb);
- bb.putInt(size);
-
+ bb.putInt(size);
+
lock.acquire();
-
+
try
- {
+ {
JournalFile usedFile = appendRecord(bb.getBuffer(), false, getTransactionCallback(txID));
-
+
JournalTransaction tx = getTransactionInfo(txID);
-
- tx.addPositive(usedFile, id);
+
+ tx.addPositive(usedFile, id);
}
finally
{
lock.release();
}
}
-
- public void appendUpdateRecordTransactional(final long txID, final long id, byte recordType, final EncodingSupport record) throws Exception
+
+ public void appendUpdateRecordTransactional(final long txID,
+ final long id,
+ byte recordType,
+ final EncodingSupport record) throws Exception
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
- int size = SIZE_UPDATE_RECORD_TX + record.getEncodeSize();
-
- ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
-
- bb.putByte(UPDATE_RECORD_TX);
+
+ int size = SIZE_UPDATE_RECORD_TX + record.getEncodeSize();
+
+ ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
+
+ bb.putByte(UPDATE_RECORD_TX);
bb.putInt(-1); // skip ID part
bb.putLong(txID);
- bb.putLong(id);
+ bb.putLong(id);
bb.putInt(record.getEncodeSize());
bb.putByte(recordType);
record.encode(bb);
- bb.putInt(size);
-
+ bb.putInt(size);
+
lock.acquire();
-
+
try
- {
+ {
JournalFile usedFile = appendRecord(bb.getBuffer(), false, getTransactionCallback(txID));
-
+
JournalTransaction tx = getTransactionInfo(txID);
-
+
tx.addPositive(usedFile, id);
}
finally
@@ -471,39 +490,38 @@
{
throw new IllegalStateException("Journal must be loaded first");
}
-
- int size = SIZE_DELETE_RECORD_TX + (record != null? record.getEncodeSize():0);
-
+
+ int size = SIZE_DELETE_RECORD_TX + (record != null ? record.getEncodeSize() : 0);
+
ByteBufferWrapper bb = new ByteBufferWrapper(newBuffer(size));
-
-
- bb.putByte(DELETE_RECORD_TX);
+
+ bb.putByte(DELETE_RECORD_TX);
bb.putInt(-1); // skip ID part
- bb.putLong(txID);
+ bb.putLong(txID);
bb.putLong(id);
bb.putInt(record != null ? record.getEncodeSize() : 0);
if (record != null)
{
record.encode(bb);
}
- bb.putInt(size);
-
+ bb.putInt(size);
+
lock.acquire();
-
+
try
- {
+ {
JournalFile usedFile = appendRecord(bb.getBuffer(), false, getTransactionCallback(txID));
-
+
JournalTransaction tx = getTransactionInfo(txID);
-
- tx.addNegative(usedFile, id);
+
+ tx.addNegative(usedFile, id);
}
finally
{
lock.release();
}
- }
-
+ }
+
/**
*
* <p>If the system crashed after a prepare was called, it should store information that is required to bring the transaction
@@ -523,17 +541,17 @@
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
JournalTransaction tx = getTransactionInfo(txID);
-
+
ByteBuffer bb = writeTransaction(PREPARE_RECORD, txID, tx, transactionData);
-
+
lock.acquire();
-
+
try
- {
+ {
JournalFile usedFile = appendRecord(bb, syncTransactional, getTransactionCallback(txID));
-
+
tx.prepare(usedFile);
}
finally
@@ -564,25 +582,25 @@
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
- }
-
+ }
+
JournalTransaction tx = transactionInfos.remove(txID);
-
+
if (tx == null)
{
throw new IllegalStateException("Cannot find tx with id " + txID);
}
-
+
ByteBuffer bb = writeTransaction(COMMIT_RECORD, txID, tx, null);
-
+
lock.acquire();
-
+
try
- {
+ {
JournalFile usedFile = appendRecord(bb, syncTransactional, getTransactionCallback(txID));
-
+
transactionCallbacks.remove(txID);
-
+
tx.commit(usedFile);
}
finally
@@ -590,38 +608,38 @@
lock.release();
}
}
-
+
public void appendRollbackRecord(final long txID) throws Exception
{
if (state != STATE_LOADED)
{
throw new IllegalStateException("Journal must be loaded first");
}
-
+
JournalTransaction tx = transactionInfos.remove(txID);
-
+
if (tx == null)
{
throw new IllegalStateException("Cannot find tx with id " + txID);
}
-
+
int size = SIZE_ROLLBACK_RECORD;
-
- ByteBuffer bb = newBuffer(size);
-
- bb.put(ROLLBACK_RECORD);
+
+ ByteBuffer bb = newBuffer(size);
+
+ bb.put(ROLLBACK_RECORD);
bb.putInt(-1); // skip ID part
bb.putLong(txID);
- bb.putInt(size);
-
+ bb.putInt(size);
+
lock.acquire();
-
+
try
- {
- JournalFile usedFile = appendRecord(bb, syncTransactional, getTransactionCallback(txID));
-
+ {
+ JournalFile usedFile = appendRecord(bb, syncTransactional, getTransactionCallback(txID));
+
transactionCallbacks.remove(txID);
-
+
tx.rollback(usedFile);
}
finally
@@ -629,17 +647,17 @@
lock.release();
}
}
-
+
/**
* @see JournalImpl#load(LoadManager)
*/
public synchronized long load(final List<RecordInfo> committedRecords,
final List<PreparedTransactionInfo> preparedTransactions) throws Exception
- {
+ {
final Set<Long> recordsToDelete = new HashSet<Long>();
final List<RecordInfo> records = new ArrayList<RecordInfo>();
-
- long maxID = load (new LoadManager()
+
+ long maxID = load(new LoadManager()
{
public void addPreparedTransaction(PreparedTransactionInfo preparedTransaction)
{
@@ -659,17 +677,17 @@
public void deleteRecord(long id)
{
recordsToDelete.add(id);
- }
+ }
});
-
- for (RecordInfo record: records)
+
+ for (RecordInfo record : records)
{
if (!recordsToDelete.contains(record.id))
{
committedRecords.add(record);
}
}
-
+
return maxID;
}
@@ -709,52 +727,58 @@
*
* */
public synchronized long load(final LoadManager loadManager) throws Exception
- {
+ {
if (state != STATE_STARTED)
{
throw new IllegalStateException("Journal must be in started state");
}
-
+
Map<Long, TransactionHolder> transactions = new LinkedHashMap<Long, TransactionHolder>();
-
+
List<JournalFile> orderedFiles = orderFiles();
-
+
int lastDataPos = SIZE_HEADER;
-
+
long maxTransactionID = -1;
-
+
long maxID = -1;
-
- for (JournalFile file: orderedFiles)
- {
+
+ for (JournalFile file : orderedFiles)
+ {
file.getFile().open(1);
-
+
ByteBuffer bb = fileFactory.newBuffer(fileSize);
-
+
int bytesRead = file.getFile().read(bb);
-
+
if (bytesRead != fileSize)
{
- //FIXME - shouldn't be just ignore the file and log a warning, rather than throw ISE?
- //We don't want to leave the user with an unusable system
+ // FIXME - shouldn't be just ignore the file and log a warning,
+ // rather than throw ISE?
+ // We don't want to leave the user with an unusable system
throw new IllegalStateException("File is wrong size " + bytesRead +
- " expected " + fileSize + " : " + file.getFile().getFileName());
+ " expected " +
+ fileSize +
+ " : " +
+ file.getFile().getFileName());
}
- //First long is the ordering timestamp, we just jump its position
+ // First long is the ordering timestamp, we just jump its position
bb.position(SIZE_HEADER);
-
+
boolean hasData = false;
-
+
while (bb.hasRemaining())
{
final int pos = bb.position();
-
+
byte recordType = bb.get();
-
+
if (recordType < ADD_RECORD || recordType > ROLLBACK_RECORD)
{
- // I - We scan for any valid record on the file. If a hole happened on the middle of the file we keep looking until all the possibilities are gone
+ // I - We scan for any valid record on the file. If a hole
+ // happened on the middle of the file we keep looking until all
+ // the possibilities are gone
continue;
}
@@ -765,20 +789,22 @@
}
// III - Every record has the file-id.
- // This is what supports us from not re-filling the whole file
+ // This is what supports us from not re-filling the whole file
int readFileId = bb.getInt();
-
- // IV - This record is from a previous file-usage. The file was reused and we need to ignore this record
+
+ // IV - This record is from a previous file-usage. The file was
+ // reused and we need to ignore this record
if (readFileId != file.getOrderingID())
{
- // If a file has damaged records, we make it a dataFile, and the next reclaiming will fix it
+ // If a file has damaged records, we make it a dataFile, and the
+ // next reclaiming will fix it
hasData = true;
bb.position(pos + 1);
-
+
continue;
}
-
+
long transactionID = 0;
if (isTransaction(recordType))
@@ -787,252 +813,271 @@
{
continue;
}
-
+
transactionID = bb.getLong();
-
- maxTransactionID = Math.max(maxTransactionID, transactionID);
+
+ maxTransactionID = Math.max(maxTransactionID, transactionID);
}
long recordID = 0;
-
+
if (!isCompleteTransaction(recordType))
{
if (bb.position() + SIZE_LONG > fileSize)
{
continue;
}
-
+
recordID = bb.getLong();
-
+
maxID = Math.max(maxID, recordID);
}
-
- // We use the size of the record to validate the health of the record.
+
+ // We use the size of the record to validate the health of the
+ // record.
// (V) We verify the size of the record
-
+
// The variable record portion used on Updates and Appends
int variableSize = 0;
-
+
// Used to hold extra data on transaction prepares
int preparedTransactionExtraDataSize = 0;
-
+
byte userRecordType = 0;
-
+
byte record[] = null;
-
+
if (isContainsBody(recordType))
{
if (bb.position() + SIZE_INT > fileSize)
{
continue;
}
-
+
variableSize = bb.getInt();
-
+
if (bb.position() + variableSize > fileSize)
{
- log.warn("Record at position " + pos + " file:" + file.getFile().getFileName() + " is corrupted and it is being ignored");
+ log.warn("Record at position " + pos +
+ " file:" +
+ file.getFile().getFileName() +
+ " is corrupted and it is being ignored");
continue;
}
-
+
if (recordType != DELETE_RECORD_TX)
{
userRecordType = bb.get();
}
-
+
record = new byte[variableSize];
-
+
bb.get(record);
}
-
+
if (recordType == PREPARE_RECORD || recordType == COMMIT_RECORD)
{
if (recordType == PREPARE_RECORD)
{
- // Add the variable size required for preparedTransactions
+ // Add the variable size required for preparedTransactions
preparedTransactionExtraDataSize = bb.getInt();
- }
- //Both commit and record contain the recordSummary, and this is used to calculate the record-size on both record-types
+ }
+ // Both commit and record contain the recordSummary, and this is
+ // used to calculate the record-size on both record-types
variableSize += bb.getInt() * SIZE_INT * 2;
}
int recordSize = getRecordSize(recordType);
- // VI - this is completing V, We will validate the size at the end of the record,
- // But we avoid buffer overflows by damaged data
- if (pos + recordSize + variableSize + preparedTransactionExtraDataSize > fileSize)
+ // VI - this is completing V, We will validate the size at the end
+ // of the record,
+ // But we avoid buffer overflows by damaged data
+ if (pos + recordSize + variableSize + preparedTransactionExtraDataSize > fileSize)
{
- // Avoid a buffer overflow caused by damaged data... continue scanning for more records...
- log.warn("Record at position " + pos + " file:" + file.getFile().getFileName() + " is corrupted and it is being ignored");
- // If a file has damaged records, we make it a dataFile, and the next reclaiming will fix it
+ // Avoid a buffer overflow caused by damaged data... continue
+ // scanning for more records...
+ log.warn("Record at position " + pos +
+ " file:" +
+ file.getFile().getFileName() +
+ " is corrupted and it is being ignored");
+ // If a file has damaged records, we make it a dataFile, and the
+ // next reclaiming will fix it
hasData = true;
-
+
continue;
}
-
+
int oldPos = bb.position();
-
+
bb.position(pos + variableSize + recordSize + preparedTransactionExtraDataSize - SIZE_INT);
-
+
int checkSize = bb.getInt();
-
- // VII - The checkSize at the end has to match with the size informed at the beggining.
- // This is like testing a hash for the record. (We could replace the checkSize by some sort of calculated hash)
- if (checkSize != variableSize + recordSize + preparedTransactionExtraDataSize)
+
+ // VII - The checkSize at the end has to match with the size
+ // informed at the beggining.
+ // This is like testing a hash for the record. (We could replace the
+ // checkSize by some sort of calculated hash)
+ if (checkSize != variableSize + recordSize + preparedTransactionExtraDataSize)
{
- log.warn("Record at position " + pos + " file:" + file.getFile().getFileName() + " is corrupted and it is being ignored");
-
- // If a file has damaged records, we make it a dataFile, and the next reclaiming will fix it
+ log.warn("Record at position " + pos +
+ " file:" +
+ file.getFile().getFileName() +
+ " is corrupted and it is being ignored");
+
+ // If a file has damaged records, we make it a dataFile, and the
+ // next reclaiming will fix it
hasData = true;
-
+
bb.position(pos + SIZE_BYTE);
-
+
continue;
}
-
+
bb.position(oldPos);
-
- // At this point everything is checked. So we relax and just load the data now.
-
+
+ // At this point everything is checked. So we relax and just load
+ // the data now.
+
switch (recordType)
{
case ADD_RECORD:
- {
-
+ {
+
loadManager.addRecord(new RecordInfo(recordID, userRecordType, record, false));
-
+
posFilesMap.put(recordID, new PosFiles(file));
-
- hasData = true;
+ hasData = true;
+
break;
- }
- case UPDATE_RECORD:
+ }
+ case UPDATE_RECORD:
{
loadManager.updateRecord(new RecordInfo(recordID, userRecordType, record, true));
-
- hasData = true;
-
+
+ hasData = true;
+
file.incPosCount();
-
+
PosFiles posFiles = posFilesMap.get(recordID);
-
+
if (posFiles != null)
{
- //It's legal for this to be null. The file(s) with the may have been deleted
- //just leaving some updates in this file
-
+ // It's legal for this to be null. The file(s) with the may
+ // have been deleted
+ // just leaving some updates in this file
+
posFiles.addUpdateFile(file);
}
-
+
break;
- }
- case DELETE_RECORD:
+ }
+ case DELETE_RECORD:
{
loadManager.deleteRecord(recordID);
-
+
hasData = true;
-
+
PosFiles posFiles = posFilesMap.remove(recordID);
-
+
if (posFiles != null)
{
posFiles.addDelete(file);
- }
-
+ }
+
break;
- }
+ }
case ADD_RECORD_TX:
case UPDATE_RECORD_TX:
- {
+ {
TransactionHolder tx = transactions.get(transactionID);
-
+
if (tx == null)
{
- tx = new TransactionHolder(transactionID);
-
+ tx = new TransactionHolder(transactionID);
+
transactions.put(transactionID, tx);
}
-
- tx.recordInfos.add(new RecordInfo(recordID, userRecordType, record, recordType == UPDATE_RECORD_TX));
-
+
+ tx.recordInfos.add(new RecordInfo(recordID, userRecordType, record, recordType == UPDATE_RECORD_TX));
+
JournalTransaction tnp = transactionInfos.get(transactionID);
-
+
if (tnp == null)
{
tnp = new JournalTransaction();
-
+
transactionInfos.put(transactionID, tnp);
}
-
+
tnp.addPositive(file, recordID);
-
- hasData = true;
-
+
+ hasData = true;
+
break;
- }
+ }
case DELETE_RECORD_TX:
- {
+ {
TransactionHolder tx = transactions.get(transactionID);
-
+
if (tx == null)
{
- tx = new TransactionHolder(transactionID);
-
+ tx = new TransactionHolder(transactionID);
+
transactions.put(transactionID, tx);
}
-
- tx.recordsToDelete.add(new RecordInfo(recordID, (byte)0, record, true));
-
+
+ tx.recordsToDelete.add(new RecordInfo(recordID, (byte) 0, record, true));
+
JournalTransaction tnp = transactionInfos.get(transactionID);
-
+
if (tnp == null)
{
tnp = new JournalTransaction();
-
+
transactionInfos.put(transactionID, tnp);
}
-
+
tnp.addNegative(file, recordID);
-
- hasData = true;
-
+
+ hasData = true;
+
break;
- }
+ }
case PREPARE_RECORD:
{
TransactionHolder tx = transactions.get(transactionID);
-
+
if (tx == null)
{
// The user could choose to prepare empty transactions
- tx = new TransactionHolder(transactionID);
-
+ tx = new TransactionHolder(transactionID);
+
transactions.put(transactionID, tx);
}
byte extraData[] = new byte[preparedTransactionExtraDataSize];
-
+
bb.get(extraData);
// Pair <FileID, NumberOfElements>
Pair<Integer, Integer>[] recordedSummary = readTransactionalElementsSummary(variableSize, bb);
-
+
tx.prepared = true;
-
+
tx.extraData = extraData;
-
+
JournalTransaction journalTransaction = transactionInfos.get(transactionID);
-
+
if (journalTransaction == null)
{
journalTransaction = new JournalTransaction();
-
+
transactionInfos.put(transactionID, journalTransaction);
}
-
+
boolean healthy = checkTransactionHealth(journalTransaction, orderedFiles, recordedSummary);
-
+
if (healthy)
{
journalTransaction.prepare(file);
@@ -1042,36 +1087,41 @@
log.warn("Prepared transaction " + healthy + " wasn't considered completed, it will be ignored");
tx.invalid = true;
}
-
- hasData = true;
-
+
+ hasData = true;
+
break;
}
case COMMIT_RECORD:
{
TransactionHolder tx = transactions.remove(transactionID);
-
- // We need to read it even if transaction was not found, or the reading checks would fail
+
+ // We need to read it even if transaction was not found, or
+ // the reading checks would fail
// Pair <OrderId, NumberOfElements>
Pair<Integer, Integer>[] recordedSummary = readTransactionalElementsSummary(variableSize, bb);
- // The commit could be alone on its own journal-file and the whole transaction body was reclaimed but not the commit-record
- // So it is completely legal to not find a transaction at this point
- // If we can't find it, we assume the TX was reclaimed and we ignore this
+ // The commit could be alone on its own journal-file and the
+ // whole transaction body was reclaimed but not the
+ // commit-record
+ // So it is completely legal to not find a transaction at this
+ // point
+ // If we can't find it, we assume the TX was reclaimed and we
+ // ignore this
if (tx != null)
- {
+ {
JournalTransaction journalTransaction = transactionInfos.remove(transactionID);
-
+
if (journalTransaction == null)
{
throw new IllegalStateException("Cannot find tx " + transactionID);
}
boolean healthy = checkTransactionHealth(journalTransaction, orderedFiles, recordedSummary);
-
+
if (healthy)
{
- for (RecordInfo txRecord: tx.recordInfos)
+ for (RecordInfo txRecord : tx.recordInfos)
{
if (txRecord.isUpdate)
{
@@ -1082,88 +1132,94 @@
loadManager.addRecord(txRecord);
}
}
-
- for (RecordInfo deleteValue: tx.recordsToDelete)
+
+ for (RecordInfo deleteValue : tx.recordsToDelete)
{
loadManager.deleteRecord(deleteValue.id);
}
-
- journalTransaction.commit(file);
+
+ journalTransaction.commit(file);
}
else
{
- log.warn("Transaction " + transactionID + " is missing elements so the transaction is being ignored");
-
+ log.warn("Transaction " + transactionID +
+ " is missing elements so the transaction is being ignored");
+
journalTransaction.forget();
}
-
- hasData = true;
+
+ hasData = true;
}
-
+
break;
}
case ROLLBACK_RECORD:
- {
+ {
TransactionHolder tx = transactions.remove(transactionID);
-
- // The rollback could be alone on its own journal-file and the whole transaction body was reclaimed but the commit-record
- // So it is completely legal to not find a transaction at this point
+
+ // The rollback could be alone on its own journal-file and the
+ // whole transaction body was reclaimed but the commit-record
+ // So it is completely legal to not find a transaction at this
+ // point
if (tx != null)
- {
+ {
JournalTransaction tnp = transactionInfos.remove(transactionID);
-
+
if (tnp == null)
{
throw new IllegalStateException("Cannot find tx " + transactionID);
}
- // There is no need to validate summaries/holes on Rollbacks.. We will ignore the data anyway.
- tnp.rollback(file);
-
- hasData = true;
+ // There is no need to validate summaries/holes on
+ // Rollbacks.. We will ignore the data anyway.
+ tnp.rollback(file);
+
+ hasData = true;
}
-
+
break;
}
- default:
+ default:
{
throw new IllegalStateException("Journal " + file.getFile().getFileName() +
- " is corrupt, invalid record type " + recordType);
+ " is corrupt, invalid record type " +
+ recordType);
}
}
-
+
checkSize = bb.getInt();
-
+
// This is a sanity check about the loading code itself.
- // If this checkSize doesn't match, it means the reading method is not doing what it was supposed to do
- if (checkSize != variableSize + recordSize + preparedTransactionExtraDataSize)
+ // If this checkSize doesn't match, it means the reading method is
+ // not doing what it was supposed to do
+ if (checkSize != variableSize + recordSize + preparedTransactionExtraDataSize)
{
throw new IllegalStateException("Internal error on loading file. Position doesn't match with checkSize");
}
-
+
lastDataPos = bb.position();
}
-
- file.getFile().close();
-
+
+ file.getFile().close();
+
if (hasData)
- {
+ {
dataFiles.add(file);
}
else
- {
- //Empty dataFiles with no data
+ {
+ // Empty dataFiles with no data
freeFiles.add(file);
- }
- }
-
+ }
+ }
+
transactionIDSequence.set(maxTransactionID + 1);
-
- //Create any more files we need
-
- //FIXME - size() involves a scan
+
+ // Create any more files we need
+
+ // FIXME - size() involves a scan
int filesToCreate = minFiles - (dataFiles.size() + freeFiles.size());
-
+
if (filesToCreate > 0)
{
for (int i = 0; i < filesToCreate; i++)
@@ -1172,78 +1228,78 @@
freeFiles.add(createFile(false));
}
}
-
- //The current file is the last one
-
+
+ // The current file is the last one
+
Iterator<JournalFile> iter = dataFiles.iterator();
-
+
while (iter.hasNext())
{
currentFile = iter.next();
-
+
if (!iter.hasNext())
{
iter.remove();
}
}
-
+
if (currentFile != null)
- {
+ {
currentFile.getFile().open();
-
+
if (this.reuseBufferSize > 0)
{
currentFile.getFile().setBufferCallback(buffersControl.callback);
}
-
+
currentFile.getFile().position(currentFile.getFile().calculateBlockStart(lastDataPos));
-
+
currentFile.setOffset(currentFile.getFile().position());
}
else
{
currentFile = freeFiles.remove();
-
+
openFile(currentFile);
}
-
+
pushOpenedFile();
-
- for (TransactionHolder transaction: transactions.values())
+
+ for (TransactionHolder transaction : transactions.values())
{
if (!transaction.prepared || transaction.invalid)
{
log.warn("Uncommitted transaction with id " + transaction.transactionID + " found and discarded");
-
+
JournalTransaction transactionInfo = transactionInfos.get(transaction.transactionID);
-
+
if (transactionInfo == null)
{
throw new IllegalStateException("Cannot find tx " + transaction.transactionID);
}
-
- //Reverse the refs
+
+ // Reverse the refs
transactionInfo.forget();
-
+
// Remove the transactionInfo
transactionInfos.remove(transaction.transactionID);
}
else
{
PreparedTransactionInfo info = new PreparedTransactionInfo(transaction.transactionID, transaction.extraData);
-
+
info.records.addAll(transaction.recordInfos);
-
+
info.recordsToDelete.addAll(transaction.recordsToDelete);
-
+
loadManager.addPreparedTransaction(info);
}
}
-
+
state = STATE_LOADED;
-
+
checkAndReclaimFiles();
-
+
return maxID;
}
@@ -1251,73 +1307,80 @@
{
return this.fileFactory.getAlignment();
}
-
- // TestableJournal implementation --------------------------------------------------------------
-
+
+ // TestableJournal implementation
+ // --------------------------------------------------------------
+
public void setAutoReclaim(final boolean autoReclaim)
{
this.autoReclaim = autoReclaim;
}
-
+
public boolean isAutoReclaim()
{
return this.autoReclaim;
}
-
+
public String debug() throws Exception
{
this.checkReclaimStatus();
-
+
StringBuilder builder = new StringBuilder();
-
- for (JournalFile file: dataFiles)
+
+ for (JournalFile file : dataFiles)
{
- builder.append("DataFile:" + file + " posCounter = " + file.getPosCount() + " reclaimStatus = " + file.isCanReclaim() + "\n");
+ builder.append("DataFile:" + file +
+ " posCounter = " +
+ file.getPosCount() +
+ " reclaimStatus = " +
+ file.isCanReclaim() +
+ "\n");
if (file instanceof JournalFileImpl)
{
- builder.append(((JournalFileImpl)file).debug());
-
+ builder.append(((JournalFileImpl) file).debug());
+
}
}
-
- for (JournalFile file: freeFiles)
+
+ for (JournalFile file : freeFiles)
{
builder.append("FreeFile:" + file + "\n");
}
-
+
if (currentFile != null)
{
- builder.append("CurrentFile:" + currentFile+ " posCounter = " + currentFile.getPosCount() + "\n");
-
+ builder.append("CurrentFile:" + currentFile + " posCounter = " + currentFile.getPosCount() + "\n");
+
if (currentFile instanceof JournalFileImpl)
{
- builder.append(((JournalFileImpl)currentFile).debug());
+ builder.append(((JournalFileImpl) currentFile).debug());
}
}
else
{
builder.append("CurrentFile: No current file at this point!");
}
-
+
builder.append("#Opened Files:" + this.openedFiles.size());
-
+
return builder.toString();
}
-
+
/** Method for use on testcases.
* It will call waitComplete on every transaction, so any assertions on the file system will be correct after this */
public void debugWait() throws Exception
{
- for (TransactionCallback callback: transactionCallbacks.values())
+ for (TransactionCallback callback : transactionCallbacks.values())
{
callback.waitCompletion();
}
-
+
if (filesExecutor != null && !filesExecutor.isShutdown())
{
- // Send something to the closingExecutor, just to make sure we went until its end
+ // Send something to the closingExecutor, just to make sure we went
+ // until its end
final CountDownLatch latch = new CountDownLatch(1);
-
+
this.filesExecutor.execute(new Runnable()
{
public void run()
@@ -1325,39 +1388,40 @@
latch.countDown();
}
});
-
+
latch.await();
}
-
+
}
-
+
public void checkAndReclaimFiles() throws Exception
{
checkReclaimStatus();
-
- for (JournalFile file: dataFiles)
- {
+
+ for (JournalFile file : dataFiles)
+ {
if (file.isCanReclaim())
{
- //File can be reclaimed or deleted
-
- if (trace) trace("Reclaiming file " + file);
-
+ // File can be reclaimed or deleted
+
+ if (trace)
+ trace("Reclaiming file " + file);
+
dataFiles.remove(file);
-
- //FIXME - size() involves a scan!!!
+
+ // FIXME - size() involves a scan!!!
if (freeFiles.size() + dataFiles.size() + 1 + openedFiles.size() < minFiles)
{
- //Re-initialise it
-
+ // Re-initialise it
+
JournalFile jf = reinitializeFile(file);
-
- freeFiles.add(jf);
+
+ freeFiles.add(jf);
}
else
{
file.getFile().open(1);
-
+
file.getFile().delete();
}
}
@@ -1368,62 +1432,62 @@
{
return dataFiles.size();
}
-
+
public int getFreeFilesCount()
{
return freeFiles.size();
}
-
+
public int getOpenedFilesCount()
{
return openedFiles.size();
}
-
+
public int getIDMapSize()
{
return posFilesMap.size();
}
-
+
public int getFileSize()
{
return fileSize;
}
-
+
public int getMinFiles()
{
return minFiles;
}
-
+
public boolean isSyncTransactional()
{
return syncTransactional;
}
-
+
public boolean isSyncNonTransactional()
{
return syncNonTransactional;
}
-
+
public String getFilePrefix()
{
return filePrefix;
}
-
+
public String getFileExtension()
{
return fileExtension;
}
-
+
public int getMaxAIO()
{
return maxAIO;
}
-
+
// In some tests we need to force the journal to move to a next file
public void forceMoveNextFile() throws Exception
{
lock.acquire();
-
+
try
{
moveNextFile();
@@ -1432,120 +1496,124 @@
{
lock.release();
}
-
+
debugWait();
}
- // MessagingComponent implementation ---------------------------------------------------
-
+ // MessagingComponent implementation
+ // ---------------------------------------------------
+
public synchronized boolean isStarted()
{
return state != STATE_STOPPED;
}
-
+
public synchronized void start()
{
if (state != STATE_STOPPED)
{
throw new IllegalStateException("Journal is not stopped");
}
-
- filesExecutor = Executors.newSingleThreadExecutor();
-
+
+ filesExecutor = Executors.newSingleThreadExecutor();
+
state = STATE_STARTED;
}
-
+
public synchronized void stop() throws Exception
{
if (state == STATE_STOPPED)
{
throw new IllegalStateException("Journal is already stopped");
}
-
+
if (currentFile != null)
{
currentFile.getFile().close();
}
-
+
filesExecutor.shutdown();
-
+
if (!filesExecutor.awaitTermination(60, TimeUnit.SECONDS))
{
log.warn("Couldn't stop journal executor after 60 seconds");
}
-
- for (JournalFile file: openedFiles)
+
+ for (JournalFile file : openedFiles)
{
file.getFile().close();
}
-
+
currentFile = null;
-
+
dataFiles.clear();
-
+
freeFiles.clear();
-
+
openedFiles.clear();
-
+
state = STATE_STOPPED;
}
-
- // Public -----------------------------------------------------------------------------
-
- // Private -----------------------------------------------------------------------------
+ // Public
+ // -----------------------------------------------------------------------------
+
+ // Private
+ // -----------------------------------------------------------------------------
+
private void checkReclaimStatus() throws Exception
{
JournalFile[] files = new JournalFile[dataFiles.size()];
-
- reclaimer.scan(dataFiles.toArray(files));
+
+ reclaimer.scan(dataFiles.toArray(files));
}
-
+
// Discard the old JournalFile and set it with a new ID
private JournalFile reinitializeFile(final JournalFile file) throws Exception
{
int newOrderingID = generateOrderingID();
-
+
SequentialFile sf = file.getFile();
-
+
sf.open(1);
-
- ByteBuffer bb = fileFactory.newBuffer(SIZE_INT);
-
+
+ ByteBuffer bb = fileFactory.newBuffer(SIZE_INT);
+
bb.putInt(newOrderingID);
-
+
int bytesWritten = sf.write(bb, true);
-
+
JournalFile jf = new JournalFileImpl(sf, newOrderingID);
-
+
sf.position(bytesWritten);
-
+
jf.setOffset(bytesWritten);
-
+
sf.close();
-
+
return jf;
}
-
+
/** It will read the elements-summary back from the commit/prepare transaction
* Pair<FileID, Counter> */
- @SuppressWarnings("unchecked") // See comment on the method body
+ @SuppressWarnings("unchecked")
+ // See comment on the method body
private Pair<Integer, Integer>[] readTransactionalElementsSummary(final int variableSize, final ByteBuffer bb)
{
int numberOfFiles = variableSize / (SIZE_INT * 2);
-
- // This line aways show an annoying compilation-warning, the SupressWarning is to avoid a warning about this cast
- Pair<Integer, Integer> values[] = (Pair<Integer, Integer> [])new Pair[numberOfFiles];
-
+
+ // This line aways show an annoying compilation-warning, the
+ // SupressWarning is to avoid a warning about this cast
+ Pair<Integer, Integer> values[] = (Pair<Integer, Integer>[]) new Pair[numberOfFiles];
+
for (int i = 0; i < numberOfFiles; i++)
{
values[i] = new Pair<Integer, Integer>(bb.getInt(), bb.getInt());
}
-
+
return values;
}
-
/**
* <p> Check for holes on the transaction (a commit written but with an incomplete transaction) </p>
* <p>This method will validate if the transaction (PREPARE/COMMIT) is complete as stated on the COMMIT-RECORD.</p>
@@ -1565,31 +1633,34 @@
final Pair<Integer, Integer>[] recordedSummary)
{
boolean healthy = true;
-
+
// (I) First we get the summary of what we really have on the files now:
-
+
// FileID, NumberOfElements
Map<Integer, AtomicInteger> currentSummary = journalTransaction.getElementsSummary();
- // (II) We compare the recorded summary on the commit, against to the reality on the files
- for (Pair<Integer, Integer> ref: recordedSummary)
+ // (II) We compare the recorded summary on the commit, against to the
+ // reality on the files
+ for (Pair<Integer, Integer> ref : recordedSummary)
{
AtomicInteger counter = currentSummary.get(ref.a);
-
+
if (counter == null)
{
- // (III) One of the original files didn't show any record. This would still be okay if the file was reclaimed
+ // (III) One of the original files didn't show any record. This
+ // would still be okay if the file was reclaimed
boolean found = false;
-
- for (JournalFile lookupFile: orderedFiles)
+
+ for (JournalFile lookupFile : orderedFiles)
{
if (lookupFile.getOrderingID() == ref.a)
{
- // (IV) oops, we were expecting at least one record on this file.
- // The file still exists and no records were found.
- // That means the transaction crashed before complete,
- // so this transaction is broken and needs to be ignored.
- // This is probably a hole caused by a crash during commit.
+ // (IV) oops, we were expecting at least one record on this
+ // file.
+ // The file still exists and no records were found.
+ // That means the transaction crashed before complete,
+ // so this transaction is broken and needs to be ignored.
+ // This is probably a hole caused by a crash during commit.
found = true;
break;
}
@@ -1597,14 +1668,15 @@
if (found)
{
healthy = false;
-
+
break;
}
}
else
{
- // (V) Missing a record... Transaction was not completed as stated. we will ignore the whole transaction
- // This is probably a hole caused by a crash during commit/prepare.
+ // (V) Missing a record... Transaction was not completed as stated.
+ // we will ignore the whole transaction
+ // This is probably a hole caused by a crash during commit/prepare.
if (counter.get() != ref.b)
{
healthy = false;
@@ -1637,14 +1709,19 @@
* @return
* @throws Exception
*/
- private ByteBuffer writeTransaction(final byte recordType, final long txID, final JournalTransaction tx, EncodingSupport transactionData) throws Exception
+ private ByteBuffer writeTransaction(final byte recordType,
+ final long txID,
+ final JournalTransaction tx,
+ EncodingSupport transactionData) throws Exception
{
- int size = SIZE_COMPLETE_TRANSACTION_RECORD + tx.getElementsSummary().size() * SIZE_INT * 2 +
- (transactionData != null ? transactionData.getEncodeSize() + SIZE_INT : 0);
-
- ByteBuffer bb = newBuffer(size);
-
- bb.put(recordType);
+ int size = SIZE_COMPLETE_TRANSACTION_RECORD + tx.getElementsSummary().size() *
+ SIZE_INT *
+ 2 +
+ (transactionData != null ? transactionData.getEncodeSize() + SIZE_INT : 0);
+
+ ByteBuffer bb = newBuffer(size);
+
+ bb.put(recordType);
bb.putInt(-1); // skip ID part
bb.putLong(txID);
@@ -1652,46 +1729,47 @@
{
bb.putInt(transactionData.getEncodeSize());
}
-
+
bb.putInt(tx.getElementsSummary().size());
-
+
if (transactionData != null)
{
transactionData.encode(new ByteBufferWrapper(bb));
}
- for (Map.Entry<Integer, AtomicInteger> entry: tx.getElementsSummary().entrySet())
+ for (Map.Entry<Integer, AtomicInteger> entry : tx.getElementsSummary().entrySet())
{
bb.putInt(entry.getKey());
bb.putInt(entry.getValue().get());
}
-
- bb.putInt(size);
-
+
+ bb.putInt(size);
+
return bb;
}
private boolean isTransaction(final byte recordType)
{
- return recordType == ADD_RECORD_TX || recordType == UPDATE_RECORD_TX ||
- recordType == DELETE_RECORD_TX || isCompleteTransaction(recordType);
+ return recordType == ADD_RECORD_TX || recordType == UPDATE_RECORD_TX ||
+ recordType == DELETE_RECORD_TX ||
+ isCompleteTransaction(recordType);
}
private boolean isCompleteTransaction(final byte recordType)
{
- return recordType == COMMIT_RECORD || recordType == PREPARE_RECORD || recordType == ROLLBACK_RECORD;
+ return recordType == COMMIT_RECORD || recordType == PREPARE_RECORD || recordType == ROLLBACK_RECORD;
}
-
+
private boolean isContainsBody(final byte recordType)
{
return recordType >= ADD_RECORD && recordType <= DELETE_RECORD_TX;
}
-
+
private int getRecordSize(final byte recordType)
{
// The record size (without the variable portion)
int recordSize = 0;
- switch(recordType)
+ switch (recordType)
{
case ADD_RECORD:
recordSize = SIZE_ADD_RECORD;
@@ -1721,9 +1799,10 @@
recordSize = SIZE_ROLLBACK_RECORD;
break;
default:
- // Sanity check, this was previously tested, nothing different should be on this switch
+ // Sanity check, this was previously tested, nothing different
+ // should be on this switch
throw new IllegalStateException("Record other than expected");
-
+
}
return recordSize;
}
@@ -1731,73 +1810,74 @@
private List<JournalFile> orderFiles() throws Exception
{
List<String> fileNames = fileFactory.listFiles(fileExtension);
-
+
List<JournalFile> orderedFiles = new ArrayList<JournalFile>(fileNames.size());
-
- for (String fileName: fileNames)
+
+ for (String fileName : fileNames)
{
SequentialFile file = fileFactory.createSequentialFile(fileName, maxAIO);
-
+
file.open(1);
-
+
ByteBuffer bb = fileFactory.newBuffer(SIZE_INT);
-
+
file.read(bb);
-
+
int orderingID = bb.getInt();
-
+
if (nextOrderingId.get() < orderingID)
{
nextOrderingId.set(orderingID);
}
-
+
orderedFiles.add(new JournalFileImpl(file, orderingID));
-
+
file.close();
}
-
- //Now order them by ordering id - we can't use the file name for ordering since we can re-use dataFiles
-
+
+ // Now order them by ordering id - we can't use the file name for ordering
+ // since we can re-use dataFiles
+
class JournalFileComparator implements Comparator<JournalFile>
{
public int compare(JournalFile f1, JournalFile f2)
{
int id1 = f1.getOrderingID();
int id2 = f2.getOrderingID();
-
+
return (id1 < id2 ? -1 : (id1 == id2 ? 0 : 1));
}
}
-
+
Collections.sort(orderedFiles, new JournalFileComparator());
-
+
return orderedFiles;
}
-
+
/**
* You need to call lock.acquire before calling this method
* */
private JournalFile appendRecord(final ByteBuffer bb, final boolean sync, final TransactionCallback callback) throws Exception
- {
+ {
int size = bb.limit();
-
+
checkFile(size);
-
+
bb.position(SIZE_BYTE);
-
+
if (currentFile == null)
{
throw new IllegalStateException("Current file = null");
}
-
+
bb.putInt(currentFile.getOrderingID());
-
+
bb.rewind();
-
+
if (callback != null)
{
currentFile.getFile().write(bb, callback);
-
+
if (sync)
{
callback.waitCompletion();
@@ -1805,15 +1885,14 @@
}
else
{
- currentFile.getFile().write(bb, sync);
+ currentFile.getFile().write(bb, sync);
}
-
+
currentFile.extendOffset(size);
-
+
return currentFile;
}
-
-
+
/**
* This method will create a new file on the file system, pre-fill it with FILL_CHARACTER
* @param keepOpened
@@ -1823,85 +1902,90 @@
private JournalFile createFile(final boolean keepOpened) throws Exception
{
int orderingID = generateOrderingID();
-
+
String fileName = filePrefix + "-" + orderingID + "." + fileExtension;
-
- if (trace) { trace("Creating file " + fileName); }
-
+
+ if (trace)
+ {
+ trace("Creating file " + fileName);
+ }
+
SequentialFile sequentialFile = fileFactory.createSequentialFile(fileName, maxAIO);
-
+
sequentialFile.open();
-
+
sequentialFile.fill(0, fileSize, FILL_CHARACTER);
-
- ByteBuffer bb = fileFactory.newBuffer(SIZE_INT);
-
+
+ ByteBuffer bb = fileFactory.newBuffer(SIZE_INT);
+
bb.putInt(orderingID);
-
+
bb.rewind();
-
+
int bytesWritten = sequentialFile.write(bb, true);
-
+
JournalFile info = new JournalFileImpl(sequentialFile, orderingID);
-
+
info.extendOffset(bytesWritten);
-
+
if (!keepOpened)
{
sequentialFile.close();
}
-
+
return info;
}
-
+
private void openFile(final JournalFile file) throws Exception
{
file.getFile().open();
-
+
file.getFile().position(file.getFile().calculateBlockStart(SIZE_HEADER));
-
+
file.setOffset(file.getFile().calculateBlockStart(SIZE_HEADER));
-
+
if (this.reuseBufferSize > 0)
{
file.getFile().setBufferCallback(buffersControl.callback);
}
}
-
+
private int generateOrderingID()
{
return nextOrderingId.incrementAndGet();
}
-
- // You need to guarantee lock.acquire() over currentFile before calling this method
+
+ // You need to guarantee lock.acquire() over currentFile before calling this
+ // method
private void checkFile(final int size) throws Exception
- {
+ {
if (size % currentFile.getFile().getAlignment() != 0)
{
- throw new IllegalStateException("You can't write blocks in a size different than " + currentFile.getFile().getAlignment());
+ throw new IllegalStateException("You can't write blocks in a size different than " + currentFile.getFile()
+ .getAlignment());
}
-
- //We take into account the first timestamp long
+
+ // We take into account the first timestamp long
if (size > fileSize - currentFile.getFile().calculateBlockStart(SIZE_HEADER))
{
throw new IllegalArgumentException("Record is too large to store " + size);
}
-
+
if (currentFile == null || fileSize - currentFile.getOffset() < size)
{
moveNextFile();
-
- }
+
+ }
}
-
+
// You need to guarantee lock.acquire() before calling this method
private void moveNextFile() throws InterruptedException
{
closeFile(currentFile);
-
+
currentFile = enqueueOpenFile();
}
-
+
/**
* This method will instantly return the opened file, and schedule opening and reclaiming.
* In case there are no cached opened files, this method will block until the file was opened. (what would happen only if the system is under load).
@@ -1910,8 +1994,9 @@
* */
private JournalFile enqueueOpenFile() throws InterruptedException
{
- if (trace) trace("enqueueOpenFile with openedFiles.size=" + openedFiles.size());
-
+ if (trace)
+ trace("enqueueOpenFile with openedFiles.size=" + openedFiles.size());
+
filesExecutor.execute(new Runnable()
{
public void run()
@@ -1926,7 +2011,7 @@
}
}
});
-
+
if (autoReclaim)
{
filesExecutor.execute(new Runnable()
@@ -1935,7 +2020,7 @@
{
try
{
- checkAndReclaimFiles();
+ checkAndReclaimFiles();
}
catch (Exception e)
{
@@ -1944,21 +2029,21 @@
}
});
}
-
+
JournalFile nextFile = null;
-
+
while (nextFile == null)
{
nextFile = openedFiles.poll(60, TimeUnit.SECONDS);
if (nextFile == null)
{
- log.warn("Couldn't open a file in 60 Seconds", new Exception ("Warning: Couldn't open a file in 60 Seconds"));
+ log.warn("Couldn't open a file in 60 Seconds", new Exception("Warning: Couldn't open a file in 60 Seconds"));
}
}
-
+
return nextFile;
}
-
+
/**
*
* Open a file and place it into the openedFiles queue
@@ -1973,7 +2058,7 @@
catch (NoSuchElementException ignored)
{
}
-
+
if (nextOpenedFile == null)
{
nextOpenedFile = createFile(true);
@@ -1982,71 +2067,73 @@
{
openFile(nextOpenedFile);
}
-
+
openedFiles.offer(nextOpenedFile);
}
-
+
private void closeFile(final JournalFile file)
{
- filesExecutor.execute(new Runnable() { public void run()
+ filesExecutor.execute(new Runnable()
{
- try
+ public void run()
{
- file.getFile().close();
+ try
+ {
+ file.getFile().close();
+ }
+ catch (Exception e)
+ {
+ log.warn(e.getMessage(), e);
+ }
+ dataFiles.add(file);
}
- catch (Exception e)
- {
- log.warn(e.getMessage(), e);
- }
- dataFiles.add(file);
- }
});
}
-
+
private JournalTransaction getTransactionInfo(final long txID)
{
JournalTransaction tx = transactionInfos.get(txID);
-
+
if (tx == null)
{
tx = new JournalTransaction();
-
+
JournalTransaction trans = transactionInfos.putIfAbsent(txID, tx);
-
+
if (trans != null)
{
tx = trans;
}
}
-
+
return tx;
}
-
+
private TransactionCallback getTransactionCallback(final long transactionId) throws MessagingException
{
if (fileFactory.isSupportsCallbacks() && syncTransactional)
{
TransactionCallback callback = this.transactionCallbacks.get(transactionId);
-
+
if (callback == null)
{
callback = new TransactionCallback();
-
+
TransactionCallback callbackCheck = transactionCallbacks.putIfAbsent(transactionId, callback);
-
+
if (callbackCheck != null)
{
callback = callbackCheck;
}
}
-
+
if (callback.errorMessage != null)
{
throw new MessagingException(callback.errorCode, callback.errorMessage);
}
-
+
callback.countUp();
-
+
return callback;
}
else
@@ -2054,181 +2141,187 @@
return null;
}
}
-
+
public ByteBuffer newBuffer(final int size)
{
return buffersControl.newBuffer(size);
}
- // Inner classes ---------------------------------------------------------------------------
-
+ // Inner classes
+ // ---------------------------------------------------------------------------
+
// Just encapsulates the VariableLatch waiting for transaction completions
// Used if the SequentialFile supports Callbacks
private static class TransactionCallback implements IOCallback
- {
+ {
private final VariableLatch countLatch = new VariableLatch();
-
+
private volatile String errorMessage = null;
-
+
private volatile int errorCode = 0;
-
+
public void countUp()
{
countLatch.up();
}
-
+
public void done()
{
countLatch.down();
}
-
+
public void waitCompletion() throws InterruptedException
{
countLatch.waitCompletion();
-
+
if (errorMessage != null)
{
throw new IllegalStateException("Error on Transaction: " + errorCode + " - " + errorMessage);
}
}
-
+
public void onError(final int errorCode, final String errorMessage)
{
this.errorMessage = errorMessage;
-
+
this.errorCode = errorCode;
-
+
countLatch.down();
}
-
+
}
-
+
/** Used on the ref-count for reclaiming */
private static class PosFiles
{
private final JournalFile addFile;
-
+
private List<JournalFile> updateFiles;
-
+
PosFiles(final JournalFile addFile)
{
this.addFile = addFile;
-
+
addFile.incPosCount();
}
-
+
void addUpdateFile(final JournalFile updateFile)
{
if (updateFiles == null)
{
updateFiles = new ArrayList<JournalFile>();
}
-
+
updateFiles.add(updateFile);
-
+
updateFile.incPosCount();
}
-
+
void addDelete(final JournalFile file)
{
file.incNegCount(addFile);
-
+
if (updateFiles != null)
{
- for (JournalFile jf: updateFiles)
+ for (JournalFile jf : updateFiles)
{
file.incNegCount(jf);
}
}
}
}
-
+
/** Class that will control buffer-reuse */
- class ReuseBuffersController
+ private class ReuseBuffersController
{
private volatile long bufferReuseLastTime = System.currentTimeMillis();
-
+
/** This queue is fed by {@link JournalImpl.ReuseBuffersController.LocalBufferCallback}} which is called directly by NIO or NIO.
* On the case of the AIO this is almost called by the native layer as soon as the buffer is not being used any more
* and ready to be reused or GCed */
private final ConcurrentLinkedQueue<ByteBuffer> reuseBuffers = new ConcurrentLinkedQueue<ByteBuffer>();
-
+
final BufferCallback callback = new LocalBufferCallback();
public ByteBuffer newBuffer(final int size)
{
// if a new buffer wasn't requested in 10 seconds, we clear the queue
- // This is being done this way as we don't need another Timeout Thread just to cleanup this
+ // This is being done this way as we don't need another Timeout Thread
+ // just to cleanup this
if (reuseBufferSize > 0 && System.currentTimeMillis() - bufferReuseLastTime > 10000)
{
trace("Clearing reuse buffers queue with " + reuseBuffers.size() + " elements");
-
+
bufferReuseLastTime = System.currentTimeMillis();
-
+
reuseBuffers.clear();
}
-
- // if a buffer is bigger than the configured-size, we just create a new buffer.
+
+ // if a buffer is bigger than the configured-size, we just create a new
+ // buffer.
if (size > reuseBufferSize)
{
return fileFactory.newBuffer(size);
}
else
{
- // We need to allocate buffers following the rules of the storage being used (AIO/NIO)
+ // We need to allocate buffers following the rules of the storage
+ // being used (AIO/NIO)
int alignedSize = fileFactory.calculateBlockSize(size);
// Try getting a buffer from the queue...
ByteBuffer buffer = this.reuseBuffers.poll();
-
+
if (buffer == null)
{
// if empty create a new one.
buffer = fileFactory.newBuffer(reuseBufferSize);
-
+
buffer.limit(alignedSize);
}
else
{
- // set the limit of the buffer to the size being required
+ // set the limit of the buffer to the size being required
buffer.limit(alignedSize);
-
+
fileFactory.clearBuffer(buffer);
}
-
+
buffer.rewind();
- return buffer;
+ return buffer;
}
}
-
+
private class LocalBufferCallback implements BufferCallback
{
public void bufferDone(ByteBuffer buffer)
{
bufferReuseLastTime = System.currentTimeMillis();
-
- // If a buffer has any other than the configured size, the buffer will be just sent to GC
+
+ // If a buffer has any other than the configured size, the buffer
+ // will be just sent to GC
if (buffer.capacity() == reuseBufferSize)
{
reuseBuffers.offer(buffer);
}
- }
- }
+ }
+ }
}
-
+
private class JournalTransaction
{
private List<Pair<JournalFile, Long>> pos;
-
+
private List<Pair<JournalFile, Long>> neg;
-
+
private Set<JournalFile> transactionPos;
-
- // Map of file id to number of elements participating on the transaction in that file
+
+ // Map of file id to number of elements participating on the transaction
+ // in that file
// Used to verify completion on reload
private final Map<Integer, AtomicInteger> numberOfElementsPerFile = new HashMap<Integer, AtomicInteger>();
-
+
public Map<Integer, AtomicInteger> getElementsSummary()
{
return numberOfElementsPerFile;
@@ -2238,134 +2331,140 @@
{
getCounter(file).incrementAndGet();
- addTXPosCount(file);
-
+ addTXPosCount(file);
+
if (pos == null)
{
pos = new ArrayList<Pair<JournalFile, Long>>();
}
-
+
pos.add(new Pair<JournalFile, Long>(file, id));
}
-
+
public void addNegative(final JournalFile file, final long id)
{
getCounter(file).incrementAndGet();
- addTXPosCount(file);
-
+ addTXPosCount(file);
+
if (neg == null)
{
neg = new ArrayList<Pair<JournalFile, Long>>();
}
-
- neg.add(new Pair<JournalFile, Long>(file, id));
+
+ neg.add(new Pair<JournalFile, Long>(file, id));
}
-
+
public void commit(final JournalFile file)
- {
+ {
if (pos != null)
{
- for (Pair<JournalFile, Long> p: pos)
+ for (Pair<JournalFile, Long> p : pos)
{
PosFiles posFiles = posFilesMap.get(p.b);
-
+
if (posFiles == null)
{
posFiles = new PosFiles(p.a);
-
+
posFilesMap.put(p.b, posFiles);
}
else
- {
+ {
posFiles.addUpdateFile(p.a);
}
}
}
-
+
if (neg != null)
{
- for (Pair<JournalFile, Long> n: neg)
+ for (Pair<JournalFile, Long> n : neg)
{
PosFiles posFiles = posFilesMap.remove(n.b);
-
+
if (posFiles != null)
{
posFiles.addDelete(n.a);
}
}
}
-
- //Now add negs for the pos we added in each file in which there were transactional operations
-
- for (JournalFile jf: transactionPos)
+
+ // Now add negs for the pos we added in each file in which there were
+ // transactional operations
+
+ for (JournalFile jf : transactionPos)
{
file.incNegCount(jf);
- }
+ }
}
-
+
public void rollback(final JournalFile file)
- {
- //Now add negs for the pos we added in each file in which there were transactional operations
- //Note that we do this on rollback as we do on commit, since we need to ensure the file containing
- //the rollback record doesn't get deleted before the files with the transactional operations are deleted
- //Otherwise we may run into problems especially with XA where we are just left with a prepare when the tx
- //has actually been rolled back
-
- for (JournalFile jf: transactionPos)
+ {
+ // Now add negs for the pos we added in each file in which there were
+ // transactional operations
+ // Note that we do this on rollback as we do on commit, since we need
+ // to ensure the file containing
+ // the rollback record doesn't get deleted before the files with the
+ // transactional operations are deleted
+ // Otherwise we may run into problems especially with XA where we are
+ // just left with a prepare when the tx
+ // has actually been rolled back
+
+ for (JournalFile jf : transactionPos)
{
file.incNegCount(jf);
}
}
-
+
public void prepare(final JournalFile file)
{
- //We don't want the prepare record getting deleted before time
-
+ // We don't want the prepare record getting deleted before time
+
addTXPosCount(file);
}
-
+
public void forget()
{
- //The transaction was not committed or rolled back in the file, so we reverse any pos counts we added
-
- for (JournalFile jf: transactionPos)
+ // The transaction was not committed or rolled back in the file, so we
+ // reverse any pos counts we added
+
+ for (JournalFile jf : transactionPos)
{
jf.decPosCount();
}
}
-
+
private void addTXPosCount(final JournalFile file)
{
if (transactionPos == null)
{
transactionPos = new HashSet<JournalFile>();
}
-
+
if (!transactionPos.contains(file))
{
transactionPos.add(file);
-
- //We add a pos for the transaction itself in the file - this prevents any transactional operations
- //being deleted before a commit or rollback is written
+
+ // We add a pos for the transaction itself in the file - this
+ // prevents any transactional operations
+ // being deleted before a commit or rollback is written
file.incPosCount();
- }
+ }
}
-
+
private AtomicInteger getCounter(final JournalFile file)
{
AtomicInteger value = numberOfElementsPerFile.get(file.getOrderingID());
-
+
if (value == null)
{
value = new AtomicInteger();
- numberOfElementsPerFile.put(file.getOrderingID(), value);
+ numberOfElementsPerFile.put(file.getOrderingID(), value);
}
-
+
return value;
}
-
+
}
-
-
+
}
Modified: trunk/src/main/org/jboss/messaging/core/remoting/ConnectionRegistry.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/ConnectionRegistry.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/ConnectionRegistry.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,6 +36,9 @@
RemotingConnection getConnection(ConnectorFactory connectorFactory, Map<String, Object> params,
long pingInterval, long callTimeout);
+ RemotingConnection getConnectionNoCache(ConnectorFactory connectorFactory, Map<String, Object> params,
+ long pingInterval, long callTimeout);
+
void returnConnection(Object connectionID);
int size();
Modified: trunk/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/RemotingConnection.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -39,6 +39,8 @@
Object getID();
Channel getChannel(long channelID, boolean ordered, int packetConfirmationBatchSize);
+
+ long generateChannelID();
public void setBackup(final boolean backup);
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/ConnectionRegistryImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/ConnectionRegistryImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/ConnectionRegistryImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -112,16 +112,46 @@
return connection;
}
}
+
+ public RemotingConnection getConnectionNoCache(ConnectorFactory connectorFactory, Map<String, Object> params,
+ long pingInterval, long callTimeout)
+ {
+ DelegatingBufferHandler handler = new DelegatingBufferHandler();
+
+ NoCacheConnectionLifeCycleListener listener = new NoCacheConnectionLifeCycleListener();
+
+ Connector connector = connectorFactory.createConnector(params, handler, listener);
+
+ connector.start();
+
+ Connection tc = connector.createConnection();
+ if (tc == null)
+ {
+ throw new IllegalStateException("Failed to connect");
+ }
+
+ RemotingConnection connection =
+ new RemotingConnectionImpl(tc, callTimeout, pingInterval, null, pingExecutor, null, null, true);
+
+ handler.conn = connection;
+
+ listener.conn = connection;
+
+ connection.startPinger();
+
+ return connection;
+ }
+
public synchronized void returnConnection(final Object connectionID)
{
RegistryKey key = reverseMap.get(connectionID);
if (key == null)
{
- //This is ok and might happen if connection is returned after an error occurred on it in which
+ //This is ok and might happen if conn is returned after an error occurred on it in which
//case it will have already automatically been closed and removed
- log.warn("Connection not found when returning - probably connection has failed and been automatically removed");
+ log.warn("Connection not found when returning - probably conn has failed and been automatically removed");
return;
}
@@ -183,15 +213,12 @@
if (key != null)
{
ConnectionHolder holder = connections.remove(key);
-
-
- //If conn still exists here this means that the underlying transport connection has been closed from the server side without
- //being returned from the client side so we need to fail the connection and call it's listeners
+
+ //If conn still exists here this means that the underlying transport conn has been closed from the server side without
+ //being returned from the client side so we need to fail the conn and call it's listeners
MessagingException me = new MessagingException(MessagingException.OBJECT_CLOSED,
- "The connection has been closed.");
+ "The conn has been closed.");
holder.getConnection().fail(me);
-
- holder.getConnector().close();
}
}
@@ -201,16 +228,14 @@
if (key == null)
{
- throw new IllegalStateException("Cannot find connection with id " + connectionID);
+ throw new IllegalStateException("Cannot find conn with id " + connectionID);
}
ConnectionHolder holder = connections.remove(key);
holder.getConnection().fail(me);
-
- holder.getConnector().close();
}
-
+
// Package protected ---------------------------------------------
// Protected -----------------------------------------------------
@@ -219,6 +244,31 @@
// Inner classes -------------------------------------------------
+ private static class NoCacheConnectionLifeCycleListener implements ConnectionLifeCycleListener
+ {
+ private RemotingConnection conn;
+
+ public void connectionCreated(final Connection connection)
+ {
+ }
+
+ public void connectionDestroyed(final Object connectionID)
+ {
+ if (conn != null)
+ {
+ conn.destroy();
+ }
+ }
+
+ public void connectionException(final Object connectionID, final MessagingException me)
+ {
+ if (conn != null)
+ {
+ conn.fail(me);
+ }
+ }
+ }
+
private static class ConnectionHolder
{
private final RemotingConnection connection;
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingConnectionImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -22,6 +22,7 @@
package org.jboss.messaging.core.remoting.impl;
+import static java.util.Collections.synchronizedList;
import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.CREATESESSION;
import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.CREATESESSION_RESP;
import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.EXCEPTION;
@@ -82,8 +83,10 @@
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -159,6 +162,7 @@
import org.jboss.messaging.core.remoting.spi.MessagingBuffer;
import org.jboss.messaging.util.ExecutorFactory;
import org.jboss.messaging.util.Future;
+import org.jboss.messaging.util.IDGenerator;
import org.jboss.messaging.util.OrderedExecutorFactory;
/**
@@ -167,14 +171,12 @@
* @version <tt>$Revision$</tt> $Id: RemotingConnectionImpl.java 4633
* 2008-07-04 11:43:34Z timfox $
*/
-public class RemotingConnectionImpl extends AbstractBufferHandler implements
- RemotingConnection
+public class RemotingConnectionImpl extends AbstractBufferHandler implements RemotingConnection
{
// Constants
// ------------------------------------------------------------------------------------
- private static final Logger log = Logger
- .getLogger(RemotingConnectionImpl.class);
+ private static final Logger log = Logger.getLogger(RemotingConnectionImpl.class);
private static final float EXPIRE_FACTOR = 1.5f;
@@ -188,7 +190,7 @@
private final Map<Long, ChannelImpl> channels = new ConcurrentHashMap<Long, ChannelImpl>();
- private final Set<FailureListener> failureListeners = new HashSet<FailureListener>();
+ private final List<FailureListener> failureListeners = synchronizedList(new ArrayList<FailureListener>());
private final long blockingCallTimeout;
@@ -222,19 +224,26 @@
private boolean writePackets;
- // Constructors
- // ---------------------------------------------------------------------------------
-
private final long pingPeriod;
private final ScheduledExecutorService pingExecutor;
+ // Channels 0-9 are reserved for the system
+ // 0 is for pinging
+ // 1 is for session creation and attachment
+ private final IDGenerator idGenerator = new IDGenerator(10);
+
+ // Constructors
+ // ---------------------------------------------------------------------------------
+
public RemotingConnectionImpl(final Connection transportConnection,
- final long blockingCallTimeout, final long pingPeriod,
- final ExecutorService handlerExecutor,
- final ScheduledExecutorService pingExecutor,
- final List<Interceptor> interceptors,
- final RemotingConnection replicatingConnection, final boolean client)
+ final long blockingCallTimeout,
+ final long pingPeriod,
+ final ExecutorService handlerExecutor,
+ final ScheduledExecutorService pingExecutor,
+ final List<Interceptor> interceptors,
+ final RemotingConnection replicatingConnection,
+ final boolean client)
{
this.transportConnection = transportConnection;
@@ -243,11 +252,11 @@
if (handlerExecutor != null)
{
- this.executorFactory = new OrderedExecutorFactory(handlerExecutor);
+ executorFactory = new OrderedExecutorFactory(handlerExecutor);
}
else
{
- this.executorFactory = null;
+ executorFactory = null;
}
this.interceptors = interceptors;
@@ -256,7 +265,7 @@
this.client = client;
- this.writePackets = client || !backup;
+ writePackets = client; // Gets changed when setBackup is called
this.pingPeriod = pingPeriod;
@@ -265,7 +274,7 @@
// Channel zero is reserved for pinging
pingChannel = getChannel(0, false, -1);
- ChannelHandler ppHandler = new PingPongHandler();
+ final ChannelHandler ppHandler = new PingPongHandler();
pingChannel.setHandler(ppHandler);
}
@@ -278,8 +287,7 @@
expirePeriod = (long) (EXPIRE_FACTOR * pingPeriod);
- future = pingExecutor.scheduleWithFixedDelay(pinger, 0, pingPeriod,
- TimeUnit.MILLISECONDS);
+ future = pingExecutor.scheduleWithFixedDelay(pinger, 0, pingPeriod, TimeUnit.MILLISECONDS);
}
else
{
@@ -296,14 +304,14 @@
}
public synchronized Channel getChannel(final long channelID,
- final boolean ordered, final int packetConfirmationBatchSize)
+ final boolean ordered,
+ final int packetConfirmationBatchSize)
{
ChannelImpl channel = channels.get(channelID);
if (channel == null)
{
- channel = new ChannelImpl(this, channelID, ordered,
- packetConfirmationBatchSize);
+ channel = new ChannelImpl(this, channelID, ordered, packetConfirmationBatchSize);
channels.put(channelID, channel);
}
@@ -316,7 +324,7 @@
{
this.backup = backup;
- this.writePackets = client || !backup;
+ writePackets = client || !backup;
}
public boolean isBackup()
@@ -324,21 +332,17 @@
return backup;
}
- public synchronized void addFailureListener(final FailureListener listener)
+ public void addFailureListener(final FailureListener listener)
{
- checkDestroyed();
-
if (listener == null)
{
throw new IllegalStateException("FailureListener cannot be null");
}
- // log.info("Adding failure listener " + listener);
failureListeners.add(listener);
- // log.info("There are now " + failureListeners.size());
}
- public synchronized boolean removeFailureListener(final FailureListener listener)
+ public boolean removeFailureListener(final FailureListener listener)
{
if (listener == null)
{
@@ -350,59 +354,74 @@
public MessagingBuffer createBuffer(final int size)
{
- checkDestroyed();
-
return transportConnection.createBuffer(size);
}
- public synchronized void fail(final MessagingException me)
- {
- if (destroyed)
- {
- return;
- }
-
- log.warn(me.getMessage());
+ /*
+ * This can be called concurrently by more than one thread so needs to be locked
+ */
- destroy();
+ private final Object failLock = new Object();
- // Then call the listeners
- Set<FailureListener> listenersClone = new HashSet<FailureListener>(failureListeners);
- // log.info(" client " + client + " backup " + backup + " There are " + listenersClone.size() + " listeners");
- for (FailureListener listener: listenersClone)
+ public void fail(final MessagingException me)
+ {
+ synchronized (failLock)
{
- try
+ if (destroyed)
{
- // log.info("*** calling failed on " + listener);
- listener.connectionFailed(me);
+ return;
}
- catch (Throwable t)
+
+ log.warn(me.getMessage());
+
+ destroy();
+
+ // Then call the listeners
+ final Set<FailureListener> listenersClone = new HashSet<FailureListener>(failureListeners);
+
+ for (final FailureListener listener : listenersClone)
{
- // Failure of one listener to execute shouldn't prevent others from
- // executing
- log.error("Failed to execute failure listener", t);
+ try
+ {
+ listener.connectionFailed(me);
+ }
+ catch (final Throwable t)
+ {
+ // Failure of one listener to execute shouldn't prevent others
+ // from
+ // executing
+ log.error("Failed to execute failure listener", t);
+ }
}
}
}
- public synchronized void destroy()
+ public void destroy()
{
- if (destroyed)
+ synchronized (failLock)
{
- return;
- }
+ if (destroyed)
+ {
+ return;
+ }
- if (future != null)
- {
- future.cancel(false);
- }
+ if (future != null)
+ {
+ future.cancel(false);
+ }
- pingChannel.close();
+ pingChannel.close();
- destroyed = true;
+ destroyed = true;
- // We close the underlying transport connection
- transportConnection.close();
+ // We close the underlying transport connection
+ transportConnection.close();
+
+ if (replicatingConnection != null)
+ {
+ replicatingConnection.destroy();
+ }
+ }
}
public boolean isExpired(final long now)
@@ -410,6 +429,11 @@
return expireTime != -1 && now >= expireTime;
}
+ public long generateChannelID()
+ {
+ return idGenerator.generateID();
+ }
+
/* For testing only */
public void stopPingingAfterOne()
{
@@ -419,39 +443,39 @@
// Buffer Handler implementation
// ----------------------------------------------------
- public void bufferReceived(final Object connectionID,
- final MessagingBuffer buffer)
+ public synchronized void bufferReceived(final Object connectionID, final MessagingBuffer buffer)
{
- if (destroyed)
- {
- // Ignore packets that might come in after connection is destroyed
- return;
- }
-
+ // log.info("** buffer received, client " + client + " backup " + backup);
final Packet packet = decode(buffer);
- long channelID = packet.getChannelID();
+ final long channelID = packet.getChannelID();
- ChannelImpl channel = channels.get(channelID);
+ final ChannelImpl channel = channels.get(channelID);
if (channel == null)
{
- if (packet.getType() == PacketImpl.SESS_PACKETS_CONFIRMED)
- {
- /*
- Packets confirmed can arrive after channel has been closed, e.g.
- Sending session.close with packet confirmation batch size = 1
- Session close gets replicated to backup, session closed on backup, and null response written back to client
- null response arrives on client and packet confirmation sent to backup
- null response arrives on backup but session is already closed
- */
- return;
- }
- else
- {
- throw new IllegalArgumentException("Cannot handle packet " + packet
- + " no channel is registered with id " + channelID);
- }
+ // if (packet.getType() == PacketImpl.SESS_PACKETS_CONFIRMED)
+ // {
+ // /*
+ // Packets confirmed can arrive after channel has been closed, e.g.
+ // Sending session.close with packet confirmation batch size = 1
+ // Session close gets replicated to backup, session closed on backup,
+ // and null response written back to client
+ // null response arrives on client and packet confirmation sent to
+ // backup
+ // null response arrives on backup but session is already closed
+ // */
+ // return;
+ // }
+ // else
+ // {
+ // throw new IllegalArgumentException("Cannot handle packet " + packet
+ // +
+ // " no channel is registered with id " +
+ // channelID);
+ // }
+
+ return;
}
channel.handlePacket(packet);
@@ -466,20 +490,17 @@
// Private
// --------------------------------------------------------------------------------------
- private void checkDestroyed()
- {
- if (destroyed) { throw new IllegalStateException(System
- .identityHashCode(this)
- + " Connection is destroyed"); }
- }
-
private void doWrite(final Packet packet)
{
- checkDestroyed();
+ if (destroyed)
+ {
+ // return;
- MessagingBuffer buffer = transportConnection
- .createBuffer(PacketImpl.INITIAL_BUFFER_SIZE);
+ throw new IllegalStateException("Cannot write to connection - it is destroyed");
+ }
+ final MessagingBuffer buffer = transportConnection.createBuffer(PacketImpl.INITIAL_BUFFER_SIZE);
+
packet.encode(buffer);
transportConnection.write(buffer);
@@ -487,7 +508,7 @@
private Packet decode(final MessagingBuffer in)
{
- byte packetType = in.getByte();
+ final byte packetType = in.getByte();
Packet packet;
@@ -807,8 +828,8 @@
// Inner classes
// --------------------------------------------------------------------------------
- //FIXME - improve locking on this class
-
+ // FIXME - improve locking on this class
+
// Needs to be static so we can re-assign it to another remotingconnection
private static class ChannelImpl implements Channel
{
@@ -832,13 +853,15 @@
private Channel replicatingChannel;
+ // This lock is used to block sends during failover
private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
private volatile RemotingConnectionImpl connection;
private ChannelImpl(final RemotingConnectionImpl connection,
- final long id, final boolean ordered,
- final int packetConfirmationBatchSize)
+ final long id,
+ final boolean ordered,
+ final int packetConfirmationBatchSize)
{
this.connection = connection;
@@ -855,13 +878,11 @@
this.packetConfirmationBatchSize = packetConfirmationBatchSize;
- if (packetConfirmationBatchSize != -1
- && (connection.client && !connection.backup || !connection.client
- && connection.replicatingConnection == null))
+ if (packetConfirmationBatchSize != -1 && (connection.client && !connection.backup || !connection.client && connection.replicatingConnection == null))
{
resendCache = new ConcurrentLinkedQueue<Packet>();
- this.nextConfirmation = packetConfirmationBatchSize - 1;
+ nextConfirmation = packetConfirmationBatchSize - 1;
}
else
{
@@ -870,12 +891,9 @@
if (connection.replicatingConnection != null)
{
- // log.info("Getting replicating channel");
- replicatingChannel = connection.replicatingConnection.getChannel(
- id, ordered, -1);
+ replicatingChannel = connection.replicatingConnection.getChannel(id, ordered, -1);
- replicatingChannel
- .setHandler(new ReplicatedPacketsConfirmedChannelHandler());
+ replicatingChannel.setHandler(new ReplicatedPacketsConfirmedChannelHandler());
}
else
{
@@ -883,6 +901,13 @@
}
}
+ public void setReplicatingChannel(final Channel replicatingChannel)
+ {
+ this.replicatingChannel = replicatingChannel;
+
+ replicatingChannel.setHandler(new ReplicatedPacketsConfirmedChannelHandler());
+ }
+
public long getID()
{
return id;
@@ -893,6 +918,7 @@
return lastReceivedCommandID;
}
+ // This must never called by more than one thread concurrently
public void send(final Packet packet)
{
lock.readLock().lock();
@@ -906,9 +932,8 @@
addToCache(packet);
}
- if (connection.writePackets
- || packet.getType() == PacketImpl.SESS_PACKETS_CONFIRMED
- || packet.getType() == PacketImpl.SESS_REPLICATE_DELIVERY_RESP)
+ if (connection.writePackets || packet.getType() == PacketImpl.SESS_PACKETS_CONFIRMED ||
+ packet.getType() == PacketImpl.SESS_REPLICATE_DELIVERY_RESP)
{
connection.doWrite(packet);
}
@@ -919,10 +944,8 @@
}
}
- private final Object blockingLock = new Object();
-
- public Packet sendBlocking(final Packet packet)
- throws MessagingException
+ // This must never called by more than one thread concurrently
+ public Packet sendBlocking(final Packet packet) throws MessagingException
{
lock.readLock().lock();
@@ -931,56 +954,55 @@
// For now we only allow one blocking request-response at a time per
// channel
// We can relax this but it will involve some kind of correlation id
- synchronized (blockingLock)
+ synchronized (this)
{
- synchronized (this)
+ response = null;
+
+ packet.setChannelID(id);
+
+ if (resendCache != null)
{
- response = null;
-
- packet.setChannelID(id);
-
- if (resendCache != null)
+ addToCache(packet);
+ }
+
+ connection.doWrite(packet);
+
+ long toWait = connection.blockingCallTimeout;
+
+ long start = System.currentTimeMillis();
+
+ while (response == null && toWait > 0)
+ {
+ try
{
- addToCache(packet);
+ wait(toWait);
}
-
- connection.doWrite(packet);
-
- long toWait = connection.blockingCallTimeout;
-
- long start = System.currentTimeMillis();
-
- while (response == null && toWait > 0)
+ catch (final InterruptedException e)
{
- try
- {
- wait(toWait);
- }
- catch (InterruptedException e)
- {
- }
-
- long now = System.currentTimeMillis();
-
- toWait -= now - start;
-
- start = now;
}
-
- if (response == null) { throw new IllegalStateException(
- "Timed out waiting for response"); }
-
- if (response.getType() == PacketImpl.EXCEPTION)
- {
- MessagingExceptionMessage mem = (MessagingExceptionMessage) response;
-
- throw mem.getException();
- }
- else
- {
- return response;
- }
+
+ final long now = System.currentTimeMillis();
+
+ toWait -= now - start;
+
+ start = now;
}
+
+ if (response == null)
+ {
+ throw new IllegalStateException("Timed out waiting for response");
+ }
+
+ if (response.getType() == PacketImpl.EXCEPTION)
+ {
+ final MessagingExceptionMessage mem = (MessagingExceptionMessage) response;
+
+ throw mem.getException();
+ }
+ else
+ {
+ return response;
+ }
}
}
finally
@@ -991,16 +1013,15 @@
public void setHandler(final ChannelHandler handler)
{
- // log.info("client " + connection.client + " backup " +
- // connection.backup + " setting handler " +
- // System.identityHashCode(handler));
this.handler = handler;
}
public void close()
{
- if (!connection.destroyed && connection.channels.remove(id) == null) { throw new IllegalArgumentException(
- "Cannot find channel with id " + id + " to close"); }
+ if (!connection.destroyed && connection.channels.remove(id) == null)
+ {
+ throw new IllegalArgumentException("Cannot find channel with id " + id + " to close");
+ }
if (replicatingChannel != null)
{
@@ -1024,28 +1045,37 @@
public void transferConnection(final RemotingConnection newConnection)
{
- if (executor != null)
+ //Needs to synchronize on the connection to make sure no packets from the old connection
+ //get processed after transfer has occurred
+ synchronized (connection)
{
- // First wait for anything in the executor to complete
- Future future = new Future();
+ connection.channels.remove(id);
- executor.execute(future);
+ if (executor != null)
+ {
+ // Wait for anything in the executor to complete
+ final Future future = new Future();
- boolean ok = future.await(10000);
+ executor.execute(future);
- if (!ok) { throw new IllegalStateException(
- "Timed out waiting for executor to complete"); }
- }
+ boolean ok = future.await(10000);
- RemotingConnectionImpl rnewConnection = (RemotingConnectionImpl) newConnection;
+ if (!ok)
+ {
+ throw new IllegalStateException("Timed out waiting for executor to complete");
+ }
+ }
- connection.channels.remove(id);
+ // And switch it
- rnewConnection.channels.put(id, this);
+ final RemotingConnectionImpl rnewConnection = (RemotingConnectionImpl) newConnection;
- connection = rnewConnection;
+ rnewConnection.channels.put(id, this);
- replicatingChannel = null;
+ connection = rnewConnection;
+
+ replicatingChannel = null;
+ }
}
public int replayCommands(final int otherLastReceivedCommandID)
@@ -1055,15 +1085,20 @@
Packet packet = null;
int count = 0;
+
+ //log.info("replaying commands " + resendCache.size());
- while ((packet = resendCache.poll()) != null)
+ Queue<Packet> copy = new LinkedList<Packet>(resendCache);
+ while ((packet = copy.poll()) != null)
{
connection.doWrite(packet);
count++;
}
+
+ //log.info("replayed commands, size is now " + resendCache.size());
- return this.lastReceivedCommandID;
+ return lastReceivedCommandID;
}
public void lock()
@@ -1078,8 +1113,6 @@
private void handlePacket(final Packet packet)
{
- // log.info("handling packet client " + connection.client + " backup "
- // + connection.backup);
if (packet.getType() == PacketImpl.SESS_PACKETS_CONFIRMED)
{
if (resendCache != null)
@@ -1101,7 +1134,7 @@
});
}
}
- else if (connection.replicatingConnection != null)
+ else if (replicatingChannel != null)
{
replicatingChannel.send(packet);
}
@@ -1114,20 +1147,18 @@
}
else
{
- if (replicatingChannel != null
- && packet.getType() != PacketImpl.PING)
+ if (replicatingChannel != null && packet.getType() != PacketImpl.PING)
{
replicatingChannel.send(packet);
}
if (connection.interceptors != null)
{
- for (Interceptor interceptor : connection.interceptors)
+ for (final Interceptor interceptor : connection.interceptors)
{
try
{
- boolean callNext = interceptor.intercept(packet,
- connection);
+ boolean callNext = interceptor.intercept(packet, connection);
if (!callNext)
{
@@ -1136,10 +1167,9 @@
return;
}
}
- catch (Throwable e)
+ catch (final Throwable e)
{
- log.warn("Failure in calling interceptor: " + interceptor,
- e);
+ log.warn("Failure in calling interceptor: " + interceptor, e);
}
}
}
@@ -1187,12 +1217,18 @@
{
if (packet.isUsesConfirmations() && resendCache != null)
{
+ // log.info(System.identityHashCode(connection) + " client " +
+ // connection.client +
+ // " backup " +
+ // connection.backup +
+ // " checking confirmation for packet " +
+ // packet.getType());
+
lastReceivedCommandID++;
if (lastReceivedCommandID == nextConfirmation)
{
- Packet confirmed = new PacketsConfirmedMessage(
- lastReceivedCommandID);
+ final Packet confirmed = new PacketsConfirmedMessage(lastReceivedCommandID);
nextConfirmation += packetConfirmationBatchSize;
@@ -1206,28 +1242,55 @@
private void addToCache(final Packet packet)
{
resendCache.add(packet);
+
+// log.info(System.identityHashCode(connection) + ":" +
+// System.identityHashCode(this) +
+// "client " +
+// connection.client +
+// " backup " +
+// connection.backup +
+// " addtocache cache size now " +
+// resendCache.size());
}
private void clearUpTo(final int lastReceivedCommandID)
{
- int numberToClear = 1 + lastReceivedCommandID - firstStoredCommandID;
+ final int numberToClear = 1 + lastReceivedCommandID - firstStoredCommandID;
- if (numberToClear == -1) { throw new IllegalArgumentException(
- "Invalid lastReceivedCommandID: " + lastReceivedCommandID); }
+// log.info(System.identityHashCode(connection) + ":" +
+// System.identityHashCode(this) +
+// " client " +
+// connection.client +
+// " backup " +
+// connection.backup +
+// " clearupto " +
+// lastReceivedCommandID +
+// " numberToClear " +
+// numberToClear +
+// " cache size " +
+// resendCache.size());
+ if (numberToClear == -1)
+ {
+ throw new IllegalArgumentException("Invalid lastReceivedCommandID: " + lastReceivedCommandID);
+ }
+
for (int i = 0; i < numberToClear; i++)
{
- Packet packet = resendCache.poll();
+ final Packet packet = resendCache.poll();
- if (packet == null) { throw new IllegalStateException(
- "Can't find packet to clear"); }
+ if (packet == null)
+ {
+ throw new IllegalStateException("Can't find packet to clear");
+ }
}
+
+ //log.info("There are now "+ resendCache.size());
firstStoredCommandID += numberToClear;
}
- private class ReplicatedPacketsConfirmedChannelHandler implements
- ChannelHandler
+ private class ReplicatedPacketsConfirmedChannelHandler implements ChannelHandler
{
public void handlePacket(final Packet packet)
{
@@ -1256,9 +1319,8 @@
if (!firstTime && !gotPong)
{
// Error - didn't get pong back
- MessagingException me = new MessagingException(
- MessagingException.NOT_CONNECTED,
- "Did not receive pong from server");
+ final MessagingException me = new MessagingException(MessagingException.NOT_CONNECTED,
+ "Did not receive pong from server");
fail(me);
}
@@ -1268,7 +1330,7 @@
firstTime = false;
// Send ping
- Packet ping = new Ping(expirePeriod);
+ final Packet ping = new Ping(expirePeriod);
pingChannel.send(ping);
}
@@ -1278,7 +1340,7 @@
{
public void handlePacket(final Packet packet)
{
- byte type = packet.getType();
+ final byte type = packet.getType();
if (type == PONG)
{
@@ -1291,11 +1353,10 @@
}
else if (type == PING)
{
- expireTime = System.currentTimeMillis()
- + ((Ping) packet).getExpirePeriod();
+ expireTime = System.currentTimeMillis() + ((Ping) packet).getExpirePeriod();
// Parameter is placeholder for future
- Packet pong = new Pong(-1);
+ final Packet pong = new Pong(-1);
pingChannel.send(pong);
}
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingServiceImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingServiceImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/RemotingServiceImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -246,7 +246,8 @@
RemotingConnection rc =
new RemotingConnectionImpl(connection, callTimeout, -1, remotingExecutor, null, interceptors,
- replicatingConnection, false);
+ replicatingConnection,
+ false);
rc.setBackup(backup);
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMAcceptor.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMAcceptor.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMAcceptor.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -50,8 +50,6 @@
private volatile boolean started;
- // private volatile InVMConnector connector;
-
public InVMAcceptor(final Map<String, Object> configuration, final BufferHandler handler,
final ConnectionLifeCycleListener listener)
{
@@ -105,14 +103,15 @@
return handler;
}
- public void connect(final String connectionID, final BufferHandler remoteHandler)
+ public void connect(final String connectionID, final BufferHandler remoteHandler,
+ final InVMConnector connector)
{
if (!started)
{
throw new IllegalStateException("Acceptor is not started");
}
- new InVMConnection(connectionID, remoteHandler, new Listener());
+ new InVMConnection(connectionID, remoteHandler, new Listener(connector));
}
public void disconnect(final String connectionID)
@@ -132,6 +131,13 @@
private class Listener implements ConnectionLifeCycleListener
{
+ private final InVMConnector connector;
+
+ Listener(final InVMConnector connector)
+ {
+ this.connector = connector;
+ }
+
public void connectionCreated(final Connection connection)
{
if (connections.putIfAbsent((String)connection.getID(), connection) != null)
@@ -150,7 +156,7 @@
}
//Remove on the other side too
- InVMRegistry.instance.getConnector(id).disconnect((String)connectionID);
+ connector.disconnect((String)connectionID);
listener.connectionDestroyed(connectionID);
}
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnector.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnector.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMConnector.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -67,8 +67,6 @@
InVMRegistry registry = InVMRegistry.instance;
- registry.registerConnector(id, this);
-
acceptor = registry.getAcceptor(id);
if (acceptor == null)
@@ -91,8 +89,6 @@
connections.clear();
- InVMRegistry.instance.unregisterConnector(id);
-
started = false;
}
@@ -100,7 +96,7 @@
{
Connection conn = new InVMConnection(acceptor.getHandler(), new Listener());
- acceptor.connect((String)conn.getID(), handler);
+ acceptor.connect((String)conn.getID(), handler, this);
return conn;
}
@@ -144,15 +140,13 @@
public void connectionDestroyed(final Object connectionID)
{
- if (connections.remove(connectionID) == null)
- {
- throw new IllegalArgumentException("Cannot find connection with id " + connectionID + " to remove");
+ if (connections.remove(connectionID) != null)
+ {
+ //Close the correspond connection on the other side
+ acceptor.disconnect((String)connectionID);
+
+ listener.connectionDestroyed(connectionID);
}
-
- //Close the correspond connection on the other side
- acceptor.disconnect((String)connectionID);
-
- listener.connectionDestroyed(connectionID);
}
public void connectionException(final Object connectionID, final MessagingException me)
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMRegistry.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMRegistry.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/invm/InVMRegistry.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -38,9 +38,6 @@
public static final InVMRegistry instance = new InVMRegistry();
- private ConcurrentMap<Integer, InVMConnector> connectors =
- new ConcurrentHashMap<Integer, InVMConnector>();
-
private ConcurrentMap<Integer, InVMAcceptor> acceptors =
new ConcurrentHashMap<Integer, InVMAcceptor>();
@@ -52,14 +49,6 @@
}
}
- public void registerConnector(final int id, final InVMConnector connector)
- {
- if (connectors.putIfAbsent(id, connector) != null)
- {
- throw new IllegalArgumentException("Connector with id " + id + " already registered");
- }
- }
-
public void unregisterAcceptor(final int id)
{
if (acceptors.remove(id) == null)
@@ -67,20 +56,7 @@
throw new IllegalArgumentException("Acceptor with id " + id + " not registered");
}
}
-
- public void unregisterConnector(final int id)
- {
- if (connectors.remove(id) == null)
- {
- throw new IllegalArgumentException("Connector with id " + id + " not registered");
- }
- }
-
- public InVMConnector getConnector(final int id)
- {
- return connectors.get(id);
- }
-
+
public InVMAcceptor getAcceptor(final int id)
{
return acceptors.get(id);
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/BrowseMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/BrowseMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/BrowseMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -22,8 +22,6 @@
package org.jboss.messaging.core.remoting.impl.wireformat;
-import static org.jboss.messaging.core.remoting.impl.wireformat.PacketImpl.SESS_BROWSER_MESSAGE;
-
import org.jboss.messaging.core.client.ClientMessage;
import org.jboss.messaging.core.client.impl.ClientMessageImpl;
import org.jboss.messaging.core.logging.Logger;
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,6 +36,10 @@
// Attributes ----------------------------------------------------
+ private String name;
+
+ private long sessionChannelID;
+
private int version;
private String username;
@@ -52,12 +56,17 @@
// Constructors --------------------------------------------------
- public CreateSessionMessage(final int version, final String username, final String password,
+ public CreateSessionMessage(final String name, final long sessionChannelID,
+ final int version, final String username, final String password,
final boolean xa, final boolean autoCommitSends,
final boolean autoCommitAcks)
{
super(CREATESESSION);
+ this.name = name;
+
+ this.sessionChannelID = sessionChannelID;
+
this.version = version;
this.username = username;
@@ -78,6 +87,16 @@
// Public --------------------------------------------------------
+ public String getName()
+ {
+ return name;
+ }
+
+ public long getSessionChannelID()
+ {
+ return sessionChannelID;
+ }
+
public int getVersion()
{
return version;
@@ -110,6 +129,8 @@
public void encodeBody(final MessagingBuffer buffer)
{
+ buffer.putString(name);
+ buffer.putLong(sessionChannelID);
buffer.putInt(version);
buffer.putNullableString(username);
buffer.putNullableString(password);
@@ -120,6 +141,8 @@
public void decodeBody(final MessagingBuffer buffer)
{
+ name = buffer.getString();
+ sessionChannelID = buffer.getLong();
version = buffer.getInt();
username = buffer.getNullableString();
password = buffer.getNullableString();
@@ -138,6 +161,8 @@
CreateSessionMessage r = (CreateSessionMessage)other;
boolean matches = super.equals(other) &&
+ this.name.equals(r.name) &&
+ this.sessionChannelID == r.sessionChannelID &&
this.version == r.version &&
this.xa == r.xa &&
this.autoCommitSends == r.autoCommitSends &&
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionResponseMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionResponseMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/CreateSessionResponseMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,8 +36,6 @@
// Attributes ----------------------------------------------------
- private long sessionID;
-
private int serverVersion;
private int packetConfirmationBatchSize;
@@ -46,12 +44,10 @@
// Constructors --------------------------------------------------
- public CreateSessionResponseMessage(final long sessionID, final int serverVersion, final int packetConfirmationBatchSize)
+ public CreateSessionResponseMessage(final int serverVersion, final int packetConfirmationBatchSize)
{
super(CREATESESSION_RESP);
- this.sessionID = sessionID;
-
this.serverVersion = serverVersion;
this.packetConfirmationBatchSize = packetConfirmationBatchSize;
@@ -69,11 +65,6 @@
return true;
}
- public long getSessionID()
- {
- return sessionID;
- }
-
public int getServerVersion()
{
return serverVersion;
@@ -86,14 +77,12 @@
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putLong(sessionID);
buffer.putInt(serverVersion);
buffer.putInt(packetConfirmationBatchSize);
}
public void decodeBody(final MessagingBuffer buffer)
{
- sessionID = buffer.getLong();
serverVersion = buffer.getInt();
packetConfirmationBatchSize = buffer.getInt();
}
@@ -107,8 +96,7 @@
CreateSessionResponseMessage r = (CreateSessionResponseMessage)other;
- boolean matches = super.equals(other) &&
- this.sessionID == r.sessionID &&
+ boolean matches = super.equals(other) &&
this.packetConfirmationBatchSize == r.packetConfirmationBatchSize;
return matches;
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ProducerFlowCreditMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ProducerFlowCreditMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ProducerFlowCreditMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -37,7 +37,7 @@
// Attributes ----------------------------------------------------
- private int producerID;
+ private long producerID;
private int credits;
@@ -45,7 +45,7 @@
// Constructors --------------------------------------------------
- public ProducerFlowCreditMessage(final int producerID, final int credits)
+ public ProducerFlowCreditMessage(final long producerID, final int credits)
{
super(SESS_RECEIVETOKENS);
@@ -61,7 +61,7 @@
// Public --------------------------------------------------------
- public int getProducerID()
+ public long getProducerID()
{
return producerID;
}
@@ -73,13 +73,13 @@
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(producerID);
+ buffer.putLong(producerID);
buffer.putInt(credits);
}
public void decodeBody(final MessagingBuffer buffer)
{
- producerID = buffer.getInt();
+ producerID = buffer.getLong();
credits = buffer.getInt();
}
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -37,7 +37,7 @@
// Attributes ----------------------------------------------------
- private long sessionID;
+ private String name;
private int lastReceivedCommandID;
@@ -45,12 +45,12 @@
// Constructors --------------------------------------------------
- public ReattachSessionMessage(final long sessionID, final int lastReceivedCommandID)
+ public ReattachSessionMessage(final String name, final int lastReceivedCommandID)
{
super(REATTACH_SESSION);
- this.sessionID = sessionID;
-
+ this.name = name;
+
this.lastReceivedCommandID = lastReceivedCommandID;
}
@@ -61,9 +61,9 @@
// Public --------------------------------------------------------
- public long getSessionID()
+ public String getName()
{
- return sessionID;
+ return name;
}
public int getLastReceivedCommandID()
@@ -73,13 +73,13 @@
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putLong(sessionID);
+ buffer.putString(name);
buffer.putInt(lastReceivedCommandID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- sessionID = buffer.getLong();
+ name = buffer.getString();
lastReceivedCommandID = buffer.getInt();
}
@@ -92,8 +92,8 @@
ReattachSessionMessage r = (ReattachSessionMessage)other;
- return super.equals(other) && this.lastReceivedCommandID == r.lastReceivedCommandID &&
- this.sessionID == r.sessionID;
+ return super.equals(other) && this.name.equals(r.name) &&
+ this.lastReceivedCommandID == r.lastReceivedCommandID;
}
// Package protected ---------------------------------------------
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionResponseMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionResponseMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReattachSessionResponseMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -38,7 +38,7 @@
// Attributes ----------------------------------------------------
private int lastReceivedCommandID;
-
+
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
@@ -63,12 +63,12 @@
}
public void encodeBody(final MessagingBuffer buffer)
- {
+ {
buffer.putInt(lastReceivedCommandID);
}
public void decodeBody(final MessagingBuffer buffer)
- {
+ {
lastReceivedCommandID = buffer.getInt();
}
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReceiveMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReceiveMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/ReceiveMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -41,10 +41,9 @@
private static final Logger log = Logger.getLogger(ReceiveMessage.class);
-
// Attributes ----------------------------------------------------
- private int consumerID;
+ private long consumerID;
private ClientMessage clientMessage;
@@ -58,7 +57,7 @@
// Constructors --------------------------------------------------
- public ReceiveMessage(final int consumerID, final ServerMessage message, final int deliveryCount, final long deliveryID)
+ public ReceiveMessage(final long consumerID, final ServerMessage message, final int deliveryCount, final long deliveryID)
{
super(SESS_RECEIVE_MSG);
@@ -80,7 +79,7 @@
// Public --------------------------------------------------------
- public int getConsumerID()
+ public long getConsumerID()
{
return consumerID;
}
@@ -107,7 +106,7 @@
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(consumerID);
+ buffer.putLong(consumerID);
buffer.putInt(deliveryCount);
buffer.putLong(deliveryID);
serverMessage.encode(buffer);
@@ -117,7 +116,7 @@
{
//TODO can be optimised
- consumerID = buffer.getInt();
+ consumerID = buffer.getLong();
deliveryCount = buffer.getInt();
deliveryID = buffer.getLong();
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SendMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SendMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SendMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -42,7 +42,7 @@
// Attributes ----------------------------------------------------
- private int producerID;
+ private long producerID;
private ClientMessage clientMessage;
@@ -54,7 +54,7 @@
// Constructors --------------------------------------------------
- public SendMessage(final int producerID, final ClientMessage message, final boolean requiresResponse)
+ public SendMessage(final long producerID, final ClientMessage message, final boolean requiresResponse)
{
super(SESS_SEND);
@@ -72,9 +72,9 @@
// Public --------------------------------------------------------
- public int getProducerID()
+ public long getProducerID()
{
- return this.producerID;
+ return producerID;
}
public ClientMessage getClientMessage()
@@ -94,7 +94,7 @@
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(producerID);
+ buffer.putLong(producerID);
if (clientMessage != null)
{
@@ -113,7 +113,7 @@
{
//TODO can be optimised
- producerID = buffer.getInt();
+ producerID = buffer.getLong();
serverMessage = new ServerMessageImpl();
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserCloseMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserCloseMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserCloseMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -35,13 +35,13 @@
// Attributes ----------------------------------------------------
- private int browserID;
+ private long browserID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionBrowserCloseMessage(final int browserID)
+ public SessionBrowserCloseMessage(final long browserID)
{
super(SESS_BROWSER_CLOSE);
@@ -55,19 +55,19 @@
// Public --------------------------------------------------------
- public int getBrowserID()
+ public long getBrowserID()
{
return browserID;
}
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(browserID);
+ buffer.putLong(browserID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- browserID = buffer.getInt();
+ browserID = buffer.getLong();
}
@Override
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserHasNextMessageMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserHasNextMessageMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserHasNextMessageMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,13 +36,13 @@
// Attributes ----------------------------------------------------
- private int browserID;
+ private long browserID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionBrowserHasNextMessageMessage(final int browserID)
+ public SessionBrowserHasNextMessageMessage(final long browserID)
{
super(SESS_BROWSER_HASNEXTMESSAGE);
@@ -56,19 +56,19 @@
// Public --------------------------------------------------------
- public int getBrowserID()
+ public long getBrowserID()
{
return browserID;
}
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(browserID);
+ buffer.putLong(browserID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- browserID = buffer.getInt();
+ browserID = buffer.getLong();
}
@Override
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserNextMessageMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserNextMessageMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserNextMessageMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,13 +36,13 @@
// Attributes ----------------------------------------------------
- private int browserID;
+ private long browserID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionBrowserNextMessageMessage(final int browserID)
+ public SessionBrowserNextMessageMessage(final long browserID)
{
super(SESS_BROWSER_NEXTMESSAGE);
@@ -56,19 +56,19 @@
// Public --------------------------------------------------------
- public int getBrowserID()
+ public long getBrowserID()
{
return browserID;
}
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(browserID);
+ buffer.putLong(browserID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- browserID = buffer.getInt();
+ browserID = buffer.getLong();
}
@Override
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserResetMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserResetMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionBrowserResetMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -37,13 +37,13 @@
// Attributes ----------------------------------------------------
- private int browserID;
+ private long browserID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionBrowserResetMessage(final int browserID)
+ public SessionBrowserResetMessage(final long browserID)
{
super(SESS_BROWSER_RESET);
@@ -57,19 +57,19 @@
// Public --------------------------------------------------------
- public int getBrowserID()
+ public long getBrowserID()
{
return browserID;
}
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(browserID);
+ buffer.putLong(browserID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- browserID = buffer.getInt();
+ browserID = buffer.getLong();
}
@Override
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionConsumerCloseMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionConsumerCloseMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionConsumerCloseMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -35,13 +35,13 @@
// Attributes ----------------------------------------------------
- private int consumerID;
+ private long consumerID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionConsumerCloseMessage(final int objectID)
+ public SessionConsumerCloseMessage(final long objectID)
{
super(SESS_CONSUMER_CLOSE);
@@ -55,19 +55,19 @@
// Public --------------------------------------------------------
- public int getConsumerID()
+ public long getConsumerID()
{
return consumerID;
}
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(consumerID);
+ buffer.putLong(consumerID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- consumerID = buffer.getInt();
+ consumerID = buffer.getLong();
}
@Override
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionFlowCreditMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionFlowCreditMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionFlowCreditMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,7 +36,7 @@
// Attributes ----------------------------------------------------
- private int consumerID;
+ private long consumerID;
private int credits;
@@ -44,7 +44,7 @@
// Constructors --------------------------------------------------
- public SessionFlowCreditMessage(final int consumerID, final int credits)
+ public SessionFlowCreditMessage(final long consumerID, final int credits)
{
super(SESS_FLOWTOKEN);
@@ -60,7 +60,7 @@
// Public --------------------------------------------------------
- public int getConsumerID()
+ public long getConsumerID()
{
return consumerID;
}
@@ -72,13 +72,13 @@
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(consumerID);
+ buffer.putLong(consumerID);
buffer.putInt(credits);
}
public void decodeBody(final MessagingBuffer buffer)
{
- consumerID = buffer.getInt();
+ consumerID = buffer.getLong();
credits = buffer.getInt();
}
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionProducerCloseMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionProducerCloseMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionProducerCloseMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -35,13 +35,13 @@
// Attributes ----------------------------------------------------
- private int producerID;
+ private long producerID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionProducerCloseMessage(final int producerID)
+ public SessionProducerCloseMessage(final long producerID)
{
super(SESS_PRODUCER_CLOSE);
@@ -55,19 +55,19 @@
// Public --------------------------------------------------------
- public int getProducerID()
+ public long getProducerID()
{
return producerID;
}
public void encodeBody(final MessagingBuffer buffer)
{
- buffer.putInt(producerID);
+ buffer.putLong(producerID);
}
public void decodeBody(final MessagingBuffer buffer)
{
- producerID = buffer.getInt();
+ producerID = buffer.getLong();
}
@Override
Modified: trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionReplicateDeliveryMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionReplicateDeliveryMessage.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/remoting/impl/wireformat/SessionReplicateDeliveryMessage.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -38,13 +38,13 @@
private long messageID;
- private int consumerID;
+ private long consumerID;
// Static --------------------------------------------------------
// Constructors --------------------------------------------------
- public SessionReplicateDeliveryMessage(final long messageID, final int consumerID)
+ public SessionReplicateDeliveryMessage(final long consumerID, final long messageID)
{
super(SESS_REPLICATE_DELIVERY);
@@ -65,7 +65,7 @@
return messageID;
}
- public int getConsumerID()
+ public long getConsumerID()
{
return consumerID;
}
@@ -73,13 +73,13 @@
public void encodeBody(final MessagingBuffer buffer)
{
buffer.putLong(messageID);
- buffer.putInt(consumerID);
+ buffer.putLong(consumerID);
}
public void decodeBody(final MessagingBuffer buffer)
{
messageID = buffer.getLong();
- consumerID = buffer.getInt();
+ consumerID = buffer.getLong();
}
public boolean isUsesConfirmations()
Modified: trunk/src/main/org/jboss/messaging/core/server/Delivery.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/Delivery.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/Delivery.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,7 +36,7 @@
long getDeliveryID();
- int getConsumerID();
+ long getConsumerID();
void deliver();
}
Modified: trunk/src/main/org/jboss/messaging/core/server/MessagingServer.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/MessagingServer.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/MessagingServer.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -75,17 +75,19 @@
Version getVersion();
- ReattachSessionResponseMessage reattachSession(RemotingConnection connection,
- long sessionID, int lastReceivedCommandID);
+ ReattachSessionResponseMessage reattachSession(RemotingConnection connection,
+ String name,
+ int lastReceivedCommandID);
- CreateSessionResponseMessage createSession(String username, String password,
+ CreateSessionResponseMessage createSession(String name, long channelID,
+ String username, String password,
int incrementingVersion,
RemotingConnection remotingConnection,
boolean autoCommitSends,
boolean autoCommitAcks,
boolean xa) throws Exception;
- void removeSession(long sessionID);
+ void removeSession(String name);
boolean isStarted();
Modified: trunk/src/main/org/jboss/messaging/core/server/ServerConsumer.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/ServerConsumer.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/ServerConsumer.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -32,7 +32,7 @@
*/
public interface ServerConsumer extends Consumer
{
- int getID();
+ long getID();
void close() throws Exception;
Modified: trunk/src/main/org/jboss/messaging/core/server/ServerProducer.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/ServerProducer.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/ServerProducer.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -32,7 +32,7 @@
*/
public interface ServerProducer
{
- int getID();
+ long getID();
void close() throws Exception;
Modified: trunk/src/main/org/jboss/messaging/core/server/ServerSession.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/ServerSession.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/ServerSession.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -120,23 +120,23 @@
void createBrowser(SimpleString queueName, SimpleString filterString) throws Exception;
- void closeConsumer(int consumerID) throws Exception;
+ void closeConsumer(long consumerID) throws Exception;
- void closeProducer(int producerID) throws Exception;
+ void closeProducer(long producerID) throws Exception;
- void closeBrowser(int browserID) throws Exception;
+ void closeBrowser(long browserID) throws Exception;
- void receiveConsumerCredits(int consumerID, int credits) throws Exception;
+ void receiveConsumerCredits(long consumerID, int credits) throws Exception;
- void sendProducerMessage(int producerID, ServerMessage message) throws Exception;
+ void sendProducerMessage(long producerID, ServerMessage message) throws Exception;
- boolean browserHasNextMessage(int browserID) throws Exception;
+ boolean browserHasNextMessage(long browserID) throws Exception;
- ServerMessage browserNextMessage(int browserID) throws Exception;
+ ServerMessage browserNextMessage(long browserID) throws Exception;
- void browserReset(int browserID) throws Exception;
+ void browserReset(long browserID) throws Exception;
- void handleReplicateDelivery(long messageID, int consumerID) throws Exception;
+ void handleReplicateDelivery(long consumerID, long messageID) throws Exception;
void handleDeferredDelivery();
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/DeliveryImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/DeliveryImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/DeliveryImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -41,14 +41,14 @@
private final MessageReference reference;
- private final int consumerID;
+ private final long consumerID;
private final long deliveryID;
private final Channel channel;
public DeliveryImpl(final MessageReference reference,
- final int consumerID,
+ final long consumerID,
final long deliveryID, final Channel channel)
{
this.reference = reference;
@@ -67,7 +67,7 @@
return deliveryID;
}
- public int getConsumerID()
+ public long getConsumerID()
{
return consumerID;
}
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -26,12 +26,12 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.messaging.core.config.Configuration;
import org.jboss.messaging.core.config.TransportConfiguration;
@@ -48,7 +48,6 @@
import org.jboss.messaging.core.postoffice.impl.PostOfficeImpl;
import org.jboss.messaging.core.remoting.Channel;
import org.jboss.messaging.core.remoting.ChannelHandler;
-import org.jboss.messaging.core.remoting.ConnectionRegistry;
import org.jboss.messaging.core.remoting.RemotingConnection;
import org.jboss.messaging.core.remoting.RemotingService;
import org.jboss.messaging.core.remoting.impl.ConnectionRegistryImpl;
@@ -109,9 +108,9 @@
private HierarchicalRepository<Set<Role>> securityRepository;
private ResourceManager resourceManager;
private MessagingServerControlMBean serverManagement;
- private RemotingConnection replicatingConnection;
- private final AtomicInteger sessionIDSequence = new AtomicInteger(2);
- private final Map<Long, ServerSession> sessions = new ConcurrentHashMap<Long, ServerSession>();
+ private final ConcurrentMap<String, ServerSession> sessions = new ConcurrentHashMap<String, ServerSession>();
+ private ConnectorFactory backupConnectorFactory;
+ private Map<String, Object> backupConnectorParams;
// plugins
@@ -220,18 +219,13 @@
try
{
Class<?> clz = loader.loadClass(backupConnector.getFactoryClassName());
- ConnectorFactory connectorFactory = (ConnectorFactory) clz.newInstance();
- ConnectionRegistry registry = ConnectionRegistryImpl.instance;
- //TODO don't hardcode ping interval and call timeout here
- replicatingConnection =
- registry.getConnection(connectorFactory, backupConnector.getParams(),
- -1, 30000);
- replicatingConnection.setBackup(true);
+ this.backupConnectorFactory = (ConnectorFactory) clz.newInstance();
}
catch (Exception e)
{
throw new IllegalArgumentException("Error instantiating interceptor \"" + backupConnector.getFactoryClassName() + "\"", e);
}
+ this.backupConnectorParams = backupConnector.getParams();
}
remotingService.setMessagingServer(this);
@@ -245,10 +239,6 @@
return;
}
- if (this.replicatingConnection != null)
- {
- ConnectionRegistryImpl.instance.returnConnection(replicatingConnection.getID());
- }
securityStore = null;
postOffice.stop();
postOffice = null;
@@ -377,16 +367,19 @@
}
public ReattachSessionResponseMessage reattachSession(final RemotingConnection connection,
- final long sessionID,
+ final String name,
final int lastReceivedCommandID)
{
- ServerSession session = sessions.get(sessionID);
+ ServerSession session = sessions.get(name);
if (session == null)
{
- throw new IllegalArgumentException("Cannot find session with id " + sessionID + " to reattach");
- }
+ throw new IllegalArgumentException("Cannot find session with name " + name + " to reattach");
+ }
+ //Reconnect the channel to the new connection
+ session.transferConnection(connection);
+
//This is necessary for invm since the replicating connection will be the same connection
//as the original replicating connection since the key is the same in the registry, and that connection
//won't have any resend buffer etc
@@ -395,12 +388,9 @@
postOffice.setBackup(false);
configuration.setBackup(false);
-
+
remotingService.setBackup(false);
-
- //Reconnect the channel to the new connection
- session.transferConnection(connection);
-
+
int serverLastReceivedCommandID = session.replayCommands(lastReceivedCommandID);
connection.setBackup(false);
@@ -408,7 +398,9 @@
return new ReattachSessionResponseMessage(serverLastReceivedCommandID);
}
- public CreateSessionResponseMessage createSession(final String username, final String password,
+ public CreateSessionResponseMessage createSession(final String name,
+ final long channelID,
+ final String username, final String password,
final int incrementingVersion,
final RemotingConnection remotingConnection,
final boolean autoCommitSends,
@@ -429,14 +421,12 @@
// up thread local immediately after we used the information, otherwise some other people
// security my be screwed up, on account of thread local security stack being corrupted.
- securityStore.authenticate(username, password);
-
- long sessionID = this.generateSessionID();
-
+ securityStore.authenticate(username, password);
+
Channel channel =
- remotingConnection.getChannel(sessionID, true, configuration.getPacketConfirmationBatchSize());
+ remotingConnection.getChannel(channelID, true, configuration.getPacketConfirmationBatchSize());
- final ServerSessionImpl session = new ServerSessionImpl(sessionID, username, password,
+ final ServerSessionImpl session = new ServerSessionImpl(name, channelID, username, password,
autoCommitSends, autoCommitAcks, xa,
remotingConnection,
storageManager, postOffice,
@@ -447,7 +437,10 @@
channel,
this);
- sessions.put(sessionID, session);
+ if (sessions.putIfAbsent(name, session) != null)
+ {
+ throw new IllegalArgumentException("Session with name " + name + " already exists");
+ }
ChannelHandler handler = new ServerSessionPacketHandler(session, channel);
@@ -456,17 +449,39 @@
remotingConnection.addFailureListener(session);
return
- new CreateSessionResponseMessage(sessionID, version.getIncrementingVersion(),
+ new CreateSessionResponseMessage(version.getIncrementingVersion(),
configuration.getPacketConfirmationBatchSize());
}
- public void removeSession(final long sessionID)
+ public RemotingConnection getReplicatingConnection()
{
- if (sessions.remove(sessionID) == null)
+ //Note we must always get a new connection each time - since there must be a one to one correspondence
+ //between connections to clients and replicating connections, since we need to preserve channel ids
+ //before and after failover
+
+ if (backupConnectorFactory != null)
{
- throw new IllegalArgumentException("Cannot find session with id " + sessionID + " to remove");
+ //TODO don't hardcode ping interval and code timeout
+ RemotingConnection replicatingConnection =
+ ConnectionRegistryImpl.instance.getConnectionNoCache(backupConnectorFactory, backupConnectorParams, 5000, 30000);
+
+ replicatingConnection.setBackup(true);
+
+ return replicatingConnection;
}
+ else
+ {
+ return null;
+ }
}
+
+ public void removeSession(final String name)
+ {
+ if (sessions.remove(name) == null)
+ {
+ throw new IllegalArgumentException("Cannot find session with name " + name + " to remove");
+ }
+ }
public MessagingServerControlMBean getServerManagement()
{
@@ -483,11 +498,6 @@
return postOffice;
}
- public RemotingConnection getReplicatingConnection()
- {
- return replicatingConnection;
- }
-
// Public ---------------------------------------------------------------------------------------
// Package protected ----------------------------------------------------------------------------
@@ -495,19 +505,6 @@
// Protected ------------------------------------------------------------------------------------
// Private --------------------------------------------------------------------------------------
-
- private int generateSessionID()
- {
- int id = sessionIDSequence.getAndIncrement();
-
- //Channel zero is reserved for pinging, channel 1 is reserved for messaging server
- if (id == 0 || id == 1)
- {
- id = this.generateSessionID();
- }
-
- return id;
- }
-
+
// Inner classes --------------------------------------------------------------------------------
}
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/MessagingServerPacketHandler.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -74,9 +74,11 @@
if (type == CREATESESSION)
{
CreateSessionMessage request = (CreateSessionMessage) packet;
-
+
response =
- server.createSession(request.getUsername(), request.getPassword(),
+ server.createSession(request.getName(),
+ request.getSessionChannelID(),
+ request.getUsername(), request.getPassword(),
request.getVersion(),
connection,
request.isAutoCommitSends(),
@@ -88,7 +90,8 @@
ReattachSessionMessage request = (ReattachSessionMessage)packet;
response =
- server.reattachSession(connection, request.getSessionID(), request.getLastReceivedCommandID());
+ server.reattachSession(connection, request.getName(),
+ request.getLastReceivedCommandID());
}
else
{
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/RoundRobinDistributionPolicy.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/RoundRobinDistributionPolicy.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/RoundRobinDistributionPolicy.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -36,7 +36,7 @@
*/
public class RoundRobinDistributionPolicy implements DistributionPolicy
{
- public int select(List<Consumer> consumers, int pos)
+ public int select(final List<Consumer> consumers, int pos)
{
if (pos == -1)
{
@@ -52,6 +52,7 @@
pos = 0;
}
}
+
return pos;
}
}
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/ServerBrowserImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/ServerBrowserImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/ServerBrowserImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -56,7 +56,7 @@
// Attributes -----------------------------------------------------------------------------------
- private final int id;
+ private final long id;
private final ServerSession session;
private final Queue destination;
private final Filter filter;
@@ -64,7 +64,7 @@
// Constructors ---------------------------------------------------------------------------------
- public ServerBrowserImpl(final int id, final ServerSession session,
+ public ServerBrowserImpl(final long id, final ServerSession session,
final Queue destination, final String messageFilter) throws MessagingException
{
this.id = id;
@@ -85,7 +85,7 @@
// BrowserEndpoint implementation ---------------------------------------------------------------
- public int getID()
+ public long getID()
{
return id;
}
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/ServerConsumerImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -57,7 +57,7 @@
private final boolean trace = log.isTraceEnabled();
- private final int id;
+ private final long id;
private final Queue messageQueue;
@@ -79,7 +79,7 @@
// Constructors ---------------------------------------------------------------------------------
- public ServerConsumerImpl(final int id, final ServerSession session,
+ public ServerConsumerImpl(final long id, final ServerSession session,
final Queue messageQueue, final Filter filter,
final boolean enableFlowControl, final int maxRate,
final boolean started,
@@ -117,7 +117,7 @@
// ServerConsumer implementation ----------------------------------------------------------------------
- public int getID()
+ public long getID()
{
return id;
}
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/ServerProducerImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/ServerProducerImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/ServerProducerImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -45,7 +45,7 @@
{
private static final Logger log = Logger.getLogger(ServerProducerImpl.class);
- private final int id;
+ private final long id;
private final ServerSession session;
@@ -63,7 +63,7 @@
// Constructors ----------------------------------------------------------------
- public ServerProducerImpl(final int id, final ServerSession session,
+ public ServerProducerImpl(final long id, final ServerSession session,
final SimpleString address,
final FlowController flowController,
final int windowSize,
@@ -84,7 +84,7 @@
// ServerProducer implementation --------------------------------------------
- public int getID()
+ public long getID()
{
return id;
}
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionImpl.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -72,6 +72,7 @@
import org.jboss.messaging.core.transaction.ResourceManager;
import org.jboss.messaging.core.transaction.Transaction;
import org.jboss.messaging.core.transaction.impl.TransactionImpl;
+import org.jboss.messaging.util.IDGenerator;
import org.jboss.messaging.util.SimpleString;
/**
@@ -97,6 +98,8 @@
private final boolean trace = log.isTraceEnabled();
+ private final String name;
+
private final long id;
private final String username;
@@ -109,11 +112,11 @@
private volatile RemotingConnection remotingConnection;
- private final Map<Integer, ServerConsumer> consumers = new ConcurrentHashMap<Integer, ServerConsumer>();
+ private final Map<Long, ServerConsumer> consumers = new ConcurrentHashMap<Long, ServerConsumer>();
- private final Map<Integer, ServerBrowserImpl> browsers = new ConcurrentHashMap<Integer, ServerBrowserImpl>();
+ private final Map<Long, ServerBrowserImpl> browsers = new ConcurrentHashMap<Long, ServerBrowserImpl>();
- private final Map<Integer, ServerProducer> producers = new ConcurrentHashMap<Integer, ServerProducer>();
+ private final Map<Long, ServerProducer> producers = new ConcurrentHashMap<Long, ServerProducer>();
private final java.util.Queue<Delivery> deliveries = new ConcurrentLinkedQueue<Delivery>();
@@ -145,14 +148,15 @@
private volatile boolean started = false;
- private volatile int objectIDSequence;
-
private final List<Runnable> failureRunners = new ArrayList<Runnable>();
+ private final IDGenerator idGenerator = new IDGenerator(0);
+
// Constructors
// ---------------------------------------------------------------------------------
public ServerSessionImpl(
+ final String name,
final long id,
final String username,
final String password,
@@ -169,6 +173,8 @@
final Channel channel,
final MessagingServer server) throws Exception
{
+ this.name = name;
+
this.id = id;
this.username = username;
@@ -265,7 +271,7 @@
{
deferredDeliveries.add(delivery);
- Packet msg = new SessionReplicateDeliveryMessage(ref.getMessage().getMessageID(), consumer.getID());
+ Packet msg = new SessionReplicateDeliveryMessage(consumer.getID(), ref.getMessage().getMessageID());
replicatingChannel.send(msg);
}
@@ -337,7 +343,7 @@
channel.close();
- server.removeSession(id);
+ server.removeSession(name);
}
public void promptDelivery(final Queue queue)
@@ -1065,8 +1071,8 @@
queueName.toString()).getConsumerMaxRate();
maxRate = queueMaxRate != null ? queueMaxRate : maxRate;
-
- ServerConsumer consumer = new ServerConsumerImpl(generateID(), this,
+
+ ServerConsumer consumer = new ServerConsumerImpl(idGenerator.generateID(), this,
binding.getQueue(), filter, windowSize != -1, maxRate, started,
storageManager, queueSettingsRepository, postOffice);
@@ -1144,7 +1150,7 @@
securityStore.check(binding.getAddress(), CheckType.READ, this);
- ServerBrowserImpl browser = new ServerBrowserImpl(generateID(), this, binding
+ ServerBrowserImpl browser = new ServerBrowserImpl(idGenerator.generateID(), this, binding
.getQueue(), filterString == null ? null : filterString
.toString());
@@ -1182,7 +1188,7 @@
final int serverWindowSize = windowToUse == -1 ? -1
: (int) (windowToUse * 0.75);
- ServerProducerImpl producer = new ServerProducerImpl(generateID(), this,
+ ServerProducerImpl producer = new ServerProducerImpl(idGenerator.generateID(), this,
address, flowController, serverWindowSize,
channel);
@@ -1197,47 +1203,47 @@
return new SessionCreateProducerResponseMessage(initialCredits, maxRateToUse);
}
- public boolean browserHasNextMessage(final int browserID) throws Exception
+ public boolean browserHasNextMessage(final long browserID) throws Exception
{
return browsers.get(browserID).hasNextMessage();
}
- public ServerMessage browserNextMessage(int browserID) throws Exception
+ public ServerMessage browserNextMessage(final long browserID) throws Exception
{
return browsers.get(browserID).nextMessage();
}
- public void browserReset(int browserID) throws Exception
+ public void browserReset(final long browserID) throws Exception
{
browsers.get(browserID).reset();
}
- public void closeBrowser(int browserID) throws Exception
+ public void closeBrowser(final long browserID) throws Exception
{
browsers.get(browserID).close();
}
- public void closeConsumer(int consumerID) throws Exception
+ public void closeConsumer(final long consumerID) throws Exception
{
consumers.get(consumerID).close();
}
- public void closeProducer(int producerID) throws Exception
+ public void closeProducer(final long producerID) throws Exception
{
producers.get(producerID).close();
}
- public void receiveConsumerCredits(int consumerID, int credits) throws Exception
+ public void receiveConsumerCredits(final long consumerID, final int credits) throws Exception
{
consumers.get(consumerID).receiveCredits(credits);
}
- public void sendProducerMessage(int producerID, ServerMessage message) throws Exception
+ public void sendProducerMessage(final long producerID, final ServerMessage message) throws Exception
{
producers.get(producerID).send(message);
}
- public void handleReplicateDelivery(long messageID, int consumerID) throws Exception
+ public void handleReplicateDelivery(final long consumerID, final long messageID) throws Exception
{
consumers.get(consumerID).deliverMessage(messageID);
@@ -1259,17 +1265,17 @@
}
public void transferConnection(final RemotingConnection newConnection)
- {
- channel.transferConnection(newConnection);
-
+ {
remotingConnection.removeFailureListener(this);
+ channel.transferConnection(newConnection);
+
//Destroy the old connection
- // remotingConnection.destroy();
+ remotingConnection.destroy();
remotingConnection = newConnection;
- remotingConnection.addFailureListener(this);
+ remotingConnection.addFailureListener(this);
}
public int replayCommands(final int lastReceivedCommandID)
@@ -1320,11 +1326,6 @@
// Private
// --------------------------------------------------------------------------------------------
- private int generateID()
- {
- return objectIDSequence++;
- }
-
private void doAck(final MessageReference ref) throws Exception
{
ServerMessage message = ref.getMessage();
Modified: trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/src/main/org/jboss/messaging/core/server/impl/ServerSessionPacketHandler.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -355,7 +355,7 @@
case SESS_REPLICATE_DELIVERY:
{
SessionReplicateDeliveryMessage message = (SessionReplicateDeliveryMessage)packet;
- session.handleReplicateDelivery(message.getMessageID(), message.getConsumerID());
+ session.handleReplicateDelivery(message.getConsumerID(), message.getMessageID());
break;
}
case SESS_REPLICATE_DELIVERY_RESP:
Added: trunk/src/main/org/jboss/messaging/util/IDGenerator.java
===================================================================
--- trunk/src/main/org/jboss/messaging/util/IDGenerator.java (rev 0)
+++ trunk/src/main/org/jboss/messaging/util/IDGenerator.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.util;
+
+/**
+ * A IDGenerator
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class IDGenerator
+{
+ private long idSequence;
+
+ private boolean wrapped;
+
+ public IDGenerator(final long startID)
+ {
+ this.idSequence = startID;
+ }
+
+ public synchronized long generateID()
+ {
+ long id = idSequence++;
+
+ if (idSequence == Long.MIN_VALUE)
+ {
+ wrapped = true;
+ }
+
+ if (wrapped)
+ {
+ //Wrap - Very unlikely to happen
+ throw new IllegalStateException("Exhausted ids to use!");
+ }
+
+ return id;
+ }
+}
Modified: trunk/tests/src/org/jboss/messaging/tests/integration/cluster/ReplicationTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/integration/cluster/ReplicationTest.java 2008-09-13 03:51:32 UTC (rev 4938)
+++ trunk/tests/src/org/jboss/messaging/tests/integration/cluster/ReplicationTest.java 2008-09-13 18:39:51 UTC (rev 4939)
@@ -121,13 +121,14 @@
backupService.stop();
}
+
public void testFailoverSameConnectionFactory() throws Exception
{
final SimpleString QUEUE = new SimpleString("CoreClientTestQueue");
Configuration backupConf = new ConfigurationImpl();
backupConf.setSecurityEnabled(false);
- backupConf.setPacketConfirmationBatchSize(10);
+ backupConf.setPacketConfirmationBatchSize(1);
Map<String, Object> backupParams = new HashMap<String, Object>();
backupParams.put(TransportConstants.SERVER_ID_PROP_NAME, 1);
backupConf.getAcceptorConfigurations().add(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMAcceptorFactory", backupParams));
@@ -137,7 +138,7 @@
Configuration liveConf = new ConfigurationImpl();
liveConf.setSecurityEnabled(false);
- liveConf.setPacketConfirmationBatchSize(10);
+ liveConf.setPacketConfirmationBatchSize(1);
liveConf.getAcceptorConfigurations().add(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMAcceptorFactory"));
liveConf.setBackupConnectorConfiguration(new TransportConfiguration("org.jboss.messaging.core.remoting.impl.invm.InVMConnectorFactory", backupParams));
MessagingService liveService = MessagingServiceImpl.newNullStorageMessagingServer(liveConf);
@@ -163,6 +164,7 @@
message.getBody().putString("testINVMCoreClient");
message.getBody().flip();
producer.send(message);
+ // log.info("sent " + i);
}
RemotingConnection conn = ((ClientSessionImpl)session).getConnection();
@@ -206,7 +208,7 @@
session.acknowledge();
- // log.info("got message " + message2.getProperty(new SimpleString("blah")));
+ //log.info("got message " + message2.getProperty(new SimpleString("blah")));
}
ClientMessage message3 = consumer.receive(1000);
@@ -215,10 +217,7 @@
liveService.stop();
backupService.stop();
-
- // todo - do we need to failover connection factories too?????
-
-
+
}
// public void testFailoverChangeConnectionFactory() throws Exception
More information about the jboss-cvs-commits
mailing list