/**
* Persistent Key-Value storage layer. Current implementation is transient,
* but assume to be backed on disk when you do your project.
*
* @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.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import java.util.Set;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
* This is a dummy KeyValue Store. Ideally this would go to disk,
* or some other backing store. For this project, we simulate the disk like
* system using a manual delay.
*
*
*
*/
public class KVStore implements KeyValueInterface {
private Map<String, String> store = null;
WriteLock writeLock;
public WriteLock getWriteLock() {
return writeLock;
}
public KVStore() {
writeLock = (new ReentrantReadWriteLock()).writeLock();
resetStore();
}
private void resetStore() {
store = new HashMap<String, String>();
}
public void put(String key, String value) throws KVException {
AutoGrader.agStorePutStarted(key, value);
try {
putDelay();
store.put(key, value);
} finally {
AutoGrader.agStorePutFinished(key, value);
}
}
public String get(String key) throws KVException {
AutoGrader.agStoreGetStarted(key);
try {
getDelay();
String retVal = this.store.get(key);
if (retVal == null) {
KVMessage msg = new KVMessage("resp", "key \"" + key + "\" does not exist in store");
throw new KVException(msg);
}
return retVal;
} finally {
AutoGrader.agStoreGetFinished(key);
}
}
public void del(String key) throws KVException {
AutoGrader.agStoreDelStarted(key);
try {
delDelay();
if(key != null)
this.store.remove(key);
} finally {
AutoGrader.agStoreDelFinished(key);
}
}
private void getDelay() {
AutoGrader.agStoreDelay();
}
private void putDelay() {
AutoGrader.agStoreDelay();
}
private void delDelay() {
AutoGrader.agStoreDelay();
}
public String toXML() {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try{
docBuilder = docFactory.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
ex.printStackTrace();
}
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("KVStore");
doc.appendChild(rootElement);
Set<String> keys = store.keySet();
for (String k : keys){
String v = store.get(k);
Element childKVPair = doc.createElement("KVPair");
Element childKey = doc.createElement("Key");
Element childValue = doc.createElement("Value");
childKey.setTextContent(k);
childValue.setTextContent(v);
childKVPair.appendChild(childKey);
childKVPair.appendChild(childValue);
rootElement.appendChild(childKVPair);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = null;
try {
transformer = transformerFactory.newTransformer();
} catch (TransformerConfigurationException ex){
ex.printStackTrace();
}
DOMSource source = new DOMSource(doc);
StringWriter strwrite = new StringWriter();
StreamResult result = new StreamResult(strwrite);
try {
transformer.transform(source,result);
} catch (TransformerException ex){
ex.printStackTrace();
}
String output = strwrite.getBuffer().toString();
return output;
}
public void dumpToFile(String fileName) {
String xmlData = toXML();
try{
FileWriter fileWrite = new FileWriter(fileName);
BufferedWriter write = new BufferedWriter(fileWrite);
write.write(xmlData);
write.close();
} catch(IOException ex){
ex.printStackTrace();
}
}
/**
* Replaces the contents of the store with the contents of a file
* written by dumpToFile; the previous contents of the store are lost.
* @param fileName the file to be read.
*/
public void restoreFromFile(String fileName) {
if (fileName != null){
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = null;
try {
docBuilder = docFactory.newDocumentBuilder();
} catch (ParserConfigurationException ex){
ex.printStackTrace();
}
try{
Document doc = docBuilder.parse(fileName);
Element docElement = doc.getDocumentElement();
NodeList kvPairs = docElement.getElementsByTagName("KVPair");
if (kvPairs != null && kvPairs.getLength() > 0){
for (int i = 0; i < kvPairs.getLength(); i++){
Element element = (Element) kvPairs.item(i);
String keys = element.getFirstChild().getTextContent();
String values = element.getLastChild().getTextContent();
store.put(keys,values);
}
}
} catch (SAXException ex){
ex.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
}
}