From 40e3dfc61702a5c6c9b5710b525e1db43cd2920e Mon Sep 17 00:00:00 2001 From: Nitin Kumar Maharana Date: Sat, 31 Oct 2015 00:53:53 +0530 Subject: [PATCH 1/3] CLOUDSTACK-9231: Root volume migration from one primary to another primary storage within the same cluster is failing This situation arises when there are two management server accessing the same database. When the migration request comes the command is forwarded from one management server to another because the host is owned by the second management server. So, serialization of map from one to another fails. This is fixed by converting the maps to lists. --- .../agent/api/MigrateWithStorageCommand.java | 7 ++++ .../api/MigrateWithStorageReceiveAnswer.java | 12 +++--- .../api/MigrateWithStorageReceiveCommand.java | 9 +++-- .../api/MigrateWithStorageSendCommand.java | 12 +++--- ...grateWithStorageReceiveCommandWrapper.java | 17 ++++---- ...0MigrateWithStorageSendCommandWrapper.java | 30 +++++++++----- .../XenServerStorageMotionStrategy.java | 11 ++--- .../xenbase/XenServer610WrapperTest.java | 40 +++++++++---------- 8 files changed, 82 insertions(+), 56 deletions(-) diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java b/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java index 515dd2d0ab6..860c2bcfdec 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java @@ -40,6 +40,13 @@ public class MigrateWithStorageCommand extends Command { this.tgtHost = null; } + public MigrateWithStorageCommand(VirtualMachineTO vm, List> volumeToFilerAsList) { + this.vm = vm; + this.volumeToFiler = null; + this.volumeToFilerAsList = volumeToFilerAsList; + this.tgtHost = null; + } + public MigrateWithStorageCommand(VirtualMachineTO vm, Map volumeToFiler, String tgtHost) { this.vm = vm; this.volumeToFiler = volumeToFiler; diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java b/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java index 694e7642858..4dc8622a2f9 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java @@ -19,15 +19,17 @@ package com.cloud.agent.api; +import java.util.List; import java.util.Map; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.utils.Pair; public class MigrateWithStorageReceiveAnswer extends Answer { - Map volumeToSr; - Map nicToNetwork; + List> volumeToSr; + List> nicToNetwork; Map token; public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Exception ex) { @@ -37,7 +39,7 @@ public class MigrateWithStorageReceiveAnswer extends Answer { token = null; } - public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Map volumeToSr, Map nicToNetwork, + public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, List> volumeToSr, List> nicToNetwork, Map token) { super(cmd, true, null); this.volumeToSr = volumeToSr; @@ -45,11 +47,11 @@ public class MigrateWithStorageReceiveAnswer extends Answer { this.token = token; } - public Map getVolumeToSr() { + public List> getVolumeToSr() { return volumeToSr; } - public Map getNicToNetwork() { + public List> getNicToNetwork() { return nicToNetwork; } diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java b/core/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java index f75d1ee355c..66aecdbddca 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java @@ -19,17 +19,18 @@ package com.cloud.agent.api; -import java.util.Map; +import java.util.List; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.utils.Pair; public class MigrateWithStorageReceiveCommand extends Command { VirtualMachineTO vm; - Map volumeToFiler; + List> volumeToFiler; - public MigrateWithStorageReceiveCommand(VirtualMachineTO vm, Map volumeToFiler) { + public MigrateWithStorageReceiveCommand(VirtualMachineTO vm, List> volumeToFiler) { this.vm = vm; this.volumeToFiler = volumeToFiler; } @@ -38,7 +39,7 @@ public class MigrateWithStorageReceiveCommand extends Command { return vm; } - public Map getVolumeToFiler() { + public List> getVolumeToFiler() { return volumeToFiler; } diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java b/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java index 3c703ca695f..4a918334953 100644 --- a/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java +++ b/core/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java @@ -19,19 +19,21 @@ package com.cloud.agent.api; +import java.util.List; import java.util.Map; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.utils.Pair; public class MigrateWithStorageSendCommand extends Command { VirtualMachineTO vm; - Map volumeToSr; - Map nicToNetwork; + List> volumeToSr; + List> nicToNetwork; Map token; - public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map volumeToSr, Map nicToNetwork, Map token) { + public MigrateWithStorageSendCommand(VirtualMachineTO vm, List> volumeToSr, List> nicToNetwork, Map token) { this.vm = vm; this.volumeToSr = volumeToSr; this.nicToNetwork = nicToNetwork; @@ -42,11 +44,11 @@ public class MigrateWithStorageSendCommand extends Command { return vm; } - public Map getVolumeToSr() { + public List> getVolumeToSr() { return volumeToSr; } - public Map getNicToNetwork() { + public List> getNicToNetwork() { return nicToNetwork; } diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java index a377a80774e..046a4253404 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageReceiveCommandWrapper.java @@ -19,8 +19,10 @@ package com.cloud.hypervisor.xenserver.resource.wrapper.xen610; +import java.util.ArrayList; import java.util.HashMap; import java.util.Map; +import java.util.List; import com.google.gson.Gson; import org.apache.log4j.Logger; @@ -39,6 +41,7 @@ import com.cloud.network.Networks.TrafficType; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.Pair; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Host; import com.xensource.xenapi.Network; @@ -53,7 +56,7 @@ public final class XenServer610MigrateWithStorageReceiveCommandWrapper extends C public Answer execute(final MigrateWithStorageReceiveCommand command, final XenServer610Resource xenServer610Resource) { final Connection connection = xenServer610Resource.getConnection(); final VirtualMachineTO vmSpec = command.getVirtualMachine(); - final Map volumeToFiler = command.getVolumeToFiler(); + final List> volumeToFiler = command.getVolumeToFiler(); try { // In a cluster management server setup, the migrate with storage receive and send @@ -66,18 +69,18 @@ public final class XenServer610MigrateWithStorageReceiveCommandWrapper extends C // storage send command execution. Gson gson = new Gson(); // Get a map of all the SRs to which the vdis will be migrated. - final Map volumeToSr = new HashMap(); - for (final Map.Entry entry : volumeToFiler.entrySet()) { - final StorageFilerTO storageFiler = entry.getValue(); + final List> volumeToSr = new ArrayList>(); + for (final Pair entry : volumeToFiler) { + final StorageFilerTO storageFiler = entry.second(); final SR sr = xenServer610Resource.getStorageRepository(connection, storageFiler.getUuid()); - volumeToSr.put(entry.getKey(), gson.toJson(sr)); + volumeToSr.add(new Pair(entry.first(), sr)); } // Get the list of networks to which the vifs will attach. - final Map nicToNetwork = new HashMap(); + final List> nicToNetwork = new ArrayList>(); for (final NicTO nicTo : vmSpec.getNics()) { final Network network = xenServer610Resource.getNetwork(connection, nicTo); - nicToNetwork.put(nicTo, gson.toJson(network)); + nicToNetwork.add(new Pair(nicTo, network)); } final XsLocalNetwork nativeNetworkForTraffic = xenServer610Resource.getNativeNetworkForTraffic(connection, TrafficType.Storage, null); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java index 616660964e5..d847cd9e844 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xen610/XenServer610MigrateWithStorageSendCommandWrapper.java @@ -22,6 +22,7 @@ package com.cloud.hypervisor.xenserver.resource.wrapper.xen610; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.List; import com.google.gson.Gson; import org.apache.log4j.Logger; @@ -36,6 +37,7 @@ import com.cloud.hypervisor.xenserver.resource.XenServer610Resource; import com.cloud.resource.CommandWrapper; import com.cloud.resource.ResourceWrapper; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.Pair; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Network; import com.xensource.xenapi.SR; @@ -55,8 +57,8 @@ public final class XenServer610MigrateWithStorageSendCommandWrapper extends Comm final Connection connection = xenServer610Resource.getConnection(); final VirtualMachineTO vmSpec = command.getVirtualMachine(); - final Map volumeToSr = command.getVolumeToSr(); - final Map nicToNetwork = command.getNicToNetwork(); + final List> volumeToSr = command.getVolumeToSr(); + final List> nicToNetwork = command.getNicToNetwork(); final Map token = command.getToken(); final String vmName = vmSpec.getName(); @@ -78,10 +80,14 @@ public final class XenServer610MigrateWithStorageSendCommandWrapper extends Comm // Create the vdi map which tells what volumes of the vm need to go // on which sr on the destination. final Map vdiMap = new HashMap(); - for (final Map.Entry entry : volumeToSr.entrySet()) { - SR sr = gson.fromJson(entry.getValue(), SR.class); - VDI vdi = xenServer610Resource.getVDIbyUuid(connection, entry.getKey().getPath()); - vdiMap.put(vdi, sr); + for (final Pair entry : volumeToSr) { + if (entry.second() instanceof SR) { + final SR sr = (SR)entry.second(); + final VDI vdi = xenServer610Resource.getVDIbyUuid(connection, entry.first().getPath()); + vdiMap.put(vdi, sr); + } else { + throw new CloudRuntimeException("The object " + entry.second() + " passed is not of type SR."); + } } final Set vms = VM.getByNameLabel(connection, vmSpec.getName()); @@ -92,10 +98,14 @@ public final class XenServer610MigrateWithStorageSendCommandWrapper extends Comm // Create the vif map. final Map vifMap = new HashMap(); - for (final Map.Entry entry : nicToNetwork.entrySet()) { - Network network = gson.fromJson(entry.getValue(), Network.class); - VIF vif = xenServer610Resource.getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); - vifMap.put(vif, network); + for (final Pair entry : nicToNetwork) { + if (entry.second() instanceof Network) { + final Network network = (Network)entry.second(); + final VIF vif = xenServer610Resource.getVifByMac(connection, vmToMigrate, entry.first().getMac()); + vifMap.put(vif, network); + } else { + throw new CloudRuntimeException("The object " + entry.second() + " passed is not of type Network."); + } } // Check migration with storage is possible. diff --git a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java index c8367dd3ac1..36b8ad6ccf5 100644 --- a/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java +++ b/plugins/hypervisors/xenserver/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java @@ -18,7 +18,7 @@ */ package org.apache.cloudstack.storage.motion; -import java.util.HashMap; +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -59,6 +59,7 @@ import com.cloud.storage.StoragePool; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.Pair; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.VMInstanceDao; @@ -135,12 +136,12 @@ public class XenServerStorageMotionStrategy implements DataMotionStrategy { // Initiate migration of a virtual machine with it's volumes. try { - Map volumeToFilerto = new HashMap(); + List> volumeToFilerto = new ArrayList>(); for (Map.Entry entry : volumeToPool.entrySet()) { VolumeInfo volume = entry.getKey(); VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); - volumeToFilerto.put(volumeTo, filerTo); + volumeToFilerto.add(new Pair(volumeTo, filerTo)); } // Migration across cluster needs to be done in three phases. @@ -193,12 +194,12 @@ public class XenServerStorageMotionStrategy implements DataMotionStrategy { // Initiate migration of a virtual machine with it's volumes. try { - Map volumeToFilerto = new HashMap(); + List> volumeToFilerto = new ArrayList>(); for (Map.Entry entry : volumeToPool.entrySet()) { VolumeInfo volume = entry.getKey(); VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); - volumeToFilerto.put(volumeTo, filerTo); + volumeToFilerto.add(new Pair(volumeTo, filerTo)); } MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto); diff --git a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java index d5177da02a1..f294af118fc 100644 --- a/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java +++ b/plugins/hypervisors/xenserver/test/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/XenServer610WrapperTest.java @@ -56,6 +56,7 @@ import com.cloud.hypervisor.xenserver.resource.XsLocalNetwork; import com.cloud.network.Networks.TrafficType; import com.cloud.network.PhysicalNetworkSetupInfo; import com.cloud.storage.StoragePool; +import com.cloud.utils.Pair; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Network; import com.xensource.xenapi.SR; @@ -203,9 +204,9 @@ public class XenServer610WrapperTest { final StorageFilerTO storage1 = Mockito.mock(StorageFilerTO.class); final StorageFilerTO storage2 = Mockito.mock(StorageFilerTO.class); - final Map volumeToFiler = new HashMap(); - volumeToFiler.put(vol1, storage1); - volumeToFiler.put(vol2, storage2); + final List> volumeToFiler = new ArrayList>(); + volumeToFiler.add(new Pair(vol1, storage1)); + volumeToFiler.add(new Pair(vol2, storage2)); final NicTO nicTO1 = Mockito.mock(NicTO.class); final NicTO nicTO2 = Mockito.mock(NicTO.class); @@ -302,14 +303,13 @@ public class XenServer610WrapperTest { final Network network1 = Mockito.mock(Network.class); final Network network2 = Mockito.mock(Network.class); - final Map volumeToSr = new HashMap(); - Gson gson = new Gson(); - volumeToSr.put(volume1, gson.toJson(sr1)); - volumeToSr.put(volume2, gson.toJson(sr2)); + final List> volumeToSr = new ArrayList>(); + volumeToSr.add(new Pair(volume1, sr1)); + volumeToSr.add(new Pair(volume2, sr2)); - final Map nicToNetwork = new HashMap(); - nicToNetwork.put(nic1, gson.toJson(network1)); - nicToNetwork.put(nic2, gson.toJson(network2)); + final List> nicToNetwork = new ArrayList>(); + nicToNetwork.add(new Pair(nic1, network1)); + nicToNetwork.add(new Pair(nic2, network2)); final Map token = new HashMap(); @@ -368,11 +368,11 @@ public class XenServer610WrapperTest { final VolumeTO volume1 = Mockito.mock(VolumeTO.class); final VolumeTO volume2 = Mockito.mock(VolumeTO.class); - final Map volumeToSr = new HashMap(); - volumeToSr.put(volume1, "a"); - volumeToSr.put(volume2, "b"); + final List> volumeToSr = new ArrayList>(); + volumeToSr.add(new Pair(volume1, new String("a"))); + volumeToSr.add(new Pair(volume2, new String("b"))); - final Map nicToNetwork = new HashMap(); + final List> nicToNetwork = new ArrayList>(); final Map token = new HashMap(); final MigrateWithStorageSendCommand migrateStorageCommand = new MigrateWithStorageSendCommand(vmSpec, volumeToSr, nicToNetwork, token); @@ -411,13 +411,13 @@ public class XenServer610WrapperTest { final NicTO nic2 = Mockito.mock(NicTO.class); Gson gson = new Gson(); - final Map volumeToSr = new HashMap(); - volumeToSr.put(volume1, gson.toJson(sr1)); - volumeToSr.put(volume2, gson.toJson(sr2)); + final List> volumeToSr = new ArrayList>(); + volumeToSr.add(new Pair(volume1, sr1)); + volumeToSr.add(new Pair(volume2, sr2)); - final Map nicToNetwork = new HashMap(); - nicToNetwork.put(nic1, "a"); - nicToNetwork.put(nic2, "b"); + final List> nicToNetwork = new ArrayList>(); + nicToNetwork.add(new Pair(nic1, new String("a"))); + nicToNetwork.add(new Pair(nic2, new String("b"))); final Map token = new HashMap(); From 21d2423709946d77981d6bc151c4729bb361b2ec Mon Sep 17 00:00:00 2001 From: Miguel Ferreira Date: Thu, 17 Dec 2015 16:29:59 +0100 Subject: [PATCH 2/3] Add test to check that each thread has it's own execution counter --- .../network/nicira/ExecutionCounterTest.java | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java index 18797dfc544..f063b7597c3 100644 --- a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java +++ b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java @@ -22,6 +22,10 @@ package com.cloud.network.nicira; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicInteger; + import org.junit.Test; public class ExecutionCounterTest { @@ -52,4 +56,45 @@ public class ExecutionCounterTest { assertThat(executionCounter.hasReachedExecutionLimit(), equalTo(true)); } + + @Test + public void testConcurrentUpdatesToCounter() throws Exception { + final ExecutionCounter executionCounter = new ExecutionCounter(0); + final ExecutorService executorService = Executors.newFixedThreadPool(3); + final AtomicInteger counterTask1 = new AtomicInteger(-1); + final AtomicInteger counterTask2 = new AtomicInteger(-1); + final AtomicInteger counterTask3 = new AtomicInteger(-1); + + final Runnable task1 = new Runnable() { + @Override + public void run() { + executionCounter.incrementExecutionCounter().incrementExecutionCounter(); + executionCounter.incrementExecutionCounter().incrementExecutionCounter(); + counterTask1.set(executionCounter.getValue()); + } + }; + final Runnable task2 = new Runnable() { + @Override + public void run() { + executionCounter.incrementExecutionCounter().incrementExecutionCounter(); + counterTask2.set(executionCounter.getValue()); + } + }; + final Runnable task3 = new Runnable() { + @Override + public void run() { + counterTask3.set(executionCounter.getValue()); + } + }; + + executorService.execute(task1); + executorService.execute(task2); + executorService.execute(task3); + + executorService.shutdown(); + + assertThat(counterTask1.get(), equalTo(4)); + assertThat(counterTask2.get(), equalTo(2)); + assertThat(counterTask3.get(), equalTo(0)); + } } From c35c4164d94cd6c1878b841080e96ac073342ddd Mon Sep 17 00:00:00 2001 From: Miguel Ferreira Date: Thu, 17 Dec 2015 19:47:08 +0100 Subject: [PATCH 3/3] Fix execution counter to support separate counts per thread --- .../com/cloud/network/nicira/ExecutionCounter.java | 12 ++++++++---- .../cloud/network/nicira/ExecutionCounterTest.java | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/nicira/ExecutionCounter.java b/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/nicira/ExecutionCounter.java index 1314498211b..7eedebbf1d9 100644 --- a/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/nicira/ExecutionCounter.java +++ b/plugins/network-elements/nicira-nvp/src/main/java/com/cloud/network/nicira/ExecutionCounter.java @@ -19,15 +19,19 @@ package com.cloud.network.nicira; -import java.util.concurrent.atomic.AtomicInteger; - public class ExecutionCounter { private final int executionLimit; - private final AtomicInteger executionCount = new AtomicInteger(0); + private final ThreadLocal executionCount; public ExecutionCounter(final int executionLimit) { this.executionLimit = executionLimit; + executionCount = new ThreadLocal() { + @Override + protected Integer initialValue() { + return new Integer(0); + } + }; } public ExecutionCounter resetExecutionCounter() { @@ -40,7 +44,7 @@ public class ExecutionCounter { } public ExecutionCounter incrementExecutionCounter() { - executionCount.incrementAndGet(); + executionCount.set(executionCount.get() + 1); return this; } diff --git a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java index f063b7597c3..b14694dc098 100644 --- a/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java +++ b/plugins/network-elements/nicira-nvp/src/test/java/com/cloud/network/nicira/ExecutionCounterTest.java @@ -24,6 +24,7 @@ import static org.hamcrest.Matchers.equalTo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; @@ -92,6 +93,7 @@ public class ExecutionCounterTest { executorService.execute(task3); executorService.shutdown(); + executorService.awaitTermination(5L, TimeUnit.SECONDS); assertThat(counterTask1.get(), equalTo(4)); assertThat(counterTask2.get(), equalTo(2));