comparison src/main/java/org/monetdb/util/SQLRestore.java @ 391:f523727db392

Moved Java classes from packages starting with nl.cwi.monetdb.* to package org.monetdb.* This naming complies to the Java Package Naming convention as MonetDB's main website is www.monetdb.org.
author Martin van Dinther <martin.van.dinther@monetdbsolutions.com>
date Thu, 12 Nov 2020 22:02:01 +0100 (2020-11-12)
parents src/main/java/nl/cwi/monetdb/util/SQLRestore.java@54137aeb1f92
children bf9f6b6ecf40
comparison
equal deleted inserted replaced
390:6199e0be3c6e 391:f523727db392
1 /*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 *
6 * Copyright 1997 - July 2008 CWI, August 2008 - 2020 MonetDB B.V.
7 */
8
9 package org.monetdb.util;
10
11 import java.io.BufferedReader;
12 import java.io.File;
13 import java.io.IOException;
14 import java.util.concurrent.atomic.AtomicBoolean;
15
16 import org.monetdb.mcl.io.BufferedMCLReader;
17 import org.monetdb.mcl.io.BufferedMCLWriter;
18 import org.monetdb.mcl.net.MapiSocket;
19
20 /**
21 * Use this class to restore an SQL dump file.
22 */
23 public final class SQLRestore {
24
25 private final String _host;
26 private final int _port;
27 private final String _user;
28 private final String _password;
29 private final String _dbName;
30
31 public SQLRestore(final String host, final int port, final String user, final String password, final String dbName) throws IOException {
32 if (host == null || user == null || password == null || dbName == null)
33 throw new NullPointerException();
34 _host = host;
35 _port = port;
36 _user = user;
37 _password = password;
38 _dbName = dbName;
39 }
40
41 private static final class ServerResponseReader implements Runnable {
42 private final BufferedMCLReader _is;
43 private final AtomicBoolean _errorState = new AtomicBoolean(false);
44 private String _errorMessage = null;
45
46 ServerResponseReader(final BufferedMCLReader is) {
47 _is = is;
48 }
49
50 public void run() {
51 try {
52 while (true) {
53 final String line = _is.readLine();
54 if (line == null)
55 break;
56 final int result = _is.getLineType();
57 switch (result) {
58 case BufferedMCLReader.ERROR:
59 _errorMessage = line;
60 _errorState.set(true);
61 return;
62 default:
63 // do nothing...
64 }
65 }
66 } catch (IOException e) {
67 _errorMessage = e.getMessage();
68 _errorState.set(true);
69 } finally {
70 try {
71 _is.close();
72 } catch (IOException e) {
73 // ignore errors
74 }
75 }
76 }
77
78 /**
79 * @return whether the server has responded with an error. Any
80 * error is regarded as fatal.
81 */
82 public boolean inErrorState() {
83 return _errorState.get();
84 }
85
86 /**
87 * @return the error message if inErrorState() is true. Behaviour is
88 * not defined if called before inErrorState is true.
89 */
90 public String getErrorMessage() {
91 return _errorMessage;
92 }
93 }
94
95 /**
96 * Restores a given SQL dump to the database.
97 *
98 * @param source file object
99 * @throws IOException when IO exception occurred
100 */
101 public void restore(final File source) throws IOException {
102 final MapiSocket ms = new MapiSocket();
103 try {
104 ms.setLanguage("sql");
105 ms.setDatabase(_dbName);
106 ms.connect(_host, _port, _user, _password);
107
108 final BufferedMCLWriter os = ms.getWriter();
109 final BufferedMCLReader reader = ms.getReader();
110
111 final ServerResponseReader srr = new ServerResponseReader(reader);
112
113 final Thread responseReaderThread = new Thread(srr);
114 responseReaderThread.start();
115 try {
116 // FIXME: we assume here that the dump is in system's default encoding
117 final BufferedReader sourceData = new BufferedReader(new java.io.FileReader(source));
118 try {
119 os.write('s'); // signal that a new statement (or series of) is coming
120 while(!srr.inErrorState()) {
121 final char[] buf = new char[4096];
122 final int result = sourceData.read(buf);
123 if (result < 0)
124 break;
125 os.write(buf, 0, result);
126 }
127
128 os.flush(); // mark the end of the statement (or series of)
129 os.close();
130 } finally {
131 sourceData.close();
132 }
133 } finally {
134 try {
135 responseReaderThread.join();
136 } catch (InterruptedException e) {
137 throw new IOException(e.getMessage());
138 }
139
140 // if the server signalled an error, we should respect it...
141 if (srr.inErrorState()) {
142 throw new IOException(srr.getErrorMessage());
143 }
144 }
145 } catch (org.monetdb.mcl.MCLException e) {
146 throw new IOException(e.getMessage());
147 } catch (org.monetdb.mcl.parser.MCLParseException e) {
148 throw new IOException(e.getMessage());
149 } finally {
150 ms.close();
151 }
152 }
153
154 public void close() {
155 // do nothing at the moment...
156 }
157
158
159 public static void main(String[] args) throws IOException {
160 if (args.length != 6) {
161 System.err.println("USAGE: java " + SQLRestore.class.getName() +
162 " <host> <port> <user> <password> <dbname> <dumpfile>");
163 System.exit(1);
164 }
165
166 // parse arguments
167 final String host = args[0];
168 final int port = Integer.parseInt(args[1]); // FIXME: catch NumberFormatException
169 final String user = args[2];
170 final String password = args[3];
171 final String dbName = args[4];
172 final File dumpFile = new File(args[5]);
173
174 // check arguments
175 if (!dumpFile.isFile() || !dumpFile.canRead()) {
176 System.err.println("Cannot read: " + dumpFile);
177 System.exit(1);
178 }
179
180 final SQLRestore md = new SQLRestore(host, port, user, password, dbName);
181 try {
182 System.out.println("Start restoring " + dumpFile);
183 long duration = -System.currentTimeMillis();
184 md.restore(dumpFile);
185 duration += System.currentTimeMillis();
186 System.out.println("Restoring took: " + duration + "ms");
187 } finally {
188 md.close();
189 }
190 }
191 }