/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2016-2016 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ package org.pentaho.di.concurrency; import org.junit.Before; import org.junit.Test; import org.pentaho.di.www.CarteObjectEntry; import org.pentaho.di.www.SocketPortAllocation; import org.pentaho.di.www.TransformationMap; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; public class TransformationMapConcurrentTest { TransformationMap transformationMap; int numberOfSameAllocations = 10; int numberOfSameSourceAndTargetSlaveNameAllocations = 40; int numberOfDifferentAllocations = 100; int numberOfSameHosts = 100; int numberOfDeallocateTasks = 100; List<ConcurrentAllocate> concurrentAllocateTasks; List<ConcurrentDeallocate> concurrentDeallocateTasks; @Before public void setup() throws Exception { transformationMap = new TransformationMap(); concurrentAllocateTasks = new ArrayList<>(); concurrentDeallocateTasks = new ArrayList<>(); // adding equal port allocations for ( int i = 1; i <= numberOfSameAllocations; i++ ) { concurrentAllocateTasks.add( new ConcurrentAllocate( 40000, "host0", "id0", "trans0", "slave0", "source0", "0", "slave-0", "target0", "0" ) ); } // adding allocations with equal hostname, source and slave name. Should not allocate one port as there is // no deallocate tasks and !spa.isAllocated() returns true for ( int i = 1; i <= numberOfSameSourceAndTargetSlaveNameAllocations; i++ ) { concurrentAllocateTasks.add( new ConcurrentAllocate( 40000, "host1", "id" + i, "trans" + i, "slave-1", "source" + i, "" + i, "slave-2", "target" + i, "" + i ) ); } // adding different allocations for ( int i = 2; i <= numberOfDifferentAllocations + 1; i++ ) { concurrentAllocateTasks.add( new ConcurrentAllocate( 40000, "host" + i, "id" + i, "trans" + i, "slave-" + i, "source" + i, "" + i, "slave-" + i, "target" + i, "" + i ) ); } // adding allocations which have the same hostname as different ones but diff properties for ( int i = 1; i <= numberOfSameHosts; i++ ) { concurrentAllocateTasks.add( new ConcurrentAllocate( 40000, "host" + i, "diff", "diff", "diff", "diff", "diff", "diff", "diff", "diff" ) ); } for ( int i = 0; i < numberOfDeallocateTasks; i++ ) { CarteObjectEntry carteObjectEntry = new CarteObjectEntry( "trans" + i, "id" + 1 ); concurrentDeallocateTasks.add( new ConcurrentDeallocate( i, "host" + i, carteObjectEntry ) ); } } @Test public void testConcurrentAllocateServerSocketPort() throws Exception { ConcurrencyTestRunner.runAndCheckNoExceptionRaised( concurrentAllocateTasks, Collections.emptyList(), new AtomicBoolean( true ) ); } @Test public void testConcurrentAllocateAndDeallocateServerSocketPort() throws Exception { ConcurrencyTestRunner.runAndCheckNoExceptionRaised( concurrentDeallocateTasks, concurrentAllocateTasks, new AtomicBoolean( true ) ); } private class ConcurrentAllocate implements Callable<SocketPortAllocation> { int portRangeStart; String hostname; String clusteredRunId; String transformationName; String sourceSlaveName; String sourceStepName; String sourceStepCopy; String targetSlaveName; String targetStepName; String targetStepCopy; public ConcurrentAllocate( int portRangeStart, String hostname, String clusteredRunId, String transformationName, String sourceSlaveName, String sourceStepName, String sourceStepCopy, String targetSlaveName, String targetStepName, String targetStepCopy ) { this.portRangeStart = portRangeStart; this.hostname = hostname; this.clusteredRunId = clusteredRunId; this.transformationName = transformationName; this.sourceSlaveName = sourceSlaveName; this.sourceStepName = sourceStepName; this.sourceStepCopy = sourceStepCopy; this.targetSlaveName = targetSlaveName; this.targetStepName = targetStepName; this.targetStepCopy = targetStepCopy; } @Override public SocketPortAllocation call() throws Exception { return transformationMap.allocateServerSocketPort( portRangeStart, hostname, clusteredRunId, transformationName, sourceSlaveName, sourceStepName, sourceStepCopy, targetSlaveName, targetStepName, targetStepCopy ); } } private class ConcurrentDeallocate implements Callable<Object> { int port; String hostname; CarteObjectEntry entry; ConcurrentDeallocate( int port, String hostname, CarteObjectEntry entry ) { this.port = port; this.hostname = hostname; this.entry = entry; } @Override public Object call() throws Exception { transformationMap.deallocateServerSocketPorts( entry ); transformationMap.deallocateServerSocketPort( port, hostname ); return null; } } }