/** * Copyright 2013-2015 Seagate Technology LLC. * * This Source Code Form is subject to the terms of the Mozilla * Public License, v. 2.0. If a copy of the MPL was not * distributed with this file, You can obtain one at * https://mozilla.org/MP:/2.0/. * * This program is distributed in the hope that it will be useful, * but is provided AS-IS, WITHOUT ANY WARRANTY; including without * the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or * FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public * License for more details. * * See www.openkinetic.org for more project information */ package com.seagate.kinetic.concurrent; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.Test; import org.testng.Assert; import static com.seagate.kinetic.KineticTestHelpers.toByteArray; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.logging.Logger; import kinetic.client.Entry; import kinetic.client.EntryMetadata; import kinetic.client.KineticClient; import kinetic.client.KineticClientFactory; import kinetic.client.KineticException; import com.seagate.kinetic.IntegrationTestCase; import com.seagate.kinetic.IntegrationTestLoggerFactory; /** * * Multi client(thread) concurrent put the same key with increased version * number into simulator/drive. Verify the put result and put order. * <p> * */ @Test(groups = {"simulator", "drive"}) public class KineticPutConcurrentTest extends IntegrationTestCase { private static final Logger logger = IntegrationTestLoggerFactory .getLogger(KineticPutConcurrentTest.class.getName()); private int writeThreads = 2; private int writesEachThread = 100; /** * * Concurrent threads put same key test. * * @throws KineticException * if any kinetic internal error occurred. * @throws InterruptedException * if any interrupt error occurred. */ @Test(dataProvider = "transportProtocolOptions") public void sameKeyConcurrentPutTest(String clientName) throws KineticException, InterruptedException { String key = "samekey"; CountDownLatch latch = new CountDownLatch(writeThreads); ExecutorService pool = Executors.newCachedThreadPool(); getClient(clientName).deleteForced(toByteArray(key)); // thread pool generate threads(concurrent client number) KineticClient kineticClient = null; for (int i = 0; i < writeThreads; i++) { kineticClient = KineticClientFactory .createInstance(kineticClientConfigutations.get(clientName)); // every threads write using the same key pool.execute(new SameKeyWriteThread(kineticClient, key, writesEachThread, latch)); } // wait all threads finish latch.await(); pool.shutdown(); // kineticClient.deleteForced(toByteArray(key)); logger.info(this.testEndInfo()); } /** * * Every thread(client) execute writeCount number * <p> * */ class SameKeyWriteThread implements Runnable { private int writeCount = 0; private CountDownLatch latch; private String key; private KineticClient kineticClient; public SameKeyWriteThread(KineticClient kineticClient, String key, int writeCount, CountDownLatch latch) { this.kineticClient = kineticClient; this.key = key; this.writeCount = writeCount; this.latch = latch; } @Override public void run() { int count = 0; int versionAsInt = 0; byte[] dbVersion = null; Entry vPut = null; Entry vPutReturn = null; Entry vGetReturn = null; byte[] version = null; while (true) { try { version = ("" + versionAsInt).getBytes(); EntryMetadata entryMetadata = new EntryMetadata(); entryMetadata.setVersion(dbVersion); vPut = new Entry(toByteArray(key), version, entryMetadata); vPutReturn = kineticClient.put(vPut, version); assertEquals(new String(vPutReturn.getEntryMetadata() .getVersion()), new String(vPutReturn.getValue())); // logger.info("put version: " + new String(version) // + " success"); dbVersion = vPutReturn.getEntryMetadata().getVersion(); versionAsInt++; count++; } catch (KineticException e1) { // logger.info("put operation expected version mismatch exception, " // + e1.getMessage()); try { vGetReturn = kineticClient.get(key.getBytes()); versionAsInt = Integer.parseInt(new String(vGetReturn .getEntryMetadata().getVersion())); assertTrue(versionAsInt >= Integer.parseInt(new String( version))); dbVersion = vGetReturn.getEntryMetadata().getVersion(); versionAsInt++; count++; } catch (KineticException e) { Assert.fail("fail to get the version" + e.getMessage()); } } finally { if (count == writeCount) { break; } } } try { kineticClient.close(); } catch (KineticException e) { Assert.fail("close kineticClient failed, " + e.getMessage()); } latch.countDown(); } } }