/** * Client component for generating load for the KeyValue store. * This is also used by the Master server to reach the slave nodes. * * @author Mosharaf Chowdhury (http://www.mosharaf.com) * @author Prashanth Mohan (http://www.cs.berkeley.edu/~prmohan) * * Copyright (c) 2012, University of California at Berkeley * All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of University of California, Berkeley nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package edu.berkeley.cs162; import java.net.Socket; /** * This class is used to communicate with (appropriately marshalling and * unmarshalling) objects implementing the {@link KeyValueInterface}. * * @param <K> * Java Generic type for the Key * @param <V> * Java Generic type for the Value */ public class KVClient implements KeyValueInterface { private boolean ignoreNext = false; private String server = null; private int port = 0; /** * @param server * is the DNS reference to the Key-Value server * @param port * is the port on which the Key-Value server is listening */ public KVClient(String server, int port) { this.server = server; this.port = port; } private Socket connectHost() throws KVException { KVMessage errorMessage; Socket serverSock; try { serverSock = new Socket(server, port); } catch (java.net.UnknownHostException e) { errorMessage = new KVMessage("resp", "Network Error: Could not connect"); throw new KVException(errorMessage); } catch (java.io.IOException e) { errorMessage = new KVMessage("resp", "Network Error: Could not create socket"); throw new KVException(errorMessage); } return serverSock; } private void closeHost(Socket sock) throws KVException { KVMessage errorMessage = new KVMessage("resp", "Network Error: Could not close socket"); try { sock.close(); } catch (java.io.IOException e) { throw new KVException(errorMessage); } if (!sock.isClosed()) { throw new KVException(errorMessage); } } public void put(String key, String value) throws KVException { if (ignoreNext) { ignoreNext = false; } else { KVMessage putResponse; Socket serverSock = connectHost(); KVMessage putMessage = new KVMessage("putreq"); putMessage.setKey(key); putMessage.setValue(value); try { putMessage.sendMessage(serverSock); } catch (KVException e) { KVMessage errorMessage = new KVMessage("resp", "Network Error: could not send data"); throw new KVException(errorMessage); } putResponse = new KVMessage(serverSock); if (!putResponse.getMessage().equals("Success")) { throw new KVException(putResponse); } closeHost(serverSock); } } public String get(String key) throws KVException { if (ignoreNext) { ignoreNext = false; return ""; } else { KVMessage getResponse; Socket serverSock = connectHost(); KVMessage getMessage = new KVMessage("getreq"); getMessage.setKey(key); try { getMessage.sendMessage(serverSock); } catch (KVException e) { KVMessage errorMessage = new KVMessage("resp", "Network Error: could not send data"); throw new KVException(errorMessage); } getResponse = new KVMessage(serverSock); if (!getResponse.getMessage().equals("Success")) { throw new KVException(getResponse); } closeHost(serverSock); return getResponse.getValue(); } } public void del(String key) throws KVException { if (ignoreNext) { ignoreNext = false; } else { KVMessage delResponse; Socket serverSock = connectHost(); KVMessage delMessage = new KVMessage("delreq"); delMessage.setKey(key); try { delMessage.sendMessage(serverSock); } catch (KVException e) { KVMessage errorMessage = new KVMessage("resp", "Network Error: could not send data"); throw new KVException(errorMessage); } delResponse = new KVMessage(serverSock); if (!delResponse.getMessage().equals("Success")) { throw new KVException(delResponse); } closeHost(serverSock); } } public void ignoreNext() throws KVException { ignoreNext = true; } }