Skip to content

Commit

Permalink
refactor: throwing more proper exceptions
Browse files Browse the repository at this point in the history
wrapping IO and thread related exceptions at index level using InternalOperationException
  • Loading branch information
sepgh committed Jun 22, 2024
1 parent 0037acc commit 8e48d13
Show file tree
Hide file tree
Showing 29 changed files with 312 additions and 223 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.github.sepgh.internal.exception;

public class IndexExistsException extends Exception {
public IndexExistsException() {
super("Index already exists!");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.github.sepgh.internal.exception;

public class InternalOperationException extends Exception {
public InternalOperationException(Exception exception) {
super("Operation failed", exception);
}

public InternalOperationException(String message, Exception exception) {
super(message, exception);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package com.github.sepgh.internal.index;

import com.github.sepgh.internal.exception.IndexExistsException;
import com.github.sepgh.internal.exception.InternalOperationException;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.data.ImmutableBinaryObjectWrapper;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicReference;

public class CachedIndexManagerDecorator<K extends Comparable<K>, V extends Comparable<V>> extends IndexManagerDecorator<K, V> {
private final Cache<TableIdentifier<K>, V> cache;
Expand All @@ -26,15 +27,15 @@ public CachedIndexManagerDecorator(IndexManager<K, V> indexManager, Cache<TableI
}

@Override
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws ExecutionException, InterruptedException, IOException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue, IndexExistsException {
AbstractTreeNode<K> baseClusterTreeNode = super.addIndex(table, identifier, value);
cache.put(new TableIdentifier<>(table, identifier), value);
sizeCache.computeIfPresent(table, (k, v) -> v + 1);
return baseClusterTreeNode;
}

@Override
public Optional<V> getIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public Optional<V> getIndex(int table, K identifier) throws InternalOperationException {
TableIdentifier<K> lookup = new TableIdentifier<>(table, identifier);
V optionalPointer = cache.getIfPresent(lookup);
if (optionalPointer != null)
Expand All @@ -45,7 +46,7 @@ public Optional<V> getIndex(int table, K identifier) throws ExecutionException,
}

@Override
public boolean removeIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public boolean removeIndex(int table, K identifier) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
if (super.removeIndex(table, identifier)) {
cache.invalidate(new TableIdentifier<>(table, identifier));
sizeCache.computeIfPresent(table, (k, v) -> v - 1);
Expand All @@ -55,14 +56,22 @@ public boolean removeIndex(int table, K identifier) throws ExecutionException, I
}

@Override
public int size(int table) {
return sizeCache.computeIfAbsent(table, key -> {
public int size(int table) throws InternalOperationException {
AtomicReference<InternalOperationException> atomicExceptionReference = new AtomicReference<>();
int size = sizeCache.computeIfAbsent(table, key -> {
try {
return super.size(table);
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
} catch (InternalOperationException e) {
atomicExceptionReference.set(e);
return -1;
}
});

InternalOperationException exception = atomicExceptionReference.get();
if (exception != null)
throw exception;

return size;
}

public record TableIdentifier<K extends Comparable<K>>(int table, K identifier){
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.github.sepgh.internal.index;

import com.github.sepgh.internal.exception.IndexExistsException;
import com.github.sepgh.internal.exception.InternalOperationException;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.data.ImmutableBinaryObjectWrapper;

import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class DBLevelAsyncIndexManagerDecorator<K extends Comparable<K>, V extends Comparable<V>> extends IndexManagerDecorator<K, V> {
Expand All @@ -17,7 +17,7 @@ public DBLevelAsyncIndexManagerDecorator(IndexManager<K, V> indexManager) {
}

@Override
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws ExecutionException, InterruptedException, IOException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue, IndexExistsException {
writeLock.lock();
try {
return super.addIndex(table, identifier, value);
Expand All @@ -27,7 +27,7 @@ public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws Exe
}

@Override
public Optional<V> getIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public Optional<V> getIndex(int table, K identifier) throws InternalOperationException {
readLock.lock();
try {
return super.getIndex(table, identifier);
Expand All @@ -37,7 +37,7 @@ public Optional<V> getIndex(int table, K identifier) throws ExecutionException,
}

@Override
public boolean removeIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public boolean removeIndex(int table, K identifier) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
writeLock.lock();
try {
return super.removeIndex(table, identifier);
Expand Down
12 changes: 6 additions & 6 deletions src/main/java/com/github/sepgh/internal/index/IndexManager.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.github.sepgh.internal.index;

import com.github.sepgh.internal.exception.IndexExistsException;
import com.github.sepgh.internal.exception.InternalOperationException;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.data.ImmutableBinaryObjectWrapper;

import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

public interface IndexManager<K extends Comparable<K>, V extends Comparable<V>> {
AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws ExecutionException, InterruptedException, IOException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue;
Optional<V> getIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException;
boolean removeIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException;
int size(int table) throws InterruptedException, ExecutionException, IOException;
AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws IndexExistsException, InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue;
Optional<V> getIndex(int table, K identifier) throws InternalOperationException;
boolean removeIndex(int table, K identifier) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue;
int size(int table) throws InternalOperationException;
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.github.sepgh.internal.index;

import com.github.sepgh.internal.exception.IndexExistsException;
import com.github.sepgh.internal.exception.InternalOperationException;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.data.ImmutableBinaryObjectWrapper;

import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

public class IndexManagerDecorator<K extends Comparable<K>, V extends Comparable<V>> implements IndexManager<K, V> {
private final IndexManager<K, V> indexManager;
Expand All @@ -14,23 +14,19 @@ public IndexManagerDecorator(IndexManager<K, V> indexManager) {
this.indexManager = indexManager;
}

public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws ExecutionException, InterruptedException, IOException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue, IndexExistsException {
return this.indexManager.addIndex(table, identifier, value);
}
public Optional<V> getIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public Optional<V> getIndex(int table, K identifier) throws InternalOperationException {
return this.indexManager.getIndex(table, identifier);
}

public boolean removeIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public boolean removeIndex(int table, K identifier) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
return this.indexManager.removeIndex(table, identifier);
}

@Override
public int size(int table) throws ExecutionException, InterruptedException {
try {
return this.indexManager.size(table);
} catch (IOException e) {
return 0;
}
public int size(int table) throws InternalOperationException {
return this.indexManager.size(table);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.github.sepgh.internal.index;

import com.github.sepgh.internal.exception.IndexExistsException;
import com.github.sepgh.internal.exception.InternalOperationException;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.data.ImmutableBinaryObjectWrapper;

import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class TableLevelAsyncIndexManagerDecorator<K extends Comparable<K>, V extends Comparable<V>> extends IndexManagerDecorator<K, V> {
Expand All @@ -21,7 +21,7 @@ protected LockManager getLockManager(int table){
}

@Override
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws ExecutionException, InterruptedException, IOException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue, IndexExistsException {
LockManager lockManager = getLockManager(table);
lockManager.writeLock.lock();
try {
Expand All @@ -32,7 +32,7 @@ public AbstractTreeNode<K> addIndex(int table, K identifier, V value) throws Exe
}

@Override
public Optional<V> getIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public Optional<V> getIndex(int table, K identifier) throws InternalOperationException {
LockManager lockManager = getLockManager(table);
lockManager.readLock.lock();
try {
Expand All @@ -43,7 +43,7 @@ public Optional<V> getIndex(int table, K identifier) throws ExecutionException,
}

@Override
public boolean removeIndex(int table, K identifier) throws ExecutionException, InterruptedException, IOException {
public boolean removeIndex(int table, K identifier) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
LockManager lockManager = getLockManager(table);
lockManager.writeLock.lock();
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.github.sepgh.internal.index.tree;

import com.github.sepgh.internal.exception.IndexExistsException;
import com.github.sepgh.internal.exception.InternalOperationException;
import com.github.sepgh.internal.index.Pointer;
import com.github.sepgh.internal.index.tree.node.AbstractLeafTreeNode;
import com.github.sepgh.internal.index.tree.node.AbstractTreeNode;
import com.github.sepgh.internal.index.tree.node.InternalTreeNode;
import com.github.sepgh.internal.index.tree.node.data.ImmutableBinaryObjectWrapper;
import com.github.sepgh.internal.storage.session.IndexIOSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;

public class BPlusTreeIndexCreateOperation<K extends Comparable<K>, V extends Comparable<V>> {
private final int degree;
Expand All @@ -26,7 +26,7 @@ public BPlusTreeIndexCreateOperation(int degree, IndexIOSession<K> indexIOSessio
this.valueImmutableBinaryObjectWrapper = valueImmutableBinaryObjectWrapper;
}

public AbstractTreeNode<K> addIndex(AbstractTreeNode<K> root, K identifier, V value) throws ExecutionException, InterruptedException, IOException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue {
public AbstractTreeNode<K> addIndex(AbstractTreeNode<K> root, K identifier, V value) throws InternalOperationException, ImmutableBinaryObjectWrapper.InvalidBinaryObjectWrapperValue, IndexExistsException {
List<AbstractTreeNode<K>> path = new LinkedList<>();
BPlusTreeUtils.getPathToResponsibleNode(indexIOSession, path, root, identifier, degree);

Expand All @@ -42,8 +42,13 @@ public AbstractTreeNode<K> addIndex(AbstractTreeNode<K> root, K identifier, V va
if (i == 0){
/* current node is a leaf which should handle storing the data */

List<K> currentNodeKeyList = currentNode.getKeyList(degree, valueImmutableBinaryObjectWrapper.size());

if (currentNodeKeyList.contains(identifier))
throw new IndexExistsException();

/* If current node has space, store and exit */
if (currentNode.getKeyList(degree, valueImmutableBinaryObjectWrapper.size()).size() < (degree - 1)){
if (currentNodeKeyList.size() < (degree - 1)){
((AbstractLeafTreeNode<K, V>) currentNode).addKeyValue(identifier, value, degree);
indexIOSession.write(currentNode);
indexIOSession.commit();
Expand All @@ -60,7 +65,7 @@ public AbstractTreeNode<K> addIndex(AbstractTreeNode<K> root, K identifier, V va
indexIOSession.write(newSiblingLeafNode);
indexIOSession.write(currentNode);

answer = currentNode.getKeyList(degree, valueImmutableBinaryObjectWrapper.size()).contains(identifier) ? currentNode : newSiblingLeafNode;
answer = currentNodeKeyList.contains(identifier) ? currentNode : newSiblingLeafNode;

/* this leaf doesn't have a parent! create one and deal with it right here! */
if (path.size() == 1) {
Expand Down Expand Up @@ -138,7 +143,7 @@ public AbstractTreeNode<K> addIndex(AbstractTreeNode<K> root, K identifier, V va
throw new RuntimeException("Logic error: probably failed to store index?");
}

private void fixSiblingPointers(AbstractLeafTreeNode<K, V> currentNode, AbstractLeafTreeNode<K, V> newLeafTreeNode) throws ExecutionException, InterruptedException, IOException {
private void fixSiblingPointers(AbstractLeafTreeNode<K, V> currentNode, AbstractLeafTreeNode<K, V> newLeafTreeNode) throws InternalOperationException {
Optional<Pointer> currentNodeNextSiblingPointer = currentNode.getNextSiblingPointer(degree);
currentNode.setNextSiblingPointer(newLeafTreeNode.getPointer(), degree);
newLeafTreeNode.setPreviousSiblingPointer(currentNode.getPointer(), degree);
Expand Down
Loading

0 comments on commit 8e48d13

Please sign in to comment.