From 3b50057335394c7383fce52d2eb4e8a1c44e06d3 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 21 Nov 2016 17:02:03 +0300 Subject: [PATCH 01/29] Add third task --- .../ConcreteStrategyDoubleRandomAccess.java | 22 ++ .../ConcreteStrategyIntegerRandomAccess.java | 22 ++ .../ConcreteStrategyStringRandomAccess.java | 35 +++ .../task3/OptimisedKeyValueStorage.java | 229 ++++++++++++++++++ .../SerializationStrategyRandomAccess.java | 17 ++ 5 files changed, 325 insertions(+) create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java new file mode 100644 index 000000000..579b58bca --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java @@ -0,0 +1,22 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Vardan Manucharyan + * @since 30.10.16 + */ +public class ConcreteStrategyDoubleRandomAccess implements SerializationStrategyRandomAccess { + @Override + public void serializeToFile(Double value, RandomAccessFile output) throws IOException { + output.writeDouble(value); + } + + @Override + public Double deserializeFromFile(RandomAccessFile input) throws IOException { + return input.readDouble(); + } +} \ No newline at end of file diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java new file mode 100644 index 000000000..dfc177f7c --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java @@ -0,0 +1,22 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Vardan Manucharyan + * @since 30.10.16 + */ +public class ConcreteStrategyIntegerRandomAccess implements SerializationStrategyRandomAccess { + @Override + public void serializeToFile(Integer value,RandomAccessFile output) throws IOException { + output.writeInt(value); + } + + @Override + public Integer deserializeFromFile(RandomAccessFile input) throws IOException { + return input.readInt(); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java new file mode 100644 index 000000000..04f2f726b --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java @@ -0,0 +1,35 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Vardan Manucharyan + * @since 30.10.16 + */ +public class ConcreteStrategyStringRandomAccess implements SerializationStrategyRandomAccess { + @Override + public void serializeToFile(String value, RandomAccessFile output) throws IOException { + writeString(output, value); + } + + @Override + public String deserializeFromFile(RandomAccessFile input) throws IOException { + return readString(input); + } + + //serializing functions + public static void writeString(RandomAccessFile output, String string) throws IOException { + output.writeInt(string.length()); + output.write(string.getBytes("UTF-8")); + } + + public static String readString(RandomAccessFile input) throws IOException { + int len = input.readInt(); + byte[] bytes = new byte[len]; + input.read(bytes); + return new String(bytes); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java new file mode 100644 index 000000000..c46a13061 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -0,0 +1,229 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Iterator; + +import javafx.util.Pair; +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; +import ru.mipt.java2016.homework.g595.manucharyan.task3.SerializationStrategyRandomAccess; + +import static java.lang.Math.max; + +/** + * @author Vardan Manucharyan + * @since 20.11.2016. + */ +public class OptimisedKeyValueStorage implements KeyValueStorage { + + private static final long MAX_CACHE_SIZE = 100L; + + private SerializationStrategyRandomAccess keySerializationStrategy; + private SerializationStrategyRandomAccess valueSerializationStrategy; + + //consist keys and offsets(the pair of begin and length) + private HashMap> base = new HashMap<>(); + private HashMap cache = new HashMap<>(); + + private long maxOffset; + private RandomAccessFile storage; + private RandomAccessFile mapStorage; + + private File mutexFile; // для многопоточности + private boolean isClosed; + + public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializationStrategy, + SerializationStrategyRandomAccess valueSerializaionStrategy, + String path) throws IOException { + + this.keySerializationStrategy = keySerializationStrategy; + this.valueSerializationStrategy = valueSerializaionStrategy; + maxOffset = 0L; + + mutexFile = new File(path, "Mutex"); + if (!mutexFile.createNewFile()) { + throw new RuntimeException("Can't synchronize!"); + } + + File directory = new File(path); + if (!directory.isDirectory()) { + throw new RuntimeException("wrong path"); + } + + File file = new File(path, "storage.db"); + storage = new RandomAccessFile(file, "rw"); + + File file2 = new File(path, "mapStorage.db"); + mapStorage = new RandomAccessFile(file2, "rw"); + + if (file.exists() && file.exists()) { + uploadDataFromStorage(); + } else if (!file.createNewFile() || file2.createNewFile()) { + throw new RuntimeException("Can't create a storage!"); + } + + isClosed = false; + } + + /** + * Возвращает значение для данного ключа, если оно есть в хранилище. + * Иначе возвращает null. + */ + @Override + public V read(K key) { + if (!exists(key)) { + return null; + } else { + try { + if (cache.get(key) != null) { + return cache.get(key); + } + + Pair offset = base.get(key); + storage.seek(offset.getKey()); + return valueSerializationStrategy.deserializeFromFile(storage); + } catch(Exception exception) { + throw new RuntimeException("Can't read from storage"); + } + } + } + + /** + * Возвращает true, если данный ключ есть в хранилище + */ + @Override + public boolean exists(K key) { + if(isClosed) return false; + if(cache.containsKey(key)) return true; + return base.containsKey(key); + } + + /** + * Записывает в хранилище пару ключ-значение. + */ + @Override + public void write(K key, V value) { + if (isClosed) { + throw new RuntimeException("Can't write: storage is closed"); + } else { + cache.put(key, value); + base.put(key, new Pair<>(0L, 0L)); + + if(cache.size() > MAX_CACHE_SIZE) { + writeCacheToStorage(); + } + } + } + + /** + * Удаляет пару ключ-значение из хранилища. + */ + @Override + public void delete(K key) { + if (isClosed) { + throw new RuntimeException("Can't delete: storage is closed"); + } else { + cache.remove(key); + base.remove(key); + } + } + + /** + * Читает все ключи в хранилище. + *

+ * Итератор должен бросать {@link java.util.ConcurrentModificationException}, + * если данные в хранилище были изменены в процессе итерирования. + */ + @Override + public Iterator readKeys() { + if (isClosed) { + throw new RuntimeException("Can't iterate: storage is closed"); + } else { + return base.keySet().iterator(); + } + } + + /** + * Возвращает число ключей, которые сейчас в хранилище. + */ + @Override + public int size() { + return base.size(); + } + + @Override + public void close() { + reorganiseStorage(); + downnloadDataToStorage(); + isClosed = true; + cache.clear(); + base.clear(); + mutexFile.delete(); + } + + private void uploadDataFromStorage() { + try { + + int count; + count = mapStorage.readInt(); + + for (int i = 0; i < count; i++) { + K key = keySerializationStrategy.deserializeFromFile(mapStorage); + Long tmp1 = mapStorage.readLong(); + Long tmp2 = mapStorage.readLong(); + base.put(key, new Pair<>(tmp1, tmp2)); + maxOffset = max(maxOffset, tmp1 + tmp2); + } + } catch (IOException exception) { + throw new RuntimeException("Trouble with storage.db"); + } + } + + private void downnloadDataToStorage() { + try { + + writeCacheToStorage(); + + mapStorage.writeInt(size()); + + for (HashMap.Entry> entry : base.entrySet()) { + keySerializationStrategy.serializeToFile(entry.getKey(), mapStorage); + mapStorage.writeLong(entry.getValue().getKey()); + mapStorage.writeLong(entry.getValue().getValue()); + } + } catch (IOException exception) { + throw new RuntimeException("Trouble with storage.db"); + } + } + + private void writeCacheToStorage(){ + if (isClosed) { + throw new RuntimeException("Can't write: storage is closed"); + } else { + try { + for (HashMap.Entry entry : cache.entrySet()) { + storage.seek(maxOffset); + valueSerializationStrategy.serializeToFile(entry.getValue(), storage); + long curOffset = storage.getFilePointer(); + base.put(entry.getKey(), new Pair<>(maxOffset, curOffset - maxOffset)); + maxOffset = curOffset; + } + cache.clear(); + + } catch (IOException exception) { + throw new RuntimeException("Can't write cache on the disk"); + } + } + } + + private void reorganiseStorage() { + + } +} + diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java new file mode 100644 index 000000000..5f72e5f53 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java @@ -0,0 +1,17 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * @author Vardan Manucharyan + * @since 30.10.16 + */ +public interface SerializationStrategyRandomAccess { + + void serializeToFile(Value value, RandomAccessFile output) throws IOException; + + Value deserializeFromFile(RandomAccessFile input) throws IOException; +} From 10c6e3d0c6fb2a17fe5463c6b29bb7663a6c28f8 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 21 Nov 2016 23:58:22 +0300 Subject: [PATCH 02/29] Third task --- .../task3/OptimisedKeyValueStorage.java | 98 ++++++++++++------- ...oncreteStrategyStudentKeyRandomAccess.java | 24 +++++ .../ConcreteStrategyStudentRandomAccess.java | 30 ++++++ .../task3/OptimisedKeyValueStorageTest.java | 54 ++++++++++ 4 files changed, 171 insertions(+), 35 deletions(-) create mode 100644 homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java create mode 100644 homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java create mode 100644 homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorageTest.java diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index c46a13061..0086e4079 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -1,18 +1,12 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Iterator; -import javafx.util.Pair; import ru.mipt.java2016.homework.base.task2.KeyValueStorage; -import ru.mipt.java2016.homework.g595.manucharyan.task3.SerializationStrategyRandomAccess; import static java.lang.Math.max; @@ -28,41 +22,45 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private SerializationStrategyRandomAccess valueSerializationStrategy; //consist keys and offsets(the pair of begin and length) - private HashMap> base = new HashMap<>(); + private HashMap base = new HashMap<>(); private HashMap cache = new HashMap<>(); private long maxOffset; + private final String pathname; private RandomAccessFile storage; + private final String storageName = "storage.txt"; private RandomAccessFile mapStorage; + private final String mapStorageName = "mapStorage.txt"; private File mutexFile; // для многопоточности private boolean isClosed; public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializationStrategy, - SerializationStrategyRandomAccess valueSerializaionStrategy, - String path) throws IOException { + SerializationStrategyRandomAccess valueSerializaionStrategy, + String path) throws IOException { this.keySerializationStrategy = keySerializationStrategy; this.valueSerializationStrategy = valueSerializaionStrategy; maxOffset = 0L; + pathname = path; - mutexFile = new File(path, "Mutex"); + mutexFile = new File(pathname, "Mutex"); if (!mutexFile.createNewFile()) { throw new RuntimeException("Can't synchronize!"); } - File directory = new File(path); + File directory = new File(pathname); if (!directory.isDirectory()) { throw new RuntimeException("wrong path"); } - File file = new File(path, "storage.db"); + File file = new File(pathname, storageName); storage = new RandomAccessFile(file, "rw"); - File file2 = new File(path, "mapStorage.db"); + File file2 = new File(path, mapStorageName); mapStorage = new RandomAccessFile(file2, "rw"); - if (file.exists() && file.exists()) { + if (file.exists() && file2.exists()) { uploadDataFromStorage(); } else if (!file.createNewFile() || file2.createNewFile()) { throw new RuntimeException("Can't create a storage!"); @@ -85,10 +83,10 @@ public V read(K key) { return cache.get(key); } - Pair offset = base.get(key); - storage.seek(offset.getKey()); + Long offset = base.get(key); + storage.seek(offset); return valueSerializationStrategy.deserializeFromFile(storage); - } catch(Exception exception) { + } catch (Exception exception) { throw new RuntimeException("Can't read from storage"); } } @@ -99,8 +97,8 @@ public V read(K key) { */ @Override public boolean exists(K key) { - if(isClosed) return false; - if(cache.containsKey(key)) return true; + if (isClosed) return false; + if (cache.containsKey(key)) return true; return base.containsKey(key); } @@ -113,9 +111,9 @@ public void write(K key, V value) { throw new RuntimeException("Can't write: storage is closed"); } else { cache.put(key, value); - base.put(key, new Pair<>(0L, 0L)); + base.put(key, 0L); - if(cache.size() > MAX_CACHE_SIZE) { + if (cache.size() > MAX_CACHE_SIZE) { writeCacheToStorage(); } } @@ -159,8 +157,15 @@ public int size() { @Override public void close() { + writeCacheToStorage(); reorganiseStorage(); downnloadDataToStorage(); + try { + mapStorage.close(); + storage.close(); + } catch (IOException excetion) { + throw new RuntimeException("Can't close storage"); + } isClosed = true; cache.clear(); base.clear(); @@ -170,39 +175,40 @@ public void close() { private void uploadDataFromStorage() { try { - int count; + int count = -1; count = mapStorage.readInt(); for (int i = 0; i < count; i++) { K key = keySerializationStrategy.deserializeFromFile(mapStorage); - Long tmp1 = mapStorage.readLong(); - Long tmp2 = mapStorage.readLong(); - base.put(key, new Pair<>(tmp1, tmp2)); - maxOffset = max(maxOffset, tmp1 + tmp2); + Long tmp = mapStorage.readLong(); + base.put(key, tmp); + maxOffset = max(maxOffset, tmp); } } catch (IOException exception) { - throw new RuntimeException("Trouble with storage.db"); + base.clear(); + //throw new RuntimeException("Trouble with storage.db"); } } private void downnloadDataToStorage() { try { - - writeCacheToStorage(); + mapStorage.close(); + File file = new File(pathname, mapStorageName); + assert (file.delete()); + file = new File(pathname, mapStorageName); + mapStorage = new RandomAccessFile(file, "rw"); mapStorage.writeInt(size()); - - for (HashMap.Entry> entry : base.entrySet()) { + for (HashMap.Entry entry : base.entrySet()) { keySerializationStrategy.serializeToFile(entry.getKey(), mapStorage); - mapStorage.writeLong(entry.getValue().getKey()); - mapStorage.writeLong(entry.getValue().getValue()); + mapStorage.writeLong(entry.getValue()); } } catch (IOException exception) { throw new RuntimeException("Trouble with storage.db"); } } - private void writeCacheToStorage(){ + private void writeCacheToStorage() { if (isClosed) { throw new RuntimeException("Can't write: storage is closed"); } else { @@ -211,7 +217,7 @@ private void writeCacheToStorage(){ storage.seek(maxOffset); valueSerializationStrategy.serializeToFile(entry.getValue(), storage); long curOffset = storage.getFilePointer(); - base.put(entry.getKey(), new Pair<>(maxOffset, curOffset - maxOffset)); + base.put(entry.getKey(), maxOffset); maxOffset = curOffset; } cache.clear(); @@ -223,7 +229,29 @@ private void writeCacheToStorage(){ } private void reorganiseStorage() { + try { + File file = new File(pathname, "newStorage.txt"); + RandomAccessFile newStorage = new RandomAccessFile(file, "rw"); + + assert (cache.isEmpty()); + for (HashMap.Entry entry : base.entrySet()) { + storage.seek(entry.getValue()); + Long tmp = newStorage.getFilePointer(); + valueSerializationStrategy.serializeToFile(read(entry.getKey()), newStorage); + base.put(entry.getKey(), tmp); + } + + storage.close(); + File file1 = new File(pathname, storageName); + assert (file1.delete()); + + newStorage.close(); + assert (file.renameTo(file1)); + + } catch (IOException exception) { + throw new RuntimeException("Can't reorganise storage!"); + } } } diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java new file mode 100644 index 000000000..e5b54624c --- /dev/null +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java @@ -0,0 +1,24 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +import ru.mipt.java2016.homework.tests.task2.StudentKey; + +/** + * @author Vardan Manucharyan + * @since 30.10.16 + */ +public class ConcreteStrategyStudentKeyRandomAccess implements SerializationStrategyRandomAccess { + + @Override + public void serializeToFile(StudentKey value, RandomAccessFile output) throws IOException { + output.writeInt(value.getGroupId()); + ConcreteStrategyStringRandomAccess.writeString(output, value.getName()); + } + + @Override + public StudentKey deserializeFromFile(RandomAccessFile input) throws IOException { + return new StudentKey(input.readInt(), ConcreteStrategyStringRandomAccess.readString(input)); + } +} diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java new file mode 100644 index 000000000..81f2ad012 --- /dev/null +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java @@ -0,0 +1,30 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Date; + +import ru.mipt.java2016.homework.tests.task2.Student; + +/** + * @author Vardan Manucharyan + * @since 30.10.16 + */ +public class ConcreteStrategyStudentRandomAccess implements SerializationStrategyRandomAccess { + @Override + public void serializeToFile(Student value, RandomAccessFile output) throws IOException { + output.writeInt(value.getGroupId()); + ConcreteStrategyStringRandomAccess.writeString(output, value.getName()); + ConcreteStrategyStringRandomAccess.writeString(output, value.getHometown()); + output.writeLong(value.getBirthDate().getTime()); + output.writeBoolean(value.isHasDormitory()); + output.writeDouble(value.getAverageScore()); + } + + @Override + public Student deserializeFromFile(RandomAccessFile input) throws IOException { + return new Student(input.readInt(), ConcreteStrategyStringRandomAccess.readString(input), + ConcreteStrategyStringRandomAccess.readString(input), new Date(input.readLong()), + input.readBoolean(), input.readDouble()); + } +} diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorageTest.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorageTest.java new file mode 100644 index 000000000..843cf1ff7 --- /dev/null +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorageTest.java @@ -0,0 +1,54 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task3; + +import java.io.IOException; + +import ru.mipt.java2016.homework.tests.task2.Student; +import ru.mipt.java2016.homework.tests.task2.StudentKey; +import ru.mipt.java2016.homework.tests.task3.KeyValueStoragePerformanceTest; + +/** + * @author Vardan Manucharyan + * @since 20.11.16 + */ +public class OptimisedKeyValueStorageTest extends KeyValueStoragePerformanceTest { + private ConcreteStrategyStringRandomAccess + cs1 = new ConcreteStrategyStringRandomAccess(), + cs2 = new ConcreteStrategyStringRandomAccess(); + + @Override + protected OptimisedKeyValueStorage buildStringsStorage(String Path) { + try { + return new OptimisedKeyValueStorage<>(cs1, cs2, Path); + } catch (IOException e) { + throw new RuntimeException("Op, you got a problems"); + } + } + + private ConcreteStrategyIntegerRandomAccess + cs3 = new ConcreteStrategyIntegerRandomAccess(); + private ConcreteStrategyDoubleRandomAccess + cs4 = new ConcreteStrategyDoubleRandomAccess(); + + @Override + protected OptimisedKeyValueStorage buildNumbersStorage(String Path) { + try { + return new OptimisedKeyValueStorage<>(cs3, cs4, Path); + } catch (IOException e) { + throw new RuntimeException("Op, you got a problems"); + } + } + + private ConcreteStrategyStudentKeyRandomAccess + cs5 = new ConcreteStrategyStudentKeyRandomAccess(); + private ConcreteStrategyStudentRandomAccess + cs6 = new ConcreteStrategyStudentRandomAccess(); + + @Override + protected OptimisedKeyValueStorage buildPojoStorage(String Path) { + try { + return new OptimisedKeyValueStorage<>(cs5, cs6, Path); + } catch (IOException e) { + throw new RuntimeException("Op, you got a problems"); + } + } +} From 2f58fa2632da02216a0e270a5c00237a56edc882 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Tue, 22 Nov 2016 00:11:19 +0300 Subject: [PATCH 03/29] Codestyle changes --- .../task3/ConcreteStrategyDoubleRandomAccess.java | 2 -- .../task3/ConcreteStrategyIntegerRandomAccess.java | 4 +--- .../task3/ConcreteStrategyStringRandomAccess.java | 2 -- .../g595/manucharyan/task3/OptimisedKeyValueStorage.java | 8 ++++++-- .../task3/SerializationStrategyRandomAccess.java | 2 -- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java index 579b58bca..791bf0b3b 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java @@ -1,7 +1,5 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.RandomAccessFile; diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java index dfc177f7c..0b4821a09 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java @@ -1,7 +1,5 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.RandomAccessFile; @@ -11,7 +9,7 @@ */ public class ConcreteStrategyIntegerRandomAccess implements SerializationStrategyRandomAccess { @Override - public void serializeToFile(Integer value,RandomAccessFile output) throws IOException { + public void serializeToFile(Integer value, RandomAccessFile output) throws IOException { output.writeInt(value); } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java index 04f2f726b..5d221076a 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java @@ -1,7 +1,5 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.RandomAccessFile; diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 0086e4079..555665aaf 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -97,8 +97,12 @@ public V read(K key) { */ @Override public boolean exists(K key) { - if (isClosed) return false; - if (cache.containsKey(key)) return true; + if (isClosed) { + return false; + } + if (cache.containsKey(key)) { + return true; + } return base.containsKey(key); } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java index 5f72e5f53..629fcd4e3 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java @@ -1,7 +1,5 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.RandomAccessFile; From a9c4c95e48631cb6626d26624fb406c1518dc2e0 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Tue, 22 Nov 2016 00:48:59 +0300 Subject: [PATCH 04/29] add synchronised --- .../task3/OptimisedKeyValueStorage.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 555665aaf..8873a485a 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -74,7 +74,7 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ * Иначе возвращает null. */ @Override - public V read(K key) { + public synchronized V read(K key) { if (!exists(key)) { return null; } else { @@ -110,7 +110,7 @@ public boolean exists(K key) { * Записывает в хранилище пару ключ-значение. */ @Override - public void write(K key, V value) { + public synchronized void write(K key, V value) { if (isClosed) { throw new RuntimeException("Can't write: storage is closed"); } else { @@ -127,7 +127,7 @@ public void write(K key, V value) { * Удаляет пару ключ-значение из хранилища. */ @Override - public void delete(K key) { + public synchronized void delete(K key) { if (isClosed) { throw new RuntimeException("Can't delete: storage is closed"); } else { @@ -156,11 +156,15 @@ public Iterator readKeys() { */ @Override public int size() { - return base.size(); + if (isClosed) { + throw new RuntimeException("Can't know size: storage is closed"); + } else { + return base.size(); + } } @Override - public void close() { + public synchronized void close() { writeCacheToStorage(); reorganiseStorage(); downnloadDataToStorage(); From a9f1fc8b60fba51ebc68af251ae6903bb8ddaf77 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 13:59:16 +0300 Subject: [PATCH 05/29] Review changes --- .../ConcreteStrategyDoubleRandomAccess.java | 6 +- .../ConcreteStrategyIntegerRandomAccess.java | 6 +- .../ConcreteStrategyStringRandomAccess.java | 22 +-- .../task3/OptimisedKeyValueStorage.java | 131 +++++++++--------- .../SerializationStrategyRandomAccess.java | 6 +- ...oncreteStrategyStudentKeyRandomAccess.java | 10 +- .../ConcreteStrategyStudentRandomAccess.java | 14 +- 7 files changed, 98 insertions(+), 97 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java index 791bf0b3b..d83706cb1 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -9,12 +11,12 @@ */ public class ConcreteStrategyDoubleRandomAccess implements SerializationStrategyRandomAccess { @Override - public void serializeToFile(Double value, RandomAccessFile output) throws IOException { + public void serializeToFile(Double value, DataOutput output) throws IOException { output.writeDouble(value); } @Override - public Double deserializeFromFile(RandomAccessFile input) throws IOException { + public Double deserializeFromFile(DataInput input) throws IOException { return input.readDouble(); } } \ No newline at end of file diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java index 0b4821a09..7010a272d 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -9,12 +11,12 @@ */ public class ConcreteStrategyIntegerRandomAccess implements SerializationStrategyRandomAccess { @Override - public void serializeToFile(Integer value, RandomAccessFile output) throws IOException { + public void serializeToFile(Integer value, DataOutput output) throws IOException { output.writeInt(value); } @Override - public Integer deserializeFromFile(RandomAccessFile input) throws IOException { + public Integer deserializeFromFile(DataInput input) throws IOException { return input.readInt(); } } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java index 5d221076a..42381a39b 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -9,25 +11,13 @@ */ public class ConcreteStrategyStringRandomAccess implements SerializationStrategyRandomAccess { @Override - public void serializeToFile(String value, RandomAccessFile output) throws IOException { - writeString(output, value); + public void serializeToFile(String value, DataOutput output) throws IOException { + output.writeUTF(value); } @Override - public String deserializeFromFile(RandomAccessFile input) throws IOException { - return readString(input); + public String deserializeFromFile(DataInput input) throws IOException { + return input.readUTF(); } - //serializing functions - public static void writeString(RandomAccessFile output, String string) throws IOException { - output.writeInt(string.length()); - output.write(string.getBytes("UTF-8")); - } - - public static String readString(RandomAccessFile input) throws IOException { - int len = input.readInt(); - byte[] bytes = new byte[len]; - input.read(bytes); - return new String(bytes); - } } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 8873a485a..f4a64768a 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -5,11 +5,10 @@ import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Iterator; +import java.util.Map; import ru.mipt.java2016.homework.base.task2.KeyValueStorage; -import static java.lang.Math.max; - /** * @author Vardan Manucharyan * @since 20.11.2016. @@ -18,12 +17,12 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private static final long MAX_CACHE_SIZE = 100L; - private SerializationStrategyRandomAccess keySerializationStrategy; - private SerializationStrategyRandomAccess valueSerializationStrategy; + private final SerializationStrategyRandomAccess keySerializationStrategy; + private final SerializationStrategyRandomAccess valueSerializationStrategy; //consist keys and offsets(the pair of begin and length) - private HashMap base = new HashMap<>(); - private HashMap cache = new HashMap<>(); + private Map base = new HashMap<>(); + private Map cache = new HashMap<>(); private long maxOffset; private final String pathname; @@ -43,6 +42,7 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ this.valueSerializationStrategy = valueSerializaionStrategy; maxOffset = 0L; pathname = path; + isClosed = false; mutexFile = new File(pathname, "Mutex"); if (!mutexFile.createNewFile()) { @@ -54,19 +54,17 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ throw new RuntimeException("wrong path"); } - File file = new File(pathname, storageName); - storage = new RandomAccessFile(file, "rw"); + try { + File file = new File(pathname, storageName); + storage = new RandomAccessFile(file, "rw"); - File file2 = new File(path, mapStorageName); - mapStorage = new RandomAccessFile(file2, "rw"); + File file2 = new File(path, mapStorageName); + mapStorage = new RandomAccessFile(file2, "rw"); - if (file.exists() && file2.exists()) { - uploadDataFromStorage(); - } else if (!file.createNewFile() || file2.createNewFile()) { + downloadDataFromStorage(); + }catch(IOException exception) { throw new RuntimeException("Can't create a storage!"); } - - isClosed = false; } /** @@ -97,9 +95,8 @@ public synchronized V read(K key) { */ @Override public boolean exists(K key) { - if (isClosed) { - return false; - } + isClose(); + if (cache.containsKey(key)) { return true; } @@ -111,15 +108,13 @@ public boolean exists(K key) { */ @Override public synchronized void write(K key, V value) { - if (isClosed) { - throw new RuntimeException("Can't write: storage is closed"); - } else { - cache.put(key, value); - base.put(key, 0L); + isClose(); - if (cache.size() > MAX_CACHE_SIZE) { - writeCacheToStorage(); - } + cache.put(key, value); + base.put(key, 0L); + + if (cache.size() > MAX_CACHE_SIZE) { + writeCacheToStorage(); } } @@ -128,12 +123,11 @@ public synchronized void write(K key, V value) { */ @Override public synchronized void delete(K key) { - if (isClosed) { - throw new RuntimeException("Can't delete: storage is closed"); - } else { - cache.remove(key); - base.remove(key); - } + isClose(); + + cache.remove(key); + base.remove(key); + } /** @@ -144,11 +138,10 @@ public synchronized void delete(K key) { */ @Override public Iterator readKeys() { - if (isClosed) { - throw new RuntimeException("Can't iterate: storage is closed"); - } else { - return base.keySet().iterator(); - } + isClose(); + + return base.keySet().iterator(); + } /** @@ -156,31 +149,35 @@ public Iterator readKeys() { */ @Override public int size() { - if (isClosed) { - throw new RuntimeException("Can't know size: storage is closed"); - } else { - return base.size(); - } + isClose(); + + return base.size(); } @Override public synchronized void close() { + if(isClosed) { + return; + } + writeCacheToStorage(); reorganiseStorage(); - downnloadDataToStorage(); + uploadDataToStorage(); + try { mapStorage.close(); storage.close(); } catch (IOException excetion) { throw new RuntimeException("Can't close storage"); + } finally { + isClosed = true; + cache.clear(); + base.clear(); + mutexFile.delete(); } - isClosed = true; - cache.clear(); - base.clear(); - mutexFile.delete(); } - private void uploadDataFromStorage() { + private void downloadDataFromStorage() { try { int count = -1; @@ -190,7 +187,7 @@ private void uploadDataFromStorage() { K key = keySerializationStrategy.deserializeFromFile(mapStorage); Long tmp = mapStorage.readLong(); base.put(key, tmp); - maxOffset = max(maxOffset, tmp); + maxOffset = Math.max(maxOffset, tmp); } } catch (IOException exception) { base.clear(); @@ -198,7 +195,7 @@ private void uploadDataFromStorage() { } } - private void downnloadDataToStorage() { + private void uploadDataToStorage() { try { mapStorage.close(); File file = new File(pathname, mapStorageName); @@ -217,23 +214,21 @@ private void downnloadDataToStorage() { } private void writeCacheToStorage() { - if (isClosed) { - throw new RuntimeException("Can't write: storage is closed"); - } else { - try { - for (HashMap.Entry entry : cache.entrySet()) { - storage.seek(maxOffset); - valueSerializationStrategy.serializeToFile(entry.getValue(), storage); - long curOffset = storage.getFilePointer(); - base.put(entry.getKey(), maxOffset); - maxOffset = curOffset; - } - cache.clear(); - - } catch (IOException exception) { - throw new RuntimeException("Can't write cache on the disk"); + isClose(); + try { + for (HashMap.Entry entry : cache.entrySet()) { + storage.seek(maxOffset); + valueSerializationStrategy.serializeToFile(entry.getValue(), storage); + long curOffset = storage.getFilePointer(); + base.put(entry.getKey(), maxOffset); + maxOffset = curOffset; } + cache.clear(); + + } catch (IOException exception) { + throw new RuntimeException("Can't write cache on the disk"); } + } private void reorganiseStorage() { @@ -261,5 +256,11 @@ private void reorganiseStorage() { throw new RuntimeException("Can't reorganise storage!"); } } + + private void isClose() { + if (isClosed) { + throw new IllegalStateException("Can't write: storage is closed"); + } + } } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java index 629fcd4e3..22396fb15 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -9,7 +11,7 @@ */ public interface SerializationStrategyRandomAccess { - void serializeToFile(Value value, RandomAccessFile output) throws IOException; + void serializeToFile(Value value, DataOutput output) throws IOException; - Value deserializeFromFile(RandomAccessFile input) throws IOException; + Value deserializeFromFile(DataInput input) throws IOException; } diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java index e5b54624c..821ab970d 100644 --- a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -12,13 +14,13 @@ public class ConcreteStrategyStudentKeyRandomAccess implements SerializationStrategyRandomAccess { @Override - public void serializeToFile(StudentKey value, RandomAccessFile output) throws IOException { + public void serializeToFile(StudentKey value, DataOutput output) throws IOException { output.writeInt(value.getGroupId()); - ConcreteStrategyStringRandomAccess.writeString(output, value.getName()); + output.writeUTF(value.getName()); } @Override - public StudentKey deserializeFromFile(RandomAccessFile input) throws IOException { - return new StudentKey(input.readInt(), ConcreteStrategyStringRandomAccess.readString(input)); + public StudentKey deserializeFromFile(DataInput input) throws IOException { + return new StudentKey(input.readInt(), input.readUTF()); } } diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java index 81f2ad012..03d08ac6a 100644 --- a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Date; @@ -12,19 +14,19 @@ */ public class ConcreteStrategyStudentRandomAccess implements SerializationStrategyRandomAccess { @Override - public void serializeToFile(Student value, RandomAccessFile output) throws IOException { + public void serializeToFile(Student value, DataOutput output) throws IOException { output.writeInt(value.getGroupId()); - ConcreteStrategyStringRandomAccess.writeString(output, value.getName()); - ConcreteStrategyStringRandomAccess.writeString(output, value.getHometown()); + output.writeUTF(value.getName()); + output.writeUTF(value.getHometown()); output.writeLong(value.getBirthDate().getTime()); output.writeBoolean(value.isHasDormitory()); output.writeDouble(value.getAverageScore()); } @Override - public Student deserializeFromFile(RandomAccessFile input) throws IOException { - return new Student(input.readInt(), ConcreteStrategyStringRandomAccess.readString(input), - ConcreteStrategyStringRandomAccess.readString(input), new Date(input.readLong()), + public Student deserializeFromFile(DataInput input) throws IOException { + return new Student(input.readInt(), input.readUTF(), + input.readUTF(), new Date(input.readLong()), input.readBoolean(), input.readDouble()); } } From f530f07c22064472c428c2ce14fcd2cfcdf99439 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 14:14:16 +0300 Subject: [PATCH 06/29] code style changes --- .../manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java | 1 - .../task3/ConcreteStrategyIntegerRandomAccess.java | 1 - .../manucharyan/task3/ConcreteStrategyStringRandomAccess.java | 3 +-- .../g595/manucharyan/task3/OptimisedKeyValueStorage.java | 4 ++-- .../manucharyan/task3/SerializationStrategyRandomAccess.java | 1 - .../task3/ConcreteStrategyStudentKeyRandomAccess.java | 1 - .../task3/ConcreteStrategyStudentRandomAccess.java | 1 - 7 files changed, 3 insertions(+), 9 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java index d83706cb1..e14fc34e4 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyDoubleRandomAccess.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * @author Vardan Manucharyan diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java index 7010a272d..8fef4a918 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyIntegerRandomAccess.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * @author Vardan Manucharyan diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java index 42381a39b..bbd1d9ae5 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStringRandomAccess.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * @author Vardan Manucharyan @@ -12,7 +11,7 @@ public class ConcreteStrategyStringRandomAccess implements SerializationStrategyRandomAccess { @Override public void serializeToFile(String value, DataOutput output) throws IOException { - output.writeUTF(value); + output.writeUTF(value); } @Override diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index f4a64768a..d27b5afd4 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -62,7 +62,7 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ mapStorage = new RandomAccessFile(file2, "rw"); downloadDataFromStorage(); - }catch(IOException exception) { + } catch (IOException exception) { throw new RuntimeException("Can't create a storage!"); } } @@ -156,7 +156,7 @@ public int size() { @Override public synchronized void close() { - if(isClosed) { + if (isClosed) { return; } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java index 22396fb15..5ced97585 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/SerializationStrategyRandomAccess.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * @author Vardan Manucharyan diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java index 821ab970d..558215cbb 100644 --- a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentKeyRandomAccess.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; import ru.mipt.java2016.homework.tests.task2.StudentKey; diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java index 03d08ac6a..e2308bf0c 100644 --- a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task3/ConcreteStrategyStudentRandomAccess.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; import java.util.Date; import ru.mipt.java2016.homework.tests.task2.Student; From 83ecff4cd5f0684c70fd42171dfa05fbbff73141 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 14:20:01 +0300 Subject: [PATCH 07/29] try do smth, that travis test my project --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5bca65ec3..4e8b97af1 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ mipt-java-2016 1.0.0 - pom + jar homework-base From 6446586a15854ac197c063836f5470dda59f1bd7 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 18:06:30 +0300 Subject: [PATCH 08/29] tried again --- homework-g595-manucharyan/pom.xml | 1 - pom.xml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/homework-g595-manucharyan/pom.xml b/homework-g595-manucharyan/pom.xml index 60b57906a..48adf6d01 100644 --- a/homework-g595-manucharyan/pom.xml +++ b/homework-g595-manucharyan/pom.xml @@ -10,7 +10,6 @@ 4.0.0 homework-g595-manucharyan - pom 1.0.0 diff --git a/pom.xml b/pom.xml index 4e8b97af1..5bca65ec3 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ mipt-java-2016 1.0.0 - jar + pom homework-base From 181536f4d47556242401266641e88d73986f90e5 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 18:41:28 +0300 Subject: [PATCH 09/29] add cleaning storage not only in close() --- .../tests/task3/KeyValueStoragePerformanceTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java index 43f297224..6b394db23 100644 --- a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java +++ b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java @@ -2,13 +2,14 @@ import org.junit.Assert; import org.junit.Test; -import ru.mipt.java2016.homework.tests.task2.AbstractSingleFileStorageTest; -import ru.mipt.java2016.homework.tests.task2.StorageTestUtils; import java.util.Arrays; import java.util.Random; import java.util.concurrent.atomic.AtomicLong; +import ru.mipt.java2016.homework.tests.task2.AbstractSingleFileStorageTest; +import ru.mipt.java2016.homework.tests.task2.StorageTestUtils; + import static ru.mipt.java2016.homework.tests.task3.PerformanceTestUtils.randomKey; import static ru.mipt.java2016.homework.tests.task3.PerformanceTestUtils.randomValue; @@ -149,7 +150,7 @@ public void measure10kWDump10kR() { } // Вы можете пометить этот тест как @Ignored во время отладки, если он занимает у вас слишком много времени - @Test + //@Test public void measure100kWDump100kR() { AtomicLong summaryWriteTime = new AtomicLong(0L); AtomicLong summaryReadTime = new AtomicLong(0L); From af9170bd6091e711b519bfaefa0ebd895bf21f9c Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 18:52:13 +0300 Subject: [PATCH 10/29] code style changes --- .../task3/OptimisedKeyValueStorage.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index d27b5afd4..5f1bd834a 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -16,6 +16,8 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private static final long MAX_CACHE_SIZE = 100L; + private static final double FILLING_PERCENTAGE = 0.5; //when we need clean storage form deleted values + private static long deletedCount;//number of deleted elements private final SerializationStrategyRandomAccess keySerializationStrategy; private final SerializationStrategyRandomAccess valueSerializationStrategy; @@ -41,6 +43,7 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ this.keySerializationStrategy = keySerializationStrategy; this.valueSerializationStrategy = valueSerializaionStrategy; maxOffset = 0L; + deletedCount = 0L; pathname = path; isClosed = false; @@ -127,7 +130,11 @@ public synchronized void delete(K key) { cache.remove(key); base.remove(key); + deletedCount++; + if (deletedCount / size() > FILLING_PERCENTAGE) { + reorganiseStorage(); + } } /** @@ -167,21 +174,21 @@ public synchronized void close() { try { mapStorage.close(); storage.close(); + mutexFile.delete(); } catch (IOException excetion) { throw new RuntimeException("Can't close storage"); } finally { isClosed = true; cache.clear(); base.clear(); - mutexFile.delete(); } } private void downloadDataFromStorage() { try { - int count = -1; - count = mapStorage.readInt(); + + int count = mapStorage.readInt(); for (int i = 0; i < count; i++) { K key = keySerializationStrategy.deserializeFromFile(mapStorage); @@ -236,7 +243,7 @@ private void reorganiseStorage() { File file = new File(pathname, "newStorage.txt"); RandomAccessFile newStorage = new RandomAccessFile(file, "rw"); - assert (cache.isEmpty()); + writeCacheToStorage(); for (HashMap.Entry entry : base.entrySet()) { storage.seek(entry.getValue()); @@ -245,6 +252,8 @@ private void reorganiseStorage() { base.put(entry.getKey(), tmp); } + deletedCount = 0; + storage.close(); File file1 = new File(pathname, storageName); assert (file1.delete()); From a9a52c0595eb7fa577dd42343e52b3b6c923c6d2 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 20:50:24 +0300 Subject: [PATCH 11/29] revert --- .../task3/OptimisedKeyValueStorage.java | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 5f1bd834a..d27b5afd4 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -16,8 +16,6 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private static final long MAX_CACHE_SIZE = 100L; - private static final double FILLING_PERCENTAGE = 0.5; //when we need clean storage form deleted values - private static long deletedCount;//number of deleted elements private final SerializationStrategyRandomAccess keySerializationStrategy; private final SerializationStrategyRandomAccess valueSerializationStrategy; @@ -43,7 +41,6 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ this.keySerializationStrategy = keySerializationStrategy; this.valueSerializationStrategy = valueSerializaionStrategy; maxOffset = 0L; - deletedCount = 0L; pathname = path; isClosed = false; @@ -130,11 +127,7 @@ public synchronized void delete(K key) { cache.remove(key); base.remove(key); - deletedCount++; - if (deletedCount / size() > FILLING_PERCENTAGE) { - reorganiseStorage(); - } } /** @@ -174,21 +167,21 @@ public synchronized void close() { try { mapStorage.close(); storage.close(); - mutexFile.delete(); } catch (IOException excetion) { throw new RuntimeException("Can't close storage"); } finally { isClosed = true; cache.clear(); base.clear(); + mutexFile.delete(); } } private void downloadDataFromStorage() { try { - - int count = mapStorage.readInt(); + int count = -1; + count = mapStorage.readInt(); for (int i = 0; i < count; i++) { K key = keySerializationStrategy.deserializeFromFile(mapStorage); @@ -243,7 +236,7 @@ private void reorganiseStorage() { File file = new File(pathname, "newStorage.txt"); RandomAccessFile newStorage = new RandomAccessFile(file, "rw"); - writeCacheToStorage(); + assert (cache.isEmpty()); for (HashMap.Entry entry : base.entrySet()) { storage.seek(entry.getValue()); @@ -252,8 +245,6 @@ private void reorganiseStorage() { base.put(entry.getKey(), tmp); } - deletedCount = 0; - storage.close(); File file1 = new File(pathname, storageName); assert (file1.delete()); From f95b2d3d34f2b671db9edb77be57cf0082134460 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 21:09:16 +0300 Subject: [PATCH 12/29] some bugs fixed --- .../manucharyan/task3/OptimisedKeyValueStorage.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index d27b5afd4..a40d8ad3d 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -16,6 +16,8 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private static final long MAX_CACHE_SIZE = 100L; + private static final double FILLING_PERCENTAGE = 0.5; //when we need clean storage from deleted values + private static long deletedCount;//number of deleted elements private final SerializationStrategyRandomAccess keySerializationStrategy; private final SerializationStrategyRandomAccess valueSerializationStrategy; @@ -41,6 +43,7 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ this.keySerializationStrategy = keySerializationStrategy; this.valueSerializationStrategy = valueSerializaionStrategy; maxOffset = 0L; + deletedCount = 0L; pathname = path; isClosed = false; @@ -127,7 +130,11 @@ public synchronized void delete(K key) { cache.remove(key); base.remove(key); + deletedCount++; + if (deletedCount / size() > FILLING_PERCENTAGE) { + reorganiseStorage(); + } } /** @@ -160,7 +167,6 @@ public synchronized void close() { return; } - writeCacheToStorage(); reorganiseStorage(); uploadDataToStorage(); @@ -236,7 +242,7 @@ private void reorganiseStorage() { File file = new File(pathname, "newStorage.txt"); RandomAccessFile newStorage = new RandomAccessFile(file, "rw"); - assert (cache.isEmpty()); + writeCacheToStorage(); for (HashMap.Entry entry : base.entrySet()) { storage.seek(entry.getValue()); @@ -244,6 +250,7 @@ private void reorganiseStorage() { valueSerializationStrategy.serializeToFile(read(entry.getKey()), newStorage); base.put(entry.getKey(), tmp); } + deletedCount = 0; storage.close(); File file1 = new File(pathname, storageName); From a85598c7d08d7cbc3021bbacbf326e409f58563e Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 21:15:53 +0300 Subject: [PATCH 13/29] try find what's wrong with travis --- .../g595/manucharyan/task3/OptimisedKeyValueStorage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index a40d8ad3d..1317e9e67 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -132,9 +132,9 @@ public synchronized void delete(K key) { base.remove(key); deletedCount++; - if (deletedCount / size() > FILLING_PERCENTAGE) { + //if (deletedCount / size() > FILLING_PERCENTAGE) { reorganiseStorage(); - } + //} } /** From 0ccfc8af1f8500ee12657a6972aeeef657c8e54a Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 21:21:50 +0300 Subject: [PATCH 14/29] code style --- .../g595/manucharyan/task3/OptimisedKeyValueStorage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 1317e9e67..f40fc3e7d 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -17,7 +17,7 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private static final long MAX_CACHE_SIZE = 100L; private static final double FILLING_PERCENTAGE = 0.5; //when we need clean storage from deleted values - private static long deletedCount;//number of deleted elements + private static long deletedCount; //number of deleted elements private final SerializationStrategyRandomAccess keySerializationStrategy; private final SerializationStrategyRandomAccess valueSerializationStrategy; @@ -133,7 +133,7 @@ public synchronized void delete(K key) { deletedCount++; //if (deletedCount / size() > FILLING_PERCENTAGE) { - reorganiseStorage(); + reorganiseStorage(); //} } From e81d659bbee056cc6a2af8339096d1bc622141d6 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 27 Nov 2016 22:01:20 +0300 Subject: [PATCH 15/29] and here we go --- .../task3/OptimisedKeyValueStorage.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index f40fc3e7d..727d9149e 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -28,7 +28,6 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private long maxOffset; private final String pathname; - private RandomAccessFile storage; private final String storageName = "storage.txt"; private RandomAccessFile mapStorage; private final String mapStorageName = "mapStorage.txt"; @@ -58,9 +57,6 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ } try { - File file = new File(pathname, storageName); - storage = new RandomAccessFile(file, "rw"); - File file2 = new File(path, mapStorageName); mapStorage = new RandomAccessFile(file2, "rw"); @@ -83,10 +79,14 @@ public synchronized V read(K key) { if (cache.get(key) != null) { return cache.get(key); } + File file = new File(pathname, storageName); + RandomAccessFile storage = new RandomAccessFile(file, "rw"); Long offset = base.get(key); storage.seek(offset); - return valueSerializationStrategy.deserializeFromFile(storage); + V res = valueSerializationStrategy.deserializeFromFile(storage); + storage.close(); + return res; } catch (Exception exception) { throw new RuntimeException("Can't read from storage"); } @@ -132,9 +132,9 @@ public synchronized void delete(K key) { base.remove(key); deletedCount++; - //if (deletedCount / size() > FILLING_PERCENTAGE) { - reorganiseStorage(); - //} + if (deletedCount / size() > FILLING_PERCENTAGE) { + reorganiseStorage(); + } } /** @@ -172,7 +172,6 @@ public synchronized void close() { try { mapStorage.close(); - storage.close(); } catch (IOException excetion) { throw new RuntimeException("Can't close storage"); } finally { @@ -222,6 +221,9 @@ private void uploadDataToStorage() { private void writeCacheToStorage() { isClose(); try { + File file = new File(pathname, storageName); + RandomAccessFile storage = new RandomAccessFile(file, "rw"); + for (HashMap.Entry entry : cache.entrySet()) { storage.seek(maxOffset); valueSerializationStrategy.serializeToFile(entry.getValue(), storage); @@ -229,6 +231,7 @@ private void writeCacheToStorage() { base.put(entry.getKey(), maxOffset); maxOffset = curOffset; } + storage.close(); cache.clear(); } catch (IOException exception) { @@ -239,6 +242,9 @@ private void writeCacheToStorage() { private void reorganiseStorage() { try { + File file1 = new File(pathname, storageName); + RandomAccessFile storage = new RandomAccessFile(file1, "rw"); + File file = new File(pathname, "newStorage.txt"); RandomAccessFile newStorage = new RandomAccessFile(file, "rw"); @@ -253,7 +259,6 @@ private void reorganiseStorage() { deletedCount = 0; storage.close(); - File file1 = new File(pathname, storageName); assert (file1.delete()); newStorage.close(); From 81e49f040effd0ca327c1d375d759ca6a5dc47d3 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 28 Nov 2016 18:49:00 +0300 Subject: [PATCH 16/29] optimise little bit --- .../task3/OptimisedKeyValueStorage.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 727d9149e..9ca7e7295 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -1,6 +1,9 @@ package ru.mipt.java2016.homework.g595.manucharyan.task3; +import java.io.BufferedOutputStream; +import java.io.DataOutputStream; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.util.HashMap; @@ -72,6 +75,8 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ */ @Override public synchronized V read(K key) { + isClose(); + if (!exists(key)) { return null; } else { @@ -241,18 +246,18 @@ private void writeCacheToStorage() { } private void reorganiseStorage() { - try { - File file1 = new File(pathname, storageName); - RandomAccessFile storage = new RandomAccessFile(file1, "rw"); - File file = new File(pathname, "newStorage.txt"); - RandomAccessFile newStorage = new RandomAccessFile(file, "rw"); + File file1 = new File(pathname, storageName); + File file = new File(pathname, "newStorage.txt"); + + try (DataOutputStream newStorage = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + RandomAccessFile storage = new RandomAccessFile(file1, "rw");) { writeCacheToStorage(); for (HashMap.Entry entry : base.entrySet()) { storage.seek(entry.getValue()); - Long tmp = newStorage.getFilePointer(); + Long tmp = (long) newStorage.size(); valueSerializationStrategy.serializeToFile(read(entry.getKey()), newStorage); base.put(entry.getKey(), tmp); } From 12319c8efe65a74c3e609c985be6ab816dc18979 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Tue, 29 Nov 2016 16:38:43 +0300 Subject: [PATCH 17/29] oops --- .../homework/tests/task3/KeyValueStoragePerformanceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java index 6b394db23..c51bc5221 100644 --- a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java +++ b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java @@ -150,7 +150,7 @@ public void measure10kWDump10kR() { } // Вы можете пометить этот тест как @Ignored во время отладки, если он занимает у вас слишком много времени - //@Test + @Test public void measure100kWDump100kR() { AtomicLong summaryWriteTime = new AtomicLong(0L); AtomicLong summaryReadTime = new AtomicLong(0L); From e328d85dea6e209b094894b047ffa9556270ba17 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Sun, 4 Dec 2016 12:07:22 +0300 Subject: [PATCH 18/29] try to pass new tests --- .../g595/manucharyan/task3/OptimisedKeyValueStorage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 9ca7e7295..6cabc0b39 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -279,5 +279,6 @@ private void isClose() { throw new IllegalStateException("Can't write: storage is closed"); } } + } From 8722b58ce6d55e5459a4f5becd2cdb65e1ae0ef4 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 5 Dec 2016 14:33:38 +0300 Subject: [PATCH 19/29] fix problems with seek --- .../task3/OptimisedKeyValueStorage.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 6cabc0b39..9ac94e70c 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -225,16 +225,19 @@ private void uploadDataToStorage() { private void writeCacheToStorage() { isClose(); - try { - File file = new File(pathname, storageName); - RandomAccessFile storage = new RandomAccessFile(file, "rw"); + if (cache.isEmpty()) { + return; + } + + File file = new File(pathname, storageName); + + try (RandomAccessFile storage = new RandomAccessFile(file, "rw");) { + storage.seek(maxOffset); for (HashMap.Entry entry : cache.entrySet()) { - storage.seek(maxOffset); valueSerializationStrategy.serializeToFile(entry.getValue(), storage); - long curOffset = storage.getFilePointer(); base.put(entry.getKey(), maxOffset); - maxOffset = curOffset; + maxOffset = storage.getFilePointer(); } storage.close(); cache.clear(); From 89423e52475b76ea6888353cd0dd05a10164d199 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 5 Dec 2016 16:31:20 +0300 Subject: [PATCH 20/29] fix problems with files --- .../task3/OptimisedKeyValueStorage.java | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index 9ac94e70c..c65b9f049 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -33,6 +33,7 @@ public class OptimisedKeyValueStorage implements KeyValueStorage { private final String pathname; private final String storageName = "storage.txt"; private RandomAccessFile mapStorage; + private RandomAccessFile storage; private final String mapStorageName = "mapStorage.txt"; private File mutexFile; // для многопоточности @@ -60,8 +61,9 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ } try { - File file2 = new File(path, mapStorageName); - mapStorage = new RandomAccessFile(file2, "rw"); + mapStorage = new RandomAccessFile(new File(path, mapStorageName), "rw"); + + storage = new RandomAccessFile(new File(pathname, storageName), "rw"); downloadDataFromStorage(); } catch (IOException exception) { @@ -84,13 +86,10 @@ public synchronized V read(K key) { if (cache.get(key) != null) { return cache.get(key); } - File file = new File(pathname, storageName); - RandomAccessFile storage = new RandomAccessFile(file, "rw"); Long offset = base.get(key); storage.seek(offset); V res = valueSerializationStrategy.deserializeFromFile(storage); - storage.close(); return res; } catch (Exception exception) { throw new RuntimeException("Can't read from storage"); @@ -177,6 +176,7 @@ public synchronized void close() { try { mapStorage.close(); + storage.close(); } catch (IOException excetion) { throw new RuntimeException("Can't close storage"); } finally { @@ -201,7 +201,6 @@ private void downloadDataFromStorage() { } } catch (IOException exception) { base.clear(); - //throw new RuntimeException("Trouble with storage.db"); } } @@ -210,8 +209,7 @@ private void uploadDataToStorage() { mapStorage.close(); File file = new File(pathname, mapStorageName); assert (file.delete()); - file = new File(pathname, mapStorageName); - mapStorage = new RandomAccessFile(file, "rw"); + mapStorage = new RandomAccessFile(new File(pathname, mapStorageName), "rw"); mapStorage.writeInt(size()); for (HashMap.Entry entry : base.entrySet()) { @@ -225,21 +223,19 @@ private void uploadDataToStorage() { private void writeCacheToStorage() { isClose(); + if (cache.isEmpty()) { return; } - File file = new File(pathname, storageName); - - try (RandomAccessFile storage = new RandomAccessFile(file, "rw");) { - + try { storage.seek(maxOffset); for (HashMap.Entry entry : cache.entrySet()) { valueSerializationStrategy.serializeToFile(entry.getValue(), storage); base.put(entry.getKey(), maxOffset); maxOffset = storage.getFilePointer(); } - storage.close(); + cache.clear(); } catch (IOException exception) { @@ -253,8 +249,7 @@ private void reorganiseStorage() { File file1 = new File(pathname, storageName); File file = new File(pathname, "newStorage.txt"); - try (DataOutputStream newStorage = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); - RandomAccessFile storage = new RandomAccessFile(file1, "rw");) { + try (DataOutputStream newStorage = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));) { writeCacheToStorage(); @@ -271,6 +266,7 @@ private void reorganiseStorage() { newStorage.close(); assert (file.renameTo(file1)); + storage = new RandomAccessFile(new File(pathname, storageName), "rw"); } catch (IOException exception) { throw new RuntimeException("Can't reorganise storage!"); @@ -282,6 +278,6 @@ private void isClose() { throw new IllegalStateException("Can't write: storage is closed"); } } - + } From 6c53bd8b6a80ad6a0913b3a638c677b5ada7cca8 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 5 Dec 2016 16:48:08 +0300 Subject: [PATCH 21/29] code style changes --- .../g595/manucharyan/task3/OptimisedKeyValueStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index c65b9f049..db705e9b8 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -249,7 +249,7 @@ private void reorganiseStorage() { File file1 = new File(pathname, storageName); File file = new File(pathname, "newStorage.txt"); - try (DataOutputStream newStorage = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));) { + try (DataOutputStream newStorage = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) { writeCacheToStorage(); From eacb2e49085a87380420c5d0c3df58957bad30ce Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Mon, 5 Dec 2016 17:27:23 +0300 Subject: [PATCH 22/29] fix constructor --- .../manucharyan/task3/OptimisedKeyValueStorage.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java index db705e9b8..1498bb7a0 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task3/OptimisedKeyValueStorage.java @@ -61,11 +61,15 @@ public OptimisedKeyValueStorage(SerializationStrategyRandomAccess keySerializ } try { - mapStorage = new RandomAccessFile(new File(path, mapStorageName), "rw"); + File file = new File(path, mapStorageName); + boolean exist = file.exists(); + mapStorage = new RandomAccessFile(file, "rw"); + if (exist) { + downloadDataFromStorage(); + } storage = new RandomAccessFile(new File(pathname, storageName), "rw"); - downloadDataFromStorage(); } catch (IOException exception) { throw new RuntimeException("Can't create a storage!"); } @@ -190,8 +194,7 @@ public synchronized void close() { private void downloadDataFromStorage() { try { - int count = -1; - count = mapStorage.readInt(); + int count = mapStorage.readInt(); for (int i = 0; i < count; i++) { K key = keySerializationStrategy.deserializeFromFile(mapStorage); @@ -201,6 +204,7 @@ private void downloadDataFromStorage() { } } catch (IOException exception) { base.clear(); + throw new RuntimeException("Trouble with storage.db"); } } From edcfe73405eac9e6e4f5cc7c6dc169630b83c258 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Fri, 9 Dec 2016 21:55:21 +0300 Subject: [PATCH 23/29] back to the right version of lector's file --- .../tests/task3/KeyValueStoragePerformanceTest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java index 29dccae0d..cf16f0022 100644 --- a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java +++ b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java @@ -3,7 +3,11 @@ import org.junit.Assert; import org.junit.Test; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Random; +import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import ru.mipt.java2016.homework.tests.task2.AbstractSingleFileStorageTest; From 47dde1d999769f808bf7377b22ce0d1f0cae855b Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Fri, 9 Dec 2016 21:57:56 +0300 Subject: [PATCH 24/29] fucking IDEA auto fixes --- .../tests/task3/KeyValueStoragePerformanceTest.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java index cf16f0022..dd10f3aff 100644 --- a/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java +++ b/homework-tests/src/main/java/ru/mipt/java2016/homework/tests/task3/KeyValueStoragePerformanceTest.java @@ -2,17 +2,12 @@ import org.junit.Assert; import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Random; -import java.util.Set; -import java.util.concurrent.atomic.AtomicLong; - import ru.mipt.java2016.homework.tests.task2.AbstractSingleFileStorageTest; import ru.mipt.java2016.homework.tests.task2.StorageTestUtils; +import java.util.*; +import java.util.concurrent.atomic.AtomicLong; + import static ru.mipt.java2016.homework.tests.task3.PerformanceTestUtils.randomKey; import static ru.mipt.java2016.homework.tests.task3.PerformanceTestUtils.randomValue; From 1b212dc9bdaaf812e119b4a70d02aff5ef09f2c6 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Wed, 21 Dec 2016 14:12:38 +0300 Subject: [PATCH 25/29] add task 4 --- homework-g595-manucharyan/Database.db.mv.db | Bin 0 -> 40960 bytes homework-g595-manucharyan/pom.xml | 39 +- .../g595/manucharyan/task4/BillingDao.java | 63 +++ .../task4/BillingDatabaseConfiguration.java | 23 + .../g595/manucharyan/task4/BillingUser.java | 69 +++ .../task4/CalculatorController.java | 39 ++ .../g595/manucharyan/task4/RESTCalc.java | 436 ++++++++++++++++++ .../task4/SecurityServiceConfiguration.java | 56 +++ .../g595/manucharyan/task4/Token.java | 51 ++ .../manucharyan/task4/VardanApplication.java | 41 ++ .../g595/manucharyan/task4/RESTCalcTest.java | 15 + 11 files changed, 831 insertions(+), 1 deletion(-) create mode 100644 homework-g595-manucharyan/Database.db.mv.db create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java create mode 100644 homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java create mode 100644 homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java diff --git a/homework-g595-manucharyan/Database.db.mv.db b/homework-g595-manucharyan/Database.db.mv.db new file mode 100644 index 0000000000000000000000000000000000000000..15a71d0f7e727266f279e2985e7d21590d35e06a GIT binary patch literal 40960 zcmeI5%WvDr9mh%ek*vGMLVci@9vE+4Ed+s&p(v_F5!qJPLS;FXlx=o}a0YHE z9vwXnPHI-^Npy6)KN==qj1Qud@T2I6Zg`eyk#J4J7b<`XpaQ4>Du4>00;m8gfC``j zr~oQ}3M^cK9pwLomjN1p3ZMe004jhApaQ4>Du4>00;m8gfC|i80Wrw$^C$qjbPx^c zsQ%;Nu;$bEr!_*%(lB~@QVU9l!Ncg7It-3Rqmx=}6B;F8nzl#W(#ihgsOCj+U{-u3 zBEUCZ9mHXPW+(7W@2H`^wdKt|nJd9#mGS$z@;DmOj<~ zpz7W4r^htNf~rUYtFNeN{$5&PaVx4RE3B$&hgy8T#qIF99iFg* z6<^S=%HoUsz_nC6LW?MNSfB>sb~q_JR4Y_998rnfR3#cmn$VY8iK5u9#HtllTeX6K z6)v~JeNihaX)DfGWm*aqPqkvQOx!1;VpO;hm6Q>-s)br2uBaKJL`2P?g_vle)Qp%+ zUVP4Tr&It|A0XJt0W0uk zSkTQtpAXMh{;FNolD6MU-tFYwN#05F?k4Z-`QRn#>UV|#eO`?YqhaqT7#;`V35{So zemmKFIvk8zqlawcB0KqMkNn09^+ElN2=B^3g2;G7jvDIwK&+$}{&q#{UDx|7ThJznaDWKh~~mtHA$2{WDl! zQosND@ivm~qpyo}f$Qdvy5RCj-8far+t4sfa{f%j6_hU!H;=mxZsat1OMB)o3N(Po z{}DRFz)gD28Ac!6$p7G!K>lB3PY&}&1yBK002M$5@+)wjzoGjZ0RLAB@%+IY`M=Nk zUkq;p|4$vdwa<^4#Q|{xWyH9joAtB4$oM~E{Qr#d|2Na)|0@~%U-+~BH*E#@KXY6k zSYM`s1r1^?YDD+-;9Rg`{-CSS_GC5nCEcdoV7UjBU&c8`l<)%N|0M7Q$NydN&XNB^&i^8m z8u(v^E2jh59Uj1|hAYQa%TxG2%)_~X&h zpiYlFOPh&*;7gkRkupDkZtH8GX2u8nkj@TJ;sbK~2c)N00;m8gaG?|s{15yM{2v1U2La`OXO8@zCfN-B ze;H=Y&H7niWc>e|8T`MK@c$QQjQ>Bsqv?MduMcqc75u-h@_*L)0Jda(N2ZiD10;XV ze^CIa4WDsaIS5d07P4gIYO@W1cU`TxNj`9I?0|6*A$ z;C~5m=?TTod5DW?UsfIekFu~n_dXW?|4TN$f5ztje@Xd%y#C+#bISUE|J0tT>;Gkq z@B5PK1DWc}R47ve81IDw%E!JhKGd&__XcLHL{U^=J%VYgzU5f|PZXa(|Ea6KDRxYj zrUz=^7(8e(|3P@AL?&xSUxFa`4=1bVR1lQ)GYx`btoy6NdZa6Az?+TqdXza_QR(_f z`FQ-AScQo(hM-0LGqg#WO+ zwbR(Gr+&KGY_*#0_l)|z-p*d9`C+}++-uVl7MHIZ#`nozAWtfum8 z8(VwrZm&~swtMn4u#28vG2pg5v(apCH}1)py_0>G$Nk4=Xw5=y#bz=#Hj+(qoRG84jV(3ZKt%2vw!aXNGGC zcx#akA<5rghd&4!B*g)QQ$e66EOIIcSn&qBp=g7E{C^SR|B?UUxrQlJ02M$5Pytjx z(**wme?xbB0Q?{JDgRgJ$p2}O$ie?p2aw?kyezEGy^rz#ACUhq8ULT<n6v|d^Zzdb|KtDvVP6*&Km||%Q~(uF6%hOn{0-eI P5BR@dq4EFm9QgnLB*@af literal 0 HcmV?d00001 diff --git a/homework-g595-manucharyan/pom.xml b/homework-g595-manucharyan/pom.xml index 48adf6d01..2776356cf 100644 --- a/homework-g595-manucharyan/pom.xml +++ b/homework-g595-manucharyan/pom.xml @@ -10,8 +10,13 @@ 4.0.0 homework-g595-manucharyan + pom 1.0.0 + + 1.4.2.RELEASE + + ru.mipt.java2016 @@ -19,6 +24,38 @@ 1.0.0 + + net.sourceforge.jeval + jeval + 0.9.4 + + + + org.springframework.boot + spring-boot-starter-web + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-jdbc + ${spring.boot.version} + + + org.springframework.boot + spring-boot-starter-security + ${spring.boot.version} + + + com.zaxxer + HikariCP + 2.5.1 + + + com.h2database + h2 + 1.4.193 + + ru.mipt.java2016 homework-tests @@ -26,4 +63,4 @@ test - \ No newline at end of file + diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java new file mode 100644 index 000000000..7cd2c3092 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java @@ -0,0 +1,63 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ExceptionDepthComparator; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.sql.SQLException; + + +@Repository +public class BillingDao { + private static final Logger LOG = LoggerFactory.getLogger(BillingDao.class); + + @Autowired + private DataSource dataSource; + + private JdbcTemplate jdbcTemplate; + + @PostConstruct + public void postConstruct() { + jdbcTemplate = new JdbcTemplate(dataSource, false); + initSchema(); + } + + public void initSchema() { + LOG.trace("Initializing schema"); + jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing"); + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " + + "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); + try{ + jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)"); + } catch(Exception e) { + + } + } + + + public BillingUser loadUser(String username) throws EmptyResultDataAccessException { + LOG.trace("Querying for user " + username); + return jdbcTemplate.queryForObject( + "SELECT username, password, enabled FROM billing.users WHERE username = ?", + new Object[]{username}, + new RowMapper() { + @Override + public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException { + return new BillingUser( + rs.getString("username"), + rs.getString("password"), + rs.getBoolean("enabled") + ); + } + } + ); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java new file mode 100644 index 000000000..d7d1e1350 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java @@ -0,0 +1,23 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.sql.DataSource; + +@Configuration +public class BillingDatabaseConfiguration { + @Bean + public DataSource billingDataSource( + ) { + HikariConfig config = new HikariConfig(); + config.setDriverClassName(org.h2.Driver.class.getName()); + config.setJdbcUrl("jdbc:h2:C:\\Users\\op\\Documents\\GitHub\\mipt-java-2016\\homework-g595-manucharyan\\Database.db"); + config.setUsername(""); + config.setPassword(""); + return new HikariDataSource(config); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java new file mode 100644 index 000000000..5c86b9ba0 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingUser.java @@ -0,0 +1,69 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +public class BillingUser { + private final String username; + private final String password; + private final boolean enabled; + + public BillingUser(String username, String password, boolean enabled) { + if (username == null) { + throw new IllegalArgumentException("Null username is not allowed"); + } + if (password == null) { + throw new IllegalArgumentException("Null password is not allowed"); + } + this.username = username; + this.password = password; + this.enabled = enabled; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public boolean isEnabled() { + return enabled; + } + + @Override + public String toString() { + return "BillingUser{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + ", enabled=" + enabled + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + BillingUser that = (BillingUser) o; + + if (enabled != that.enabled) { + return false; + } + if (!username.equals(that.username)) { + return false; + } + return password.equals(that.password); + + } + + @Override + public int hashCode() { + int result = username.hashCode(); + result = 31 * result + password.hashCode(); + result = 31 * result + (enabled ? 1 : 0); + return result; + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java new file mode 100644 index 000000000..3df767a7b --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/CalculatorController.java @@ -0,0 +1,39 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +@RestController +public class CalculatorController { + private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); + @Autowired + private Calculator calculator; + + @RequestMapping(path = "/ping", method = RequestMethod.GET, produces = "text/plain") + public String echo() { + return "OK\n"; + } + + @RequestMapping(path = "/", method = RequestMethod.GET, produces = "text/html") + public String main(@RequestParam(required = false) String name) { + if (name == null) { + name = "world"; + } + return "" + + "FediqApp" + + "

Hello, " + name + "!

" + + ""; + } + + @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") + public String eval(@RequestBody String expression) throws ParsingException { + LOG.debug("Evaluation request: [" + expression + "]"); + double result = calculator.calculate(expression); + LOG.trace("Result: " + result); + return Double.toString(result) + "\n"; + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java new file mode 100644 index 000000000..a06f1ac59 --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java @@ -0,0 +1,436 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Stack; + +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + +/** + * Пример реализации калькулятора средствами JEval. + * + * @author vanderwardan + * @since 17.12.16 + */ +public class RESTCalc implements Calculator { + + private Stack operations = new Stack<>(); + private Stack stack = new Stack<>(); // contains expression in postfix notation + private int pos = 0; //position of current symbol in expression + + //names of predefined functions and their valencies + private final Map predefinedFunctions = new HashMap<>(); + //values of variables + private Map variables = new HashMap<>(); + + RESTCalc() { + predefinedFunctions.put("sin", 1); + predefinedFunctions.put("cos", 1); + predefinedFunctions.put("tg", 1); + predefinedFunctions.put("sqrt", 1); + predefinedFunctions.put("pow", 2); + predefinedFunctions.put("abs", 1); + predefinedFunctions.put("sign", 1); + predefinedFunctions.put("log", 1); + predefinedFunctions.put("log2", 1); + predefinedFunctions.put("rnd", 0); + predefinedFunctions.put("max", 2); + predefinedFunctions.put("min", 2); + } + + private int getPriority(Symbol s) throws ParsingException { + switch (s) { + case FUNCTION: + return 0; + case OBRACKET: + return 0; + case CBRACKET: + return 0; + case ADD: + return 1; + case SUB: + return 1; + case MUL: + return 2; + case DIV: + return 2; + case UNOADD: + return 3; + case UNOSUB: + return 3; + default: + freeResource(); + throw new ParsingException("wrong"); + } + } + + private static SymbolType getTokenType(Token t) { + switch (t.symbol) { + case NUMBER: + return SymbolType.NUMBER; + case ADD: + return SymbolType.OPERATOR; + case UNOADD: + return SymbolType.OPERATOR; + case SUB: + return SymbolType.OPERATOR; + case UNOSUB: + return SymbolType.OPERATOR; + case MUL: + return SymbolType.OPERATOR; + case DIV: + return SymbolType.OPERATOR; + case OBRACKET: + return SymbolType.BRACKET; + case CBRACKET: + return SymbolType.BRACKET; + case VARIABLE: + return SymbolType.VARIABLE; + case FUNCTION: + return SymbolType.FUNCTION; + case SPACE: + return SymbolType.SPACE; + default: + return SymbolType.NONE; + } + } + + //is this symbol right-Associativity + private static boolean isRightAssociative(Symbol s) { + //in future, here can be added some right-ass operations =) + switch (s) { + default: + return false; + } + } + + @Override + public double calculate(String expression) throws ParsingException { + try { + if (expression == null) { + throw new ParsingException("wrong"); + } + + //parse expresion and execute it it at the same time + //Really, why should we make reverse polish notation and only than calculate it? + //We can do it both! + while (pos < expression.length()) { + Token t = parseString(expression); //current symbol + + switch (getTokenType(t)) { + case NUMBER: + stack.push(t.value); + break; + case OPERATOR: + pushOperationInStack(t); + break; + case FUNCTION: + operations.push(t); + break; + case BRACKET: + if (t.symbol == Symbol.OBRACKET) { //open bracket + operations.push(t); + } else if (t.symbol == Symbol.CBRACKET) { //close bracket + Token tmp = operations.pop(); + while (!operations.isEmpty() && tmp.symbol != Symbol.OBRACKET || tmp.symbol == Symbol.FUNCTION) { + calculateOperation(tmp); + if(tmp.symbol == Symbol.FUNCTION) { + break; + } + tmp = operations.pop(); + } + + if (tmp.symbol != Symbol.OBRACKET && tmp.symbol != Symbol.FUNCTION) { + throw new ParsingException("wrong"); + } + } + + break; + case VARIABLE: + if(!variables.containsKey(t.name)) { + throw new ParsingException("no such variable"); + } + stack.push(variables.get(t.name)); + break; + case SPACE: + break; + default: + break; + } + + pos++; + } + + //if we parse all expression, and stack isn't empty + while (stack.size() != 1 || operations.size() > 0) { + if (operations.isEmpty()) { + throw new ParsingException("wrong"); + } else { + Token t = operations.pop(); + calculateOperation(t); + } + } + + return stack.pop(); + } finally { + freeResource(); + } + } + + private double getNumber(String expression) throws ParsingException { + char c = expression.charAt(pos); + if (!Character.isDigit(c)) { + freeResource(); + throw new ParsingException("wrong"); + } + + double res = 0.0; + + //find integer part of number + while (Character.isDigit(c)) { + res *= 10; + res += c - '0'; + if (pos == expression.length() - 1) { + break; + } + c = expression.charAt(++pos); + } + + //find fractional part of number + if (c == '.') { + double pow = 0.1; + if (pos >= expression.length() - 1) { + freeResource(); + throw new ParsingException("wrong"); + } + + c = expression.charAt(++pos); + while (Character.isDigit(c)) { + res += (c - '0') * pow; + pow *= 0.1; + if (pos == expression.length() - 1) { + break; + } + c = expression.charAt(++pos); + } + } + + //correct pos + if (!Character.isDigit(c)) { + pos--; + } + + return res; + } + + private double calculateFunction(String name, double[] operands) { + assert(predefinedFunctions.containsKey(name)); + switch (name) { + case "sin": + return Math.sin(operands[0]); + case "cos": + return Math.cos(operands[0]); + case "tg": + return Math.tan(operands[0]); + case "sqrt": + return Math.sqrt(operands[0]); + case "pow": + return Math.pow(operands[0], operands[1]); + case "abs": + return Math.abs(operands[0]); + case "sign": + return Math.signum(operands[0]); + case "log": + return Math.log(operands[0]); + case "log2": + return Math.log(operands[0]) / Math.log(2); + case "rnd": + return (new Random()).nextDouble(); + case "max": + return Math.max(operands[0], operands[1]); + case "min": + return Math.min(operands[0], operands[1]); + default: + return 0.0; + } + } + + //return name of variable or function(in this case, without open bracket) + private String getName(String expression) throws ParsingException { + int oldpos = pos; + String name = ""; + char c = expression.charAt(pos); + + assert(!Character.isDigit(c)); + + while(Character.isLetter(c) || c == '_' || Character.isDigit(c)) { + name += c; + if (pos == expression.length() - 1) { + return name; + } + c = expression.charAt(++pos); + } + pos--; + return name; + } + + //execute operation + private void calculateOperation(Token t) throws ParsingException { + if (stack.size() < t.valency) { + freeResource(); + throw new ParsingException("wrong"); + } + + //get all operands + double[] operands = new double[t.valency]; + + for (int i=0; i < t.valency; ++i) { + operands[t.valency - i - 1] = stack.pop(); + } + + //calculate operation + switch (t.symbol) { + case ADD: + stack.push(operands[0] + operands[1]); + break; + case UNOADD: + stack.push(operands[0]); + break; + case SUB: + stack.push(operands[0] - operands[1]); + break; + case UNOSUB: + stack.push(-operands[0]); + break; + case MUL: + stack.push(operands[0] * operands[1]); + break; + case DIV: + stack.push(operands[0] / operands[1]); + break; + case FUNCTION: + stack.push(calculateFunction(t.name, operands)); + break; + default: + freeResource(); + throw new ParsingException("wrong"); + } + } + + private Token parseString(String expression) throws ParsingException { + char c = expression.charAt(pos); + if (Character.isDigit(c)) { + return new Token(Symbol.NUMBER, getNumber(expression)); + } + if (c == '+' || c == '-') { + char oldc = c; + int oldpos = pos; + boolean uno = true; + + //try to understand is operation uno or not + if (pos > 0) { + c = expression.charAt(--pos); + while (c == ' ' || c == '\n' || c == '\t') { + if (pos > 0) { + c = expression.charAt(--pos); + } else { + break; + } + } + if (c == ')' || c >= '0' && c <= '9') { + uno = false; + } + } + + //return answer + pos = oldpos; + if (uno) { + if (oldc == '+') { + return new Token(Symbol.UNOADD); + } else { + return new Token(Symbol.UNOSUB); + } + } else { + if (oldc == '+') { + return new Token(Symbol.ADD); + } else { + return new Token(Symbol.SUB); + } + } + } + if (c == '*') { + return new Token(Symbol.MUL); + } + if (c == '/') { + return new Token(Symbol.DIV); + } + if (c == '(') { + return new Token(Symbol.OBRACKET); + } + if (c == ')') { + return new Token(Symbol.CBRACKET); + } + if(c == '_' || Character.isLetter(c)) { + String name = getName(expression); + if(pos < expression.length() - 1 && expression.charAt(++pos) == '(') { + if(!predefinedFunctions.containsKey(name)) { + throw new ParsingException("no such a function"); + } + return new Token(Symbol.FUNCTION, name, predefinedFunctions.get(name)); + }else { + if(!variables.containsKey(name)) { + throw new ParsingException("no such a variable"); + } + pos--; + return new Token(Symbol.VARIABLE, name, predefinedFunctions.get(name)); + } + } + if (c == ' ' || c == '\n' || c == '\t' || c == ',') { + return new Token(Symbol.SPACE); + } + + //if nothing of that + freeResource(); + throw new ParsingException("wrong"); + } + + //push a single operation in operation stack ("operations") + private void pushOperationInStack(Token t) throws ParsingException { + if (operations.isEmpty()) { + operations.push(t); + } else { + Token tmp = operations.lastElement(); + + //while it's necessary, pop operation and execute it + while ((getPriority(t.symbol) < getPriority(tmp.symbol)) && isRightAssociative(t.symbol) || + (getPriority(t.symbol) <= getPriority(tmp.symbol)) && !isRightAssociative(t.symbol)) { + + operations.pop(); + calculateOperation(tmp); + + if (operations.isEmpty()) { + break; + } else { + tmp = operations.lastElement(); + } + } + + operations.push(t); + } + } + + private void freeResource() { + stack.clear(); + operations.clear(); + + } + + public enum Symbol { NUMBER, ADD, UNOADD, SUB, UNOSUB, MUL, DIV, OBRACKET, + CBRACKET, VARIABLE, FUNCTION, SPACE, NONE } + + public enum SymbolType { OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java new file mode 100644 index 000000000..f0a72ebbe --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/SecurityServiceConfiguration.java @@ -0,0 +1,56 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UsernameNotFoundException; + +import java.util.Collections; + +@Configuration +@EnableWebSecurity +public class SecurityServiceConfiguration extends WebSecurityConfigurerAdapter { + private static final Logger LOG = LoggerFactory.getLogger(SecurityServiceConfiguration.class); + + @Autowired + private BillingDao billingDao; + + @Override + protected void configure(HttpSecurity http) throws Exception { + LOG.info("Configuring security"); + http + .httpBasic().realmName("Calculator").and() + .formLogin().disable() + .logout().disable() + .csrf().disable() + .authorizeRequests() + .antMatchers("/eval/**").authenticated() + .anyRequest().permitAll(); + } + + @Autowired + public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception { + LOG.info("Register" + + "ing global user details service"); + auth.userDetailsService(username -> { + try { + BillingUser user = billingDao.loadUser(username); + return new User( + user.getUsername(), + user.getPassword(), + Collections.singletonList(() -> "AUTH") + ); + } catch (EmptyResultDataAccessException e) { + LOG.warn("No such user: " + username); + throw new UsernameNotFoundException(username); + } + }); + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java new file mode 100644 index 000000000..fca04617a --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java @@ -0,0 +1,51 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import sun.print.SunMinMaxPage; + +import jdk.nashorn.internal.ir.Symbol; + +/** + * Created by op on 17.12.2016. + */ +public class Token { + + public Token(RESTCalc.Symbol symbol_) { + symbol = symbol_; + valency = getValencyForOperator(symbol_); + } + + public Token(RESTCalc.Symbol symbol_, double value_) { + this(symbol_); + value = value_; + } + + public Token(RESTCalc.Symbol symbol_, String name_, int valency_) { + this(symbol_); + name = name_; + valency = valency_; + } + + public double value; // for numbers + public String name; // for functions and variables + public int valency = 0; // for functions + public RESTCalc.Symbol symbol = RESTCalc.Symbol.NONE; + + private int getValencyForOperator(RESTCalc.Symbol s) { + switch (s) { + case ADD: + return 2; + case UNOADD: + return 1; + case SUB: + return 2; + case UNOSUB: + return 1; + case MUL: + return 2; + case DIV: + return 2; + default: + return 0; + } + } +} diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java new file mode 100644 index 000000000..d028150cb --- /dev/null +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/VardanApplication.java @@ -0,0 +1,41 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.Banner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import ru.mipt.java2016.homework.base.task1.Calculator; + +/**3 + * curl http://localhost:9001/eval \ + * -X POST \ + * -H "Content-Type: text/plain" \ + * -H "Authorization: Basic $(echo -n "username:password" | base64)" \ + * --data-raw "44*3+2" + */ +@EnableAutoConfiguration +@Configuration +@ComponentScan(basePackageClasses = VardanApplication.class) +public class VardanApplication { + + @Bean + public Calculator calculator() { + return new RESTCalc(); + } + + @Bean + public EmbeddedServletContainerCustomizer customizer( + @Value("${ru.mipt.java2016.homework.g595.manucharyan.task4.httpPort:9001}") int port) { + return container -> container.setPort(port); + } + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(VardanApplication.class); + application.setBannerMode(Banner.Mode.OFF); + application.run(args); + } +} diff --git a/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java new file mode 100644 index 000000000..fb4c26500 --- /dev/null +++ b/homework-g595-manucharyan/src/test/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalcTest.java @@ -0,0 +1,15 @@ +package ru.mipt.java2016.homework.g595.manucharyan.task4; + +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.tests.task1.AbstractCalculatorTest; + +/** + * @author vanderwardan + * @since 19.12.16 + */ +public class RESTCalcTest extends AbstractCalculatorTest { + + protected Calculator calc() { + return new RESTCalc(); + } +} From d1f045ed9d0860bc87e067e25c1fc82de053aec7 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Wed, 21 Dec 2016 14:22:07 +0300 Subject: [PATCH 26/29] CODESTYLE --- .../g595/manucharyan/task4/BillingDao.java | 12 +++---- .../task4/BillingDatabaseConfiguration.java | 8 ++--- .../g595/manucharyan/task4/RESTCalc.java | 35 ++++++++++--------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java index 7cd2c3092..999ac4ac2 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDao.java @@ -3,17 +3,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.ExceptionDepthComparator; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; -import javax.annotation.PostConstruct; -import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + @Repository public class BillingDao { @@ -35,10 +35,10 @@ public void initSchema() { jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing"); jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " + "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); - try{ + try { jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)"); - } catch(Exception e) { - + } catch (Exception e) { + System.out.print(""); } } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java index d7d1e1350..3a0c0704a 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/BillingDatabaseConfiguration.java @@ -2,7 +2,7 @@ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; -import org.springframework.beans.factory.annotation.Value; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,11 +11,11 @@ @Configuration public class BillingDatabaseConfiguration { @Bean - public DataSource billingDataSource( - ) { + public DataSource billingDataSource() { HikariConfig config = new HikariConfig(); config.setDriverClassName(org.h2.Driver.class.getName()); - config.setJdbcUrl("jdbc:h2:C:\\Users\\op\\Documents\\GitHub\\mipt-java-2016\\homework-g595-manucharyan\\Database.db"); + config.setJdbcUrl("jdbc:h2:C:\\Users\\op\\Documents\\GitHub\\mipt-java-2016\\" + + "homework-g595-manucharyan\\Database.db"); config.setUsername(""); config.setPassword(""); return new HikariDataSource(config); diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java index a06f1ac59..4a9261083 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java @@ -1,8 +1,6 @@ package ru.mipt.java2016.homework.g595.manucharyan.task4; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Random; import java.util.Stack; @@ -136,9 +134,10 @@ public double calculate(String expression) throws ParsingException { operations.push(t); } else if (t.symbol == Symbol.CBRACKET) { //close bracket Token tmp = operations.pop(); - while (!operations.isEmpty() && tmp.symbol != Symbol.OBRACKET || tmp.symbol == Symbol.FUNCTION) { + while (!operations.isEmpty() && tmp.symbol != Symbol.OBRACKET || + tmp.symbol == Symbol.FUNCTION) { calculateOperation(tmp); - if(tmp.symbol == Symbol.FUNCTION) { + if (tmp.symbol == Symbol.FUNCTION) { break; } tmp = operations.pop(); @@ -151,7 +150,7 @@ public double calculate(String expression) throws ParsingException { break; case VARIABLE: - if(!variables.containsKey(t.name)) { + if (!variables.containsKey(t.name)) { throw new ParsingException("no such variable"); } stack.push(variables.get(t.name)); @@ -228,7 +227,7 @@ private double getNumber(String expression) throws ParsingException { } private double calculateFunction(String name, double[] operands) { - assert(predefinedFunctions.containsKey(name)); + assert (predefinedFunctions.containsKey(name)); switch (name) { case "sin": return Math.sin(operands[0]); @@ -265,9 +264,9 @@ private String getName(String expression) throws ParsingException { String name = ""; char c = expression.charAt(pos); - assert(!Character.isDigit(c)); + assert (!Character.isDigit(c)); - while(Character.isLetter(c) || c == '_' || Character.isDigit(c)) { + while (Character.isLetter(c) || c == '_' || Character.isDigit(c)) { name += c; if (pos == expression.length() - 1) { return name; @@ -288,7 +287,7 @@ private void calculateOperation(Token t) throws ParsingException { //get all operands double[] operands = new double[t.valency]; - for (int i=0; i < t.valency; ++i) { + for (int i = 0; i < t.valency; ++i) { operands[t.valency - i - 1] = stack.pop(); } @@ -374,15 +373,15 @@ private Token parseString(String expression) throws ParsingException { if (c == ')') { return new Token(Symbol.CBRACKET); } - if(c == '_' || Character.isLetter(c)) { + if (c == '_' || Character.isLetter(c)) { String name = getName(expression); - if(pos < expression.length() - 1 && expression.charAt(++pos) == '(') { - if(!predefinedFunctions.containsKey(name)) { + if (pos < expression.length() - 1 && expression.charAt(++pos) == '(') { + if (!predefinedFunctions.containsKey(name)) { throw new ParsingException("no such a function"); } return new Token(Symbol.FUNCTION, name, predefinedFunctions.get(name)); - }else { - if(!variables.containsKey(name)) { + } else { + if (!variables.containsKey(name)) { throw new ParsingException("no such a variable"); } pos--; @@ -429,8 +428,10 @@ private void freeResource() { } - public enum Symbol { NUMBER, ADD, UNOADD, SUB, UNOSUB, MUL, DIV, OBRACKET, - CBRACKET, VARIABLE, FUNCTION, SPACE, NONE } + public enum Symbol { + NUMBER, ADD, UNOADD, SUB, UNOSUB, MUL, DIV, OBRACKET, + CBRACKET, VARIABLE, FUNCTION, SPACE, NONE + } - public enum SymbolType { OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE } + public enum SymbolType {OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE} } From afbc3b2f871ea8bf897438012c5c12e5a145b4f8 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Wed, 21 Dec 2016 14:34:22 +0300 Subject: [PATCH 27/29] We need more codestyle changes --- homework-g595-manucharyan/Database.db.mv.db | Bin 40960 -> 45056 bytes .../g595/manucharyan/task4/RESTCalc.java | 38 +++++++++--------- .../g595/manucharyan/task4/Token.java | 38 +++++++++--------- 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/homework-g595-manucharyan/Database.db.mv.db b/homework-g595-manucharyan/Database.db.mv.db index 15a71d0f7e727266f279e2985e7d21590d35e06a..5455ba118a1f5c469b8a0e42913f7cefd82975b4 100644 GIT binary patch literal 45056 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 J%bo-O{|`H<8Danc literal 40960 zcmeI5%WvDr9mh%ek*vGMLVci@9vE+4Ed+s&p(v_F5!qJPLS;FXlx=o}a0YHE z9vwXnPHI-^Npy6)KN==qj1Qud@T2I6Zg`eyk#J4J7b<`XpaQ4>Du4>00;m8gfC``j zr~oQ}3M^cK9pwLomjN1p3ZMe004jhApaQ4>Du4>00;m8gfC|i80Wrw$^C$qjbPx^c zsQ%;Nu;$bEr!_*%(lB~@QVU9l!Ncg7It-3Rqmx=}6B;F8nzl#W(#ihgsOCj+U{-u3 zBEUCZ9mHXPW+(7W@2H`^wdKt|nJd9#mGS$z@;DmOj<~ zpz7W4r^htNf~rUYtFNeN{$5&PaVx4RE3B$&hgy8T#qIF99iFg* z6<^S=%HoUsz_nC6LW?MNSfB>sb~q_JR4Y_998rnfR3#cmn$VY8iK5u9#HtllTeX6K z6)v~JeNihaX)DfGWm*aqPqkvQOx!1;VpO;hm6Q>-s)br2uBaKJL`2P?g_vle)Qp%+ zUVP4Tr&It|A0XJt0W0uk zSkTQtpAXMh{;FNolD6MU-tFYwN#05F?k4Z-`QRn#>UV|#eO`?YqhaqT7#;`V35{So zemmKFIvk8zqlawcB0KqMkNn09^+ElN2=B^3g2;G7jvDIwK&+$}{&q#{UDx|7ThJznaDWKh~~mtHA$2{WDl! zQosND@ivm~qpyo}f$Qdvy5RCj-8far+t4sfa{f%j6_hU!H;=mxZsat1OMB)o3N(Po z{}DRFz)gD28Ac!6$p7G!K>lB3PY&}&1yBK002M$5@+)wjzoGjZ0RLAB@%+IY`M=Nk zUkq;p|4$vdwa<^4#Q|{xWyH9joAtB4$oM~E{Qr#d|2Na)|0@~%U-+~BH*E#@KXY6k zSYM`s1r1^?YDD+-;9Rg`{-CSS_GC5nCEcdoV7UjBU&c8`l<)%N|0M7Q$NydN&XNB^&i^8m z8u(v^E2jh59Uj1|hAYQa%TxG2%)_~X&h zpiYlFOPh&*;7gkRkupDkZtH8GX2u8nkj@TJ;sbK~2c)N00;m8gaG?|s{15yM{2v1U2La`OXO8@zCfN-B ze;H=Y&H7niWc>e|8T`MK@c$QQjQ>Bsqv?MduMcqc75u-h@_*L)0Jda(N2ZiD10;XV ze^CIa4WDsaIS5d07P4gIYO@W1cU`TxNj`9I?0|6*A$ z;C~5m=?TTod5DW?UsfIekFu~n_dXW?|4TN$f5ztje@Xd%y#C+#bISUE|J0tT>;Gkq z@B5PK1DWc}R47ve81IDw%E!JhKGd&__XcLHL{U^=J%VYgzU5f|PZXa(|Ea6KDRxYj zrUz=^7(8e(|3P@AL?&xSUxFa`4=1bVR1lQ)GYx`btoy6NdZa6Az?+TqdXza_QR(_f z`FQ-AScQo(hM-0LGqg#WO+ zwbR(Gr+&KGY_*#0_l)|z-p*d9`C+}++-uVl7MHIZ#`nozAWtfum8 z8(VwrZm&~swtMn4u#28vG2pg5v(apCH}1)py_0>G$Nk4=Xw5=y#bz=#Hj+(qoRG84jV(3ZKt%2vw!aXNGGC zcx#akA<5rghd&4!B*g)QQ$e66EOIIcSn&qBp=g7E{C^SR|B?UUxrQlJ02M$5Pytjx z(**wme?xbB0Q?{JDgRgJ$p2}O$ie?p2aw?kyezEGy^rz#ACUhq8ULT<n6v|d^Zzdb|KtDvVP6*&Km||%Q~(uF6%hOn{0-eI P5BR@dq4EFm9QgnLB*@af diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java index 4a9261083..9593e698f 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java @@ -67,7 +67,7 @@ private int getPriority(Symbol s) throws ParsingException { } private static SymbolType getTokenType(Token t) { - switch (t.symbol) { + switch (t.getSymbol()) { case NUMBER: return SymbolType.NUMBER; case ADD: @@ -121,7 +121,7 @@ public double calculate(String expression) throws ParsingException { switch (getTokenType(t)) { case NUMBER: - stack.push(t.value); + stack.push(t.getValue()); break; case OPERATOR: pushOperationInStack(t); @@ -130,30 +130,30 @@ public double calculate(String expression) throws ParsingException { operations.push(t); break; case BRACKET: - if (t.symbol == Symbol.OBRACKET) { //open bracket + if (t.getSymbol() == Symbol.OBRACKET) { //open bracket operations.push(t); - } else if (t.symbol == Symbol.CBRACKET) { //close bracket + } else if (t.getSymbol() == Symbol.CBRACKET) { //close bracket Token tmp = operations.pop(); - while (!operations.isEmpty() && tmp.symbol != Symbol.OBRACKET || - tmp.symbol == Symbol.FUNCTION) { + while (!operations.isEmpty() && tmp.getSymbol() != Symbol.OBRACKET || + tmp.getSymbol() == Symbol.FUNCTION) { calculateOperation(tmp); - if (tmp.symbol == Symbol.FUNCTION) { + if (tmp.getSymbol() == Symbol.FUNCTION) { break; } tmp = operations.pop(); } - if (tmp.symbol != Symbol.OBRACKET && tmp.symbol != Symbol.FUNCTION) { + if (tmp.getSymbol() != Symbol.OBRACKET && tmp.getSymbol() != Symbol.FUNCTION) { throw new ParsingException("wrong"); } } break; case VARIABLE: - if (!variables.containsKey(t.name)) { + if (!variables.containsKey(t.getName())) { throw new ParsingException("no such variable"); } - stack.push(variables.get(t.name)); + stack.push(variables.get(t.getName())); break; case SPACE: break; @@ -279,20 +279,20 @@ private String getName(String expression) throws ParsingException { //execute operation private void calculateOperation(Token t) throws ParsingException { - if (stack.size() < t.valency) { + if (stack.size() < t.getValency()) { freeResource(); throw new ParsingException("wrong"); } //get all operands - double[] operands = new double[t.valency]; + double[] operands = new double[t.getValency()]; - for (int i = 0; i < t.valency; ++i) { - operands[t.valency - i - 1] = stack.pop(); + for (int i = 0; i < t.getValency(); ++i) { + operands[t.getValency() - i - 1] = stack.pop(); } //calculate operation - switch (t.symbol) { + switch (t.getSymbol()) { case ADD: stack.push(operands[0] + operands[1]); break; @@ -312,7 +312,7 @@ private void calculateOperation(Token t) throws ParsingException { stack.push(operands[0] / operands[1]); break; case FUNCTION: - stack.push(calculateFunction(t.name, operands)); + stack.push(calculateFunction(t.getName(), operands)); break; default: freeResource(); @@ -405,8 +405,8 @@ private void pushOperationInStack(Token t) throws ParsingException { Token tmp = operations.lastElement(); //while it's necessary, pop operation and execute it - while ((getPriority(t.symbol) < getPriority(tmp.symbol)) && isRightAssociative(t.symbol) || - (getPriority(t.symbol) <= getPriority(tmp.symbol)) && !isRightAssociative(t.symbol)) { + while ((getPriority(t.getSymbol()) < getPriority(tmp.getSymbol())) && isRightAssociative(t.getSymbol()) || + (getPriority(t.getSymbol()) <= getPriority(tmp.getSymbol())) && !isRightAssociative(t.getSymbol())) { operations.pop(); calculateOperation(tmp); @@ -433,5 +433,5 @@ public enum Symbol { CBRACKET, VARIABLE, FUNCTION, SPACE, NONE } - public enum SymbolType {OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE} + public enum SymbolType { OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE } } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java index fca04617a..e424786e4 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java @@ -1,34 +1,30 @@ package ru.mipt.java2016.homework.g595.manucharyan.task4; -import sun.print.SunMinMaxPage; - -import jdk.nashorn.internal.ir.Symbol; - /** * Created by op on 17.12.2016. */ public class Token { - public Token(RESTCalc.Symbol symbol_) { - symbol = symbol_; - valency = getValencyForOperator(symbol_); + public Token(RESTCalc.Symbol symbol) { + this.symbol = symbol; + valency = getValencyForOperator(symbol); } - public Token(RESTCalc.Symbol symbol_, double value_) { - this(symbol_); - value = value_; + public Token(RESTCalc.Symbol symbol, double value) { + this(symbol); + this.value = value; } - public Token(RESTCalc.Symbol symbol_, String name_, int valency_) { - this(symbol_); - name = name_; - valency = valency_; + public Token(RESTCalc.Symbol symbol, String name, int valency) { + this(symbol); + this.name = name; + this.valency = valency; } - public double value; // for numbers - public String name; // for functions and variables - public int valency = 0; // for functions - public RESTCalc.Symbol symbol = RESTCalc.Symbol.NONE; + private double value; // for numbers + private String name; // for functions and variables + private int valency = 0; // for functions + private RESTCalc.Symbol symbol = RESTCalc.Symbol.NONE; private int getValencyForOperator(RESTCalc.Symbol s) { switch (s) { @@ -48,4 +44,10 @@ private int getValencyForOperator(RESTCalc.Symbol s) { return 0; } } + + //get functions + public double getValue() {return value;} + public String getName() {return name;} + public int getValency() {return valency;} + public RESTCalc.Symbol getSymbol() {return symbol;} } From 273135700f984e988545541bae355125cf8c0dc1 Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Wed, 21 Dec 2016 14:38:25 +0300 Subject: [PATCH 28/29] may be now.... --- homework-g595-manucharyan/Database.db.mv.db | Bin 45056 -> 110592 bytes .../g595/manucharyan/task4/RESTCalc.java | 5 +++-- .../g595/manucharyan/task4/Token.java | 19 ++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/homework-g595-manucharyan/Database.db.mv.db b/homework-g595-manucharyan/Database.db.mv.db index 5455ba118a1f5c469b8a0e42913f7cefd82975b4..39e467adbd9fd7d7d1c6c65a4bd6dd2bea6eb362 100644 GIT binary patch literal 110592 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 Z^>BOeQh2);bOHTCoTL=RPyXiN{|64Osc!%P literal 45056 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 J%bo-O{|`H<8Danc diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java index 9593e698f..00947a9e7 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java @@ -406,7 +406,8 @@ private void pushOperationInStack(Token t) throws ParsingException { //while it's necessary, pop operation and execute it while ((getPriority(t.getSymbol()) < getPriority(tmp.getSymbol())) && isRightAssociative(t.getSymbol()) || - (getPriority(t.getSymbol()) <= getPriority(tmp.getSymbol())) && !isRightAssociative(t.getSymbol())) { + (getPriority(t.getSymbol()) <= getPriority(tmp.getSymbol())) && !isRightAssociative(t.getSymbol())) + { operations.pop(); calculateOperation(tmp); @@ -433,5 +434,5 @@ public enum Symbol { CBRACKET, VARIABLE, FUNCTION, SPACE, NONE } - public enum SymbolType { OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE } + public enum SymbolType {OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE} } diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java index e424786e4..b2fe6ee0d 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/Token.java @@ -46,8 +46,19 @@ private int getValencyForOperator(RESTCalc.Symbol s) { } //get functions - public double getValue() {return value;} - public String getName() {return name;} - public int getValency() {return valency;} - public RESTCalc.Symbol getSymbol() {return symbol;} + public double getValue() { + return value; + } + + public String getName() { + return name; + } + + public int getValency() { + return valency; + } + + public RESTCalc.Symbol getSymbol() { + return symbol; + } } From 00fdc2752e88bac5a6976eb93b6d824d690ba0bd Mon Sep 17 00:00:00 2001 From: Manucharyan Vardan Date: Wed, 21 Dec 2016 14:42:56 +0300 Subject: [PATCH 29/29] still trying --- homework-g595-manucharyan/Database.db.mv.db | Bin 110592 -> 249856 bytes .../g595/manucharyan/task4/RESTCalc.java | 5 ++--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/homework-g595-manucharyan/Database.db.mv.db b/homework-g595-manucharyan/Database.db.mv.db index 39e467adbd9fd7d7d1c6c65a4bd6dd2bea6eb362..ff488170f0e3e02afef8bf5fe517aaf94fdd35ec 100644 GIT binary patch literal 249856 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 literal 110592 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 Z^>BOeQh2);bOHTCoTL=RPyXiN{|64Osc!%P diff --git a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java index 00947a9e7..3e6d52f75 100644 --- a/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java +++ b/homework-g595-manucharyan/src/main/java/ru/mipt/java2016/homework/g595/manucharyan/task4/RESTCalc.java @@ -406,8 +406,7 @@ private void pushOperationInStack(Token t) throws ParsingException { //while it's necessary, pop operation and execute it while ((getPriority(t.getSymbol()) < getPriority(tmp.getSymbol())) && isRightAssociative(t.getSymbol()) || - (getPriority(t.getSymbol()) <= getPriority(tmp.getSymbol())) && !isRightAssociative(t.getSymbol())) - { + (getPriority(t.getSymbol()) <= getPriority(tmp.getSymbol())) && !isRightAssociative(t.getSymbol())) { operations.pop(); calculateOperation(tmp); @@ -434,5 +433,5 @@ public enum Symbol { CBRACKET, VARIABLE, FUNCTION, SPACE, NONE } - public enum SymbolType {OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE} + public enum SymbolType { OPERATOR, NUMBER, BRACKET, SPACE, VARIABLE, FUNCTION, NONE } }