diff --git a/homework-g596-proskurina/pom.xml b/homework-g596-proskurina/pom.xml index 2601fce37..3167acfd9 100644 --- a/homework-g596-proskurina/pom.xml +++ b/homework-g596-proskurina/pom.xml @@ -25,5 +25,10 @@ 1.0.0 test + + com.google.guava + guava + 19.0 + \ No newline at end of file diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/FileWorker.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/FileWorker.java index f8cd6066c..5bc16778f 100644 --- a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/FileWorker.java +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/FileWorker.java @@ -14,19 +14,26 @@ private static void exists(String fileName) throws FileNotFoundException { } } + public FileWorker() { + } + public static String read(String fileName) throws FileNotFoundException { StringBuffer inputData = new StringBuffer(); exists(fileName); File file = new File(fileName); - try (BufferedReader in = new BufferedReader(new FileReader(file.getAbsoluteFile()))) { - String s; - while ((s = in.readLine()) != null) { - inputData.append(s); - inputData.append("\n"); + try { + BufferedReader in = new BufferedReader(new FileReader(file.getAbsoluteFile())); + try { + String s; + while ((s = in.readLine()) != null) { + inputData.append(s); + inputData.append("\n"); + } + } finally { + in.close(); } - } catch (IOException e) { throw new RuntimeException(e); } @@ -50,4 +57,4 @@ public static void write(String fileName, String text) { throw new RuntimeException(e); } } -} +} \ No newline at end of file diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorage.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorage.java index b5189196e..fac6b4e31 100644 --- a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorage.java +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorage.java @@ -2,7 +2,6 @@ import ru.mipt.java2016.homework.base.task2.KeyValueStorage; -import java.io.File; import java.io.FileNotFoundException; import java.util.HashMap; import java.util.Iterator; @@ -13,7 +12,10 @@ */ public class ImplementationKeyValueStorage implements KeyValueStorage { - private final Map map = new HashMap<>(); + private final HashMap map = new HashMap<>(); + + private final String keyName; + private final String valueName; private final SerialiserInterface keySerialiser; private final SerialiserInterface valueSerialiser; @@ -28,11 +30,14 @@ public ImplementationKeyValueStorage(String keyName, String valueName, SerialiserInterface keySerialiser, SerialiserInterface valueSerialiser, String directoryPath) { + this.keyName = keyName; + this.valueName = valueName; + this.keySerialiser = keySerialiser; this.valueSerialiser = valueSerialiser; file = new FileWorker(); - fileName = directoryPath + File.separator + "myFile.db"; + fileName = directoryPath + "/myFile.db"; try { String inputData = file.read(fileName); @@ -62,60 +67,57 @@ public ImplementationKeyValueStorage(String keyName, String valueName, } - private void checkIfFileIsOpen() { - if (!openFlag) { - throw new RuntimeException("Storage is closed"); - } - } - @Override public V read(K key) { - checkIfFileIsOpen(); - return map.get(key); - + if (openFlag) { + return map.get(key); + } else { + throw new RuntimeException("Storage is closed"); + } } @Override public boolean exists(K key) { - checkIfFileIsOpen(); return map.containsKey(key); } @Override public void write(K key, V value) { - checkIfFileIsOpen(); - map.put(key, value); + if (openFlag) { + map.put(key, value); + } else { + throw new RuntimeException("Storage is closed"); + } } @Override public void delete(K key) { - checkIfFileIsOpen(); map.remove(key); } @Override public Iterator readKeys() { - checkIfFileIsOpen(); - return map.keySet().iterator(); + if (openFlag) { + return map.keySet().iterator(); + } else { + throw new RuntimeException("Storage is closed"); + } } @Override public int size() { - checkIfFileIsOpen(); return map.size(); } @Override public void close() { - checkIfFileIsOpen(); openFlag = false; writeData(); - map.clear(); } public void writeData() { StringBuffer text = new StringBuffer(VALIDATION_STRING + "\n"); - text.append(keySerialiser.getType()).append('\n').append(valueSerialiser.getType()).append('\n'); + text.append(keyName).append('\n').append(valueName).append('\n'); text.append(map.size()).append('\n'); for (Map.Entry entry : map.entrySet()) { text.append(keySerialiser.serialise(entry.getKey())) @@ -127,4 +129,4 @@ public void writeData() { } -} +} \ No newline at end of file diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseDouble.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseDouble.java index 35015e12e..5b6613a34 100644 --- a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseDouble.java +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseDouble.java @@ -14,8 +14,4 @@ public Double deserialise(String inString) { return Double.parseDouble(inString); } - @Override - public String getType() { - return "Double"; - } } diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseInteger.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseInteger.java index 2d58a183b..1b92d7f95 100644 --- a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseInteger.java +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseInteger.java @@ -15,8 +15,4 @@ public Integer deserialise(String inString) { return Integer.parseInt(inString); } - @Override - public String getType() { - return "Integer"; - } } diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseString.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseString.java index 3ca159ecd..f51b6d343 100644 --- a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseString.java +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseString.java @@ -16,8 +16,4 @@ public String deserialise(String inString) { return inString; } - @Override - public String getType() { - return "String"; - } } diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiserInterface.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiserInterface.java index c92800c09..e26ace3b3 100644 --- a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiserInterface.java +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiserInterface.java @@ -9,5 +9,4 @@ public interface SerialiserInterface { T deserialise(String inString); - String getType(); } diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task3/FileWorker.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task3/FileWorker.java new file mode 100644 index 000000000..182704eeb --- /dev/null +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task3/FileWorker.java @@ -0,0 +1,167 @@ +package ru.mipt.java2016.homework.g596.proskurina.task3; + +import java.io.*; +import java.nio.ByteBuffer; + +/** + * Created by Lenovo on 31.10.2016. + */ +public class FileWorker implements Closeable { + + private final File file; + private final String fileName; + + private InputStream readBuffer; + private OutputStream writeBuffer; + + private long currentPositionInStream; + + public FileWorker(String fileName) { + this.file = new File(fileName); + this.fileName = fileName; + } + + public void createFile() { + try { + file.createNewFile(); + } catch (IOException e) { + System.out.println("file didn't created"); + throw new RuntimeException(e); + } + } + + public void rename(String newName) { + File newFile = new File(newName); + file.renameTo(newFile); + } + + public void appendMode() { + try { + close(); + writeBuffer = new FileOutputStream(file.getAbsoluteFile(), true); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public boolean exist() { + return file.exists(); + } + + private boolean innerExist() throws FileNotFoundException { + if (!exist()) { + throw new FileNotFoundException(fileName); + } + return true; + } + + public void flushSubmit() { + if (writeBuffer != null) { + try { + writeBuffer.flush(); + writeBuffer.close(); + writeBuffer = null; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + public long write(String str) { + try { + innerExist(); + if (writeBuffer == null) { + writeBuffer = new BufferedOutputStream(new FileOutputStream(file.getAbsoluteFile())); + } + byte[] bytes = str.getBytes(); + byte[] bytesNumber = ByteBuffer.allocate(4).putInt(bytes.length).array(); + writeBuffer.write(bytesNumber); + writeBuffer.write(bytes); + return 4 + bytes.length; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public String read() { + try { + innerExist(); + if (readBuffer == null) { + readBuffer = new BufferedInputStream(new FileInputStream(file.getAbsoluteFile())); + currentPositionInStream = 0; + } + if (readBuffer.available() < 4) { + readBuffer.close(); + readBuffer = null; + return null; + } + byte[] bytesNumberArray = new byte[4]; + int bytesNumberArraySize = readBuffer.read(bytesNumberArray, 0, 4); + //addToCalc(bytes); + if (bytesNumberArraySize < 4) { + readBuffer.close(); + throw new RuntimeException("Error in reading bytes number"); + } + currentPositionInStream += bytesNumberArraySize; + int bytesNumber = ByteBuffer.wrap(bytesNumberArray).getInt(); + byte[] bytesArray = new byte[bytesNumber]; + int bytesArraySize = readBuffer.read(bytesArray, 0, bytesNumber); + if (bytesArraySize < bytesNumber) { + readBuffer.close(); + throw new RuntimeException("Error in reading bytes"); + } + currentPositionInStream += bytesArraySize; + return new String(bytesArray); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public long fileLength() { + try (FileInputStream inputStream = new FileInputStream(file.getAbsoluteFile())) { + return inputStream.available(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void goToPosition(long position) { + try { + innerExist(); + if (readBuffer == null || currentPositionInStream > position) { + if (readBuffer != null) { + readBuffer.close(); + } + readBuffer = new BufferedInputStream(new FileInputStream(file.getAbsoluteFile())); + currentPositionInStream = 0; + } + while (currentPositionInStream < position) { + currentPositionInStream += readBuffer.skip(position - currentPositionInStream); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public void delete() { + file.delete(); + } + + @Override + public void close() { + try { + if (readBuffer != null) { + readBuffer.close(); + currentPositionInStream = 0; + readBuffer = null; + } + if (writeBuffer != null) { + writeBuffer.flush(); + writeBuffer.close(); + writeBuffer = null; + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task3/ImplementationKeyValueStorage.java b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task3/ImplementationKeyValueStorage.java new file mode 100644 index 000000000..006e8bd68 --- /dev/null +++ b/homework-g596-proskurina/src/main/java/ru/mipt/java2016/homework/g596/proskurina/task3/ImplementationKeyValueStorage.java @@ -0,0 +1,264 @@ +package ru.mipt.java2016.homework.g596.proskurina.task3; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; +import ru.mipt.java2016.homework.g596.proskurina.task2.SerialiserInterface; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Created by Lenovo on 31.10.2016. + */ +public class ImplementationKeyValueStorage implements KeyValueStorage { + + private final Map keyPositionMap; + + private final SerialiserInterface keySerialiser; + private final SerialiserInterface valueSerialiser; + + private final Set deleteKeySet = new HashSet<>(); + + private final FileWorker keyPositionFile; + private final FileWorker valuesFile; + private final FileWorker deleteKeyFile; + private final FileWorker lockFile; + + private final String directoryPath; + + private Long currentPositionInValuesFile = new Long(0); + + private final ReentrantReadWriteLock rwlock = new ReentrantReadWriteLock(); + private final Lock rlock = rwlock.readLock(); + private final Lock wlock = rwlock.writeLock(); + + private boolean writing = true; + private boolean needRebuild = false; + private boolean openFlag = true; + + private final int maxSizeOfCache = 42; + + private LoadingCache cacheValues = CacheBuilder.newBuilder() + .maximumSize(maxSizeOfCache) + .build( + new CacheLoader() { + @Override + public V load(K k) throws RuntimeException { + V result = readKey(keyPositionMap.get(k)); + if (result == null) { + throw new RuntimeException("no such key"); + } + return result; + } + }); + + public ImplementationKeyValueStorage(SerialiserInterface keySerialiser, SerialiserInterface valueSerialiser, + String directoryPath) { + + this.keySerialiser = keySerialiser; + this.valueSerialiser = valueSerialiser; + + keyPositionMap = new HashMap<>(); + + if (directoryPath == null || directoryPath.equals("")) { + this.directoryPath = ""; + } else { + this.directoryPath = directoryPath + File.separator; + } + keyPositionFile = new FileWorker(this.directoryPath + "keyPositionFile.db"); + valuesFile = new FileWorker(this.directoryPath + "valuesFile.db"); + deleteKeyFile = new FileWorker(this.directoryPath + "deleteKeyFile.db"); + lockFile = new FileWorker(this.directoryPath + "lockFile.db"); + if (lockFile.exist()) { + throw new RuntimeException("we already have working storage"); + } else { + lockFile.createFile(); + } + if (!keyPositionFile.exist()) { + keyPositionFile.createFile(); + valuesFile.createFile(); + deleteKeyFile.createFile(); + } else { + currentPositionInValuesFile = valuesFile.fileLength(); + initStorage(); + } + valuesFile.appendMode(); + } + + private void initStorage() { + keyPositionFile.close(); + int cnt = 0; + String nextKey = keyPositionFile.read(); + while (nextKey != null) { + Long position = Long.parseLong(keyPositionFile.read()); + keyPositionMap.put(keySerialiser.deserialise(nextKey), position); + nextKey = keyPositionFile.read(); + cnt++; + } + nextKey = deleteKeyFile.read(); + while (nextKey != null) { + K key = keySerialiser.deserialise(nextKey); + deleteKeySet.add(key); + keyPositionMap.remove(key); + nextKey = deleteKeyFile.read(); + cnt++; + } + keyPositionFile.appendMode(); + deleteKeyFile.close(); + if (cnt > 2 * keyPositionMap.size()) { + needRebuild = true; + } + } + + private void checkIfStorageIsOpen() { + if (!openFlag) { + throw new RuntimeException("Storage is closed"); + } + } + + @Override + public V read(K key) { + wlock.lock(); + try { + checkIfStorageIsOpen(); + Long position = keyPositionMap.get(key); + if (position != null) { + try { + return cacheValues.get(key); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } else { + return null; + } + } finally { + wlock.unlock(); + } + } + + @Override + public boolean exists(K key) { + wlock.lock(); + try { + checkIfStorageIsOpen(); + return keyPositionMap.containsKey(key); + } finally { + wlock.unlock(); + } + } + + + @Override + public void write(K key, V value) { + wlock.lock(); + checkIfStorageIsOpen(); + deleteKeySet.remove(key); + keyPositionMap.put(key, currentPositionInValuesFile); + writeToFile(key, value); + wlock.unlock(); + } + + @Override + public void delete(K key) { + wlock.lock(); + checkIfStorageIsOpen(); + deleteKeySet.add(key); + keyPositionMap.remove(key); + wlock.unlock(); + } + + @Override + public Iterator readKeys() { + wlock.lock(); + try { + checkIfStorageIsOpen(); + return keyPositionMap.keySet().iterator(); + } finally { + wlock.unlock(); + } + } + + @Override + public int size() { + rlock.lock(); + try { + checkIfStorageIsOpen(); + return keyPositionMap.size(); + } finally { + rlock.unlock(); + } + } + + @Override + public void close() throws IOException { + wlock.lock(); + if (openFlag) { + openFlag = false; + keyPositionFile.close(); + if (needRebuild) { + rebuild(); + } else { + writeToFileDeleteKeySet(); + valuesFile.close(); + } + deleteKeyFile.close(); + lockFile.delete(); + } + wlock.unlock(); + } + + private void rebuild() { + try (FileWorker newValuesFile = new FileWorker(directoryPath + "newValuesFile.db")) { + newValuesFile.createFile(); + currentPositionInValuesFile = 0L; + for (Map.Entry entry : keyPositionMap.entrySet()) { + keyPositionFile.write(keySerialiser.serialise(entry.getKey())); + keyPositionFile.write(currentPositionInValuesFile.toString()); + currentPositionInValuesFile += + newValuesFile.write(valueSerialiser.serialise(readKey(entry.getValue()))); + } + keyPositionFile.flushSubmit(); + newValuesFile.flushSubmit(); + valuesFile.close(); + valuesFile.delete(); + newValuesFile.rename(directoryPath + "valuesFile.db"); + } + } + + private V readKey(long position) { + if (writing) { + valuesFile.close(); + writing = false; + } + valuesFile.goToPosition(position); + return valueSerialiser.deserialise(valuesFile.read()); + } + + private void writeToFile(K key, V value) { + if (!writing) { + valuesFile.close(); + valuesFile.appendMode(); + writing = true; + } + keyPositionFile.write(keySerialiser.serialise(key)); + keyPositionFile.write(currentPositionInValuesFile.toString()); + currentPositionInValuesFile += valuesFile.write(valueSerialiser.serialise(value)); + } + + private void writeToFileDeleteKeySet() { + if (!deleteKeyFile.exist()) { + deleteKeyFile.createFile(); + } + for (K entry : deleteKeySet) { + deleteKeyFile.write(keySerialiser.serialise(entry)); + } + deleteKeyFile.flushSubmit(); + deleteKeySet.clear(); + } +} diff --git a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorageTest.java b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorageTest.java index 5bd639b6f..376193d5a 100644 --- a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorageTest.java +++ b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/ImplementationKeyValueStorageTest.java @@ -2,27 +2,25 @@ import ru.mipt.java2016.homework.base.task2.KeyValueStorage; import ru.mipt.java2016.homework.tests.task2.AbstractSingleFileStorageTest; -import ru.mipt.java2016.homework.tests.task2.Student; -import ru.mipt.java2016.homework.tests.task2.StudentKey; public class ImplementationKeyValueStorageTest extends AbstractSingleFileStorageTest { @Override - protected KeyValueStorage buildStringsStorage(String path) { - return new ImplementationKeyValueStorage<>("String", "String", - new SerialiseString(), new SerialiseString(), + protected KeyValueStorage buildStringsStorage(String path) { + return new ImplementationKeyValueStorage<>("String", "Sering", + new SerialiseString(), new SerialiseString(), path) ; } @Override - protected KeyValueStorage buildNumbersStorage(String path) { + protected KeyValueStorage buildNumbersStorage(String path) { return new ImplementationKeyValueStorage<>("Integer", "Double", new SerialiseInteger(), new SerialiseDouble(), path) ; } @Override - protected KeyValueStorage buildPojoStorage(String path) { + protected KeyValueStorage buildPojoStorage(String path) { return new ImplementationKeyValueStorage<>("StudentKey", "Student", new SerialiseStudentKey(), new SerialiseStudent(), path) ; diff --git a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudent.java b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudent.java index fa855b060..6adba6192 100644 --- a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudent.java +++ b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudent.java @@ -42,8 +42,4 @@ public Student deserialise(String inString) { return new Student(groupId, name, hometown, birthDate, hasDormitory, averageScore); } - @Override - public String getType() { - return "Student"; - } } diff --git a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudentKey.java b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudentKey.java index ec2d9f40e..827451ec3 100644 --- a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudentKey.java +++ b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task2/SerialiseStudentKey.java @@ -27,9 +27,4 @@ public StudentKey deserialise(String inString) { return new StudentKey(groupId, name); } - @Override - public String getType() { - return "StudentKey"; - } - } diff --git a/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task3/ImplementationKeyValueStoragePerformanceTest.java b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task3/ImplementationKeyValueStoragePerformanceTest.java new file mode 100644 index 000000000..e161fe8fc --- /dev/null +++ b/homework-g596-proskurina/src/test/java/ru/mipt/java2016/homework/g596/proskurina/task3/ImplementationKeyValueStoragePerformanceTest.java @@ -0,0 +1,30 @@ +package ru.mipt.java2016.homework.g596.proskurina.task3; + +import ru.mipt.java2016.homework.g596.proskurina.task2.*; +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; +import ru.mipt.java2016.homework.tests.task3.KeyValueStoragePerformanceTest; + +/** + * Created by Lenovo on 17.12.2016. + */ +public class ImplementationKeyValueStoragePerformanceTest extends KeyValueStoragePerformanceTest { + + @Override + protected KeyValueStorage buildStringsStorage(String path) { + return new ImplementationKeyValueStorage<>(new SerialiseString(), new SerialiseString(), + path) ; + } + + @Override + protected KeyValueStorage buildNumbersStorage(String path) { + return new ImplementationKeyValueStorage<>(new SerialiseInteger(), new SerialiseDouble(), + path) ; + } + + @Override + protected KeyValueStorage buildPojoStorage(String path) { + return new ImplementationKeyValueStorage<>(new SerialiseStudentKey(), new SerialiseStudent(), + path) ; + } + +}