Skip to content
This repository has been archived by the owner on Mar 3, 2024. It is now read-only.

[IGNORE] Homework3 #157

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
3a175a5
- Dao and Factory implementing.
Sep 26, 2023
872d426
- Dao and Factory implementing.
Sep 26, 2023
165880d
- Fix get(from, to) using if-else statements
Sep 26, 2023
a781ad9
Merge branch 'main' into main
incubos Sep 27, 2023
d1b4400
- Fix ordering
Sep 27, 2023
4336bc7
- CodeClimate fix
Sep 27, 2023
9067f3f
- Fixed orElseThrow in toString, adding orElse for another types of M…
Sep 27, 2023
6f9db69
Merge branch 'polis-vk:main' into main
podobaAlex Sep 28, 2023
40b84c1
Merge branch 'polis-vk:main' into homework2
podobaAlex Oct 3, 2023
b15918b
- Homework 2
Oct 4, 2023
f454e23
Merge branch 'polis-vk:main' into homework2
podobaAlex Oct 4, 2023
11b1dff
- CodeClimateFix
Oct 4, 2023
2c2a140
Merge branch 'main' into homework2
incubos Oct 5, 2023
6f05e7f
Merge branch 'main' into homework2
incubos Oct 5, 2023
8d6fe99
Merge branch 'main' into main
incubos Oct 5, 2023
04e4b03
Merge branch 'polis-vk:main' into main
podobaAlex Oct 5, 2023
6082135
Merge branch 'polis-vk:main' into homework2
podobaAlex Oct 5, 2023
73b4cfd
Merge remote-tracking branch 'origin/main'
Oct 5, 2023
1b65c04
Merge remote-tracking branch 'origin/homework2'
Oct 5, 2023
37f7fdb
- CodeClimateFix
Oct 5, 2023
b1a34f7
Merge branch 'main' into homework2
podobaAlex Oct 5, 2023
f19104f
Merge branch 'polis-vk:main' into homework3
podobaAlex Oct 6, 2023
a9fd880
- log2 save and read file
Oct 9, 2023
2f9fe92
- log2 save and read file
Oct 9, 2023
f03a762
Merge branch 'polis-vk:main' into homework3
podobaAlex Oct 9, 2023
e0e4895
Merge branch 'polis-vk:main' into homework3
podobaAlex Oct 11, 2023
9425377
- log2 save and read file
Oct 15, 2023
473b52f
Merge remote-tracking branch 'origin/homework3' into homework3
Oct 15, 2023
b59f409
Merge branch 'polis-vk:main' into homework3
podobaAlex Oct 15, 2023
4318a3f
Merge remote-tracking branch 'origin/homework3' into homework3
Oct 15, 2023
18172a3
- fix sstable priority
Oct 15, 2023
4f85228
- SSTable split into SSTableReader and SSTableWriter
Oct 18, 2023
a23f680
- CodeClimate fix
Oct 18, 2023
f0b31ca
Merge branch 'polis-vk:main' into homework3
podobaAlex Oct 18, 2023
c913373
- CodeClimate fix
Oct 18, 2023
7241172
- CodeClimate fix
Oct 18, 2023
6609630
Merge remote-tracking branch 'POLIS/main' into homework3
Oct 18, 2023
a580e66
Merge branch 'main' into homework3
incubos Oct 20, 2023
0cb6edf
Merge branch 'main' into homework3
incubos Oct 20, 2023
dc8da89
Merge branch 'main' into homework3
incubos Oct 20, 2023
492ef87
Merge branch 'polis-vk:main' into homework3
podobaAlex Oct 26, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/main/java/ru/vk/itmo/podobaalexandr/InMemoryDaoImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package ru.vk.itmo.podobaalexandr;

import ru.vk.itmo.Config;
import ru.vk.itmo.Dao;
import ru.vk.itmo.Entry;

import java.lang.foreign.MemorySegment;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;

public class InMemoryDaoImpl implements Dao<MemorySegment, Entry<MemorySegment>> {

private static final Comparator<MemorySegment> comparator = MemorySegmentUtils::compare;

private final ConcurrentNavigableMap<MemorySegment, Entry<MemorySegment>> memorySegmentEntryMap
= new ConcurrentSkipListMap<>(comparator);

private final SSTableWriter ssTableWriter;

private final SSTableReader ssTableReader;

public InMemoryDaoImpl() {
this(new Config(Path.of("standard")));
}

public InMemoryDaoImpl(Config config) {
ssTableReader = new SSTableReader(config.basePath());
ssTableWriter = new SSTableWriter(config.basePath(), ssTableReader.size());
}

@Override
public Iterator<Entry<MemorySegment>> get(MemorySegment from, MemorySegment to) {
ConcurrentNavigableMap<MemorySegment, Entry<MemorySegment>> innerMap = memorySegmentEntryMap;
Collection<Entry<MemorySegment>> entries;

if (from == null && to == null) {
entries = ssTableReader.allPages(innerMap);
} else if (from == null) {
innerMap = innerMap.headMap(to);
entries = ssTableReader.allPagesTo(to, innerMap);
} else if (to == null) {
innerMap = innerMap.tailMap(from);
entries = ssTableReader.allPagesFrom(from, innerMap);
} else {
innerMap = innerMap.subMap(from, to);
entries = ssTableReader.allPagesFromTo(from, to, innerMap);
}

entries.removeIf(it -> it.value() == null);
return entries.iterator();
}

@Override
public void upsert(Entry<MemorySegment> entry) {
memorySegmentEntryMap.put(entry.key(), entry);
}

@Override
public void close() {
if (ssTableReader.isArenaPresented()) {
if (!ssTableReader.isAlive()) {
return;
}

ssTableReader.close();
}

ssTableWriter.save(memorySegmentEntryMap.values());
}

@Override
public Entry<MemorySegment> get(MemorySegment key) {
if (memorySegmentEntryMap.containsKey(key)) {
Entry<MemorySegment> entry = memorySegmentEntryMap.get(key);
return entry.value() == null ? null : entry;
}

return ssTableReader.get(key);
}

}
73 changes: 73 additions & 0 deletions src/main/java/ru/vk/itmo/podobaalexandr/MemorySegmentUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ru.vk.itmo.podobaalexandr;

import ru.vk.itmo.BaseEntry;
import ru.vk.itmo.Entry;

import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;

public final class MemorySegmentUtils {

private MemorySegmentUtils() {

}

public static int compare(MemorySegment o1, MemorySegment o2) {
return compareSegments(o1, o1.byteSize(), o2, 0, o2.byteSize());
}

public static int compareSegments(MemorySegment src, long srcEnd,
MemorySegment dest, long destOffset, long destEnd) {
long destLength = destEnd - destOffset;

int sizeDiff = Long.compare(srcEnd, destLength);

if (srcEnd == 0 || destLength == 0) {
return sizeDiff;
}

long mismatch = MemorySegment.mismatch(src, 0, srcEnd, dest, destOffset, destEnd);

if (mismatch == destLength || mismatch == srcEnd) {
return sizeDiff;
}

return mismatch == -1
? 0
: Byte.compare(src.get(ValueLayout.JAVA_BYTE, mismatch),
dest.get(ValueLayout.JAVA_BYTE, destOffset + mismatch));
}

public static Entry<MemorySegment> getKeyValueFromOffset(MemorySegment page,
long offset, long keySize, long keysSize) {
long offsetLocal = offset;

MemorySegment key = page.asSlice(offsetLocal, keySize);
offsetLocal += keySize;

long offsetToV = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);

if (offsetToV == 0) {
return new BaseEntry<>(key, null);
}

offsetLocal += 2 * Long.BYTES + Byte.BYTES;
MemorySegment value = null;
long size = 0;
while (size <= 0 && offsetLocal < keysSize) {
long keySizeNextKey = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
offsetLocal += Long.BYTES + keySizeNextKey;

size = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal) - offsetToV;
if (size > 0) {
value = page.asSlice(offsetToV, size);
}
offsetLocal += 2 * Long.BYTES + Byte.BYTES;
}

value = value == null ? page.asSlice(offsetToV) : value;

return new BaseEntry<>(key, value);
}

}
227 changes: 227 additions & 0 deletions src/main/java/ru/vk/itmo/podobaalexandr/SSTable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
package ru.vk.itmo.podobaalexandr;

import ru.vk.itmo.Entry;

import java.io.IOException;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.NavigableMap;

public class SSTable {

private final long keysSize;

private final MemorySegment page;

public SSTable(Path file, Arena arena) throws IOException {
try (FileChannel fileChannel = FileChannel.open(file, StandardOpenOption.READ)) {
long size = Files.size(file);
page = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, size, arena);
}

keysSize = page.get(ValueLayout.JAVA_LONG_UNALIGNED, 0);
}

private boolean isOutOfKeyOffset(long offset) {
return keysSize <= offset || offset == 0;
}

//Invariant: FROM < TO
public void allPageFromTo(NavigableMap<MemorySegment, Entry<MemorySegment>> entries,
long offset, MemorySegment from, MemorySegment to) {
if (isOutOfKeyOffset(offset)) {
return;
}

Entry<MemorySegment> last;
long offsetLocal = offset;

long keySize = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
offsetLocal += Long.BYTES;

int compareFrom = MemorySegmentUtils
.compareSegments(from, from.byteSize(), page, offsetLocal, offsetLocal + keySize);
int compareTo = MemorySegmentUtils
.compareSegments(to, to.byteSize(), page, offsetLocal, offsetLocal + keySize);

if (compareFrom < 0 && compareTo > 0) {
last = MemorySegmentUtils.getKeyValueFromOffset(page, offsetLocal, keySize, keysSize);
offsetLocal += keySize + Long.BYTES;

long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPageFrom(entries, offsetToL, from);
offsetLocal += Long.BYTES;

entries.putIfAbsent(last.key(), last);

byte isRightHere = page.get(ValueLayout.JAVA_BYTE, offsetLocal);
long rightOffset = isRightHere == 1 ? offsetLocal + Byte.BYTES : 0;
allPageTo(entries, rightOffset, to);
} else if (compareFrom == 0) {
last = MemorySegmentUtils.getKeyValueFromOffset(page, offsetLocal, keySize, keysSize);
offsetLocal += keySize + 2 * Long.BYTES;

entries.putIfAbsent(last.key(), last);
long rightOffset = page.get(ValueLayout.JAVA_BYTE, offsetLocal) == 1 ? offsetLocal + Byte.BYTES : 0;
allPageTo(entries, rightOffset, to);
} else if (compareTo == 0) {
offsetLocal += keySize + Long.BYTES;
long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPageFrom(entries, offsetToL, from);
} else if (compareFrom > 0) {
offsetLocal += keySize + 2 * Long.BYTES;
long rightOffset = page.get(ValueLayout.JAVA_BYTE, offsetLocal) == 1 ? offsetLocal + Byte.BYTES : 0;
allPageFromTo(entries, rightOffset, from, to);
} else {
offsetLocal += keySize + Long.BYTES;
long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPageFromTo(entries, offsetToL, from, to);
}
}

public void allPageTo(NavigableMap<MemorySegment, Entry<MemorySegment>> entries,
long offset, MemorySegment to) {
if (isOutOfKeyOffset(offset)) {
return;
}

Entry<MemorySegment> last;
long offsetLocal = offset;

long keySize = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
offsetLocal += Long.BYTES;

int compare = MemorySegmentUtils
.compareSegments(to, to.byteSize(), page, offsetLocal, offsetLocal + keySize);

if (compare == 0) {
offsetLocal += keySize + Long.BYTES;

long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPage(entries, offsetToL);
} else if (compare > 0) {
last = MemorySegmentUtils.getKeyValueFromOffset(page, offsetLocal, keySize, keysSize);
offsetLocal += keySize + Long.BYTES;

long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
offsetLocal += Long.BYTES;

allPage(entries, offsetToL);

entries.putIfAbsent(last.key(), last);

byte isRightHere = page.get(ValueLayout.JAVA_BYTE, offsetLocal);
allPageTo(entries, isRightHere == 1 ? offsetLocal + Byte.BYTES : 0, to);
} else {
offsetLocal += keySize + Long.BYTES;

long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPageTo(entries, offsetToL, to);
}
}

public void allPageFrom(NavigableMap<MemorySegment, Entry<MemorySegment>> entries,
long offset, MemorySegment from) {
if (isOutOfKeyOffset(offset)) {
return;
}

Entry<MemorySegment> last;
long offsetLocal = offset;

long keySize = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
offsetLocal += Long.BYTES;

int compare = MemorySegmentUtils
.compareSegments(from, from.byteSize(), page, offsetLocal, offsetLocal + keySize);

if (compare == 0) {
last = MemorySegmentUtils.getKeyValueFromOffset(page, offsetLocal, keySize, keysSize);
offsetLocal += 2 * Long.BYTES + keySize;

entries.putIfAbsent(last.key(), last);

byte isRightHere = page.get(ValueLayout.JAVA_BYTE, offsetLocal);
allPage(entries, isRightHere == 1 ? offsetLocal + Byte.BYTES : 0);
} else if (compare > 0) {
offsetLocal += keySize + 2 * Long.BYTES;
byte isRightHere = page.get(ValueLayout.JAVA_BYTE, offsetLocal);
allPageFrom(entries, isRightHere == 1 ? offsetLocal + Byte.BYTES : 0, from);
} else {
last = MemorySegmentUtils.getKeyValueFromOffset(page, offsetLocal, keySize, keysSize);
offsetLocal += keySize + Long.BYTES;

long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPageFrom(entries, offsetToL, from);
offsetLocal += Long.BYTES;

entries.putIfAbsent(last.key(), last);

byte isRightHere = page.get(ValueLayout.JAVA_BYTE, offsetLocal);
allPage(entries, isRightHere == 1 ? offsetLocal + Byte.BYTES : 0);
}
}

public void allPage(NavigableMap<MemorySegment, Entry<MemorySegment>> entries, long offset) {
if (isOutOfKeyOffset(offset)) {
return;
}

Entry<MemorySegment> last;
long offsetLocal = offset;

long keySize = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
offsetLocal += Long.BYTES;

last = MemorySegmentUtils.getKeyValueFromOffset(page, offsetLocal, keySize, keysSize);

offsetLocal += keySize + Long.BYTES;
long offsetToL = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offsetLocal);
allPage(entries, offsetToL);

entries.putIfAbsent(last.key(), last);

offsetLocal += Long.BYTES;
byte isRightHere = page.get(ValueLayout.JAVA_BYTE, offsetLocal);
allPage(entries, isRightHere == 1 ? offsetLocal + Byte.BYTES : 0);
}

public Entry<MemorySegment> getFromPage(MemorySegment keySearch) {
long offset = Long.BYTES;
Entry<MemorySegment> res = null;

while (offset < keysSize) {
long keySize = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offset);
offset += Long.BYTES;

int compare = MemorySegmentUtils
.compareSegments(keySearch, keySearch.byteSize(), page, offset, offset + keySize);

if (compare == 0) {
res = MemorySegmentUtils.getKeyValueFromOffset(page, offset, keySize, keysSize);
break;
} else if (compare > 0) {
offset += keySize + 2 * Long.BYTES;
byte isRightExist = page.get(ValueLayout.JAVA_BYTE, offset);
if (isRightExist == 0) {
return null;
}
offset += Byte.BYTES;
} else {
offset += keySize + Long.BYTES;
offset = page.get(ValueLayout.JAVA_LONG_UNALIGNED, offset);
if (offset == 0) {
return null;
}
}
}

return res;
}

}
Loading