Skip to content
This repository has been archived by the owner on Sep 27, 2022. It is now read-only.

Commit

Permalink
Merge pull request #470 from AndreosGhost/Task07-Proxy
Browse files Browse the repository at this point in the history
07-Proxy, Федоров Андрей, 393 группа
  • Loading branch information
vpavlenko committed Dec 21, 2014
2 parents 094d062 + 9fe6eb1 commit 7410e57
Show file tree
Hide file tree
Showing 43 changed files with 2,412 additions and 654 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.db;

import ru.fizteh.fivt.storage.structured.TableProvider;

interface AutoCloseableProvider extends TableProvider, AutoCloseable {
@Override
void close();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.db;

import ru.fizteh.fivt.storage.structured.Table;

interface AutoCloseableTable extends Table, AutoCloseable {
@Override
void close();
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,16 +1,74 @@
package ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.db;

import ru.fizteh.fivt.proxy.LoggingProxyFactory;
import ru.fizteh.fivt.storage.structured.TableProviderFactory;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.exception.DatabaseIOException;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.support.Log;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.support.LoggingProxyFactoryImpl;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.support.Utility;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.support.ValidityController;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.support.ValidityController.KillLock;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.support.ValidityController.UseLock;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.IdentityHashMap;

public class DBTableProviderFactory implements TableProviderFactory {
public final class DBTableProviderFactory implements TableProviderFactory, AutoCloseable {
private static final LoggingProxyFactory LOGGING_PROXY_FACTORY = new LoggingProxyFactoryImpl();
private static final Writer LOG_WRITER;

static {
Writer tempWriter;

try {
tempWriter = new OutputStreamWriter(new FileOutputStream("Proxy.log"));
} catch (IOException exc) {
Log.log(DBTableProviderFactory.class, exc, "Failed to create log");
tempWriter = null;
}

LOG_WRITER = tempWriter;
}

private final ValidityController validityController = new ValidityController();
private final IdentityHashMap<AutoCloseableProvider, Boolean> generatedProviders =
new IdentityHashMap<>();

static <T> T wrapImplementation(T implementation, Class<T> interfaceClass) {
if (LOG_WRITER != null) {
return (T) LOGGING_PROXY_FACTORY.wrap(LOG_WRITER, implementation, interfaceClass);
} else {
return implementation;
}
}

@Override
public synchronized void close() {
try (KillLock lock = validityController.useAndKill()) {
for (AutoCloseableProvider provider : generatedProviders.keySet()) {
provider.close();
}
generatedProviders.clear();
}
}

/**
* Unregisters the given provider.
* @param provider
* Pure (not proxied) link to the closed provider.
*/
synchronized void onProviderClosed(AutoCloseableProvider provider) {
try (UseLock useLock = validityController.use()) {
generatedProviders.remove(provider);
}
}

private void checkDatabaseDirectory(final Path databaseRoot) throws DatabaseIOException {
if (!Files.isDirectory(databaseRoot)) {
Expand All @@ -31,25 +89,37 @@ private void checkDatabaseDirectory(final Path databaseRoot) throws DatabaseIOEx
}

@Override
public DBTableProvider create(String dir) throws IllegalArgumentException, DatabaseIOException {
Utility.checkNotNull(dir, "Directory");

Path databaseRoot = Paths.get(dir).normalize();
if (!Files.exists(databaseRoot)) {
if (databaseRoot.getParent() == null || !Files.isDirectory(databaseRoot.getParent())) {
throw new DatabaseIOException(
"Database directory parent path does not exist or is not a directory");
}
protected void finalize() throws Throwable {
super.finalize();
close();
}

@Override
public synchronized AutoCloseableProvider create(String dir)
throws IllegalArgumentException, DatabaseIOException {
try (UseLock useLock = validityController.use()) {
Utility.checkNotNull(dir, "Directory");

try {
Files.createDirectory(databaseRoot);
} catch (IOException exc) {
throw new DatabaseIOException("Failed to establish database on path " + dir, exc);
Path databaseRoot = Paths.get(dir).normalize();
if (!Files.exists(databaseRoot)) {
if (databaseRoot.getParent() == null || !Files.isDirectory(databaseRoot.getParent())) {
throw new DatabaseIOException(
"Database directory parent path does not exist or is not a directory");
}

try {
Files.createDirectory(databaseRoot);
} catch (IOException exc) {
throw new DatabaseIOException("Failed to establish database on path " + dir, exc);
}
} else {
checkDatabaseDirectory(databaseRoot);
}
} else {
checkDatabaseDirectory(databaseRoot);
}

return new DBTableProvider(databaseRoot);
AutoCloseableProvider provider = new DBTableProvider(databaseRoot, this);
AutoCloseableProvider wrappedProvider = wrapImplementation(provider, AutoCloseableProvider.class);
generatedProviders.put(provider, Boolean.TRUE);
return wrappedProvider;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
* Database class responsible for a set of tables assigned to it.
* @author phoenix
*/
public class Database {
protected final TableProvider provider;
public class Database implements AutoCloseable {
private final TableProvider provider;
/**
* Root directory of all database files
*/
Expand Down Expand Up @@ -69,6 +69,13 @@ public void dropTable(String tableName) throws IllegalArgumentException, IOExcep
}
}

@Override
public void close() throws Exception {
if (provider instanceof AutoCloseable) {
((AutoCloseable) provider).close();
}
}

public Table getActiveTable() throws NoActiveTableException {
checkCurrentTableIsOpen();
return activeTable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,53 @@
import ru.fizteh.fivt.storage.structured.ColumnFormatException;
import ru.fizteh.fivt.storage.structured.Storeable;
import ru.fizteh.fivt.storage.structured.Table;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.json.JSONComplexObject;
import ru.fizteh.fivt.students.fedorov_andrew.databaselibrary.json.JSONField;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* Implementation of Storeable that can be put to the table it is assigned to as a value.<br/>
* Not thread-safe.
* Not thread-safe.<br/>
* Not bound to any table.
*/
public class StoreableImpl implements Storeable {
@JSONComplexObject(wrapper = true)
public final class StoreableImpl implements Storeable {
@JSONField
private final Object[] values;

private Table host;
private final List<Class<?>> types;

/**
* Creates a new instance of Storeable with null values as default.
* @param host
* Host table.
*/
StoreableImpl(Table host) {
this.host = host;
if (host instanceof StoreableTableImpl) {
// Memory optimization.
types = ((StoreableTableImpl) host).getColumnTypes();
} else {
types = new ArrayList<>(host.getColumnsCount());
for (int i = 0; i < host.getColumnsCount(); i++) {
types.add(host.getColumnType(i));
}
}
this.values = new Object[host.getColumnsCount()];
}

Table getHost() {
return host;
List<Class<?>> getTypes() {
return types;
}

private void ensureMatchColumnType(int columnIndex, Class<?> clazz) throws ColumnFormatException {
Class<?> columnType = host.getColumnType(columnIndex);
Class<?> columnType = types.get(columnIndex);
if (!columnType.equals(clazz)) {
throw new ColumnFormatException(
String.format(
"wrong type (Table '%s', col %d: Expected instance of %s, but got %s)",
host.getName(),
"wrong type (col %d: Expected instance of %s, but got %s)",
columnIndex,
columnType.getSimpleName(),
clazz.getSimpleName()));
Expand Down Expand Up @@ -110,7 +124,7 @@ private <T> T getTypedValue(int columnIndex, Class<T> clazz)

@Override
public int hashCode() {
return host.hashCode();
return values.length;
}

@Override
Expand All @@ -120,11 +134,11 @@ public boolean equals(Object obj) {
}
StoreableImpl storeable = (StoreableImpl) obj;

if (host != storeable.host) {
if (values.length != storeable.values.length) {
return false;
}

for (int col = 0; col < host.getColumnsCount(); col++) {
for (int col = 0; col < storeable.values.length; col++) {
if (!Objects.equals(values[col], storeable.values[col])) {
return false;
}
Expand All @@ -135,9 +149,20 @@ public boolean equals(Object obj) {

@Override
public String toString() {
if (host instanceof StoreableTableImpl) {
return ((StoreableTableImpl) host).getProvider().serialize(host, this);
StringBuilder sb = new StringBuilder(StoreableImpl.class.getSimpleName()).append('[');

boolean comma = false;
for (Object obj : values) {
if (comma) {
sb.append(',');
}
comma = true;
if (obj != null) {
sb.append(obj.toString());
}
}
return super.toString();

sb.append(']');
return sb.toString();
}
}
Loading

0 comments on commit 7410e57

Please sign in to comment.