/** * 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.simulator.console.multi; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import org.testng.annotations.BeforeMethod; import org.testng.Assert; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import kinetic.client.ClientConfiguration; import kinetic.client.Entry; import kinetic.client.EntryMetadata; import kinetic.client.KineticClient; import kinetic.client.KineticClientFactory; import kinetic.client.KineticException; import kinetic.simulator.KineticSimulator; import kinetic.simulator.SimulatorConfiguration; /** * * multi server, start server, close server then restart server, do the * put/get/delete operation * <p> * * @author Chenchong(Emma) Li * */ @Test(groups = {"simulator"}) public class MultiKineticSimulatorOperationTest { private final Logger logger = Logger .getLogger(MultiKineticSimulatorOperationTest.class.getName()); private final int INIT_PORT = 18123; private final int INIT_SSL_PORT = 18443; private final int SERVER_COUNTS = 10; private final int OPERATE_COUNTS = 100; private final long SLEEP_TIME = 200; private final byte[] INIT_VERSION = "0".getBytes(); private final KVGenerator kvGenerator = new KVGenerator(); private final List<SimulatorConfiguration> serverConfigs = new ArrayList<SimulatorConfiguration>(); private final List<ClientConfiguration> clientConfigs = new ArrayList<ClientConfiguration>(); private final List<KineticSimulator> servers = new ArrayList<KineticSimulator>(); @BeforeMethod public void setUp() throws Exception { init(); startServers(); kvGenerator.reset(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticClient kineticClient = KineticClientFactory .createInstance(clientConfigs.get(i)); multiDelete(kineticClient, OPERATE_COUNTS); kineticClient.close(); } closeServers(); } @AfterMethod public void tearDown() throws Exception { startServers(); kvGenerator.reset(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticClient kineticClient = KineticClientFactory .createInstance(clientConfigs.get(i)); multiDelete(kineticClient, OPERATE_COUNTS); kineticClient.close(); } closeServers(); } @Test public void multiServerOperationTest() throws KineticException, UnsupportedEncodingException, InterruptedException { // step 1 // start server, multi put, close server startServers(); kvGenerator.reset(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticClient kineticClient = KineticClientFactory .createInstance(clientConfigs.get(i)); multiPut(kineticClient, OPERATE_COUNTS); kineticClient.close(); } closeServers(); logger.info("multi put finished"); // step 2 // start server, multi get, close server startServers(); kvGenerator.reset(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticClient kineticClient = KineticClientFactory .createInstance(clientConfigs.get(i)); multiGetAndVerify(kineticClient, OPERATE_COUNTS, false); kineticClient.close(); } closeServers(); logger.info("multi get finished"); // step 3 // start server, multi delete, close server startServers(); kvGenerator.reset(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticClient kineticClient = KineticClientFactory .createInstance(clientConfigs.get(i)); multiDelete(kineticClient, OPERATE_COUNTS); kineticClient.close(); } closeServers(); // step 4 // start server, multi get, close server startServers(); kvGenerator.reset(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticClient kineticClient = KineticClientFactory .createInstance(clientConfigs.get(i)); multiGetAndVerify(kineticClient, OPERATE_COUNTS, true); kineticClient.close(); } closeServers(); } private void init() { for (int i = 0; i < SERVER_COUNTS; i++) { SimulatorConfiguration serverConfig = new SimulatorConfiguration(); ClientConfiguration clientConfig = new ClientConfiguration(); int port = INIT_PORT + i; int sslPort = INIT_SSL_PORT + i; serverConfig.setPort(port); serverConfig.setSslPort(sslPort); serverConfig.put(SimulatorConfiguration.PERSIST_HOME, "multi_server_" + port); // set nio services thread pool size serverConfig.setNioServiceBossThreads(1); serverConfig.setNioServiceWorkerThreads(1); clientConfig.setPort(port); // nio threads in pool clientConfig.setNioServiceThreads(1); serverConfigs.add(serverConfig); clientConfigs.add(clientConfig); } } private void startServers() throws InterruptedException { servers.clear(); for (int i = 0; i < SERVER_COUNTS; i++) { KineticSimulator server = new KineticSimulator(serverConfigs.get(i)); servers.add(server); // logger.info("server start, port=" // + servers.get(i).getServerConfiguration().getPort()); Thread.sleep(SLEEP_TIME); } } private void closeServers() { for (int i = 0; i < SERVER_COUNTS; i++) { servers.get(i).close(); // logger.info("server close, port=" // + servers.get(i).getServerConfiguration().getPort()); } } private void multiPut(KineticClient client, int putCounts) throws UnsupportedEncodingException, KineticException { Entry versioned = null; for (int i = 0; i < putCounts; i++) { String key = kvGenerator.getNextKey(); String value = kvGenerator.getValue(key); EntryMetadata entryMetadata = new EntryMetadata(); versioned = new Entry(toByteArray(key), toByteArray(value), entryMetadata); client.put(versioned, INIT_VERSION); } } private void multiGetAndVerify(KineticClient client, int getCounts, boolean afterDelete) throws UnsupportedEncodingException, KineticException { for (int i = 0; i < getCounts; i++) { String key = kvGenerator.getNextKey(); Entry vGetReturn = client.get(toByteArray(key)); if (afterDelete) { if (null != vGetReturn) { Assert.fail("the value is not null after deleting"); } } else { if (null == vGetReturn) { Assert.fail("get a null vesioned"); } assertTrue(equals(toByteArray(kvGenerator.getValue(key)), vGetReturn.getValue())); } } } private void multiDelete(KineticClient client, int deleteCounts) throws KineticException, UnsupportedEncodingException { Entry versioned = null; for (int i = 0; i < deleteCounts; i++) { String key = kvGenerator.getNextKey(); versioned = client.get(toByteArray(key)); if (null != versioned && null != versioned.getKey()) { client.delete(versioned); } } } // convert String to byte[] private byte[] toByteArray(String s) throws UnsupportedEncodingException { return s.getBytes("utf8"); } // compare two byte[] equal private boolean equals(byte[] byteArray1, byte[] byteArray2) { if (null == byteArray1 && null == byteArray2) { return true; } else if (null == byteArray1 || null == byteArray2) { return false; } else { if (byteArray1.length != byteArray2.length) { return false; } else { for (int i = 0; i < byteArray1.length; i++) { if (byteArray1[i] != byteArray2[i]) { return false; } } } } return true; } // generator the key value, support reset and getNextKey and getValue class KVGenerator { private String keyPrefix = "key"; private String valuePrefix = "value"; private int start = 0; private int current = 0; private final int alignLength = ("" + Integer.MAX_VALUE).length() + 1; public KVGenerator() { } private String align(int id) { String idAsString = "" + id; int length = idAsString.length(); for (int i = 0; i < alignLength - length; i++) { idAsString = "0" + idAsString; } return idAsString; } public KVGenerator(int start) { this.start = start; this.current = start; } public KVGenerator(String keyPrefix, String valuePrefix, int start) { this.keyPrefix = keyPrefix; this.valuePrefix = valuePrefix; this.start = start; this.current = start; } public void reset() { this.current = start; } public synchronized String getNextKey() { if (current >= Integer.MAX_VALUE) { throw new RuntimeException("out of keys"); } return keyPrefix + align(current++); } public String getValue(String key) { int keyId = Integer.parseInt(key.replaceAll(keyPrefix, "")); return valuePrefix + keyId; } } }