[251751]  Provide progress monitoring for commit operations
https://bugs.eclipse.org/bugs/show_bug.cgi?id=251751

diff --git a/plugins/org.eclipse.net4j.tcp/src/org/eclipse/net4j/internal/tcp/ControlChannel.java b/plugins/org.eclipse.net4j.tcp/src/org/eclipse/net4j/internal/tcp/ControlChannel.java
index 62a1fdd..c7d8b83 100644
--- a/plugins/org.eclipse.net4j.tcp/src/org/eclipse/net4j/internal/tcp/ControlChannel.java
+++ b/plugins/org.eclipse.net4j.tcp/src/org/eclipse/net4j/internal/tcp/ControlChannel.java
@@ -46,8 +46,6 @@
 
   public static final byte OPCODE_DEREGISTRATION = 4;
 
-  public static final byte OPCODE_DEREGISTRATION_ACK = 5;
-
   public static final byte SUCCESS = 1;
 
   public static final byte FAILURE = 0;
@@ -95,7 +93,7 @@
     return acknowledged;
   }
 
-  public boolean deregisterChannel(short channelID, long timeout)
+  public void deregisterChannel(short channelID, long timeout)
   {
     if (TRACER.isEnabled())
     {
@@ -103,21 +101,11 @@
     }
 
     assertValidChannelID(channelID);
-    ISynchronizer<Boolean> acknowledgement = acknowledgements.correlate(channelID);
-
     IBuffer buffer = provideBuffer();
     ByteBuffer byteBuffer = buffer.startPutting(CONTROL_CHANNEL_INDEX);
     byteBuffer.put(OPCODE_DEREGISTRATION);
     byteBuffer.putShort(channelID);
     handleBuffer(buffer);
-
-    Boolean acknowledged = acknowledgement.get(timeout);
-    if (acknowledged == null)
-    {
-      throw new TimeoutRuntimeException("Deregistration timeout after " + timeout + " milliseconds");
-    }
-
-    return acknowledged;
   }
 
   @Override
@@ -174,7 +162,6 @@
       case OPCODE_DEREGISTRATION:
       {
         assertConnected();
-        boolean success = true;
         short channelID = byteBuffer.getShort();
         if (channelID == CONTROL_CHANNEL_INDEX)
         {
@@ -188,15 +175,12 @@
         catch (Exception ex)
         {
           OM.LOG.error(ex);
-          success = false;
         }
 
-        sendStatus(OPCODE_DEREGISTRATION_ACK, channelID, success);
         break;
       }
 
       case OPCODE_REGISTRATION_ACK:
-      case OPCODE_DEREGISTRATION_ACK:
       {
         assertConnected();
         short channelID = byteBuffer.getShort();
@@ -225,7 +209,7 @@
   @Override
   protected void doDeactivate() throws Exception
   {
-    finishDeactivate(true);
+    // Do nothing
   }
 
   private void sendStatus(byte opcode, short channelID, boolean status)
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java
index dc09607..5cbac7e 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java
@@ -73,9 +73,10 @@
 
     protocol.close();
     assertInactive(protocol);
-    assertEquals(0, serverConnector.getChannels().size());
     assertInactive(channel);
-    assertInactive(protocol);
+
+    sleep(50);
+    assertEquals(0, serverConnector.getChannels().size());
     assertInactive(serverChannel);
     assertInactive(serverProtocol);
 
@@ -91,10 +92,10 @@
     }
   }
 
-  public void testSingleThreadNoData1000() throws Exception
+  public void testSingleThreadNoData100() throws Exception
   {
     disableConsole();
-    for (int i = 0; i < 1000; i++)
+    for (int i = 0; i < 100; i++)
     {
       IOUtil.OUT().println(Thread.currentThread().getName() + ": " + i);
       testSingleThreadNoData();
@@ -114,10 +115,10 @@
     assertInactive(protocol);
   }
 
-  public void testSingleThreadTinyData1000() throws Exception
+  public void testSingleThreadTinyData100() throws Exception
   {
     disableConsole();
-    for (int i = 0; i < 1000; i++)
+    for (int i = 0; i < 100; i++)
     {
       IOUtil.OUT().println(Thread.currentThread().getName() + ": " + i);
       testSingleThreadTinyData();
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/Channel.java b/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/Channel.java
index 08a9290..4bb4f65 100644
--- a/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/Channel.java
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/Channel.java
@@ -14,12 +14,10 @@
 import org.eclipse.net4j.buffer.IBuffer;
 import org.eclipse.net4j.buffer.IBufferHandler;
 import org.eclipse.net4j.channel.IChannelMultiplexer;
-import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
 import org.eclipse.net4j.util.concurrent.IWorkSerializer;
 import org.eclipse.net4j.util.concurrent.QueueWorkerWorkSerializer;
 import org.eclipse.net4j.util.concurrent.SynchronousWorkSerializer;
 import org.eclipse.net4j.util.lifecycle.Lifecycle;
-import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
 import org.eclipse.net4j.util.om.trace.ContextTracer;
 
 import org.eclipse.internal.net4j.bundle.OM;
@@ -54,9 +52,6 @@
 
   private transient Queue<IBuffer> sendQueue;
 
-  @ExcludeFromDump
-  private transient boolean inverseClosed;
-
   public Channel()
   {
   }
@@ -251,24 +246,7 @@
   @Override
   protected void doDeactivate() throws Exception
   {
-    if (!inverseClosed)
-    {
-      channelMultiplexer.closeChannel(this);
-    }
-
-    super.doDeactivate();
-  }
-
-  public void finishDeactivate(boolean inverse)
-  {
-    inverseClosed = inverse;
-    if (inverse)
-    {
-      LifecycleUtil.deactivate(receiveHandler);
-      deactivate();
-    }
-
-    receiveHandler = null;
+    channelMultiplexer.closeChannel(this);
     if (receiveSerializer != null)
     {
       receiveSerializer.dispose();
@@ -280,6 +258,8 @@
       sendQueue.clear();
       sendQueue = null;
     }
+
+    super.doDeactivate();
   }
 
   public void close()
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/ChannelMultiplexer.java b/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/ChannelMultiplexer.java
index dab31f3..5a85aee 100644
--- a/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/ChannelMultiplexer.java
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/ChannelMultiplexer.java
@@ -178,16 +178,13 @@
   {
     InternalChannel internalChannel = channel;
     deregisterChannelFromPeer(internalChannel, getChannelTimeout());
-    removeChannel(internalChannel, false);
+    removeChannel(internalChannel);
   }
 
   public void inverseCloseChannel(short channelID) throws ChannelException
   {
     InternalChannel channel = getChannel(channelID);
-    if (channel != null && channel.isActive())
-    {
-      removeChannel(channel, true);
-    }
+    LifecycleUtil.deactivate(channel);
   }
 
   protected InternalChannel createChannel()
@@ -334,7 +331,7 @@
     fireElementAddedEvent(channel);
   }
 
-  private void removeChannel(InternalChannel channel, boolean inverse)
+  private void removeChannel(InternalChannel channel)
   {
     try
     {
@@ -351,7 +348,6 @@
 
       if (removed)
       {
-        channel.finishDeactivate(inverse);
         fireElementRemovedEvent(channel);
       }
     }
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/InternalChannel.java b/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/InternalChannel.java
index b918dd1..90f4039 100644
--- a/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/InternalChannel.java
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/spi/net4j/InternalChannel.java
@@ -46,9 +46,4 @@
   public void handleBufferFromMultiplexer(IBuffer buffer);
 
   public Queue<IBuffer> getSendQueue();
-
-  /**
-   * @since 2.0
-   */
-  public void finishDeactivate(boolean inverse);
 }