/** * 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.example.openstorage; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import kinetic.client.ClientConfiguration; import kinetic.client.Entry; import kinetic.client.KineticClient; import kinetic.client.KineticClientFactory; import kinetic.client.KineticException; /** * * Open storage client to show an example of connecting to many drives. * <p> * This class is designed such that it assumed that VirtualDrives is up and running. * <p> * By default, 1000 simulators (VirtualDrives) are running in a separate JVM. * <p> * This class instantiates 1000 instance of KineticClient and each connects to one simulator. * <P> * Each instance of the KineticClient performs PUT/GET/DELETE/... operations on the connected simulator. * <p> * The number of concurrent client instances performing operations are defined in * {@link #main(String[])} <code>MAX_THREAD</code> variable. * <p> * Please adjust the parameters in the main method as necessary to fit your test environment. * * @see VirtualDrives * @see #main(String[]) for usage information. * * @author chiaming * */ public class OpenStorageClient implements Runnable { // String to byte[] encoding public static final String UTF8 = "utf8"; // kinetic client private KineticClient client = null; //name of client instance private int name = 0; //default port. private int port = 8123; //done signal for each iteration private CountDownLatch doneSignal = null; //iteration count private long iterateCount = 0; /** * Construct a client instance with the specified parameters. * * @param name name of the client * @param host host name for the drive * @param port port number of the drive */ public OpenStorageClient (int name, String host, int port) { try { this.name = name; this.port = port; ClientConfiguration clientConfig = new ClientConfiguration(); clientConfig.setHost(host); clientConfig.setPort(port); client = KineticClientFactory.createInstance(clientConfig); } catch (Exception e) { e.printStackTrace(); } } public void setDoneSignal (CountDownLatch doneSignal) { this.doneSignal = doneSignal; } //@SuppressWarnings("unused") public void run() { this.iterateCount ++; try { System.out.println ("running client instance: " + name + ", simulator port: " + port +", iteration=" + this.iterateCount); // initial key, value and new version byte[] key1 = stringToBytes("key1-" + port + "-" + this.iterateCount); byte[] value1 = new byte[1024]; byte[] key2 = stringToBytes("key2-" + port + "-" + this.iterateCount); byte[] value2 = new byte[1024]; // create two entries Entry entry1 = new Entry(key1, value1); Entry entry2 = new Entry(key2, value2); // forced put two entries client.putForced(entry1); client.putForced(entry2); // get entry, expect to receive entry1 Entry se1 = client.get(key1); if (se1 == null) { throw new Error ("getKey1 failed."); } // get next entry, expect to receive entry2 Entry se2 = client.getNext(key1); if (se2 == null) { throw new Error ("getKey2 failed."); } // get previous entry, expect to receive simpleEntry1 entry Entry se11 = client.getPrevious(key2); if (se11 == null) { throw new Error ("get getPrevious(key2) failed."); } // get key range from entry1 to entry2, expect to receive entry1 and // entry2 List<byte[]> keys = client.getKeyRange(key1, true, key2, true, 2); if (keys.size() !=2) { throw new Error ("getKeyRange failed."); } // delete entry1 boolean deleted = client.delete(entry1); if (deleted == false) { throw new Error ("delete entry failed"); } // forced delete entry2 deleted = client.deleteForced(key2); if (deleted == false) { throw new Error ("delete entry failed"); } } catch (Exception e) { e.printStackTrace(); //throw new Error (e); } finally { System.out.println ("Done running client instance: " + name + ", simulator port: " + port +", iteration=" + this.iterateCount); doneSignal.countDown(); } } /** * close client instance. */ public void close() { try { this.client.close(); System.out.println ("closed client instance: " + name); } catch (KineticException e) { e.printStackTrace(); } } /** * convert string to byte[] using UTF8 encoding. * * @param string * string to be converted to byte[]. * * @return the byte[] representation of the specified string */ private static byte[] stringToBytes(String string) { try { return string.getBytes(UTF8); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } /** * Start many instances of kinetic client and connect to each of the specified drives. * <p> * This class is designed such that it assumed that VirtualDrives is up and running. * <p> * By default, 1000 simulators (VirtualDrives) can be deployed and started in a separate JVM. * <p> * This class instantiates the same number of instance of KineticClient and each connects to one simulator. * <P> * Each instance of the KineticClient performs PUT/GET/DELETE/... operations on the connected simulator. * <p> * The number of concurrent client instances performing operations are defined in * {@link #main(String[])} <code>MAX_THREAD</code> variable. * <p> * Please adjust the parameters in the main method as necessary to fit your test environment. * * @param args no args is used. * @throws KineticException if any internal error occurred. * * @throws InterruptedException if interrupted. */ public static void main(String[] args) throws KineticException, InterruptedException { // start port int startPort = 8123; //assume all simulators are within the same host String host = "localhost"; //port for a specific simulator int port = 0; //max concurrent client ops int MAX_THREAD = 5; //max iterations int MAX_ITERATION = 1000; //max client instances int MAX_CLIENT = VirtualDrives.MAX_SIMULATOR; //thread pool ExecutorService service = Executors.newFixedThreadPool(MAX_THREAD); //allocate client instances OpenStorageClient[] clients = new OpenStorageClient[MAX_CLIENT]; //create client instances with sequential ports for (int i = 0; i < MAX_CLIENT; i ++) { //increase port number port = startPort + i; //create a client instance clients[i] = new OpenStorageClient(i, host, port); System.out.println ("instantiated client: " + i); } /** * performing operations on each of the conencted simulator. */ for (int j = 0; j < MAX_ITERATION; j++) { //instantiate done signal CountDownLatch doneSignal = new CountDownLatch(MAX_CLIENT); for (int i = 0; i < MAX_CLIENT; i ++) { //set done signal clients[i].setDoneSignal(doneSignal); //run client service.execute(clients[i]); } //wait for operations to finish doneSignal.await(); System.out.println("*** iteration finished: " + j + ", total simulators accessed: " + MAX_CLIENT); //pause for demo (visual) purposes Thread.sleep(3000); } //all iterations finished service.shutdownNow(); /** * close all client instances */ for (int i = 0; i < MAX_CLIENT; i ++) { clients[i].close(); } System.out.println("***** test finished, total clients = " + MAX_CLIENT); } }