diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/DbTable.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/DbTable.java index bfde1953f..416362373 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/DbTable.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/DbTable.java @@ -23,6 +23,7 @@ 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.vadim_mazaev.Utility.Helper; /** * Represents the data table containing pairs key-value. The keys must be diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManager.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManager.java index 6fa12689b..28217105f 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManager.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManager.java @@ -23,6 +23,7 @@ import ru.fizteh.fivt.storage.structured.Storeable; import ru.fizteh.fivt.storage.structured.Table; import ru.fizteh.fivt.storage.structured.TableProvider; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; /** * Management class for working with the {link Table tables}. diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManagerFactory.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManagerFactory.java index c6f9f022e..35528c5cb 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManagerFactory.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TableManagerFactory.java @@ -11,7 +11,7 @@ public final class TableManagerFactory implements TableProviderFactory, AutoClos private boolean invalid; public TableManagerFactory() { - // Do nothing, only for implemented imterface. + // Do nothing, only for implemented interface. } @Override diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TablePart.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TablePart.java index 13dcfd0f8..c96933cd2 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TablePart.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/TablePart.java @@ -17,6 +17,7 @@ import java.util.Set; import ru.fizteh.fivt.storage.structured.Storeable; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; /** * Class represents a single file of type *.dir/*.dat. diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/DbTableTest.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/DbTableTest.java index b7d834fd9..00d6c7849 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/DbTableTest.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/DbTableTest.java @@ -24,8 +24,9 @@ import ru.fizteh.fivt.storage.structured.Table; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.DataBaseIOException; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.DbTable; -import ru.fizteh.fivt.students.vadim_mazaev.DataBase.Helper; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.TableManager; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.TestHelper; @SuppressWarnings("resource") public class DbTableTest { diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerFactoryTest.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerFactoryTest.java index 3a600c44e..213ade665 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerFactoryTest.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerFactoryTest.java @@ -8,8 +8,9 @@ import org.junit.Before; import org.junit.Test; -import ru.fizteh.fivt.students.vadim_mazaev.DataBase.Helper; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.TableManagerFactory; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.TestHelper; @SuppressWarnings("resource") public class TableManagerFactoryTest { diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerTest.java b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerTest.java index bebfebf5a..308c8b4ff 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerTest.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TableManagerTest.java @@ -21,8 +21,9 @@ import ru.fizteh.fivt.storage.structured.Storeable; import ru.fizteh.fivt.storage.structured.Table; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.DataBaseIOException; -import ru.fizteh.fivt.students.vadim_mazaev.DataBase.Helper; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.TableManager; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.TestHelper; @SuppressWarnings("resource") public class TableManagerTest { diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/Interpreter/Interpreter.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Interpreter/Interpreter.java index 5ed6d73e2..ff2ef67f5 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/Interpreter/Interpreter.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Interpreter/Interpreter.java @@ -16,32 +16,35 @@ public final class Interpreter { public static final String PROMPT = "$ "; public static final String NO_SUCH_COMMAND_MSG = "No such command declared: "; private static final String IGNORE_IN_DOUBLE_QUOTES_REGEX = "(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; - private static final String SPLIT_BY_SPACES_NOT_IN_BRACKETS_REGEX - = "\\s*(\".*\"|\\(.*\\)|\\[.*\\]|[^\\s]+)\\s*"; + private static final String SPLIT_BY_SPACES_NOT_IN_BRACKETS_REGEX = "\\s*(\".*\"|\\(.*\\)|\\[.*\\]|[^\\s]+)\\s*"; public static final String COMMAND_SEPARATOR = ";"; private InputStream in; private PrintStream out; - private Object connector; + private Object state; private Map commands; private Callable exitHandler; - - public Interpreter(Object connector, Command[] commands, InputStream in, PrintStream out) { + + public Interpreter(Object state, Command[] commands, InputStream in, PrintStream out) { if (in == null || out == null) { throw new IllegalArgumentException("Input or Output stream is null"); } this.commands = new HashMap<>(); this.in = in; this.out = out; - this.connector = connector; + this.state = state; for (Command cmd : commands) { this.commands.put(cmd.getName(), cmd); } } - + public Interpreter(Object connector, Command[] commands) { this(connector, commands, System.in, System.out); } - + + public int run() throws Exception { + return run(new String[0]); + } + public int run(String[] args) throws Exception { int exitStatus; try { @@ -55,11 +58,15 @@ public int run(String[] args) throws Exception { } return exitStatus; } - + public void setExitHandler(Callable callable) { exitHandler = callable; } - + + public void printMessage(String message) { + out.println(message); + } + private int batchMode(String[] args) throws Exception { int exitStatus = executeLine(String.join(" ", args)); if (exitHandler != null) { @@ -86,7 +93,7 @@ private int interactiveMode() throws Exception { } return exitStatus; } - + private int executeLine(String line) throws Exception { String[] cmds = line.split(COMMAND_SEPARATOR + IGNORE_IN_DOUBLE_QUOTES_REGEX); Pattern p = Pattern.compile(SPLIT_BY_SPACES_NOT_IN_BRACKETS_REGEX); @@ -102,11 +109,11 @@ private int executeLine(String line) throws Exception { } return 0; } catch (StopLineInterpretationException e) { - out.println(e.getMessage()); + printMessage(e.getMessage()); return 1; } } - + private void parse(String[] commandWithArgs) throws Exception { if (commandWithArgs.length > 0 && !commandWithArgs[0].isEmpty()) { String commandName = commandWithArgs[0]; @@ -125,7 +132,8 @@ private void parse(String[] commandWithArgs) throws Exception { throw new StopLineInterpretationException(NO_SUCH_COMMAND_MSG + commandName); } else { String[] args = new String[commandWithArgs.length - 1]; - //Exclude quotes along the edges of the string, if they presents. + // Exclude quotes along the edges of the string, if they + // presents. for (int i = 1; i < commandWithArgs.length; i++) { if (commandWithArgs[i].charAt(0) == '"' && commandWithArgs[i].charAt(commandWithArgs[i].length() - 1) == '"') { @@ -135,7 +143,7 @@ private void parse(String[] commandWithArgs) throws Exception { } } try { - command.execute(connector, args); + command.execute(state, args); } catch (RuntimeException e) { throw new StopLineInterpretationException(e.getMessage()); } diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/LoggingTest/LoggingProxyFactoryImplTest.java b/src/ru/fizteh/fivt/students/vadim_mazaev/LoggingTest/LoggingProxyFactoryImplTest.java index ced816314..8cf27673d 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/LoggingTest/LoggingProxyFactoryImplTest.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/LoggingTest/LoggingProxyFactoryImplTest.java @@ -11,10 +11,10 @@ import ru.fizteh.fivt.storage.structured.TableProvider; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.DbTable; -import ru.fizteh.fivt.students.vadim_mazaev.DataBase.Helper; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.TableManagerFactory; -import ru.fizteh.fivt.students.vadim_mazaev.DataBaseTest.TestHelper; import ru.fizteh.fivt.students.vadim_mazaev.Logging.LoggingProxyFactoryImpl; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.TestHelper; public class LoggingProxyFactoryImplTest { private TableManagerFactory test; diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/Main.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Main.java index af2f8c661..6eb86843e 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/Main.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Main.java @@ -1,20 +1,15 @@ package ru.fizteh.fivt.students.vadim_mazaev; import java.io.IOException; -import java.text.ParseException; -import java.util.ArrayList; import java.util.List; -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.storage.structured.TableProvider; -import ru.fizteh.fivt.students.vadim_mazaev.DataBase.DbTable; -import ru.fizteh.fivt.students.vadim_mazaev.DataBase.Helper; import ru.fizteh.fivt.students.vadim_mazaev.DataBase.TableManagerFactory; import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.Command; import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.Interpreter; import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.StopLineInterpretationException; +import ru.fizteh.fivt.students.vadim_mazaev.Remote.DataBaseState; +import ru.fizteh.fivt.students.vadim_mazaev.Remote.Server; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; public final class Main { public static void main(final String[] args) { @@ -25,182 +20,72 @@ public static void main(final String[] args) { } try (TableManagerFactory factory = new TableManagerFactory()) { DataBaseState state = new DataBaseState(factory.create(dbDirPath)); - initializeAndRunInterpreter(state, args); + Server server = new Server(state); + initializeAndRunInterpreter(server, args); } catch (RuntimeException | IOException e) { System.err.println(e.getMessage()); System.exit(1); } } - private static void initializeAndRunInterpreter(DataBaseState dbState, String[] arguments) { - Interpreter dbInterpreter = new Interpreter(dbState, new Command[] { - new Command("put", 2, (state, args) -> { - TableProvider manager = ((DataBaseState) state).getManager(); - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - try { - Storeable oldValue = link.put(args[0], manager.deserialize(link, args[1])); - if (oldValue != null) { - System.out.println("overwrite"); - System.out.println(manager.serialize(link, oldValue)); - } else { - System.out.println("new"); - } - } catch (ColumnFormatException | ParseException e) { - throw new StopLineInterpretationException("wrong type (" + e.getMessage() + ")"); - } - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("get", 1, (state, args) -> { - TableProvider manager = ((DataBaseState) state).getManager(); - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - Storeable value = link.get(args[0]); - if (value != null) { - System.out.println("found"); - System.out.println(manager.serialize(link, value)); - } else { - System.out.println("not found"); - } - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("remove", 1, (state, args) -> { - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - Storeable removedValue = link.remove(args[0]); - if (removedValue != null) { - System.out.println("removed"); - } else { - System.out.println("not found"); - } - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("list", 0, (state, args) -> { - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - System.out.println(String.join(", ", link.list())); - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("size", 0, (state, args) -> { - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - System.out.println(link.size()); - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("commit", 0, (state, args) -> { - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - try { - System.out.println(link.commit()); - } catch (IOException e) { - throw new StopLineInterpretationException(e.getMessage()); - } - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("rollback", 0, (state, args) -> { - Table link = ((DataBaseState) state).getUsedTable(); - if (link != null) { - System.out.println(link.rollback()); - } else { - throw new StopLineInterpretationException("no table"); - } - }), - new Command("create", 2, (state, args) -> { - String[] types = args[1].substring(1, args[1].length() - 1).split(" "); - List> typesList = new ArrayList<>(); - for (String type : types) { - Class typeClass = Helper.SUPPORTED_NAMES_TO_TYPES.get(type); - if (typeClass != null) { - typesList.add(typeClass); - } else { - throw new StopLineInterpretationException("wrong type (" + "unsupported type: '" + type - + "')"); - } - } - TableProvider manager = ((DataBaseState) state).getManager(); + //@formatter:off + private static void initializeAndRunInterpreter(Server server, String[] arguments) { + Interpreter serverInterpreter = new Interpreter(server, new Command[] { + new Command("start", 1, (state, args) -> { + //TODO add default port supporting try { - if (manager.createTable(args[0], typesList) != null) { - System.out.println("created"); - } else { - throw new StopLineInterpretationException(args[0] + " exists"); - } - } catch (IOException e) { + int port = Integer.parseInt(args[0].trim()); + ((Server) state).start(port); + System.out.println("started at " + port); + } catch (NumberFormatException e) { + throw new StopLineInterpretationException("not started: " + + args[0].trim() + " is wrong port number"); + } catch (IllegalStateException e) { throw new StopLineInterpretationException(e.getMessage()); } - }), new Command("use", 1, (state, args) -> { - DataBaseState dataBaseState = ((DataBaseState) state); - TableProvider manager = dataBaseState.getManager(); - Table newTable = manager.getTable(args[0]); - Table usedTable = dataBaseState.getUsedTable(); - if (newTable != null) { - if (usedTable != null && usedTable.getNumberOfUncommittedChanges() > 0) { - System.out.println(usedTable.getNumberOfUncommittedChanges() + " unsaved changes"); - } else { - dataBaseState.setUsedTable(newTable); - System.out.println("using " + args[0]); - } - } else { - throw new StopLineInterpretationException(args[0] + " not exists"); - } - }), new Command("drop", 1, (state, args) -> { - DataBaseState dataBaseState = ((DataBaseState) state); - TableProvider manager = dataBaseState.getManager(); - Table usedTable = dataBaseState.getUsedTable(); - if (usedTable != null && usedTable.getName().equals(args[0])) { - dataBaseState.setUsedTable(null); - } + }), + new Command("stop", 0, (state, args) -> { try { - manager.removeTable(args[0]); - System.out.println("dropped"); + int port = ((Server) state).stop(); + System.out.println("stopped at " + port); } catch (IllegalStateException e) { - throw new StopLineInterpretationException("tablename not exists"); + System.out.println(e.getMessage()); } catch (IOException e) { - throw new StopLineInterpretationException(e.getMessage()); + System.err.println(e.getMessage()); } - }), new Command("show", 1, (state, args) -> { - if (args[0].equals("tables")) { - TableProvider manager = ((DataBaseState) state).getManager(); - List tableNames = manager.getTableNames(); - System.out.println("table_name row_count"); - for (String name : tableNames) { - Table curTable = manager.getTable(name); - System.out.println(curTable.getName() + " " + curTable.size()); + }), + new Command("listusers", 0, (state, args) -> { + try { + List connections = ((Server) state).getListOfConnections(); + for (String connection : connections) { + System.out.println(connection); } - } else { - throw new StopLineInterpretationException(Interpreter.NO_SUCH_COMMAND_MSG + "show " + args[0]); + } catch (IllegalStateException e) { + System.out.println(e.getMessage()); } - })}); - dbInterpreter.setExitHandler(() -> { - DbTable link = (DbTable) dbState.getUsedTable(); - if (link != null && (link.getNumberOfUncommittedChanges() > 0)) { - System.out.println(link.getNumberOfUncommittedChanges() + " unsaved changes"); - return false; + }) + }); + serverInterpreter.setExitHandler(() -> { + server.close(); + return true; + }); + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + try { + server.close(); + } catch (IOException e) { + System.err.println(e.getMessage()); + } } - return true; }); - runInterpreter(dbInterpreter, arguments); - } - - private static void runInterpreter(Interpreter interpreter, String[] args) { try { - System.exit(interpreter.run(args)); + System.exit(serverInterpreter.run(arguments)); } catch (Exception e) { if (e.getMessage() != null) { System.err.println(e.getMessage()); } else { - System.err.println("Something went wrong. Unexpected error"); + System.err.println(Helper.UNEXPECTED_ERROR_MSG); e.printStackTrace(); } System.exit(1); diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/ClientDbState.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/ClientDbState.java new file mode 100644 index 000000000..5637fa51d --- /dev/null +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/ClientDbState.java @@ -0,0 +1,16 @@ +package ru.fizteh.fivt.students.vadim_mazaev.Remote; + +import java.io.PrintStream; + +public class ClientDbState extends DataBaseState { + private final PrintStream printStream; + + public ClientDbState(DataBaseState state, PrintStream printStream) { + super(state); + this.printStream = printStream; + } + + public PrintStream getPrintStream() { + return printStream; + } +} diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/Connector.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/Connector.java new file mode 100644 index 000000000..b81a843bd --- /dev/null +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/Connector.java @@ -0,0 +1,69 @@ +package ru.fizteh.fivt.students.vadim_mazaev.Remote; + +import java.io.Closeable; +import java.io.IOException; +import java.io.PrintStream; +import java.net.Socket; + +import ru.fizteh.fivt.students.vadim_mazaev.DataBase.DbTable; +import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.Interpreter; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; + +public final class Connector implements Runnable, Closeable { + private final Interpreter interpreter; + private boolean closed; + private final Socket socket; + private final Server server; + private final ClientDbState state; + + public Connector(Socket socket, Server server, ClientDbState state) throws IOException { + this.socket = socket; + this.server = server; + this.state = state; + PrintStream printer = new PrintStream(socket.getOutputStream()); + interpreter = new Interpreter(state, RemoteDbCommands.getCommands(), socket.getInputStream(), printer); + interpreter.setExitHandler(() -> { + DbTable link = (DbTable) state.getUsedTable(); + if (link != null && (link.getNumberOfUncommittedChanges() > 0)) { + printer.println(link.getNumberOfUncommittedChanges() + " unsaved changes"); + return false; + } + server.removeConnection(this); + return true; + }); + } + + @Override + public String toString() { + return socket.getInetAddress().getHostAddress().toString() + ":" + socket.getPort(); + } + + @Override + public void run() { + try { + state.getPrintStream().println("Welcome aboard. You successfully connected to database."); + interpreter.run(); + } catch (Exception e) { + if (e.getMessage() != null) { + interpreter.printMessage(e.getMessage()); + } else { + interpreter.printMessage(Helper.UNEXPECTED_ERROR_MSG); + for (StackTraceElement element : e.getStackTrace()) { + interpreter.printMessage(element.toString()); + } + } + } + } + + @Override + public void close() throws IOException { + if (!closed) { + closed = true; + if (state.getUsedTable() != null) { + state.getUsedTable().rollback(); + } + socket.close(); + server.removeConnection(this); + } + } +} diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseState.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/DataBaseState.java similarity index 69% rename from src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseState.java rename to src/ru/fizteh/fivt/students/vadim_mazaev/Remote/DataBaseState.java index 3f5feb472..f7aaa1a00 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseState.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/DataBaseState.java @@ -1,25 +1,30 @@ -package ru.fizteh.fivt.students.vadim_mazaev; +package ru.fizteh.fivt.students.vadim_mazaev.Remote; import ru.fizteh.fivt.storage.structured.Table; import ru.fizteh.fivt.storage.structured.TableProvider; -public final class DataBaseState { +public class DataBaseState { private TableProvider manager; private Table usedTable; - + public DataBaseState(TableProvider manager) { this.manager = manager; usedTable = null; } - + + public DataBaseState(DataBaseState state) { + this.manager = state.manager; + this.usedTable = state.usedTable; + } + public void setUsedTable(Table newUsedTable) { usedTable = newUsedTable; } - + public Table getUsedTable() { return usedTable; } - + public TableProvider getManager() { return manager; } diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/RemoteDbCommands.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/RemoteDbCommands.java new file mode 100644 index 000000000..70c7126d5 --- /dev/null +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/RemoteDbCommands.java @@ -0,0 +1,183 @@ +package ru.fizteh.fivt.students.vadim_mazaev.Remote; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.List; + +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.storage.structured.TableProvider; +import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.Command; +import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.Interpreter; +import ru.fizteh.fivt.students.vadim_mazaev.Interpreter.StopLineInterpretationException; +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; + +public class RemoteDbCommands { + + public static Command[] getCommands() { + return new Command[] { + PUT, GET, REMOVE, LIST, SIZE, COMMIT, ROLLBACK, CREATE, USE, DROP, SHOW}; + } + + private static final Command PUT = new Command("put", 2, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + TableProvider manager = clientDbState.getManager(); + Table link = clientDbState.getUsedTable(); + if (link != null) { + try { + Storeable oldValue = link.put(args[0], manager.deserialize(link, args[1])); + if (oldValue != null) { + clientDbState.getPrintStream().println("overwrite"); + clientDbState.getPrintStream().println(manager.serialize(link, oldValue)); + } else { + clientDbState.getPrintStream().println("new"); + } + } catch (ColumnFormatException | ParseException e) { + throw new StopLineInterpretationException("wrong type (" + e.getMessage() + ")"); + } + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command GET = new Command("get", 1, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + TableProvider manager = clientDbState.getManager(); + Table link = clientDbState.getUsedTable(); + if (link != null) { + Storeable value = link.get(args[0]); + if (value != null) { + clientDbState.getPrintStream().println("found"); + clientDbState.getPrintStream().println(manager.serialize(link, value)); + } else { + clientDbState.getPrintStream().println("not found"); + } + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command REMOVE = new Command("remove", 1, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + Table link = clientDbState.getUsedTable(); + if (link != null) { + Storeable removedValue = link.remove(args[0]); + if (removedValue != null) { + clientDbState.getPrintStream().println("removed"); + } else { + clientDbState.getPrintStream().println("not found"); + } + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command LIST = new Command("list", 0, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + Table link = clientDbState.getUsedTable(); + if (link != null) { + clientDbState.getPrintStream().println(String.join(", ", link.list())); + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command SIZE = new Command("size", 0, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + Table link = clientDbState.getUsedTable(); + if (link != null) { + clientDbState.getPrintStream().println(link.size()); + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command COMMIT = new Command("commit", 0, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + Table link = clientDbState.getUsedTable(); + if (link != null) { + try { + clientDbState.getPrintStream().println(link.commit()); + } catch (IOException e) { + throw new StopLineInterpretationException(e.getMessage()); + } + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command ROLLBACK = new Command("rollback", 0, (state, args) -> { + ClientDbState clientDbState = (ClientDbState) state; + Table link = clientDbState.getUsedTable(); + if (link != null) { + clientDbState.getPrintStream().println(link.rollback()); + } else { + throw new StopLineInterpretationException("no table"); + } + }); + private static final Command CREATE = new Command("create", 2, (state, args) -> { + String[] types = args[1].substring(1, args[1].length() - 1).split(" "); + List> typesList = new ArrayList<>(); + for (String type : types) { + Class typeClass = Helper.SUPPORTED_NAMES_TO_TYPES.get(type); + if (typeClass != null) { + typesList.add(typeClass); + } else { + throw new StopLineInterpretationException("wrong type (" + "unsupported type: '" + type + "')"); + } + } + ClientDbState clientDbState = (ClientDbState) state; + TableProvider manager = clientDbState.getManager(); + try { + if (manager.createTable(args[0], typesList) != null) { + clientDbState.getPrintStream().println("created"); + } else { + throw new StopLineInterpretationException(args[0] + " exists"); + } + } catch (IOException e) { + throw new StopLineInterpretationException(e.getMessage()); + } + }); + private static final Command USE = new Command("use", 1, (state, args) -> { + ClientDbState clientDbState = ((ClientDbState) state); + TableProvider manager = clientDbState.getManager(); + Table newTable = manager.getTable(args[0]); + Table usedTable = clientDbState.getUsedTable(); + if (newTable != null) { + if (usedTable != null && usedTable.getNumberOfUncommittedChanges() > 0) { + clientDbState.getPrintStream().println(usedTable.getNumberOfUncommittedChanges() + " unsaved changes"); + } else { + clientDbState.setUsedTable(newTable); + clientDbState.getPrintStream().println("using " + args[0]); + } + } else { + throw new StopLineInterpretationException(args[0] + " not exists"); + } + }); + private static final Command DROP = new Command("drop", 1, (state, args) -> { + ClientDbState clientDbState = ((ClientDbState) state); + TableProvider manager = clientDbState.getManager(); + Table usedTable = clientDbState.getUsedTable(); + if (usedTable != null && usedTable.getName().equals(args[0])) { + clientDbState.setUsedTable(null); + } + try { + manager.removeTable(args[0]); + clientDbState.getPrintStream().println("dropped"); + } catch (IllegalStateException e) { + throw new StopLineInterpretationException("tablename not exists"); + } catch (IOException e) { + throw new StopLineInterpretationException(e.getMessage()); + } + }); + private static final Command SHOW = new Command("show", 1, (state, args) -> { + if (args[0].equals("tables")) { + ClientDbState clientDbState = (ClientDbState) state; + TableProvider manager = clientDbState.getManager(); + List tableNames = manager.getTableNames(); + clientDbState.getPrintStream().println("table_name row_count"); + for (String name : tableNames) { + Table curTable = manager.getTable(name); + clientDbState.getPrintStream().println(curTable.getName() + " " + curTable.size()); + } + } else { + throw new StopLineInterpretationException(Interpreter.NO_SUCH_COMMAND_MSG + "show " + args[0]); + } + }); +} diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/Server.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/Server.java new file mode 100644 index 000000000..30579f1bc --- /dev/null +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Remote/Server.java @@ -0,0 +1,131 @@ +package ru.fizteh.fivt.students.vadim_mazaev.Remote; + +import java.io.Closeable; +import java.io.IOException; +import java.io.PrintStream; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import ru.fizteh.fivt.students.vadim_mazaev.Utility.Helper; + +public final class Server implements Closeable { + private static final String NOT_STARTED_MSG = "not started"; + private ServerSocket serverSocket; + private DataBaseState dbState; + private Set connections = new HashSet<>(); + private boolean cleaningUp; + private Thread serverThread; + + public Server(DataBaseState dbState) { + this.dbState = dbState; + } + + private synchronized boolean hasAlreadyStarted() { + return serverSocket != null; + } + + private void checkStarted() { + if (!hasAlreadyStarted()) { + throw new IllegalStateException(NOT_STARTED_MSG); + } + } + + public synchronized void start(int port) { + try { + if (hasAlreadyStarted()) { + throw new IllegalStateException("already started"); + } + serverSocket = new ServerSocket(port, 100, InetAddress.getByAddress(new byte[] { + 0, 0, 0, 0})); + } catch (IllegalStateException | IOException e) { + throw new IllegalStateException(NOT_STARTED_MSG + ": " + e.getMessage(), e); + } + + serverThread = new Thread(this::serverLoop); + serverThread.setDaemon(true); + serverThread.setPriority(Thread.NORM_PRIORITY); + serverThread.start(); + } + + public void start() throws IOException { + start(Helper.DEFAULT_PORT); + } + + private void serverLoop() { + try { + while (!Thread.currentThread().isInterrupted()) { + Socket clientSocket = serverSocket.accept(); + PrintStream clientPrintStream = new PrintStream(clientSocket.getOutputStream()); + ClientDbState clientDbState = new ClientDbState(dbState, clientPrintStream); + Connector connection = new Connector(clientSocket, this, clientDbState); + Thread clientThread = new Thread(connection); + clientThread.setDaemon(true); + clientThread.start(); + + synchronized (this) { + connections.add(connection); + } + } + } catch (IOException e) { + if (!Thread.currentThread().isInterrupted()) { + System.err.println("Error on listening to incoming connections"); + } + } finally { + try { + close(); + } catch (IOException e) { + System.err.println(e.getMessage()); + } + } + } + + public synchronized int stop() throws IOException { + checkStarted(); + int port = serverSocket.getLocalPort(); + close(); + return port; + } + + public synchronized List getListOfConnections() { + checkStarted(); + List connectionsList = new ArrayList<>(); + for (Connector connection : connections) { + connectionsList.add(connection.toString()); + } + return connectionsList; + } + + public synchronized void removeConnection(Connector connection) { + if (!cleaningUp) { + connections.remove(connection); + } + } + + @Override + public synchronized void close() throws IOException { + try { + if (hasAlreadyStarted()) { + cleaningUp = true; + for (Connector connection : connections) { + connection.close(); + } + cleaningUp = false; + connections.clear(); + + try { + serverThread.interrupt(); + serverSocket.close(); + } finally { + serverSocket = null; + } + } + } catch (IOException e) { + throw new IOException("Unable to stop server: " + e.getMessage(), e); + } + } +} diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/Helper.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Utility/Helper.java similarity index 87% rename from src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/Helper.java rename to src/ru/fizteh/fivt/students/vadim_mazaev/Utility/Helper.java index 859477ee7..f69781895 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBase/Helper.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Utility/Helper.java @@ -1,4 +1,4 @@ -package ru.fizteh.fivt.students.vadim_mazaev.DataBase; +package ru.fizteh.fivt.students.vadim_mazaev.Utility; import java.io.IOException; import java.lang.reflect.Method; @@ -25,11 +25,13 @@ public final class Helper { public static final String IGNORE_SYMBOLS_IN_DOUBLE_QUOTES_REGEX = "(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; // Names and other constant strings. + public static final String UNEXPECTED_ERROR_MSG = "Something went wrong. Unexpected error"; public static final String SIGNATURE_FILE_NAME = "signature.tsv"; public static final int NUMBER_OF_PARTITIONS = 16; public static final String ENCODING = "UTF-8"; public static final String FILE_NAME_REGEX = "([0-9]|1[0-5])\\.dat"; public static final String DIR_NAME_REGEX = "([0-9]|1[0-5])\\.dir"; + public static final int DEFAULT_PORT = 10001; // Lists, maps, etc. // HINT: If you want to add new type, just put it into this map, list and @@ -46,8 +48,7 @@ public final class Helper { unitializerMap.put(Boolean.class, "boolean"); unitializerMap.put(String.class, "String"); SUPPORTED_TYPES_TO_NAMES = Collections.unmodifiableMap(unitializerMap); - SUPPORTED_TYPES_LIST = Collections.unmodifiableList(new ArrayList<>( - unitializerMap.keySet())); + SUPPORTED_TYPES_LIST = Collections.unmodifiableList(new ArrayList<>(unitializerMap.keySet())); } public static final Map> SUPPORTED_NAMES_TO_TYPES = inverseMap(SUPPORTED_TYPES_TO_NAMES); // Map of getters from Storeable interface. @@ -65,8 +66,7 @@ public final class Helper { public static void recoursiveDelete(Path file) throws IOException { Files.walkFileTree(file, new SimpleFileVisitor() { @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) - throws IOException { + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { Files.delete(dir); return FileVisitResult.CONTINUE; @@ -77,22 +77,19 @@ public FileVisitResult postVisitDirectory(Path dir, IOException e) } @Override - public FileVisitResult visitFile(Path file, - BasicFileAttributes attrs) throws IOException { + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } }); } - public static Map inverseMap(Map map) - throws IllegalArgumentException { + public static Map inverseMap(Map map) throws IllegalArgumentException { Map inversed = new HashMap<>(map.size()); for (Entry e : map.entrySet()) { if (inversed.containsKey(e.getValue())) { - throw new IllegalArgumentException( - "Source map contains duplicate values"); + throw new IllegalArgumentException("Source map contains duplicate values"); } inversed.put(e.getValue(), e.getKey()); } diff --git a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TestHelper.java b/src/ru/fizteh/fivt/students/vadim_mazaev/Utility/TestHelper.java similarity index 98% rename from src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TestHelper.java rename to src/ru/fizteh/fivt/students/vadim_mazaev/Utility/TestHelper.java index 3870dcb0e..341ecbea3 100644 --- a/src/ru/fizteh/fivt/students/vadim_mazaev/DataBaseTest/TestHelper.java +++ b/src/ru/fizteh/fivt/students/vadim_mazaev/Utility/TestHelper.java @@ -1,4 +1,4 @@ -package ru.fizteh.fivt.students.vadim_mazaev.DataBaseTest; +package ru.fizteh.fivt.students.vadim_mazaev.Utility; import java.nio.file.Path; import java.nio.file.Paths;