From b1d20ab5c62530a71d894c1b23761f60a9a6662b Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 05:59:08 +0300 Subject: [PATCH 01/49] Task 3 finished --- homework-g595-yakusheva/storage.db | Bin 0 -> 232 bytes .../task2/PersistentKeyValueStorage.java | 2 +- .../g597/spirin/task3/BooleanSerializer.java | 28 +++ .../g597/spirin/task3/DateSerializer.java | 29 +++ .../g597/spirin/task3/DoubleSerializer.java | 28 +++ .../task3/HighPerformanceKeyValueStorage.java | 180 ++++++++++++++++++ .../g597/spirin/task3/IntegerSerializer.java | 30 +++ .../spirin/task3/SerializationStrategy.java | 13 ++ .../g597/spirin/task3/StringSerializer.java | 38 ++++ .../HighPerformanceKeyValueStorageTest.java | 49 +++++ .../spirin/task3/StudentKeySerializer.java | 36 ++++ .../g597/spirin/task3/StudentSerializer.java | 48 +++++ 12 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 homework-g595-yakusheva/storage.db create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java create mode 100644 homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java create mode 100644 homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java create mode 100644 homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java diff --git a/homework-g595-yakusheva/storage.db b/homework-g595-yakusheva/storage.db new file mode 100644 index 0000000000000000000000000000000000000000..c46c0a03ec33658f5ce3d6a233227643bf191e99 GIT binary patch literal 232 zcmZQjS18HIELH%b{L&(Y^8CD%)S|S~90l*x%CN+o($wIR{G!D4R0ReG1||mPwETPq z=A^_T2G+{N+}uham717Q3}Uh5<>%+;F|dav7FU*LX9ATU+$A8ofYCwT7z}{g{TcWj zGjbDC6r57?6g(2sGOMr)vN|Vb7Ulo{|6$6hCkGT59JtcJ0H`>efy*mDBTpeXH?t&z GB+URX{Ykk1 literal 0 HcmV?d00001 diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java index 168fc0dbe..334449749 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java @@ -16,7 +16,7 @@ /** * Created by whoami on 10/30/16. */ -class PersistentKeyValueStorage implements KeyValueStorage, AutoCloseable { +class PersistentKeyValueStorage implements KeyValueStorage { private final SerializationStrategy keySerializer; private final SerializationStrategy valueSerializer; diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java new file mode 100644 index 000000000..573953b41 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -0,0 +1,28 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +class BooleanSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final BooleanSerializer HOLDER_INSTANCE = new BooleanSerializer(); + } + + static BooleanSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Boolean read(RandomAccessFile file) throws IOException { + return file.readBoolean(); + } + + @Override + public void write(RandomAccessFile file, Boolean object) throws IOException { + file.writeBoolean(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java new file mode 100644 index 000000000..430ae0a33 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java @@ -0,0 +1,29 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Date; + +/** + * Created by whoami on 11/21/16. + */ +class DateSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final DateSerializer HOLDER_INSTANCE = new DateSerializer(); + } + + static DateSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Date read(RandomAccessFile file) throws IOException { + return new Date(file.readLong()); + } + + @Override + public void write(RandomAccessFile file, Date object) throws IOException { + file.writeLong(object.getTime()); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java new file mode 100644 index 000000000..1dc532ebd --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -0,0 +1,28 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +class DoubleSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final DoubleSerializer HOLDER_INSTANCE = new DoubleSerializer(); + } + + static DoubleSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Double read(RandomAccessFile file) throws IOException { + return file.readDouble(); + } + + @Override + public void write(RandomAccessFile file, Double object) throws IOException { + file.writeDouble(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java new file mode 100644 index 000000000..31b8a2ebc --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -0,0 +1,180 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Created by whoami on 11/21/16. + */ +public class HighPerformanceKeyValueStorage implements KeyValueStorage, AutoCloseable { + + private final SerializationStrategy keySerializer; + private final SerializationStrategy valueSerializer; + + private final RandomAccessFile offsetStorage; + private final RandomAccessFile dataStorage; + + private Map offsets; + + private ReadWriteLock lock; + private boolean isOpen; + + /** + * Suppose that name is a template for name of file storage + */ + HighPerformanceKeyValueStorage(String path, String name, + SerializationStrategy keySerializer, + SerializationStrategy valueSerializer) throws IOException { + + handleFileExistence(path); + + this.keySerializer = keySerializer; + this.valueSerializer = valueSerializer; + + offsetStorage = new RandomAccessFile(path + File.separator + name + ".offset", "rw"); + dataStorage = new RandomAccessFile(path + File.separator + name + ".data", "rw"); + + offsetStorage.getChannel().lock(); + + offsets = new HashMap<>(); + + lock = new ReentrantReadWriteLock(); + + loadData(); + + isOpen = true; + } + + private void handleFileExistence(String path) throws FileNotFoundException { + if (!Files.exists(Paths.get(path))) { + throw new FileNotFoundException("Passed path is not valid."); + } + } + + private void checkIfStorageIsOpen() { + if (!isOpen) { + throw new RuntimeException("Storage is not open."); + } + } + + private void loadData() throws IOException { + offsets.clear(); + offsetStorage.seek(0); + + while (offsetStorage.getFilePointer() < offsetStorage.length()) { + K key = keySerializer.read(offsetStorage); + long offset = offsetStorage.readLong(); + offsets.put(key, offset); + } + } + + @Override + public V read(K key) { + lock.readLock().lock(); + try { + checkIfStorageIsOpen(); + + Long offset = offsets.get(key); + + if (offset == null) { + return null; + } + + dataStorage.seek(offset); + return valueSerializer.read(dataStorage); + } catch (IOException e) { + throw new RuntimeException("File operation error"); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public void write(K key, V value) { + lock.writeLock().lock(); + try { + checkIfStorageIsOpen(); + + dataStorage.seek(dataStorage.length()); + long offset = dataStorage.getFilePointer(); + + valueSerializer.write(dataStorage, value); + + offsets.put(key, offset); + } catch (IOException e) { + throw new RuntimeException("File operation error"); + } finally { + lock.writeLock().unlock(); + } + } + + @Override + public void delete(K key) { + lock.writeLock().lock(); + try { + offsets.remove(key); + } finally { + lock.writeLock().unlock(); + } + } + + @Override + public boolean exists(K key) { + lock.readLock().lock(); + try { + return offsets.containsKey(key); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public int size() { + lock.readLock().lock(); + try { + return offsets.size(); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public Iterator readKeys() { + lock.readLock().lock(); + try { + return offsets.keySet().iterator(); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public void close() throws IOException { + lock.writeLock().lock(); + isOpen = false; + try { + offsetStorage.setLength(0); + offsetStorage.seek(0); + + for (Map.Entry entry : offsets.entrySet()) { + keySerializer.write(offsetStorage, entry.getKey()); + offsetStorage.writeLong(entry.getValue()); + } + + offsetStorage.close(); + } finally { + lock.writeLock().unlock(); + } + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java new file mode 100644 index 000000000..149a1c752 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -0,0 +1,30 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +class IntegerSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final IntegerSerializer HOLDER_INSTANCE = new IntegerSerializer(); + } + + static IntegerSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Integer read(RandomAccessFile file) throws IOException { + return file.readInt(); + } + + @Override + public void write(RandomAccessFile file, Integer object) throws IOException { + file.writeInt(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java new file mode 100644 index 000000000..1055c695d --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java @@ -0,0 +1,13 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +public interface SerializationStrategy { + T read(RandomAccessFile file) throws IOException; + + void write(RandomAccessFile file, T object) throws IOException; +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java new file mode 100644 index 000000000..20a94a7a3 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -0,0 +1,38 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.g597.spirin.task3.IntegerSerializer; +import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +public class StringSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final StringSerializer HOLDER_INSTANCE = new StringSerializer(); + } + + static StringSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); + + @Override + public String read(RandomAccessFile file) throws IOException { + int len = integerSerializer.read(file); + byte[] characters = new byte[len]; + file.readFully(characters); + return new String(characters); + } + + @Override + public void write(RandomAccessFile file, String object) throws IOException { + byte[] characters = object.getBytes(); + integerSerializer.write(file, characters.length); + file.write(characters); + } +} diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java new file mode 100644 index 000000000..c5f103909 --- /dev/null +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java @@ -0,0 +1,49 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; +import ru.mipt.java2016.homework.tests.task2.Student; +import ru.mipt.java2016.homework.tests.task2.StudentKey; +import ru.mipt.java2016.homework.tests.task3.KeyValueStoragePerformanceTest; + +import java.io.IOException; + +/** + * Created by whoami on 11/22/16. + */ +public class HighPerformanceKeyValueStorageTest extends KeyValueStoragePerformanceTest { + private final String filename = "storage.db"; + + @Override + protected KeyValueStorage buildStringsStorage(String path) { + try { + return new HighPerformanceKeyValueStorage<>(path, filename, + StringSerializer.getInstance(), StringSerializer.getInstance()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + } + + @Override + protected KeyValueStorage buildNumbersStorage(String path) { + try { + return new HighPerformanceKeyValueStorage<>(path, filename, + IntegerSerializer.getInstance(), DoubleSerializer.getInstance()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected KeyValueStorage buildPojoStorage(String path) { + try { + return new HighPerformanceKeyValueStorage<>(path, filename, + StudentKeySerializer.getInstance(), StudentSerializer.getInstance()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java new file mode 100644 index 000000000..902671a01 --- /dev/null +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java @@ -0,0 +1,36 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.tests.task2.StudentKey; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/22/16. + */ +public class StudentKeySerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final StudentKeySerializer HOLDER_INSTANCE = new StudentKeySerializer(); + } + + static StudentKeySerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); + private final StringSerializer stringSerializer = StringSerializer.getInstance(); + + @Override + public StudentKey read(RandomAccessFile file) throws IOException { + int groupID = integerSerializer.read(file); + String name = stringSerializer.read(file); + return new StudentKey(groupID, name); + } + + @Override + public void write(RandomAccessFile file, StudentKey object) throws IOException { + integerSerializer.write(file, object.getGroupId()); + stringSerializer.write(file, object.getName()); + } +} diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java new file mode 100644 index 000000000..6daf7d302 --- /dev/null +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java @@ -0,0 +1,48 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.tests.task2.Student; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Date; + +/** + * Created by whoami on 11/22/16. + */ +public class StudentSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final StudentSerializer HOLDER_INSTANCE = new StudentSerializer(); + } + + static StudentSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); + private final StringSerializer stringSerializer = StringSerializer.getInstance(); + private final DateSerializer dateSerializer = DateSerializer.getInstance(); + private final BooleanSerializer booleanSerializer = BooleanSerializer.getInstance(); + private final DoubleSerializer doubleSerializer = DoubleSerializer.getInstance(); + + @Override + public Student read(RandomAccessFile file) throws IOException { + int groupID = integerSerializer.read(file); + String name = stringSerializer.read(file); + String hometown = stringSerializer.read(file); + Date birthDate = dateSerializer.read(file); + boolean hasDormitory = booleanSerializer.read(file); + double averageScore = doubleSerializer.read(file); + return new Student(groupID, name, hometown, birthDate, hasDormitory, averageScore); + } + + @Override + public void write(RandomAccessFile file, Student object) throws IOException { + integerSerializer.write(file, object.getGroupId()); + stringSerializer.write(file, object.getName()); + stringSerializer.write(file, object.getHometown()); + dateSerializer.write(file, object.getBirthDate()); + booleanSerializer.write(file, object.isHasDormitory()); + doubleSerializer.write(file, object.getAverageScore()); + } +} From d665de2385332aba43ee335b02515d5b05c33456 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 06:05:43 +0300 Subject: [PATCH 02/49] Task 3 completed --- .../java2016/homework/g597/spirin/task3/IntegerSerializer.java | 2 -- .../java2016/homework/g597/spirin/task3/StringSerializer.java | 3 --- 2 files changed, 5 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index 149a1c752..8f71532a0 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -1,7 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task3; -import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; - import java.io.IOException; import java.io.RandomAccessFile; diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java index 20a94a7a3..851668bb5 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task3; -import ru.mipt.java2016.homework.g597.spirin.task3.IntegerSerializer; -import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; - import java.io.IOException; import java.io.RandomAccessFile; From bb3d94cbf9d45ebbf3220d30f160701c01ee5bf7 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 06:11:41 +0300 Subject: [PATCH 03/49] Task 3 completed --- .../homework/g597/spirin/task2/PersistentKeyValueStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java index 334449749..168fc0dbe 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java @@ -16,7 +16,7 @@ /** * Created by whoami on 10/30/16. */ -class PersistentKeyValueStorage implements KeyValueStorage { +class PersistentKeyValueStorage implements KeyValueStorage, AutoCloseable { private final SerializationStrategy keySerializer; private final SerializationStrategy valueSerializer; From 2e251a7e0fe45a84548ed548cfdf08f32e7e1b5f Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 19:31:57 +0300 Subject: [PATCH 04/49] Implementation based on cache --- .../homework/g597/spirin/task3/Cache.java | 63 +++++++++++++++++++ .../task3/HighPerformanceKeyValueStorage.java | 11 ++++ 2 files changed, 74 insertions(+) create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java new file mode 100644 index 000000000..5b6887442 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java @@ -0,0 +1,63 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; + +/** + * Created by whoami on 11/22/16. + */ + +/** + * Cache is for optimizing real-life queries for key-value storage + * @param - keys + * @param - values + */ +public class Cache { + + private int DEFAULT_MAX_CACHE_SIZE = 100; + + private int maxCacheSize; + private Map cache; + private Queue queue; + + Cache() { + this.maxCacheSize = DEFAULT_MAX_CACHE_SIZE; + cache = new HashMap<>(); + queue = new LinkedList<>(); + } + + Cache(int maxCacheSize) { + if (maxCacheSize < 1) { + throw new RuntimeException("Cache maximum size cannot be less than 1."); + } + + this.maxCacheSize = maxCacheSize; + cache = new HashMap<>(); + queue = new LinkedList<>(); + } + + void put(K key, V value) { + if (key == null || value == null) { + throw new NullPointerException("Unexpected null key or value."); + } + + if (queue.size() >= maxCacheSize) { + // Remove the last added element + cache.remove(queue.poll()); + } + + cache.put(key, value); + queue.add(key); + } + + V get(K key) { + if (key == null) { + throw new NullPointerException("Unexpected null key."); + } + + return cache.get(key); + } + +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 31b8a2ebc..acfcae80a 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -30,6 +30,8 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache; + /** * Suppose that name is a template for name of file storage */ @@ -48,6 +50,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage(); + cache = new Cache<>(); lock = new ReentrantReadWriteLock(); @@ -85,6 +88,11 @@ public V read(K key) { try { checkIfStorageIsOpen(); + V value = cache.get(key); + if (value != null) { + return value; + } + Long offset = offsets.get(key); if (offset == null) { @@ -106,6 +114,8 @@ public void write(K key, V value) { try { checkIfStorageIsOpen(); + cache.put(key, value); + dataStorage.seek(dataStorage.length()); long offset = dataStorage.getFilePointer(); @@ -174,6 +184,7 @@ public void close() throws IOException { offsetStorage.close(); } finally { + lock.writeLock().unlock(); } } From 462bf096d78f86ba045bf4639b67f944f3cda163 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 19:38:07 +0300 Subject: [PATCH 05/49] Little fix --- .../java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java index 5b6887442..ba7adfd19 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java @@ -16,7 +16,7 @@ */ public class Cache { - private int DEFAULT_MAX_CACHE_SIZE = 100; + private static final int DEFAULT_MAX_CACHE_SIZE = 100; private int maxCacheSize; private Map cache; From 8dc4a5a464f2db00a13132505f815e4e5691a220 Mon Sep 17 00:00:00 2001 From: whoami Date: Wed, 23 Nov 2016 19:49:06 +0300 Subject: [PATCH 06/49] Guava cache added --- homework-g597-spirin/pom.xml | 6 ++ .../homework/g597/spirin/task3/Cache.java | 63 ------------------- .../task3/HighPerformanceKeyValueStorage.java | 44 ++++++------- 3 files changed, 28 insertions(+), 85 deletions(-) delete mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java diff --git a/homework-g597-spirin/pom.xml b/homework-g597-spirin/pom.xml index 383b2e1f2..8e3251357 100644 --- a/homework-g597-spirin/pom.xml +++ b/homework-g597-spirin/pom.xml @@ -24,6 +24,12 @@ 1.0.0 test + + + com.google.guava + guava + 20.0 + \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java deleted file mode 100644 index ba7adfd19..000000000 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.mipt.java2016.homework.g597.spirin.task3; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.Queue; - -/** - * Created by whoami on 11/22/16. - */ - -/** - * Cache is for optimizing real-life queries for key-value storage - * @param - keys - * @param - values - */ -public class Cache { - - private static final int DEFAULT_MAX_CACHE_SIZE = 100; - - private int maxCacheSize; - private Map cache; - private Queue queue; - - Cache() { - this.maxCacheSize = DEFAULT_MAX_CACHE_SIZE; - cache = new HashMap<>(); - queue = new LinkedList<>(); - } - - Cache(int maxCacheSize) { - if (maxCacheSize < 1) { - throw new RuntimeException("Cache maximum size cannot be less than 1."); - } - - this.maxCacheSize = maxCacheSize; - cache = new HashMap<>(); - queue = new LinkedList<>(); - } - - void put(K key, V value) { - if (key == null || value == null) { - throw new NullPointerException("Unexpected null key or value."); - } - - if (queue.size() >= maxCacheSize) { - // Remove the last added element - cache.remove(queue.poll()); - } - - cache.put(key, value); - queue.add(key); - } - - V get(K key) { - if (key == null) { - throw new NullPointerException("Unexpected null key."); - } - - return cache.get(key); - } - -} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index acfcae80a..aaade517e 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -1,5 +1,8 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import ru.mipt.java2016.homework.base.task2.KeyValueStorage; import java.io.File; @@ -11,6 +14,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -30,7 +34,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache; + private LoadingCache cache; /** * Suppose that name is a template for name of file storage @@ -50,7 +54,18 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage(); - cache = new Cache<>(); + cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { + @Override + public V load(K key) throws Exception { + Long offset = offsets.get(key); + if (offset == null) { + return null; + } + + dataStorage.seek(offset); + return valueSerializer.read(dataStorage); + } + }); lock = new ReentrantReadWriteLock(); @@ -74,6 +89,7 @@ private void checkIfStorageIsOpen() { private void loadData() throws IOException { offsets.clear(); offsetStorage.seek(0); + cache.cleanUp(); while (offsetStorage.getFilePointer() < offsetStorage.length()) { K key = keySerializer.read(offsetStorage); @@ -87,21 +103,11 @@ public V read(K key) { lock.readLock().lock(); try { checkIfStorageIsOpen(); - - V value = cache.get(key); - if (value != null) { - return value; - } - - Long offset = offsets.get(key); - - if (offset == null) { + if (!offsets.containsKey(key)) { return null; } - - dataStorage.seek(offset); - return valueSerializer.read(dataStorage); - } catch (IOException e) { + return cache.get(key); + } catch (ExecutionException e) { throw new RuntimeException("File operation error"); } finally { lock.readLock().unlock(); @@ -113,15 +119,9 @@ public void write(K key, V value) { lock.writeLock().lock(); try { checkIfStorageIsOpen(); - - cache.put(key, value); - dataStorage.seek(dataStorage.length()); - long offset = dataStorage.getFilePointer(); - + offsets.put(key, dataStorage.getFilePointer()); valueSerializer.write(dataStorage, value); - - offsets.put(key, offset); } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { From 132f4434dbe32752d925600813cbc638f43a960b Mon Sep 17 00:00:00 2001 From: whoami Date: Sat, 26 Nov 2016 19:15:52 +0300 Subject: [PATCH 07/49] Some fixes --- .../g597/spirin/task3/BooleanSerializer.java | 2 +- .../g597/spirin/task3/DateSerializer.java | 2 +- .../g597/spirin/task3/DoubleSerializer.java | 2 +- .../task3/HighPerformanceKeyValueStorage.java | 35 ++++++++++--------- .../g597/spirin/task3/IntegerSerializer.java | 2 +- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java index 573953b41..6715174a2 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -6,7 +6,7 @@ /** * Created by whoami on 11/21/16. */ -class BooleanSerializer implements SerializationStrategy { +public class BooleanSerializer implements SerializationStrategy { private static class SingletonHolder { static final BooleanSerializer HOLDER_INSTANCE = new BooleanSerializer(); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java index 430ae0a33..1aa2116ec 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java @@ -7,7 +7,7 @@ /** * Created by whoami on 11/21/16. */ -class DateSerializer implements SerializationStrategy { +public class DateSerializer implements SerializationStrategy { private static class SingletonHolder { static final DateSerializer HOLDER_INSTANCE = new DateSerializer(); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java index 1dc532ebd..cb0e720df 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -6,7 +6,7 @@ /** * Created by whoami on 11/21/16. */ -class DoubleSerializer implements SerializationStrategy { +public class DoubleSerializer implements SerializationStrategy { private static class SingletonHolder { static final DoubleSerializer HOLDER_INSTANCE = new DoubleSerializer(); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index aaade517e..e5d33a98b 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -29,12 +29,23 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage offsets; + private final Map offsets = new HashMap<>(); private ReadWriteLock lock; private boolean isOpen; - private LoadingCache cache; + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { + @Override + public V load(K key) throws Exception { + Long offset = offsets.get(key); + if (offset == null) { + return null; + } + + dataStorage.seek(offset); + return valueSerializer.read(dataStorage); + } + }); /** * Suppose that name is a template for name of file storage @@ -53,20 +64,6 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage(); - cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { - @Override - public V load(K key) throws Exception { - Long offset = offsets.get(key); - if (offset == null) { - return null; - } - - dataStorage.seek(offset); - return valueSerializer.read(dataStorage); - } - }); - lock = new ReentrantReadWriteLock(); loadData(); @@ -119,6 +116,7 @@ public void write(K key, V value) { lock.writeLock().lock(); try { checkIfStorageIsOpen(); + dataStorage.seek(dataStorage.length()); offsets.put(key, dataStorage.getFilePointer()); valueSerializer.write(dataStorage, value); @@ -172,6 +170,11 @@ public Iterator readKeys() { @Override public void close() throws IOException { lock.writeLock().lock(); + + if (!isOpen) { + return; + } + isOpen = false; try { offsetStorage.setLength(0); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index 8f71532a0..1d2585edf 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -6,7 +6,7 @@ /** * Created by whoami on 11/21/16. */ -class IntegerSerializer implements SerializationStrategy { +public class IntegerSerializer implements SerializationStrategy { private static class SingletonHolder { static final IntegerSerializer HOLDER_INSTANCE = new IntegerSerializer(); From 2629413ab06d30c2ba1bac59d203c3d33fb3c2a4 Mon Sep 17 00:00:00 2001 From: whoami Date: Sat, 26 Nov 2016 19:47:41 +0300 Subject: [PATCH 08/49] Logic fixes --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index e5d33a98b..88943661f 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -32,7 +32,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage offsets = new HashMap<>(); private ReadWriteLock lock; - private boolean isOpen; + private boolean isOpen = false; private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { @Override @@ -131,6 +131,7 @@ public void write(K key, V value) { public void delete(K key) { lock.writeLock().lock(); try { + checkIfStorageIsOpen(); offsets.remove(key); } finally { lock.writeLock().unlock(); @@ -141,6 +142,7 @@ public void delete(K key) { public boolean exists(K key) { lock.readLock().lock(); try { + checkIfStorageIsOpen(); return offsets.containsKey(key); } finally { lock.readLock().unlock(); @@ -151,6 +153,7 @@ public boolean exists(K key) { public int size() { lock.readLock().lock(); try { + checkIfStorageIsOpen(); return offsets.size(); } finally { lock.readLock().unlock(); @@ -161,6 +164,7 @@ public int size() { public Iterator readKeys() { lock.readLock().lock(); try { + checkIfStorageIsOpen(); return offsets.keySet().iterator(); } finally { lock.readLock().unlock(); @@ -187,7 +191,6 @@ public void close() throws IOException { offsetStorage.close(); } finally { - lock.writeLock().unlock(); } } From a976d6d680726a67b32dc2b92f8e4b51516c8e20 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 21:43:53 +0300 Subject: [PATCH 09/49] modifying queries maintenance --- .../g597/spirin/task3/BooleanSerializer.java | 6 +- .../g597/spirin/task3/DateSerializer.java | 6 +- .../g597/spirin/task3/DoubleSerializer.java | 6 +- .../task3/HighPerformanceKeyValueStorage.java | 82 ++++++++++++++++--- .../g597/spirin/task3/IntegerSerializer.java | 6 +- .../g597/spirin/task3/LongSerializer.java | 29 +++++++ .../spirin/task3/SerializationStrategy.java | 7 +- .../g597/spirin/task3/StringSerializer.java | 6 +- .../spirin/task3/StudentKeySerializer.java | 6 +- .../g597/spirin/task3/StudentSerializer.java | 7 +- 10 files changed, 133 insertions(+), 28 deletions(-) create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java index 6715174a2..bfe5e1013 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -17,12 +19,12 @@ static BooleanSerializer getInstance() { } @Override - public Boolean read(RandomAccessFile file) throws IOException { + public Boolean read(DataInput file) throws IOException { return file.readBoolean(); } @Override - public void write(RandomAccessFile file, Boolean object) throws IOException { + public void write(DataOutput file, Boolean object) throws IOException { file.writeBoolean(object); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java index 1aa2116ec..c8548df88 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Date; @@ -18,12 +20,12 @@ static DateSerializer getInstance() { } @Override - public Date read(RandomAccessFile file) throws IOException { + public Date read(DataInput file) throws IOException { return new Date(file.readLong()); } @Override - public void write(RandomAccessFile file, Date object) throws IOException { + public void write(DataOutput file, Date object) throws IOException { file.writeLong(object.getTime()); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java index cb0e720df..b0d29eabd 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -17,12 +19,12 @@ static DoubleSerializer getInstance() { } @Override - public Double read(RandomAccessFile file) throws IOException { + public Double read(DataInput file) throws IOException { return file.readDouble(); } @Override - public void write(RandomAccessFile file, Double object) throws IOException { + public void write(DataOutput file, Double object) throws IOException { file.writeDouble(object); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 88943661f..4fb96feaa 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -5,10 +5,7 @@ import com.google.common.cache.LoadingCache; import ru.mipt.java2016.homework.base.task2.KeyValueStorage; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; @@ -26,14 +23,20 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage keySerializer; private final SerializationStrategy valueSerializer; - private final RandomAccessFile offsetStorage; - private final RandomAccessFile dataStorage; + private RandomAccessFile offsetStorage; + private RandomAccessFile dataStorage; - private final Map offsets = new HashMap<>(); + private final String path; + private final String name; - private ReadWriteLock lock; + private Map offsets = new HashMap<>(); + + private final ReadWriteLock lock = new ReentrantReadWriteLock(); private boolean isOpen = false; + private int countModifyOperations; + private static final int MAX_MODIFY_OPERATIONS = 500; + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { @Override public V load(K key) throws Exception { @@ -56,6 +59,9 @@ public V load(K key) throws Exception { handleFileExistence(path); + this.path = path; + this.name = name; + this.keySerializer = keySerializer; this.valueSerializer = valueSerializer; @@ -64,11 +70,10 @@ public V load(K key) throws Exception { offsetStorage.getChannel().lock(); - lock = new ReentrantReadWriteLock(); - loadData(); isOpen = true; + countModifyOperations = 0; } private void handleFileExistence(String path) throws FileNotFoundException { @@ -95,6 +100,33 @@ private void loadData() throws IOException { } } + private void updateStorage() throws IOException { + RandomAccessFile buffer = new RandomAccessFile(path + File.separator + name + ".buffer", "rw"); + Map updatedOffsets = new HashMap<>(); + + dataStorage.seek(0); + while (dataStorage.getFilePointer() < dataStorage.length()) { + V value = valueSerializer.read(dataStorage); + K key = keySerializer.read(dataStorage); + + if (offsets.containsKey(key)) { + updatedOffsets.put(key, buffer.getFilePointer()); + valueSerializer.write(buffer, value); + keySerializer.write(buffer, key); + } + } + dataStorage.close(); + buffer.close(); + + offsets = updatedOffsets; + + File bufferFile = new File(path + File.separator + name + ".buffer"); + File dataFile = new File(path + File.separator + name + ".data"); + + bufferFile.renameTo(dataFile); + dataStorage = new RandomAccessFile(path + File.separator + name + ".data", "rw"); + } + @Override public V read(K key) { lock.readLock().lock(); @@ -117,9 +149,22 @@ public void write(K key, V value) { try { checkIfStorageIsOpen(); + if (offsets.containsKey(key)) { + countModifyOperations += 1; + } + + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + countModifyOperations = 0; + } + dataStorage.seek(dataStorage.length()); - offsets.put(key, dataStorage.getFilePointer()); + Long offset = dataStorage.getFilePointer(); + + offsets.put(key, offset); + valueSerializer.write(dataStorage, value); + keySerializer.write(dataStorage, key); } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { @@ -132,7 +177,19 @@ public void delete(K key) { lock.writeLock().lock(); try { checkIfStorageIsOpen(); + + if (offsets.containsKey(key)) { + countModifyOperations += 1; + } + + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + countModifyOperations = 0; + } + offsets.remove(key); + } catch (IOException e) { + throw new RuntimeException("File operation error"); } finally { lock.writeLock().unlock(); } @@ -171,6 +228,7 @@ public Iterator readKeys() { } } + @Override public void close() throws IOException { lock.writeLock().lock(); @@ -181,6 +239,8 @@ public void close() throws IOException { isOpen = false; try { + updateStorage(); + offsetStorage.setLength(0); offsetStorage.seek(0); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index 1d2585edf..ad8608ce4 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -17,12 +19,12 @@ static IntegerSerializer getInstance() { } @Override - public Integer read(RandomAccessFile file) throws IOException { + public Integer read(DataInput file) throws IOException { return file.readInt(); } @Override - public void write(RandomAccessFile file, Integer object) throws IOException { + public void write(DataOutput file, Integer object) throws IOException { file.writeInt(object); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java new file mode 100644 index 000000000..db6a6f5c4 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java @@ -0,0 +1,29 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * Created by whoami on 11/28/16. + */ +public class LongSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final LongSerializer HOLDER_INSTANCE = new LongSerializer(); + } + + static LongSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Long read(DataInput file) throws IOException { + return file.readLong(); + } + + @Override + public void write(DataOutput file, Long object) throws IOException { + file.writeLong(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java index 1055c695d..e7572f661 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java @@ -1,13 +1,14 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. */ public interface SerializationStrategy { - T read(RandomAccessFile file) throws IOException; + T read(DataInput file) throws IOException; - void write(RandomAccessFile file, T object) throws IOException; + void write(DataOutput file, T object) throws IOException; } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java index 851668bb5..57791707d 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -19,7 +21,7 @@ static StringSerializer getInstance() { private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); @Override - public String read(RandomAccessFile file) throws IOException { + public String read(DataInput file) throws IOException { int len = integerSerializer.read(file); byte[] characters = new byte[len]; file.readFully(characters); @@ -27,7 +29,7 @@ public String read(RandomAccessFile file) throws IOException { } @Override - public void write(RandomAccessFile file, String object) throws IOException { + public void write(DataOutput file, String object) throws IOException { byte[] characters = object.getBytes(); integerSerializer.write(file, characters.length); file.write(characters); diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java index 902671a01..1de9c012a 100644 --- a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java @@ -2,6 +2,8 @@ import ru.mipt.java2016.homework.tests.task2.StudentKey; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -22,14 +24,14 @@ static StudentKeySerializer getInstance() { private final StringSerializer stringSerializer = StringSerializer.getInstance(); @Override - public StudentKey read(RandomAccessFile file) throws IOException { + public StudentKey read(DataInput file) throws IOException { int groupID = integerSerializer.read(file); String name = stringSerializer.read(file); return new StudentKey(groupID, name); } @Override - public void write(RandomAccessFile file, StudentKey object) throws IOException { + public void write(DataOutput file, StudentKey object) throws IOException { integerSerializer.write(file, object.getGroupId()); stringSerializer.write(file, object.getName()); } diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java index 6daf7d302..ba6e6c954 100644 --- a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java @@ -2,6 +2,9 @@ import ru.mipt.java2016.homework.tests.task2.Student; +import javax.xml.crypto.Data; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Date; @@ -26,7 +29,7 @@ static StudentSerializer getInstance() { private final DoubleSerializer doubleSerializer = DoubleSerializer.getInstance(); @Override - public Student read(RandomAccessFile file) throws IOException { + public Student read(DataInput file) throws IOException { int groupID = integerSerializer.read(file); String name = stringSerializer.read(file); String hometown = stringSerializer.read(file); @@ -37,7 +40,7 @@ public Student read(RandomAccessFile file) throws IOException { } @Override - public void write(RandomAccessFile file, Student object) throws IOException { + public void write(DataOutput file, Student object) throws IOException { integerSerializer.write(file, object.getGroupId()); stringSerializer.write(file, object.getName()); stringSerializer.write(file, object.getHometown()); From 282558dd0368d5fd5b26af758e96ff9b88a9dde6 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 21:47:38 +0300 Subject: [PATCH 10/49] unused imports reduced --- .../java2016/homework/g597/spirin/task3/BooleanSerializer.java | 1 - .../mipt/java2016/homework/g597/spirin/task3/DateSerializer.java | 1 - .../java2016/homework/g597/spirin/task3/DoubleSerializer.java | 1 - .../java2016/homework/g597/spirin/task3/IntegerSerializer.java | 1 - .../java2016/homework/g597/spirin/task3/StringSerializer.java | 1 - 5 files changed, 5 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java index bfe5e1013..e439e2fa9 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java index c8548df88..5bfa45adc 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.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; /** diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java index b0d29eabd..59fe4b088 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index ad8608ce4..4ab211c3b 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java index 57791707d..8d4ba3fb0 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. From d4506b80523357c415d9426daa95ea93444d15a6 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 21:58:35 +0300 Subject: [PATCH 11/49] one more change.. --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 4fb96feaa..a6bbfa88d 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -57,11 +57,11 @@ public V load(K key) throws Exception { SerializationStrategy keySerializer, SerializationStrategy valueSerializer) throws IOException { - handleFileExistence(path); - this.path = path; this.name = name; + handleFileExistence(); + this.keySerializer = keySerializer; this.valueSerializer = valueSerializer; @@ -76,7 +76,7 @@ public V load(K key) throws Exception { countModifyOperations = 0; } - private void handleFileExistence(String path) throws FileNotFoundException { + private void handleFileExistence() throws FileNotFoundException { if (!Files.exists(Paths.get(path))) { throw new FileNotFoundException("Passed path is not valid."); } From 9945a325834decdb83551f28b096efcb7be63d4c Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 22:17:40 +0300 Subject: [PATCH 12/49] time boost --- .../task3/HighPerformanceKeyValueStorage.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index a6bbfa88d..e97e1999f 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -37,7 +37,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(500).build(new CacheLoader() { @Override public V load(K key) throws Exception { Long offset = offsets.get(key); @@ -117,6 +117,7 @@ private void updateStorage() throws IOException { } dataStorage.close(); buffer.close(); + offsets.clear(); offsets = updatedOffsets; @@ -153,11 +154,6 @@ public void write(K key, V value) { countModifyOperations += 1; } - if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { - updateStorage(); - countModifyOperations = 0; - } - dataStorage.seek(dataStorage.length()); Long offset = dataStorage.getFilePointer(); @@ -165,6 +161,11 @@ public void write(K key, V value) { valueSerializer.write(dataStorage, value); keySerializer.write(dataStorage, key); + + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + countModifyOperations = 0; + } } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { @@ -182,12 +183,12 @@ public void delete(K key) { countModifyOperations += 1; } + offsets.remove(key); + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); countModifyOperations = 0; } - - offsets.remove(key); } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { @@ -239,7 +240,9 @@ public void close() throws IOException { isOpen = false; try { - updateStorage(); + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + } offsetStorage.setLength(0); offsetStorage.seek(0); From 88e35f27038cd2942f10b2aaf7bbad2d28a39775 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 23:50:56 +0300 Subject: [PATCH 13/49] proposed changes made --- .../task3/HighPerformanceKeyValueStorage.java | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index e97e1999f..d28cb9655 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -101,25 +101,25 @@ private void loadData() throws IOException { } private void updateStorage() throws IOException { - RandomAccessFile buffer = new RandomAccessFile(path + File.separator + name + ".buffer", "rw"); - Map updatedOffsets = new HashMap<>(); - - dataStorage.seek(0); - while (dataStorage.getFilePointer() < dataStorage.length()) { - V value = valueSerializer.read(dataStorage); - K key = keySerializer.read(dataStorage); - - if (offsets.containsKey(key)) { - updatedOffsets.put(key, buffer.getFilePointer()); - valueSerializer.write(buffer, value); - keySerializer.write(buffer, key); + try (RandomAccessFile buffer = new RandomAccessFile(path + File.separator + name + ".buffer", "rw")) { + Map updatedOffsets = new HashMap<>(); + + dataStorage.seek(0); + while (dataStorage.getFilePointer() < dataStorage.length()) { + V value = valueSerializer.read(dataStorage); + K key = keySerializer.read(dataStorage); + + if (offsets.containsKey(key)) { + updatedOffsets.put(key, buffer.getFilePointer()); + valueSerializer.write(buffer, value); + keySerializer.write(buffer, key); + } } + + offsets.clear(); + offsets = updatedOffsets; } dataStorage.close(); - buffer.close(); - offsets.clear(); - - offsets = updatedOffsets; File bufferFile = new File(path + File.separator + name + ".buffer"); File dataFile = new File(path + File.separator + name + ".data"); @@ -130,7 +130,7 @@ private void updateStorage() throws IOException { @Override public V read(K key) { - lock.readLock().lock(); + lock.writeLock().lock(); try { checkIfStorageIsOpen(); if (!offsets.containsKey(key)) { @@ -138,7 +138,7 @@ public V read(K key) { } return cache.get(key); } catch (ExecutionException e) { - throw new RuntimeException("File operation error"); + throw new RuntimeException(e); } finally { lock.readLock().unlock(); } @@ -167,7 +167,7 @@ public void write(K key, V value) { countModifyOperations = 0; } } catch (IOException e) { - throw new RuntimeException("File operation error"); + throw new RuntimeException(e); } finally { lock.writeLock().unlock(); } @@ -190,7 +190,7 @@ public void delete(K key) { countModifyOperations = 0; } } catch (IOException e) { - throw new RuntimeException("File operation error"); + throw new RuntimeException(e); } finally { lock.writeLock().unlock(); } @@ -242,6 +242,7 @@ public void close() throws IOException { try { if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); + countModifyOperations = 0; } offsetStorage.setLength(0); From d06916546815afac000552ffa4eefc949bfc88e9 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 23:57:06 +0300 Subject: [PATCH 14/49] little fix --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index d28cb9655..52133d7d0 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -242,7 +242,6 @@ public void close() throws IOException { try { if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); - countModifyOperations = 0; } offsetStorage.setLength(0); From cd1f67a3f028d67ec7df4f2c79d38a25f29010c9 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 29 Nov 2016 00:02:33 +0300 Subject: [PATCH 15/49] last update --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 52133d7d0..12792155e 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -140,7 +140,7 @@ public V read(K key) { } catch (ExecutionException e) { throw new RuntimeException(e); } finally { - lock.readLock().unlock(); + lock.writeLock().unlock(); } } @@ -242,6 +242,7 @@ public void close() throws IOException { try { if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); + countModifyOperations = 0; } offsetStorage.setLength(0); From 68f1cae11c8d7e071a542b6d481f8f067639398f Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 05:59:08 +0300 Subject: [PATCH 16/49] Task 3 finished --- homework-g595-yakusheva/storage.db | Bin 0 -> 232 bytes .../task2/PersistentKeyValueStorage.java | 2 +- .../g597/spirin/task3/BooleanSerializer.java | 28 +++ .../g597/spirin/task3/DateSerializer.java | 29 +++ .../g597/spirin/task3/DoubleSerializer.java | 28 +++ .../task3/HighPerformanceKeyValueStorage.java | 180 ++++++++++++++++++ .../g597/spirin/task3/IntegerSerializer.java | 30 +++ .../spirin/task3/SerializationStrategy.java | 13 ++ .../g597/spirin/task3/StringSerializer.java | 38 ++++ .../HighPerformanceKeyValueStorageTest.java | 49 +++++ .../spirin/task3/StudentKeySerializer.java | 36 ++++ .../g597/spirin/task3/StudentSerializer.java | 48 +++++ 12 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 homework-g595-yakusheva/storage.db create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java create mode 100644 homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java create mode 100644 homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java create mode 100644 homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java diff --git a/homework-g595-yakusheva/storage.db b/homework-g595-yakusheva/storage.db new file mode 100644 index 0000000000000000000000000000000000000000..c46c0a03ec33658f5ce3d6a233227643bf191e99 GIT binary patch literal 232 zcmZQjS18HIELH%b{L&(Y^8CD%)S|S~90l*x%CN+o($wIR{G!D4R0ReG1||mPwETPq z=A^_T2G+{N+}uham717Q3}Uh5<>%+;F|dav7FU*LX9ATU+$A8ofYCwT7z}{g{TcWj zGjbDC6r57?6g(2sGOMr)vN|Vb7Ulo{|6$6hCkGT59JtcJ0H`>efy*mDBTpeXH?t&z GB+URX{Ykk1 literal 0 HcmV?d00001 diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java index 168fc0dbe..334449749 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java @@ -16,7 +16,7 @@ /** * Created by whoami on 10/30/16. */ -class PersistentKeyValueStorage implements KeyValueStorage, AutoCloseable { +class PersistentKeyValueStorage implements KeyValueStorage { private final SerializationStrategy keySerializer; private final SerializationStrategy valueSerializer; diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java new file mode 100644 index 000000000..573953b41 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -0,0 +1,28 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +class BooleanSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final BooleanSerializer HOLDER_INSTANCE = new BooleanSerializer(); + } + + static BooleanSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Boolean read(RandomAccessFile file) throws IOException { + return file.readBoolean(); + } + + @Override + public void write(RandomAccessFile file, Boolean object) throws IOException { + file.writeBoolean(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java new file mode 100644 index 000000000..430ae0a33 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java @@ -0,0 +1,29 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Date; + +/** + * Created by whoami on 11/21/16. + */ +class DateSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final DateSerializer HOLDER_INSTANCE = new DateSerializer(); + } + + static DateSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Date read(RandomAccessFile file) throws IOException { + return new Date(file.readLong()); + } + + @Override + public void write(RandomAccessFile file, Date object) throws IOException { + file.writeLong(object.getTime()); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java new file mode 100644 index 000000000..1dc532ebd --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -0,0 +1,28 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +class DoubleSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final DoubleSerializer HOLDER_INSTANCE = new DoubleSerializer(); + } + + static DoubleSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Double read(RandomAccessFile file) throws IOException { + return file.readDouble(); + } + + @Override + public void write(RandomAccessFile file, Double object) throws IOException { + file.writeDouble(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java new file mode 100644 index 000000000..31b8a2ebc --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -0,0 +1,180 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Created by whoami on 11/21/16. + */ +public class HighPerformanceKeyValueStorage implements KeyValueStorage, AutoCloseable { + + private final SerializationStrategy keySerializer; + private final SerializationStrategy valueSerializer; + + private final RandomAccessFile offsetStorage; + private final RandomAccessFile dataStorage; + + private Map offsets; + + private ReadWriteLock lock; + private boolean isOpen; + + /** + * Suppose that name is a template for name of file storage + */ + HighPerformanceKeyValueStorage(String path, String name, + SerializationStrategy keySerializer, + SerializationStrategy valueSerializer) throws IOException { + + handleFileExistence(path); + + this.keySerializer = keySerializer; + this.valueSerializer = valueSerializer; + + offsetStorage = new RandomAccessFile(path + File.separator + name + ".offset", "rw"); + dataStorage = new RandomAccessFile(path + File.separator + name + ".data", "rw"); + + offsetStorage.getChannel().lock(); + + offsets = new HashMap<>(); + + lock = new ReentrantReadWriteLock(); + + loadData(); + + isOpen = true; + } + + private void handleFileExistence(String path) throws FileNotFoundException { + if (!Files.exists(Paths.get(path))) { + throw new FileNotFoundException("Passed path is not valid."); + } + } + + private void checkIfStorageIsOpen() { + if (!isOpen) { + throw new RuntimeException("Storage is not open."); + } + } + + private void loadData() throws IOException { + offsets.clear(); + offsetStorage.seek(0); + + while (offsetStorage.getFilePointer() < offsetStorage.length()) { + K key = keySerializer.read(offsetStorage); + long offset = offsetStorage.readLong(); + offsets.put(key, offset); + } + } + + @Override + public V read(K key) { + lock.readLock().lock(); + try { + checkIfStorageIsOpen(); + + Long offset = offsets.get(key); + + if (offset == null) { + return null; + } + + dataStorage.seek(offset); + return valueSerializer.read(dataStorage); + } catch (IOException e) { + throw new RuntimeException("File operation error"); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public void write(K key, V value) { + lock.writeLock().lock(); + try { + checkIfStorageIsOpen(); + + dataStorage.seek(dataStorage.length()); + long offset = dataStorage.getFilePointer(); + + valueSerializer.write(dataStorage, value); + + offsets.put(key, offset); + } catch (IOException e) { + throw new RuntimeException("File operation error"); + } finally { + lock.writeLock().unlock(); + } + } + + @Override + public void delete(K key) { + lock.writeLock().lock(); + try { + offsets.remove(key); + } finally { + lock.writeLock().unlock(); + } + } + + @Override + public boolean exists(K key) { + lock.readLock().lock(); + try { + return offsets.containsKey(key); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public int size() { + lock.readLock().lock(); + try { + return offsets.size(); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public Iterator readKeys() { + lock.readLock().lock(); + try { + return offsets.keySet().iterator(); + } finally { + lock.readLock().unlock(); + } + } + + @Override + public void close() throws IOException { + lock.writeLock().lock(); + isOpen = false; + try { + offsetStorage.setLength(0); + offsetStorage.seek(0); + + for (Map.Entry entry : offsets.entrySet()) { + keySerializer.write(offsetStorage, entry.getKey()); + offsetStorage.writeLong(entry.getValue()); + } + + offsetStorage.close(); + } finally { + lock.writeLock().unlock(); + } + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java new file mode 100644 index 000000000..149a1c752 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -0,0 +1,30 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +class IntegerSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final IntegerSerializer HOLDER_INSTANCE = new IntegerSerializer(); + } + + static IntegerSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Integer read(RandomAccessFile file) throws IOException { + return file.readInt(); + } + + @Override + public void write(RandomAccessFile file, Integer object) throws IOException { + file.writeInt(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java new file mode 100644 index 000000000..1055c695d --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java @@ -0,0 +1,13 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +public interface SerializationStrategy { + T read(RandomAccessFile file) throws IOException; + + void write(RandomAccessFile file, T object) throws IOException; +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java new file mode 100644 index 000000000..20a94a7a3 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -0,0 +1,38 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.g597.spirin.task3.IntegerSerializer; +import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/21/16. + */ +public class StringSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final StringSerializer HOLDER_INSTANCE = new StringSerializer(); + } + + static StringSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); + + @Override + public String read(RandomAccessFile file) throws IOException { + int len = integerSerializer.read(file); + byte[] characters = new byte[len]; + file.readFully(characters); + return new String(characters); + } + + @Override + public void write(RandomAccessFile file, String object) throws IOException { + byte[] characters = object.getBytes(); + integerSerializer.write(file, characters.length); + file.write(characters); + } +} diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java new file mode 100644 index 000000000..c5f103909 --- /dev/null +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorageTest.java @@ -0,0 +1,49 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.base.task2.KeyValueStorage; +import ru.mipt.java2016.homework.tests.task2.Student; +import ru.mipt.java2016.homework.tests.task2.StudentKey; +import ru.mipt.java2016.homework.tests.task3.KeyValueStoragePerformanceTest; + +import java.io.IOException; + +/** + * Created by whoami on 11/22/16. + */ +public class HighPerformanceKeyValueStorageTest extends KeyValueStoragePerformanceTest { + private final String filename = "storage.db"; + + @Override + protected KeyValueStorage buildStringsStorage(String path) { + try { + return new HighPerformanceKeyValueStorage<>(path, filename, + StringSerializer.getInstance(), StringSerializer.getInstance()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + } + + @Override + protected KeyValueStorage buildNumbersStorage(String path) { + try { + return new HighPerformanceKeyValueStorage<>(path, filename, + IntegerSerializer.getInstance(), DoubleSerializer.getInstance()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } + + @Override + protected KeyValueStorage buildPojoStorage(String path) { + try { + return new HighPerformanceKeyValueStorage<>(path, filename, + StudentKeySerializer.getInstance(), StudentSerializer.getInstance()); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java new file mode 100644 index 000000000..902671a01 --- /dev/null +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java @@ -0,0 +1,36 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.tests.task2.StudentKey; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Created by whoami on 11/22/16. + */ +public class StudentKeySerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final StudentKeySerializer HOLDER_INSTANCE = new StudentKeySerializer(); + } + + static StudentKeySerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); + private final StringSerializer stringSerializer = StringSerializer.getInstance(); + + @Override + public StudentKey read(RandomAccessFile file) throws IOException { + int groupID = integerSerializer.read(file); + String name = stringSerializer.read(file); + return new StudentKey(groupID, name); + } + + @Override + public void write(RandomAccessFile file, StudentKey object) throws IOException { + integerSerializer.write(file, object.getGroupId()); + stringSerializer.write(file, object.getName()); + } +} diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java new file mode 100644 index 000000000..6daf7d302 --- /dev/null +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java @@ -0,0 +1,48 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import ru.mipt.java2016.homework.tests.task2.Student; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.Date; + +/** + * Created by whoami on 11/22/16. + */ +public class StudentSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final StudentSerializer HOLDER_INSTANCE = new StudentSerializer(); + } + + static StudentSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); + private final StringSerializer stringSerializer = StringSerializer.getInstance(); + private final DateSerializer dateSerializer = DateSerializer.getInstance(); + private final BooleanSerializer booleanSerializer = BooleanSerializer.getInstance(); + private final DoubleSerializer doubleSerializer = DoubleSerializer.getInstance(); + + @Override + public Student read(RandomAccessFile file) throws IOException { + int groupID = integerSerializer.read(file); + String name = stringSerializer.read(file); + String hometown = stringSerializer.read(file); + Date birthDate = dateSerializer.read(file); + boolean hasDormitory = booleanSerializer.read(file); + double averageScore = doubleSerializer.read(file); + return new Student(groupID, name, hometown, birthDate, hasDormitory, averageScore); + } + + @Override + public void write(RandomAccessFile file, Student object) throws IOException { + integerSerializer.write(file, object.getGroupId()); + stringSerializer.write(file, object.getName()); + stringSerializer.write(file, object.getHometown()); + dateSerializer.write(file, object.getBirthDate()); + booleanSerializer.write(file, object.isHasDormitory()); + doubleSerializer.write(file, object.getAverageScore()); + } +} From cc4699a05687079cf4f11e1e181bf216df69638c Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 06:05:43 +0300 Subject: [PATCH 17/49] Task 3 completed --- .../java2016/homework/g597/spirin/task3/IntegerSerializer.java | 2 -- .../java2016/homework/g597/spirin/task3/StringSerializer.java | 3 --- 2 files changed, 5 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index 149a1c752..8f71532a0 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -1,7 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task3; -import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; - import java.io.IOException; import java.io.RandomAccessFile; diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java index 20a94a7a3..851668bb5 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task3; -import ru.mipt.java2016.homework.g597.spirin.task3.IntegerSerializer; -import ru.mipt.java2016.homework.g597.spirin.task3.SerializationStrategy; - import java.io.IOException; import java.io.RandomAccessFile; From 0c2aa38c8231406fe3809023afe2e56639f409a5 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 06:11:41 +0300 Subject: [PATCH 18/49] Task 3 completed --- .../homework/g597/spirin/task2/PersistentKeyValueStorage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java index 334449749..168fc0dbe 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task2/PersistentKeyValueStorage.java @@ -16,7 +16,7 @@ /** * Created by whoami on 10/30/16. */ -class PersistentKeyValueStorage implements KeyValueStorage { +class PersistentKeyValueStorage implements KeyValueStorage, AutoCloseable { private final SerializationStrategy keySerializer; private final SerializationStrategy valueSerializer; From c437248896a5135888012ed2097ece708d7ca8b8 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 19:31:57 +0300 Subject: [PATCH 19/49] Implementation based on cache --- .../homework/g597/spirin/task3/Cache.java | 63 +++++++++++++++++++ .../task3/HighPerformanceKeyValueStorage.java | 11 ++++ 2 files changed, 74 insertions(+) create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java new file mode 100644 index 000000000..5b6887442 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java @@ -0,0 +1,63 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; + +/** + * Created by whoami on 11/22/16. + */ + +/** + * Cache is for optimizing real-life queries for key-value storage + * @param - keys + * @param - values + */ +public class Cache { + + private int DEFAULT_MAX_CACHE_SIZE = 100; + + private int maxCacheSize; + private Map cache; + private Queue queue; + + Cache() { + this.maxCacheSize = DEFAULT_MAX_CACHE_SIZE; + cache = new HashMap<>(); + queue = new LinkedList<>(); + } + + Cache(int maxCacheSize) { + if (maxCacheSize < 1) { + throw new RuntimeException("Cache maximum size cannot be less than 1."); + } + + this.maxCacheSize = maxCacheSize; + cache = new HashMap<>(); + queue = new LinkedList<>(); + } + + void put(K key, V value) { + if (key == null || value == null) { + throw new NullPointerException("Unexpected null key or value."); + } + + if (queue.size() >= maxCacheSize) { + // Remove the last added element + cache.remove(queue.poll()); + } + + cache.put(key, value); + queue.add(key); + } + + V get(K key) { + if (key == null) { + throw new NullPointerException("Unexpected null key."); + } + + return cache.get(key); + } + +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 31b8a2ebc..acfcae80a 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -30,6 +30,8 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache; + /** * Suppose that name is a template for name of file storage */ @@ -48,6 +50,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage(); + cache = new Cache<>(); lock = new ReentrantReadWriteLock(); @@ -85,6 +88,11 @@ public V read(K key) { try { checkIfStorageIsOpen(); + V value = cache.get(key); + if (value != null) { + return value; + } + Long offset = offsets.get(key); if (offset == null) { @@ -106,6 +114,8 @@ public void write(K key, V value) { try { checkIfStorageIsOpen(); + cache.put(key, value); + dataStorage.seek(dataStorage.length()); long offset = dataStorage.getFilePointer(); @@ -174,6 +184,7 @@ public void close() throws IOException { offsetStorage.close(); } finally { + lock.writeLock().unlock(); } } From 473aaef2c3e65ab30963aa45653411cdf30a8293 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 22 Nov 2016 19:38:07 +0300 Subject: [PATCH 20/49] Little fix --- .../java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java index 5b6887442..ba7adfd19 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java @@ -16,7 +16,7 @@ */ public class Cache { - private int DEFAULT_MAX_CACHE_SIZE = 100; + private static final int DEFAULT_MAX_CACHE_SIZE = 100; private int maxCacheSize; private Map cache; From 69e58a396bde8bc9b8bda6addafc0c43479e9f13 Mon Sep 17 00:00:00 2001 From: whoami Date: Wed, 23 Nov 2016 19:49:06 +0300 Subject: [PATCH 21/49] Guava cache added --- homework-g597-spirin/pom.xml | 6 ++ .../homework/g597/spirin/task3/Cache.java | 63 ------------------- .../task3/HighPerformanceKeyValueStorage.java | 44 ++++++------- 3 files changed, 28 insertions(+), 85 deletions(-) delete mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java diff --git a/homework-g597-spirin/pom.xml b/homework-g597-spirin/pom.xml index 383b2e1f2..8e3251357 100644 --- a/homework-g597-spirin/pom.xml +++ b/homework-g597-spirin/pom.xml @@ -24,6 +24,12 @@ 1.0.0 test + + + com.google.guava + guava + 20.0 + \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java deleted file mode 100644 index ba7adfd19..000000000 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/Cache.java +++ /dev/null @@ -1,63 +0,0 @@ -package ru.mipt.java2016.homework.g597.spirin.task3; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.Queue; - -/** - * Created by whoami on 11/22/16. - */ - -/** - * Cache is for optimizing real-life queries for key-value storage - * @param - keys - * @param - values - */ -public class Cache { - - private static final int DEFAULT_MAX_CACHE_SIZE = 100; - - private int maxCacheSize; - private Map cache; - private Queue queue; - - Cache() { - this.maxCacheSize = DEFAULT_MAX_CACHE_SIZE; - cache = new HashMap<>(); - queue = new LinkedList<>(); - } - - Cache(int maxCacheSize) { - if (maxCacheSize < 1) { - throw new RuntimeException("Cache maximum size cannot be less than 1."); - } - - this.maxCacheSize = maxCacheSize; - cache = new HashMap<>(); - queue = new LinkedList<>(); - } - - void put(K key, V value) { - if (key == null || value == null) { - throw new NullPointerException("Unexpected null key or value."); - } - - if (queue.size() >= maxCacheSize) { - // Remove the last added element - cache.remove(queue.poll()); - } - - cache.put(key, value); - queue.add(key); - } - - V get(K key) { - if (key == null) { - throw new NullPointerException("Unexpected null key."); - } - - return cache.get(key); - } - -} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index acfcae80a..aaade517e 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -1,5 +1,8 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; import ru.mipt.java2016.homework.base.task2.KeyValueStorage; import java.io.File; @@ -11,6 +14,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.concurrent.ExecutionException; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -30,7 +34,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache; + private LoadingCache cache; /** * Suppose that name is a template for name of file storage @@ -50,7 +54,18 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage(); - cache = new Cache<>(); + cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { + @Override + public V load(K key) throws Exception { + Long offset = offsets.get(key); + if (offset == null) { + return null; + } + + dataStorage.seek(offset); + return valueSerializer.read(dataStorage); + } + }); lock = new ReentrantReadWriteLock(); @@ -74,6 +89,7 @@ private void checkIfStorageIsOpen() { private void loadData() throws IOException { offsets.clear(); offsetStorage.seek(0); + cache.cleanUp(); while (offsetStorage.getFilePointer() < offsetStorage.length()) { K key = keySerializer.read(offsetStorage); @@ -87,21 +103,11 @@ public V read(K key) { lock.readLock().lock(); try { checkIfStorageIsOpen(); - - V value = cache.get(key); - if (value != null) { - return value; - } - - Long offset = offsets.get(key); - - if (offset == null) { + if (!offsets.containsKey(key)) { return null; } - - dataStorage.seek(offset); - return valueSerializer.read(dataStorage); - } catch (IOException e) { + return cache.get(key); + } catch (ExecutionException e) { throw new RuntimeException("File operation error"); } finally { lock.readLock().unlock(); @@ -113,15 +119,9 @@ public void write(K key, V value) { lock.writeLock().lock(); try { checkIfStorageIsOpen(); - - cache.put(key, value); - dataStorage.seek(dataStorage.length()); - long offset = dataStorage.getFilePointer(); - + offsets.put(key, dataStorage.getFilePointer()); valueSerializer.write(dataStorage, value); - - offsets.put(key, offset); } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { From e91dd4ed5dedae029642253c8eec5adc7172c3a9 Mon Sep 17 00:00:00 2001 From: whoami Date: Sat, 26 Nov 2016 19:15:52 +0300 Subject: [PATCH 22/49] Some fixes --- .../g597/spirin/task3/BooleanSerializer.java | 2 +- .../g597/spirin/task3/DateSerializer.java | 2 +- .../g597/spirin/task3/DoubleSerializer.java | 2 +- .../task3/HighPerformanceKeyValueStorage.java | 35 ++++++++++--------- .../g597/spirin/task3/IntegerSerializer.java | 2 +- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java index 573953b41..6715174a2 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -6,7 +6,7 @@ /** * Created by whoami on 11/21/16. */ -class BooleanSerializer implements SerializationStrategy { +public class BooleanSerializer implements SerializationStrategy { private static class SingletonHolder { static final BooleanSerializer HOLDER_INSTANCE = new BooleanSerializer(); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java index 430ae0a33..1aa2116ec 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java @@ -7,7 +7,7 @@ /** * Created by whoami on 11/21/16. */ -class DateSerializer implements SerializationStrategy { +public class DateSerializer implements SerializationStrategy { private static class SingletonHolder { static final DateSerializer HOLDER_INSTANCE = new DateSerializer(); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java index 1dc532ebd..cb0e720df 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -6,7 +6,7 @@ /** * Created by whoami on 11/21/16. */ -class DoubleSerializer implements SerializationStrategy { +public class DoubleSerializer implements SerializationStrategy { private static class SingletonHolder { static final DoubleSerializer HOLDER_INSTANCE = new DoubleSerializer(); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index aaade517e..e5d33a98b 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -29,12 +29,23 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage offsets; + private final Map offsets = new HashMap<>(); private ReadWriteLock lock; private boolean isOpen; - private LoadingCache cache; + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { + @Override + public V load(K key) throws Exception { + Long offset = offsets.get(key); + if (offset == null) { + return null; + } + + dataStorage.seek(offset); + return valueSerializer.read(dataStorage); + } + }); /** * Suppose that name is a template for name of file storage @@ -53,20 +64,6 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage(); - cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { - @Override - public V load(K key) throws Exception { - Long offset = offsets.get(key); - if (offset == null) { - return null; - } - - dataStorage.seek(offset); - return valueSerializer.read(dataStorage); - } - }); - lock = new ReentrantReadWriteLock(); loadData(); @@ -119,6 +116,7 @@ public void write(K key, V value) { lock.writeLock().lock(); try { checkIfStorageIsOpen(); + dataStorage.seek(dataStorage.length()); offsets.put(key, dataStorage.getFilePointer()); valueSerializer.write(dataStorage, value); @@ -172,6 +170,11 @@ public Iterator readKeys() { @Override public void close() throws IOException { lock.writeLock().lock(); + + if (!isOpen) { + return; + } + isOpen = false; try { offsetStorage.setLength(0); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index 8f71532a0..1d2585edf 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -6,7 +6,7 @@ /** * Created by whoami on 11/21/16. */ -class IntegerSerializer implements SerializationStrategy { +public class IntegerSerializer implements SerializationStrategy { private static class SingletonHolder { static final IntegerSerializer HOLDER_INSTANCE = new IntegerSerializer(); From 4516fe5a5a7bcf5698aab5032a368ea49ce5116e Mon Sep 17 00:00:00 2001 From: whoami Date: Sat, 26 Nov 2016 19:47:41 +0300 Subject: [PATCH 23/49] Logic fixes --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index e5d33a98b..88943661f 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -32,7 +32,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage offsets = new HashMap<>(); private ReadWriteLock lock; - private boolean isOpen; + private boolean isOpen = false; private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { @Override @@ -131,6 +131,7 @@ public void write(K key, V value) { public void delete(K key) { lock.writeLock().lock(); try { + checkIfStorageIsOpen(); offsets.remove(key); } finally { lock.writeLock().unlock(); @@ -141,6 +142,7 @@ public void delete(K key) { public boolean exists(K key) { lock.readLock().lock(); try { + checkIfStorageIsOpen(); return offsets.containsKey(key); } finally { lock.readLock().unlock(); @@ -151,6 +153,7 @@ public boolean exists(K key) { public int size() { lock.readLock().lock(); try { + checkIfStorageIsOpen(); return offsets.size(); } finally { lock.readLock().unlock(); @@ -161,6 +164,7 @@ public int size() { public Iterator readKeys() { lock.readLock().lock(); try { + checkIfStorageIsOpen(); return offsets.keySet().iterator(); } finally { lock.readLock().unlock(); @@ -187,7 +191,6 @@ public void close() throws IOException { offsetStorage.close(); } finally { - lock.writeLock().unlock(); } } From a6663e21eda2182eaba3580f2f2ff74bf0fef860 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 21:43:53 +0300 Subject: [PATCH 24/49] modifying queries maintenance --- .../g597/spirin/task3/BooleanSerializer.java | 6 +- .../g597/spirin/task3/DateSerializer.java | 6 +- .../g597/spirin/task3/DoubleSerializer.java | 6 +- .../task3/HighPerformanceKeyValueStorage.java | 82 ++++++++++++++++--- .../g597/spirin/task3/IntegerSerializer.java | 6 +- .../g597/spirin/task3/LongSerializer.java | 29 +++++++ .../spirin/task3/SerializationStrategy.java | 7 +- .../g597/spirin/task3/StringSerializer.java | 6 +- .../spirin/task3/StudentKeySerializer.java | 6 +- .../g597/spirin/task3/StudentSerializer.java | 7 +- 10 files changed, 133 insertions(+), 28 deletions(-) create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java index 6715174a2..bfe5e1013 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -17,12 +19,12 @@ static BooleanSerializer getInstance() { } @Override - public Boolean read(RandomAccessFile file) throws IOException { + public Boolean read(DataInput file) throws IOException { return file.readBoolean(); } @Override - public void write(RandomAccessFile file, Boolean object) throws IOException { + public void write(DataOutput file, Boolean object) throws IOException { file.writeBoolean(object); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java index 1aa2116ec..c8548df88 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Date; @@ -18,12 +20,12 @@ static DateSerializer getInstance() { } @Override - public Date read(RandomAccessFile file) throws IOException { + public Date read(DataInput file) throws IOException { return new Date(file.readLong()); } @Override - public void write(RandomAccessFile file, Date object) throws IOException { + public void write(DataOutput file, Date object) throws IOException { file.writeLong(object.getTime()); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java index cb0e720df..b0d29eabd 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -17,12 +19,12 @@ static DoubleSerializer getInstance() { } @Override - public Double read(RandomAccessFile file) throws IOException { + public Double read(DataInput file) throws IOException { return file.readDouble(); } @Override - public void write(RandomAccessFile file, Double object) throws IOException { + public void write(DataOutput file, Double object) throws IOException { file.writeDouble(object); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 88943661f..4fb96feaa 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -5,10 +5,7 @@ import com.google.common.cache.LoadingCache; import ru.mipt.java2016.homework.base.task2.KeyValueStorage; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; +import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.HashMap; @@ -26,14 +23,20 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage keySerializer; private final SerializationStrategy valueSerializer; - private final RandomAccessFile offsetStorage; - private final RandomAccessFile dataStorage; + private RandomAccessFile offsetStorage; + private RandomAccessFile dataStorage; - private final Map offsets = new HashMap<>(); + private final String path; + private final String name; - private ReadWriteLock lock; + private Map offsets = new HashMap<>(); + + private final ReadWriteLock lock = new ReentrantReadWriteLock(); private boolean isOpen = false; + private int countModifyOperations; + private static final int MAX_MODIFY_OPERATIONS = 500; + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { @Override public V load(K key) throws Exception { @@ -56,6 +59,9 @@ public V load(K key) throws Exception { handleFileExistence(path); + this.path = path; + this.name = name; + this.keySerializer = keySerializer; this.valueSerializer = valueSerializer; @@ -64,11 +70,10 @@ public V load(K key) throws Exception { offsetStorage.getChannel().lock(); - lock = new ReentrantReadWriteLock(); - loadData(); isOpen = true; + countModifyOperations = 0; } private void handleFileExistence(String path) throws FileNotFoundException { @@ -95,6 +100,33 @@ private void loadData() throws IOException { } } + private void updateStorage() throws IOException { + RandomAccessFile buffer = new RandomAccessFile(path + File.separator + name + ".buffer", "rw"); + Map updatedOffsets = new HashMap<>(); + + dataStorage.seek(0); + while (dataStorage.getFilePointer() < dataStorage.length()) { + V value = valueSerializer.read(dataStorage); + K key = keySerializer.read(dataStorage); + + if (offsets.containsKey(key)) { + updatedOffsets.put(key, buffer.getFilePointer()); + valueSerializer.write(buffer, value); + keySerializer.write(buffer, key); + } + } + dataStorage.close(); + buffer.close(); + + offsets = updatedOffsets; + + File bufferFile = new File(path + File.separator + name + ".buffer"); + File dataFile = new File(path + File.separator + name + ".data"); + + bufferFile.renameTo(dataFile); + dataStorage = new RandomAccessFile(path + File.separator + name + ".data", "rw"); + } + @Override public V read(K key) { lock.readLock().lock(); @@ -117,9 +149,22 @@ public void write(K key, V value) { try { checkIfStorageIsOpen(); + if (offsets.containsKey(key)) { + countModifyOperations += 1; + } + + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + countModifyOperations = 0; + } + dataStorage.seek(dataStorage.length()); - offsets.put(key, dataStorage.getFilePointer()); + Long offset = dataStorage.getFilePointer(); + + offsets.put(key, offset); + valueSerializer.write(dataStorage, value); + keySerializer.write(dataStorage, key); } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { @@ -132,7 +177,19 @@ public void delete(K key) { lock.writeLock().lock(); try { checkIfStorageIsOpen(); + + if (offsets.containsKey(key)) { + countModifyOperations += 1; + } + + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + countModifyOperations = 0; + } + offsets.remove(key); + } catch (IOException e) { + throw new RuntimeException("File operation error"); } finally { lock.writeLock().unlock(); } @@ -171,6 +228,7 @@ public Iterator readKeys() { } } + @Override public void close() throws IOException { lock.writeLock().lock(); @@ -181,6 +239,8 @@ public void close() throws IOException { isOpen = false; try { + updateStorage(); + offsetStorage.setLength(0); offsetStorage.seek(0); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index 1d2585edf..ad8608ce4 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -17,12 +19,12 @@ static IntegerSerializer getInstance() { } @Override - public Integer read(RandomAccessFile file) throws IOException { + public Integer read(DataInput file) throws IOException { return file.readInt(); } @Override - public void write(RandomAccessFile file, Integer object) throws IOException { + public void write(DataOutput file, Integer object) throws IOException { file.writeInt(object); } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java new file mode 100644 index 000000000..db6a6f5c4 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/LongSerializer.java @@ -0,0 +1,29 @@ +package ru.mipt.java2016.homework.g597.spirin.task3; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; + +/** + * Created by whoami on 11/28/16. + */ +public class LongSerializer implements SerializationStrategy { + + private static class SingletonHolder { + static final LongSerializer HOLDER_INSTANCE = new LongSerializer(); + } + + static LongSerializer getInstance() { + return SingletonHolder.HOLDER_INSTANCE; + } + + @Override + public Long read(DataInput file) throws IOException { + return file.readLong(); + } + + @Override + public void write(DataOutput file, Long object) throws IOException { + file.writeLong(object); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java index 1055c695d..e7572f661 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/SerializationStrategy.java @@ -1,13 +1,14 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. */ public interface SerializationStrategy { - T read(RandomAccessFile file) throws IOException; + T read(DataInput file) throws IOException; - void write(RandomAccessFile file, T object) throws IOException; + void write(DataOutput file, T object) throws IOException; } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java index 851668bb5..57791707d 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -1,5 +1,7 @@ package ru.mipt.java2016.homework.g597.spirin.task3; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -19,7 +21,7 @@ static StringSerializer getInstance() { private final IntegerSerializer integerSerializer = IntegerSerializer.getInstance(); @Override - public String read(RandomAccessFile file) throws IOException { + public String read(DataInput file) throws IOException { int len = integerSerializer.read(file); byte[] characters = new byte[len]; file.readFully(characters); @@ -27,7 +29,7 @@ public String read(RandomAccessFile file) throws IOException { } @Override - public void write(RandomAccessFile file, String object) throws IOException { + public void write(DataOutput file, String object) throws IOException { byte[] characters = object.getBytes(); integerSerializer.write(file, characters.length); file.write(characters); diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java index 902671a01..1de9c012a 100644 --- a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentKeySerializer.java @@ -2,6 +2,8 @@ import ru.mipt.java2016.homework.tests.task2.StudentKey; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; @@ -22,14 +24,14 @@ static StudentKeySerializer getInstance() { private final StringSerializer stringSerializer = StringSerializer.getInstance(); @Override - public StudentKey read(RandomAccessFile file) throws IOException { + public StudentKey read(DataInput file) throws IOException { int groupID = integerSerializer.read(file); String name = stringSerializer.read(file); return new StudentKey(groupID, name); } @Override - public void write(RandomAccessFile file, StudentKey object) throws IOException { + public void write(DataOutput file, StudentKey object) throws IOException { integerSerializer.write(file, object.getGroupId()); stringSerializer.write(file, object.getName()); } diff --git a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java index 6daf7d302..ba6e6c954 100644 --- a/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java +++ b/homework-g597-spirin/src/test/java/ru/mipt/java2016/homework/g597/spirin/task3/StudentSerializer.java @@ -2,6 +2,9 @@ import ru.mipt.java2016.homework.tests.task2.Student; +import javax.xml.crypto.Data; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; import java.util.Date; @@ -26,7 +29,7 @@ static StudentSerializer getInstance() { private final DoubleSerializer doubleSerializer = DoubleSerializer.getInstance(); @Override - public Student read(RandomAccessFile file) throws IOException { + public Student read(DataInput file) throws IOException { int groupID = integerSerializer.read(file); String name = stringSerializer.read(file); String hometown = stringSerializer.read(file); @@ -37,7 +40,7 @@ public Student read(RandomAccessFile file) throws IOException { } @Override - public void write(RandomAccessFile file, Student object) throws IOException { + public void write(DataOutput file, Student object) throws IOException { integerSerializer.write(file, object.getGroupId()); stringSerializer.write(file, object.getName()); stringSerializer.write(file, object.getHometown()); From 5ebb5fd3913957bf1948ec605662b408c956f5ab Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 21:47:38 +0300 Subject: [PATCH 25/49] unused imports reduced --- .../java2016/homework/g597/spirin/task3/BooleanSerializer.java | 1 - .../mipt/java2016/homework/g597/spirin/task3/DateSerializer.java | 1 - .../java2016/homework/g597/spirin/task3/DoubleSerializer.java | 1 - .../java2016/homework/g597/spirin/task3/IntegerSerializer.java | 1 - .../java2016/homework/g597/spirin/task3/StringSerializer.java | 1 - 5 files changed, 5 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java index bfe5e1013..e439e2fa9 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/BooleanSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java index c8548df88..5bfa45adc 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DateSerializer.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; /** diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java index b0d29eabd..59fe4b088 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/DoubleSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java index ad8608ce4..4ab211c3b 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/IntegerSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java index 57791707d..8d4ba3fb0 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/StringSerializer.java @@ -3,7 +3,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.io.RandomAccessFile; /** * Created by whoami on 11/21/16. From 7a336518302c800fe7798bff30d39bb9c3c16de4 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 21:58:35 +0300 Subject: [PATCH 26/49] one more change.. --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 4fb96feaa..a6bbfa88d 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -57,11 +57,11 @@ public V load(K key) throws Exception { SerializationStrategy keySerializer, SerializationStrategy valueSerializer) throws IOException { - handleFileExistence(path); - this.path = path; this.name = name; + handleFileExistence(); + this.keySerializer = keySerializer; this.valueSerializer = valueSerializer; @@ -76,7 +76,7 @@ public V load(K key) throws Exception { countModifyOperations = 0; } - private void handleFileExistence(String path) throws FileNotFoundException { + private void handleFileExistence() throws FileNotFoundException { if (!Files.exists(Paths.get(path))) { throw new FileNotFoundException("Passed path is not valid."); } From 6320c23c15003f4ff5f2984fcd235c20eb459598 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 22:17:40 +0300 Subject: [PATCH 27/49] time boost --- .../task3/HighPerformanceKeyValueStorage.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index a6bbfa88d..e97e1999f 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -37,7 +37,7 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader() { + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(500).build(new CacheLoader() { @Override public V load(K key) throws Exception { Long offset = offsets.get(key); @@ -117,6 +117,7 @@ private void updateStorage() throws IOException { } dataStorage.close(); buffer.close(); + offsets.clear(); offsets = updatedOffsets; @@ -153,11 +154,6 @@ public void write(K key, V value) { countModifyOperations += 1; } - if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { - updateStorage(); - countModifyOperations = 0; - } - dataStorage.seek(dataStorage.length()); Long offset = dataStorage.getFilePointer(); @@ -165,6 +161,11 @@ public void write(K key, V value) { valueSerializer.write(dataStorage, value); keySerializer.write(dataStorage, key); + + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + countModifyOperations = 0; + } } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { @@ -182,12 +183,12 @@ public void delete(K key) { countModifyOperations += 1; } + offsets.remove(key); + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); countModifyOperations = 0; } - - offsets.remove(key); } catch (IOException e) { throw new RuntimeException("File operation error"); } finally { @@ -239,7 +240,9 @@ public void close() throws IOException { isOpen = false; try { - updateStorage(); + if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { + updateStorage(); + } offsetStorage.setLength(0); offsetStorage.seek(0); From 9d561859793f86a5505dd838c24e3db21276a03d Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 23:50:56 +0300 Subject: [PATCH 28/49] proposed changes made --- .../task3/HighPerformanceKeyValueStorage.java | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index e97e1999f..d28cb9655 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -101,25 +101,25 @@ private void loadData() throws IOException { } private void updateStorage() throws IOException { - RandomAccessFile buffer = new RandomAccessFile(path + File.separator + name + ".buffer", "rw"); - Map updatedOffsets = new HashMap<>(); - - dataStorage.seek(0); - while (dataStorage.getFilePointer() < dataStorage.length()) { - V value = valueSerializer.read(dataStorage); - K key = keySerializer.read(dataStorage); - - if (offsets.containsKey(key)) { - updatedOffsets.put(key, buffer.getFilePointer()); - valueSerializer.write(buffer, value); - keySerializer.write(buffer, key); + try (RandomAccessFile buffer = new RandomAccessFile(path + File.separator + name + ".buffer", "rw")) { + Map updatedOffsets = new HashMap<>(); + + dataStorage.seek(0); + while (dataStorage.getFilePointer() < dataStorage.length()) { + V value = valueSerializer.read(dataStorage); + K key = keySerializer.read(dataStorage); + + if (offsets.containsKey(key)) { + updatedOffsets.put(key, buffer.getFilePointer()); + valueSerializer.write(buffer, value); + keySerializer.write(buffer, key); + } } + + offsets.clear(); + offsets = updatedOffsets; } dataStorage.close(); - buffer.close(); - offsets.clear(); - - offsets = updatedOffsets; File bufferFile = new File(path + File.separator + name + ".buffer"); File dataFile = new File(path + File.separator + name + ".data"); @@ -130,7 +130,7 @@ private void updateStorage() throws IOException { @Override public V read(K key) { - lock.readLock().lock(); + lock.writeLock().lock(); try { checkIfStorageIsOpen(); if (!offsets.containsKey(key)) { @@ -138,7 +138,7 @@ public V read(K key) { } return cache.get(key); } catch (ExecutionException e) { - throw new RuntimeException("File operation error"); + throw new RuntimeException(e); } finally { lock.readLock().unlock(); } @@ -167,7 +167,7 @@ public void write(K key, V value) { countModifyOperations = 0; } } catch (IOException e) { - throw new RuntimeException("File operation error"); + throw new RuntimeException(e); } finally { lock.writeLock().unlock(); } @@ -190,7 +190,7 @@ public void delete(K key) { countModifyOperations = 0; } } catch (IOException e) { - throw new RuntimeException("File operation error"); + throw new RuntimeException(e); } finally { lock.writeLock().unlock(); } @@ -242,6 +242,7 @@ public void close() throws IOException { try { if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); + countModifyOperations = 0; } offsetStorage.setLength(0); From e6879e0fec4c7e0ccff48dc9ebe70434fd403c9d Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 28 Nov 2016 23:57:06 +0300 Subject: [PATCH 29/49] little fix --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index d28cb9655..52133d7d0 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -242,7 +242,6 @@ public void close() throws IOException { try { if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); - countModifyOperations = 0; } offsetStorage.setLength(0); From ef122aa4e167f59cf1fce74a071617eefc35deb0 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 29 Nov 2016 00:02:33 +0300 Subject: [PATCH 30/49] last update --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 52133d7d0..12792155e 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -140,7 +140,7 @@ public V read(K key) { } catch (ExecutionException e) { throw new RuntimeException(e); } finally { - lock.readLock().unlock(); + lock.writeLock().unlock(); } } @@ -242,6 +242,7 @@ public void close() throws IOException { try { if (countModifyOperations >= MAX_MODIFY_OPERATIONS) { updateStorage(); + countModifyOperations = 0; } offsetStorage.setLength(0); From 4052bf7038bcb0396c598156d7069f373a817389 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 29 Nov 2016 00:22:12 +0300 Subject: [PATCH 31/49] applied proposed recommendations --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 12792155e..064e0193c 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -253,6 +253,7 @@ public void close() throws IOException { offsetStorage.writeLong(entry.getValue()); } + dataStorage.close(); offsetStorage.close(); } finally { lock.writeLock().unlock(); From 52b3176bc256b110da3c58f0a82597dfc18737d8 Mon Sep 17 00:00:00 2001 From: whoami Date: Wed, 30 Nov 2016 16:00:14 +0300 Subject: [PATCH 32/49] changed constants --- .../g597/spirin/task3/HighPerformanceKeyValueStorage.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java index 79ecb82c0..55a466859 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task3/HighPerformanceKeyValueStorage.java @@ -35,9 +35,9 @@ public class HighPerformanceKeyValueStorage implements KeyValueStorage cache = CacheBuilder.newBuilder().maximumSize(500).build(new CacheLoader() { + private LoadingCache cache = CacheBuilder.newBuilder().maximumSize(1000).build(new CacheLoader() { @Override public V load(K key) throws Exception { Long offset = offsets.get(key); @@ -252,7 +252,7 @@ public void close() throws IOException { keySerializer.write(offsetStorage, entry.getKey()); offsetStorage.writeLong(entry.getValue()); } - + dataStorage.close(); offsetStorage.close(); } finally { From 369e7132d4632b227886964e140cae233d0aa167 Mon Sep 17 00:00:00 2001 From: whoami Date: Thu, 8 Dec 2016 02:12:21 +0300 Subject: [PATCH 33/49] changes to make pr mergeable --- homework-g595-yakusheva/storage.db | Bin 232 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 homework-g595-yakusheva/storage.db diff --git a/homework-g595-yakusheva/storage.db b/homework-g595-yakusheva/storage.db deleted file mode 100644 index c46c0a03ec33658f5ce3d6a233227643bf191e99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 232 zcmZQjS18HIELH%b{L&(Y^8CD%)S|S~90l*x%CN+o($wIR{G!D4R0ReG1||mPwETPq z=A^_T2G+{N+}uham717Q3}Uh5<>%+;F|dav7FU*LX9ATU+$A8ofYCwT7z}{g{TcWj zGjbDC6r57?6g(2sGOMr)vN|Vb7Ulo{|6$6hCkGT59JtcJ0H`>efy*mDBTpeXH?t&z GB+URX{Ykk1 From 1a953ad06f8e02e9813a98db12dea83186297ec1 Mon Sep 17 00:00:00 2001 From: whoami Date: Fri, 16 Dec 2016 22:37:11 +0300 Subject: [PATCH 34/49] first advances --- homework-g597-spirin/pom.xml | 38 ++++++ .../g597/spirin/task4/Application.java | 44 ++++++ .../g597/spirin/task4/BillingDao.java | 60 ++++++++ .../task4/BillingDatabaseConfiguration.java | 29 ++++ .../g597/spirin/task4/BillingUser.java | 73 ++++++++++ .../spirin/task4/CalculatorController.java | 42 ++++++ .../homework/g597/spirin/task4/Evaluator.java | 47 +++++++ .../g597/spirin/task4/EvaluatorHelper.java | 128 ++++++++++++++++++ .../task4/SecurityServiceConfiguration.java | 59 ++++++++ 9 files changed, 520 insertions(+) create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java diff --git a/homework-g597-spirin/pom.xml b/homework-g597-spirin/pom.xml index 8e3251357..a8217888b 100644 --- a/homework-g597-spirin/pom.xml +++ b/homework-g597-spirin/pom.xml @@ -11,6 +11,10 @@ homework-g597-spirin + + 1.4.2.RELEASE + + ru.mipt.java2016 @@ -30,6 +34,40 @@ guava 20.0 + + + 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 + 1.0.0 + test + + \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java new file mode 100644 index 000000000..4ed9460e7 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java @@ -0,0 +1,44 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +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; + +/** + * 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 = Application.class) +public class Application { + + @Bean + public Calculator calculator() { + return new Evaluator(); + } + + @Bean + public EmbeddedServletContainerCustomizer customizer( + @Value("${ru.mipt.java2016.homework.g597.spirin.task4.httpPort:9001}") int port) { + return container -> container.setPort(port); + } + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(Application.class); + application.setBannerMode(Banner.Mode.OFF); + application.run(args); + } +} \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java new file mode 100644 index 000000000..99fb7fa9f --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java @@ -0,0 +1,60 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +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)"); + jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)"); + } + + + 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-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java new file mode 100644 index 000000000..555116779 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java @@ -0,0 +1,29 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +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( + @Value("jdbc:h2:mem:testdb") String jdbcUrl, + @Value("${ru.mipt.java2016.homework.g597.spirin.task4.username:}") String username, + @Value("${ru.mipt.java2016.homework.g597.spirin.task4.password:}") String password + ) { + HikariConfig config = new HikariConfig(); + config.setDriverClassName(org.h2.Driver.class.getName()); + config.setJdbcUrl(jdbcUrl); + config.setUsername(username); + config.setPassword(password); + return new HikariDataSource(config); + } +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java new file mode 100644 index 000000000..27a30e069 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java @@ -0,0 +1,73 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +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-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java new file mode 100644 index 000000000..77df219a9 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java @@ -0,0 +1,42 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +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"; + } +} \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java new file mode 100644 index 000000000..1355cc6f9 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java @@ -0,0 +1,47 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + + +/** + * Created by whoami on 10/12/16. + */ + +public class Evaluator implements Calculator { + @Override + public double calculate(String expression) throws ParsingException { + if (expression == null) { + throw new ParsingException("Null can't be interpreted as an expression"); + } + + if (!checkIfBalanceCorrect(expression)) { + throw new ParsingException("Incorrect bracket sequence"); + } + + return new EvaluatorHelper(expression).evaluate(); + } + + // Check correctness of bracket sequence + private boolean checkIfBalanceCorrect(String expression) { + int balance = 0; + + for (Character ch : expression.toCharArray()) { + if (balance < 0) { + return false; + } + if (ch == '(') { + balance++; + } else if (ch == ')') { + balance--; + } + + } + + return balance == 0; + } +} + diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java new file mode 100644 index 000000000..30b5beae4 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java @@ -0,0 +1,128 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +import ru.mipt.java2016.homework.base.task1.ParsingException; + +// Algorithm based on grammar expressions +class EvaluatorHelper { + + // Class data members + private int pos; + private char ch; + private final String expression; + + // Constructor + EvaluatorHelper(String expression) { + this.expression = expression; + pos = -1; + } + + // Access to next character + private void getNextChar() throws ParsingException { + if (++pos < expression.length()) { + ch = expression.charAt(pos); + } else { + // Just to stop execution + ch = '&'; + } + } + + // Wait for expected character + private boolean tryCaptureChar(char charToBeCaptured) throws ParsingException { + // Skip all whitespace characters + while (Character.isWhitespace(ch)) { + getNextChar(); + } + + if (ch == charToBeCaptured) { + getNextChar(); + return true; + } + return false; + } + + // Main logic function + double evaluate() throws ParsingException { + getNextChar(); + + double result = processExpression(); + if (pos < expression.length()) { + throw new ParsingException("Unexpected appearance of: " + ch); + } + + return result; + } + + // Evaluation the whole expression + private double processExpression() throws ParsingException { + double result = processTerm(); + + while (true) { + if (tryCaptureChar('+')) { + result += processTerm(); + } else if (tryCaptureChar('-')) { + result -= processTerm(); + } else { + break; + } + } + return result; + } + + // Evaluation subterm of the expression + private double processTerm() throws ParsingException { + double result = processFactor(); + + while (true) { + if (tryCaptureChar('*')) { + result *= processFactor(); + } else if (tryCaptureChar('/')) { + result /= processFactor(); + } else { + break; + } + } + + return result; + } + + // Evaluation factors of the expression + private double processFactor() throws ParsingException { + if (tryCaptureChar('-')) { + return -processFactor(); + } + + double result; + int startPos = this.pos; + + if (tryCaptureChar('(')) { + result = processExpression(); + tryCaptureChar(')'); + } else if (Character.isDigit(ch) || ch == '.') { + + while (Character.isDigit(ch) || ch == '.') { + getNextChar(); + } + + // Number of points in a string + // Without a hack :( + int countPoints = 0; + for (int i = startPos; i < this.pos; ++i) { + countPoints += expression.charAt(i) == '.' ? 1 : 0; + } + + if (countPoints > 1) { + throw new ParsingException("Number with many points found"); + } + + result = Double.parseDouble(expression.substring(startPos, this.pos)); + } else { + throw new ParsingException("Unexpected appearance of: " + ch); + } + + return result; + } + +} diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java new file mode 100644 index 000000000..41092ef41 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java @@ -0,0 +1,59 @@ +package ru.mipt.java2016.homework.g597.spirin.task4; + +/** + * Created by whoami on 12/13/16. + */ +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("Registering 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); + } + }); + } +} + From 729dcf11f1b131aec9a9743ef1b3c553e3782f96 Mon Sep 17 00:00:00 2001 From: whoami Date: Sun, 18 Dec 2016 19:20:13 +0300 Subject: [PATCH 35/49] Database handling --- .../g597/spirin/task4/BillingDao.java | 114 +++++++++++++++++- .../g597/spirin/task4/BillingUser.java | 13 +- .../spirin/task4/CalculatorController.java | 76 +++++++++++- .../homework/g597/spirin/task4/README.md | 20 +++ 4 files changed, 203 insertions(+), 20 deletions(-) create mode 100644 homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java index 99fb7fa9f..758a7ce76 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java @@ -15,6 +15,7 @@ import javax.sql.DataSource; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; @Repository public class BillingDao { @@ -34,27 +35,128 @@ public void postConstruct() { public void initSchema() { LOG.trace("Initializing schema"); jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing"); + + // User table jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " + - "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)"); - jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)"); - } + "(username VARCHAR PRIMARY KEY, password VARCHAR)"); + + // Update initial (username, password) + jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'"); + jdbcTemplate.execute("INSERT INTO billing.users VALUES ('username', 'password')"); + // Variable table + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.variables " + + "(username VARCHAR, variable VARCHAR, value FLOAT)"); + + // Function table + jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.functions " + + "(username VARCHAR, function VARCHAR, arity INTEGER, body VARCHAR)"); + } + // Load user from user table 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 = ?", + "SELECT username, password 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") + rs.getString("password") + ); + } + } + ); + } + + // Put user into user table + public void putUser(String username, String password) { + LOG.trace("Putting user (username, password) into table"); + jdbcTemplate.execute("INSERT INTO billing.users VALUES ('" + + username + "', '" + password + "')"); + } + + // Get value of variable of particular user + public Double getVariable(String username, String variable) throws EmptyResultDataAccessException { + LOG.trace("Querying for variable " + variable + " of user " + username); + return jdbcTemplate.queryForObject( + "SELECT value FROM billing.variables WHERE username = '" + username + + "' AND variable = '" + variable + "'", + new Double[]{}, + new RowMapper() { + @Override + public Double mapRow(ResultSet rs, int rowNum) throws SQLException { + return new Double( + rs.getString("value").toString() ); } } ); } + + // Put variable of particular user + public void putVariable(String username, String variable, Double value) { + LOG.trace("Putting variable " + variable + " of user " + username); + deleteVariable(username, variable); + jdbcTemplate.execute("INSERT INTO billing.variables VALUES ('" + + username + "', '" + variable + "', " + value.toString() + ")"); + } + + // Delete variable of particular user + public void deleteVariable(String username, String variable) { + LOG.trace("Deleting variable " + variable + " of user " + username); + jdbcTemplate.execute("DELETE FROM billing.variables WHERE username = '" + + username + "' AND variable = '" + variable + "'"); + } + + // Get all variables from the service of particular user + public String[] getAllVariables(String username) { + LOG.trace("Querying for all variables of user " + username); + + List queryResult = jdbcTemplate.queryForList( + "SELECT variable FROM billing.variables WHERE username = '" + + username + "'"); + + String[] variables = new String[queryResult.size()]; + + for (int i = 0; i < queryResult.size(); ++i) { + variables[i] = queryResult.get(i).toString(); + } + + return variables; + } + + // Get function of particular user + public String getFunction(String username, String function) { + LOG.trace("Querying for function " + function + " of user " + username); + return jdbcTemplate.queryForObject( + "SELECT body FROM billing.functions WHERE username = '" + username + + "' AND function = '" + function + "'", + new String[]{}, + new RowMapper() { + @Override + public String mapRow(ResultSet rs, int rowNum) throws SQLException { + return rs.getString("body"); + } + } + ); + } + + // Put function of particular user + public void putFunction(String username, String function, Integer arity, String body) { + LOG.trace("Putting function " + function + " of user " + username); + deleteFunction(username, function); + jdbcTemplate.execute("INSERT INTO billing.functions VALUES ('" + + username + "', '" + function + "', " + arity.toString() + ", '" + + body + "')"); + } + + // Delete function of particular user + public void deleteFunction(String username, String function) { + LOG.info("Deleting function " + function + " of user " + username); + jdbcTemplate.execute("DELETE FROM billing.functions WHERE username = '" + + username + "' AND function = '" + function + "'"); + } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java index 27a30e069..d19239717 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java @@ -6,9 +6,8 @@ public class BillingUser { private final String username; private final String password; - private final boolean enabled; - public BillingUser(String username, String password, boolean enabled) { + public BillingUser(String username, String password) { if (username == null) { throw new IllegalArgumentException("Null username is not allowed"); } @@ -17,7 +16,6 @@ public BillingUser(String username, String password, boolean enabled) { } this.username = username; this.password = password; - this.enabled = enabled; } public String getUsername() { @@ -28,16 +26,11 @@ public String getPassword() { return password; } - public boolean isEnabled() { - return enabled; - } - @Override public String toString() { return "BillingUser{" + "username='" + username + '\'' + ", password='" + password + '\'' + - ", enabled=" + enabled + '}'; } @@ -52,9 +45,6 @@ public boolean equals(Object o) { BillingUser that = (BillingUser) o; - if (enabled != that.enabled) { - return false; - } if (!username.equals(that.username)) { return false; } @@ -66,7 +56,6 @@ public boolean equals(Object o) { public int hashCode() { int result = username.hashCode(); result = 31 * result + password.hashCode(); - result = 31 * result + (enabled ? 1 : 0); return result; } } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java index 77df219a9..fd0f3f909 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java @@ -6,6 +6,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import ru.mipt.java2016.homework.base.task1.Calculator; import ru.mipt.java2016.homework.base.task1.ParsingException; @@ -15,6 +16,8 @@ public class CalculatorController { private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); @Autowired private Calculator calculator; + @Autowired + private BillingDao billingDao; @RequestMapping(path = "/ping", method = RequestMethod.GET, produces = "text/plain") public String echo() { @@ -33,10 +36,79 @@ public String main(@RequestParam(required = false) String 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 + "]"); + public String eval(Authentication authentication, @RequestBody String expression) throws ParsingException { + LOG.trace("Evaluation request: [" + expression + "]"); + + String username = authentication.getName(); double result = calculator.calculate(expression); + LOG.trace("Result: " + result); + return Double.toString(result) + "\n"; } + + @RequestMapping(path = "/signup", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") + public void signUp(@RequestParam(value = "args") String[] arguments) throws ParsingException { + String username = arguments[0]; + String password = arguments[1]; + + LOG.trace(username); + LOG.trace(password); + + billingDao.putUser(username, password); + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, + consumes = "text/plain", produces = "text/plain") + public void putVariable(Authentication authentication, + @PathVariable String variableName, @RequestParam(value = "value") Double value) { + String username = authentication.getName(); + billingDao.putVariable(username, variableName, value); + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET, + consumes = "text/plain", produces = "text/plain") + public String getVariable(Authentication authentication, @PathVariable String variableName) { + String username = authentication.getName(); + Double res = billingDao.getVariable(username, variableName); + return res.toString() + "\n"; + } + + @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, + consumes = "text/plain", produces = "text/plain") + public void deleteVariable(Authentication authentication, @PathVariable String variableName) { + String username = authentication.getName(); + billingDao.deleteVariable(username, variableName); + } + + @RequestMapping(path = "/variable", method = RequestMethod.GET, consumes = "text/plain", produces = "text/plain") + public String getAllVariables(Authentication authentication) { + String username = authentication.getName(); + String[] ans = billingDao.getAllVariables(username); + return ans.toString() + "\n"; + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, + consumes = "text/plain", produces = "text/plain") + public void putFunction(Authentication authentication, @PathVariable String functionName, + @RequestParam(value = "valency") Integer arity, @RequestBody String body) { + String username = authentication.getName(); + LOG.trace(username); + billingDao.putFunction(username, functionName, arity, body); + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.DELETE, + consumes = "text/plain", produces = "text/plain") + public void deleteFunction(Authentication authentication, @PathVariable String functionName) { + String username = authentication.getName(); + billingDao.deleteFunction(username, functionName); + } + + @RequestMapping(path = "/function/{functionName}", method = RequestMethod.GET, + consumes = "text/plain", produces = "text/plain") + public String getFunction(Authentication authentication, @PathVariable String functionName) { + String username = authentication.getName(); + String ans = billingDao.getFunction(username, functionName); + return ans + "\n"; + } } \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md new file mode 100644 index 000000000..7d7e98923 --- /dev/null +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -0,0 +1,20 @@ +# Java REST Calculator (in progress) + +# Usage + +First run application, then follow commands below: + +To authorize run in shell: +curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" + +To put variable/function run in shell: +curl http://localhost:9001/variable/x?value="19" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" +curl http://localhost:9001/function/sum?valency="2" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "x+y" + +To get value of a variable/body of function run in shell: +curl http://localhost:9001/variable/x -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" +curl http://localhost:9001/function/sum -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" + +To evaluate expressions run in shell: +curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "44*3+2" +curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "mountain-viewer:1234567" | base64)" --data "sum(sum(3, 4), 4)" From 075ba378a82f24084619b4c4ecbb20e2af4b581b Mon Sep 17 00:00:00 2001 From: whoami Date: Sun, 18 Dec 2016 19:24:16 +0300 Subject: [PATCH 36/49] fix --- .../homework/g597/spirin/task4/CalculatorController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java index fd0f3f909..951312c95 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java @@ -91,7 +91,7 @@ public String getAllVariables(Authentication authentication) { @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, consumes = "text/plain", produces = "text/plain") public void putFunction(Authentication authentication, @PathVariable String functionName, - @RequestParam(value = "valency") Integer arity, @RequestBody String body) { + @RequestParam(value = "arity") Integer arity, @RequestBody String body) { String username = authentication.getName(); LOG.trace(username); billingDao.putFunction(username, functionName, arity, body); From 16817b1710a656eaa83199b6e434fc344a4d7c52 Mon Sep 17 00:00:00 2001 From: Yaroslav Spirin Date: Sun, 18 Dec 2016 19:29:04 +0300 Subject: [PATCH 37/49] Update README.md --- .../java2016/homework/g597/spirin/task4/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md index 7d7e98923..ba3f1c850 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -5,16 +5,16 @@ First run application, then follow commands below: To authorize run in shell: -curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" +`curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` To put variable/function run in shell: -curl http://localhost:9001/variable/x?value="19" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" -curl http://localhost:9001/function/sum?valency="2" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "x+y" +`curl http://localhost:9001/variable/x?value="19" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` +`curl http://localhost:9001/function/sum?valency="2" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "x+y"` To get value of a variable/body of function run in shell: -curl http://localhost:9001/variable/x -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" -curl http://localhost:9001/function/sum -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" +`curl http://localhost:9001/variable/x -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` +`curl http://localhost:9001/function/sum -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` To evaluate expressions run in shell: -curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "44*3+2" -curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "mountain-viewer:1234567" | base64)" --data "sum(sum(3, 4), 4)" +`curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "44*3+2"` +`curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "mountain-viewer:1234567" | base64)" --data "sum(sum(3, 4), 4)"` From a56520dfcfe9f09c9fe4cef8ff86fd3660b09f60 Mon Sep 17 00:00:00 2001 From: Yaroslav Spirin Date: Sun, 18 Dec 2016 19:29:45 +0300 Subject: [PATCH 38/49] Update README.md --- .../mipt/java2016/homework/g597/spirin/task4/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md index ba3f1c850..3cc7f36f9 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -5,16 +5,26 @@ First run application, then follow commands below: To authorize run in shell: + `curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` + To put variable/function run in shell: + `curl http://localhost:9001/variable/x?value="19" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` + `curl http://localhost:9001/function/sum?valency="2" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "x+y"` + To get value of a variable/body of function run in shell: + `curl http://localhost:9001/variable/x -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` + `curl http://localhost:9001/function/sum -X GET -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` + To evaluate expressions run in shell: + `curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "44*3+2"` + `curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "mountain-viewer:1234567" | base64)" --data "sum(sum(3, 4), 4)"` From 663b34df7ef8f26ccdf6ebdcadfffd5c38270050 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 19 Dec 2016 00:08:13 +0300 Subject: [PATCH 39/49] added all standard functions --- .../spirin/task4/CalculatorController.java | 8 ++--- .../g597/spirin/task4/EvaluatorHelper.java | 30 ++++++++++++++++++- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java index 951312c95..56f11a7bf 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java @@ -84,8 +84,8 @@ public void deleteVariable(Authentication authentication, @PathVariable String v @RequestMapping(path = "/variable", method = RequestMethod.GET, consumes = "text/plain", produces = "text/plain") public String getAllVariables(Authentication authentication) { String username = authentication.getName(); - String[] ans = billingDao.getAllVariables(username); - return ans.toString() + "\n"; + String[] res = billingDao.getAllVariables(username); + return res.toString() + "\n"; } @RequestMapping(path = "/function/{functionName}", method = RequestMethod.PUT, @@ -108,7 +108,7 @@ public void deleteFunction(Authentication authentication, @PathVariable String f consumes = "text/plain", produces = "text/plain") public String getFunction(Authentication authentication, @PathVariable String functionName) { String username = authentication.getName(); - String ans = billingDao.getFunction(username, functionName); - return ans + "\n"; + String res = billingDao.getFunction(username, functionName); + return res + "\n"; } } \ No newline at end of file diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java index 30b5beae4..408533eb8 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java @@ -13,6 +13,8 @@ class EvaluatorHelper { private char ch; private final String expression; + private double pendingArgument; + // Constructor EvaluatorHelper(String expression) { this.expression = expression; @@ -94,7 +96,7 @@ private double processFactor() throws ParsingException { return -processFactor(); } - double result; + double result = 0; int startPos = this.pos; if (tryCaptureChar('(')) { @@ -118,10 +120,36 @@ private double processFactor() throws ParsingException { } result = Double.parseDouble(expression.substring(startPos, this.pos)); + } else if (Character.isAlphabetic(ch)) { + while (Character.isAlphabetic(ch)) getNextChar(); + String func = expression.substring(startPos, this.pos); + if (func.equals("rnd")) { + result = Math.random(); + getNextChar(); + getNextChar(); + } else { + result = processFactor(); + if (func.equals("sqrt")) result = Math.sqrt(result); + else if (func.equals("sin")) result = Math.sin(Math.toRadians(result)); + else if (func.equals("cos")) result = Math.cos(Math.toRadians(result)); + else if (func.equals("tg")) result = Math.tan(Math.toRadians(result)); + else if (func.equals("abs")) result = Math.abs(result); + else if (func.equals("sign")) result = Math.signum(result); + else if (func.equals("log2")) result = Math.log(result) / Math.log(2); + else if (func.equals("max")) result = Math.max(result, pendingArgument); + else if (func.equals("min")) result = Math.min(result, pendingArgument); + else if (func.equals("pow")) result = Math.pow(result, pendingArgument); + else if (func.equals("log")) result = Math.log(result) / Math.log(pendingArgument); + else throw new RuntimeException("Unknown function: " + func); + } } else { throw new ParsingException("Unexpected appearance of: " + ch); } + if (tryCaptureChar(',')) { + pendingArgument = processFactor(); + } + return result; } From 1e8f0599b30c2c9c107d48ea8b6ae8dca75a7a7d Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 19 Dec 2016 00:13:57 +0300 Subject: [PATCH 40/49] style fixes --- .../g597/spirin/task4/EvaluatorHelper.java | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java index 408533eb8..0824980e7 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java @@ -129,18 +129,31 @@ private double processFactor() throws ParsingException { getNextChar(); } else { result = processFactor(); - if (func.equals("sqrt")) result = Math.sqrt(result); - else if (func.equals("sin")) result = Math.sin(Math.toRadians(result)); - else if (func.equals("cos")) result = Math.cos(Math.toRadians(result)); - else if (func.equals("tg")) result = Math.tan(Math.toRadians(result)); - else if (func.equals("abs")) result = Math.abs(result); - else if (func.equals("sign")) result = Math.signum(result); - else if (func.equals("log2")) result = Math.log(result) / Math.log(2); - else if (func.equals("max")) result = Math.max(result, pendingArgument); - else if (func.equals("min")) result = Math.min(result, pendingArgument); - else if (func.equals("pow")) result = Math.pow(result, pendingArgument); - else if (func.equals("log")) result = Math.log(result) / Math.log(pendingArgument); - else throw new RuntimeException("Unknown function: " + func); + if (func.equals("sqrt")) { + result = Math.sqrt(result); + } else if (func.equals("sin")) { + result = Math.sin(Math.toRadians(result)); + } else if (func.equals("cos")) { + result = Math.cos(Math.toRadians(result)); + } else if (func.equals("tg")) { + result = Math.tan(Math.toRadians(result)); + } else if (func.equals("abs")) { + result = Math.abs(result); + } else if (func.equals("sign")) { + result = Math.signum(result); + } else if (func.equals("log2")) { + result = Math.log(result) / Math.log(2); + } else if (func.equals("max")) { + result = Math.max(result, pendingArgument); + } else if (func.equals("min")) { + result = Math.min(result, pendingArgument); + } else if (func.equals("pow")) { + result = Math.pow(result, pendingArgument); + } else if (func.equals("log")) { + result = Math.log(result) / Math.log(pendingArgument); + } else { + throw new RuntimeException("Unknown function: " + func); + } } } else { throw new ParsingException("Unexpected appearance of: " + ch); From 0ce6e72d0d86ef865bae030f2c443ecbe53b351e Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 19 Dec 2016 00:17:07 +0300 Subject: [PATCH 41/49] once again check fixes --- .../homework/g597/spirin/task4/EvaluatorHelper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java index 0824980e7..837f7bf77 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java @@ -121,8 +121,12 @@ private double processFactor() throws ParsingException { result = Double.parseDouble(expression.substring(startPos, this.pos)); } else if (Character.isAlphabetic(ch)) { - while (Character.isAlphabetic(ch)) getNextChar(); + while (Character.isAlphabetic(ch)) { + getNextChar(); + } + String func = expression.substring(startPos, this.pos); + if (func.equals("rnd")) { result = Math.random(); getNextChar(); From 97adc6809c29a6e9558d0a3b59b73ff54bbc7af6 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 19 Dec 2016 00:42:28 +0300 Subject: [PATCH 42/49] readme.md updated --- .../java/ru/mipt/java2016/homework/g597/spirin/task4/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md index 3cc7f36f9..8868b6549 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -25,6 +25,6 @@ To get value of a variable/body of function run in shell: To evaluate expressions run in shell: -`curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "44*3+2"` +`curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "pow(sin(3 + pow(2, 4)), tg(32)) + 44*3+2"` `curl http://localhost:9001/eval -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "mountain-viewer:1234567" | base64)" --data "sum(sum(3, 4), 4)"` From 1ca0882ae75341da9d07556dab2970d4431513df Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 19 Dec 2016 00:44:21 +0300 Subject: [PATCH 43/49] readme.md updated --- .../java/ru/mipt/java2016/homework/g597/spirin/task4/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md index 8868b6549..1756b9d27 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -13,7 +13,7 @@ To put variable/function run in shell: `curl http://localhost:9001/variable/x?value="19" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` -`curl http://localhost:9001/function/sum?valency="2" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "x+y"` +`curl http://localhost:9001/function/sum?arity="2" -X PUT -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)" --data "x+y"` To get value of a variable/body of function run in shell: From 9babca299e453d0ed8fede78fda9014a27444260 Mon Sep 17 00:00:00 2001 From: whoami Date: Mon, 19 Dec 2016 22:34:04 +0300 Subject: [PATCH 44/49] resolute changes --- .../g597/spirin/task4/EvaluatorHelper.java | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java index 837f7bf77..7e9f1945a 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java @@ -5,7 +5,16 @@ */ import ru.mipt.java2016.homework.base.task1.ParsingException; +import java.util.Stack; + // Algorithm based on grammar expressions + +// Grammar: +// expression = term | expression `+` term | expression `-` term | expression, expression +// term = factor | term `*` factor | term `/` factor +// factor = `+` factor | `-` factor | `(` expression `)` +// | number | functionName factor + class EvaluatorHelper { // Class data members @@ -13,7 +22,7 @@ class EvaluatorHelper { private char ch; private final String expression; - private double pendingArgument; + private final Stack functions = new Stack<>(); // Constructor EvaluatorHelper(String expression) { @@ -57,6 +66,21 @@ private boolean tryCaptureChar(char charToBeCaptured) throws ParsingException { return result; } + // Calculate the value of call function(a, b) + private double performBinaryFunction(String function, double a, double b) throws ParsingException { + if (function.equals("max")) { + return Math.max(a, b); + } else if (function.equals("min")) { + return Math.min(a, b); + } else if (function.equals("pow")) { + return Math.pow(a, b); + } else if (function.equals("log")) { + return Math.log(a) / Math.log(b); + } else { + throw new ParsingException("Unknown function call: " + function); + } + } + // Evaluation the whole expression private double processExpression() throws ParsingException { double result = processTerm(); @@ -66,6 +90,9 @@ private double processExpression() throws ParsingException { result += processTerm(); } else if (tryCaptureChar('-')) { result -= processTerm(); + } else if (tryCaptureChar(',')) { + double pendingArgument = processExpression(); + result = performBinaryFunction(functions.pop(), result, pendingArgument); } else { break; } @@ -90,6 +117,11 @@ private double processTerm() throws ParsingException { return result; } + // Check if function is binary + private boolean isBinaryFunction(String func) { + return func.equals("pow") || func.equals("log") || func.equals("min") || func.equals("max"); + } + // Evaluation factors of the expression private double processFactor() throws ParsingException { if (tryCaptureChar('-')) { @@ -116,7 +148,7 @@ private double processFactor() throws ParsingException { } if (countPoints > 1) { - throw new ParsingException("Number with many points found"); + throw new ParsingException("Number with many points found."); } result = Double.parseDouble(expression.substring(startPos, this.pos)); @@ -127,6 +159,10 @@ private double processFactor() throws ParsingException { String func = expression.substring(startPos, this.pos); + if (isBinaryFunction(func)) { + functions.push(func); + } + if (func.equals("rnd")) { result = Math.random(); getNextChar(); @@ -147,26 +183,14 @@ private double processFactor() throws ParsingException { result = Math.signum(result); } else if (func.equals("log2")) { result = Math.log(result) / Math.log(2); - } else if (func.equals("max")) { - result = Math.max(result, pendingArgument); - } else if (func.equals("min")) { - result = Math.min(result, pendingArgument); - } else if (func.equals("pow")) { - result = Math.pow(result, pendingArgument); - } else if (func.equals("log")) { - result = Math.log(result) / Math.log(pendingArgument); - } else { - throw new RuntimeException("Unknown function: " + func); + } else if (!isBinaryFunction(func)) { + throw new ParsingException("Unknown function call: " + func); } } } else { throw new ParsingException("Unexpected appearance of: " + ch); } - if (tryCaptureChar(',')) { - pendingArgument = processFactor(); - } - return result; } From 7e190e28fcc66aa9ef9e08596c61d9a1228c8a70 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 20 Dec 2016 12:58:26 +0300 Subject: [PATCH 45/49] simplified sample --- .../java/ru/mipt/java2016/homework/g597/spirin/task4/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md index 1756b9d27..1dac72f9b 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -6,8 +6,7 @@ First run application, then follow commands below: To authorize run in shell: -`curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain" -H "Authorization: Basic $(echo -n "username:password" | base64)"` - +`curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain"` To put variable/function run in shell: From e6a31f3f15acc898d39381b85a8d83586cb81a95 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 20 Dec 2016 17:30:03 +0300 Subject: [PATCH 46/49] changed example --- .../java/ru/mipt/java2016/homework/g597/spirin/task4/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md index 1dac72f9b..eaab7410c 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/README.md @@ -6,7 +6,7 @@ First run application, then follow commands below: To authorize run in shell: -`curl http://localhost:9001/signup?args="mountain-viewer, 1234567" -X POST -H "Content-Type: text/plain"` +`curl http://localhost:9001/signup?args="mountain-viewer,1234567" -X POST -H "Content-Type: text/plain"` To put variable/function run in shell: From fe744643d6b02ee5f8ee1a619feee803a82a09f9 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 20 Dec 2016 17:51:24 +0300 Subject: [PATCH 47/49] remove wrong release date --- .../mipt/java2016/homework/g597/spirin/task4/Evaluator.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java index 1355cc6f9..0ac887cd5 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java @@ -6,11 +6,6 @@ import ru.mipt.java2016.homework.base.task1.Calculator; import ru.mipt.java2016.homework.base.task1.ParsingException; - -/** - * Created by whoami on 10/12/16. - */ - public class Evaluator implements Calculator { @Override public double calculate(String expression) throws ParsingException { From 661d46a6dd0aaa95d9719dad4f45c68e931a1032 Mon Sep 17 00:00:00 2001 From: whoami Date: Tue, 20 Dec 2016 19:09:22 +0300 Subject: [PATCH 48/49] after @ignorer recommendations --- .../homework/g597/spirin/task4/Application.java | 11 +++-------- .../homework/g597/spirin/task4/BillingDao.java | 7 ++++--- .../spirin/task4/BillingDatabaseConfiguration.java | 7 ++++--- .../homework/g597/spirin/task4/BillingUser.java | 1 + .../g597/spirin/task4/CalculatorController.java | 9 +++++---- .../homework/g597/spirin/task4/Evaluator.java | 5 +++-- .../homework/g597/spirin/task4/EvaluatorHelper.java | 6 +++--- .../spirin/task4/SecurityServiceConfiguration.java | 7 ++++--- 8 files changed, 27 insertions(+), 26 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java index 4ed9460e7..75dc2ed38 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Application.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task4; -/** - * Created by whoami on 12/13/16. - */ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; @@ -11,15 +8,13 @@ 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; /** - * 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" + * Created by whoami on 12/13/16. */ + @EnableAutoConfiguration @Configuration @ComponentScan(basePackageClasses = Application.class) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java index 758a7ce76..005bb80ba 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task4; -/** - * Created by whoami on 12/13/16. - */ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +14,10 @@ import java.sql.SQLException; import java.util.List; +/** + * Created by whoami on 12/13/16. + */ + @Repository public class BillingDao { private static final Logger LOG = LoggerFactory.getLogger(BillingDao.class); diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java index 555116779..8528d1052 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDatabaseConfiguration.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task4; -/** - * Created by whoami on 12/13/16. - */ import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.springframework.beans.factory.annotation.Value; @@ -11,6 +8,10 @@ import javax.sql.DataSource; +/** + * Created by whoami on 12/13/16. + */ + @Configuration public class BillingDatabaseConfiguration { @Bean diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java index d19239717..4de2d352a 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingUser.java @@ -3,6 +3,7 @@ /** * Created by whoami on 12/13/16. */ + public class BillingUser { private final String username; private final String password; diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java index 56f11a7bf..be6c8399b 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task4; -/** - * Created by whoami on 12/13/16. - */ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -11,6 +8,10 @@ import ru.mipt.java2016.homework.base.task1.Calculator; import ru.mipt.java2016.homework.base.task1.ParsingException; +/** + * Created by whoami on 12/13/16. + */ + @RestController public class CalculatorController { private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class); @@ -30,7 +31,7 @@ public String main(@RequestParam(required = false) String name) { name = "world"; } return "" + - "FediqApp" + + "mountain-viewer App" + "

Hello, " + name + "!

" + ""; } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java index 0ac887cd5..b3f328ed6 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/Evaluator.java @@ -1,10 +1,11 @@ package ru.mipt.java2016.homework.g597.spirin.task4; +import ru.mipt.java2016.homework.base.task1.Calculator; +import ru.mipt.java2016.homework.base.task1.ParsingException; + /** * Created by whoami on 12/13/16. */ -import ru.mipt.java2016.homework.base.task1.Calculator; -import ru.mipt.java2016.homework.base.task1.ParsingException; public class Evaluator implements Calculator { @Override diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java index 7e9f1945a..97a9317f3 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/EvaluatorHelper.java @@ -1,11 +1,11 @@ package ru.mipt.java2016.homework.g597.spirin.task4; +import ru.mipt.java2016.homework.base.task1.ParsingException; +import java.util.Stack; + /** * Created by whoami on 12/13/16. */ -import ru.mipt.java2016.homework.base.task1.ParsingException; - -import java.util.Stack; // Algorithm based on grammar expressions diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java index 41092ef41..3b4156c51 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java @@ -1,8 +1,5 @@ package ru.mipt.java2016.homework.g597.spirin.task4; -/** - * Created by whoami on 12/13/16. - */ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +14,10 @@ import java.util.Collections; +/** + * Created by whoami on 12/13/16. + */ + @Configuration @EnableWebSecurity public class SecurityServiceConfiguration extends WebSecurityConfigurerAdapter { From a94b977e431f3c466b68e08ac6627bd369b74d67 Mon Sep 17 00:00:00 2001 From: whoami Date: Wed, 21 Dec 2016 16:34:35 +0300 Subject: [PATCH 49/49] log changes --- .../homework/g597/spirin/task4/BillingDao.java | 18 +++++++++--------- .../spirin/task4/CalculatorController.java | 10 +++++----- .../task4/SecurityServiceConfiguration.java | 4 +--- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java index 005bb80ba..c0dcac9f8 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/BillingDao.java @@ -34,7 +34,7 @@ public void postConstruct() { } public void initSchema() { - LOG.trace("Initializing schema"); + LOG.info("Initializing schema"); jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing"); // User table @@ -56,7 +56,7 @@ public void initSchema() { // Load user from user table public BillingUser loadUser(String username) throws EmptyResultDataAccessException { - LOG.trace("Querying for user " + username); + LOG.info("Querying for user " + username); return jdbcTemplate.queryForObject( "SELECT username, password FROM billing.users WHERE username = ?", new Object[]{username}, @@ -74,14 +74,14 @@ public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException { // Put user into user table public void putUser(String username, String password) { - LOG.trace("Putting user (username, password) into table"); + LOG.info("Putting user (username, password) into table"); jdbcTemplate.execute("INSERT INTO billing.users VALUES ('" + username + "', '" + password + "')"); } // Get value of variable of particular user public Double getVariable(String username, String variable) throws EmptyResultDataAccessException { - LOG.trace("Querying for variable " + variable + " of user " + username); + LOG.info("Querying for variable " + variable + " of user " + username); return jdbcTemplate.queryForObject( "SELECT value FROM billing.variables WHERE username = '" + username + "' AND variable = '" + variable + "'", @@ -99,7 +99,7 @@ public Double mapRow(ResultSet rs, int rowNum) throws SQLException { // Put variable of particular user public void putVariable(String username, String variable, Double value) { - LOG.trace("Putting variable " + variable + " of user " + username); + LOG.info("Putting variable " + variable + " of user " + username); deleteVariable(username, variable); jdbcTemplate.execute("INSERT INTO billing.variables VALUES ('" + username + "', '" + variable + "', " + value.toString() + ")"); @@ -107,14 +107,14 @@ public void putVariable(String username, String variable, Double value) { // Delete variable of particular user public void deleteVariable(String username, String variable) { - LOG.trace("Deleting variable " + variable + " of user " + username); + LOG.info("Deleting variable " + variable + " of user " + username); jdbcTemplate.execute("DELETE FROM billing.variables WHERE username = '" + username + "' AND variable = '" + variable + "'"); } // Get all variables from the service of particular user public String[] getAllVariables(String username) { - LOG.trace("Querying for all variables of user " + username); + LOG.info("Querying for all variables of user " + username); List queryResult = jdbcTemplate.queryForList( "SELECT variable FROM billing.variables WHERE username = '" + @@ -131,7 +131,7 @@ public String[] getAllVariables(String username) { // Get function of particular user public String getFunction(String username, String function) { - LOG.trace("Querying for function " + function + " of user " + username); + LOG.info("Querying for function " + function + " of user " + username); return jdbcTemplate.queryForObject( "SELECT body FROM billing.functions WHERE username = '" + username + "' AND function = '" + function + "'", @@ -147,7 +147,7 @@ public String mapRow(ResultSet rs, int rowNum) throws SQLException { // Put function of particular user public void putFunction(String username, String function, Integer arity, String body) { - LOG.trace("Putting function " + function + " of user " + username); + LOG.info("Putting function " + function + " of user " + username); deleteFunction(username, function); jdbcTemplate.execute("INSERT INTO billing.functions VALUES ('" + username + "', '" + function + "', " + arity.toString() + ", '" diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java index be6c8399b..db55ba517 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/CalculatorController.java @@ -31,19 +31,19 @@ public String main(@RequestParam(required = false) String name) { name = "world"; } return "" + - "mountain-viewer App" + + "mountain-viewer app" + "

Hello, " + name + "!

" + ""; } @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain") public String eval(Authentication authentication, @RequestBody String expression) throws ParsingException { - LOG.trace("Evaluation request: [" + expression + "]"); + LOG.info("Evaluation request: [" + expression + "]"); String username = authentication.getName(); double result = calculator.calculate(expression); - LOG.trace("Result: " + result); + LOG.info("Result: " + result); return Double.toString(result) + "\n"; } @@ -53,8 +53,8 @@ public void signUp(@RequestParam(value = "args") String[] arguments) throws Pars String username = arguments[0]; String password = arguments[1]; - LOG.trace(username); - LOG.trace(password); + LOG.info(username); + LOG.info(password); billingDao.putUser(username, password); } diff --git a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java index 3b4156c51..49a476f27 100644 --- a/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java +++ b/homework-g597-spirin/src/main/java/ru/mipt/java2016/homework/g597/spirin/task4/SecurityServiceConfiguration.java @@ -14,9 +14,7 @@ import java.util.Collections; -/** - * Created by whoami on 12/13/16. - */ + @Configuration @EnableWebSecurity