提交 ab1e8d62 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 784e7774
#Fri Oct 19 18:51:44 CEST 2007
javac=javac
#Fri Oct 26 09:46:47 CEST 2007
benchmark.drivers.dir=C\:/data/java
javac=javac
path.servlet.jar=C\:/data/classpath/servlet-api.jar
version.name.maven=1.0.60
jdk=1.4
......@@ -46,7 +46,7 @@
<delete file="src/tools/org/h2/tools/code/CodeSwitch.class"/>
</target>
<target name="codeswitchPrepare">
<target name="codeswitchPrepare" depends="clean">
<javac executable="${javac}" srcdir="src/tools" destdir="bin" debug="true" includes="org/h2/tools/code/CodeSwitch.java"/>
</target>
......
......@@ -17,6 +17,7 @@ import java.util.StringTokenizer;
import org.h2.server.web.DbContextRule;
import org.h2.tools.Csv;
import org.h2.util.Resources;
import org.h2.util.StringCache;
import org.h2.util.StringUtils;
public class Bnf {
......@@ -254,6 +255,8 @@ public class Bnf {
StringTokenizer tokenizer = new StringTokenizer(syntax, SEPARATORS, true);
while (tokenizer.hasMoreTokens()) {
String s = tokenizer.nextToken();
// avoid duplicate strings
s = StringCache.get(s);
if (s.length() == 1) {
if (" \r\n".indexOf(s.charAt(0)) >= 0) {
continue;
......
......@@ -54,7 +54,7 @@ public class BackupCommand extends Prepared {
try {
String name = db.getName();
name = FileUtils.getFileName(name);
OutputStream zip = FileUtils.openFileOutputStream(fileName);
OutputStream zip = FileUtils.openFileOutputStream(fileName, false);
ZipOutputStream out = new ZipOutputStream(zip);
LogSystem log = db.getLog();
try {
......
......@@ -93,11 +93,7 @@ public abstract class ScriptBase extends Prepared implements DataHandler {
// always use a big buffer, otherwise end-of-block is written a lot
out = new BufferedOutputStream(out, Constants.IO_BUFFER_SIZE_COMPRESS);
} else {
try {
outStream = FileUtils.openFileOutputStream(fileName);
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
outStream = FileUtils.openFileOutputStream(fileName, false);
out = new BufferedOutputStream(outStream, Constants.IO_BUFFER_SIZE);
out = CompressTool.wrapOutputStream(out, compressionAlgorithm, Constants.SCRIPT_SQL);
}
......
......@@ -376,7 +376,7 @@ public class ScriptCommand extends ScriptBase {
}
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("SELECT BDATA FROM SYSTEM_LOB_STREAM WHERE ID=" + id + " ORDER BY PART");
OutputStream out = FileUtils.openFileOutputStream(TEMP_LOB_FILENAME);
OutputStream out = FileUtils.openFileOutputStream(TEMP_LOB_FILENAME, false);
while (rs.next()) {
InputStream in = rs.getBinaryStream(1);
IOUtils.copyAndCloseInput(in, out);
......
......@@ -11,6 +11,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.h2.api.DatabaseEventListener;
import org.h2.command.dml.SetTypes;
import org.h2.constant.ErrorCode;
......@@ -37,6 +38,7 @@ import org.h2.store.FileStore;
import org.h2.store.RecordReader;
import org.h2.store.Storage;
import org.h2.store.WriterThread;
import org.h2.store.fs.FileSystem;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.MetaTable;
......@@ -51,7 +53,6 @@ import org.h2.util.ClassUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.IntHashMap;
import org.h2.util.MemoryFile;
import org.h2.util.ObjectArray;
import org.h2.util.StringUtils;
import org.h2.value.CompareMode;
......@@ -224,14 +225,8 @@ public class Database implements DataHandler {
byte[] magicText = Constants.MAGIC_FILE_HEADER_TEXT.getBytes();
byte[] magicBinary = Constants.MAGIC_FILE_HEADER.getBytes();
try {
byte[] magic;
if (FileUtils.isInMemory(fileName)) {
MemoryFile file = FileUtils.getMemoryFile(fileName);
magic = file.getMagic();
} else {
InputStream fin = FileUtils.openFileInputStream(fileName);
magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
}
InputStream fin = FileUtils.openFileInputStream(fileName);
byte[] magic = IOUtils.readBytesAndClose(fin, magicBinary.length);
if (ByteUtils.compareNotNull(magic, magicText) == 0) {
return true;
} else if (ByteUtils.compareNotNull(magic, magicBinary) == 0) {
......@@ -422,7 +417,7 @@ public class Database implements DataHandler {
}
dummy = DataPage.create(this, 0);
if (persistent) {
if (readOnly || FileUtils.isInMemory(databaseName)) {
if (readOnly) {
traceSystem = new TraceSystem(null, false);
} else {
traceSystem = new TraceSystem(databaseName + Constants.SUFFIX_TRACE_FILE, true);
......@@ -1069,7 +1064,7 @@ public class Database implements DataHandler {
boolean inTempDir = readOnly;
String name = databaseName;
if (!persistent) {
name = FileUtils.MEMORY_PREFIX + name;
name = FileSystem.MEMORY_PREFIX + name;
}
return FileUtils.createTempFile(name, Constants.SUFFIX_TEMP_FILE, true, inTempDir);
} catch (IOException e) {
......
......@@ -97,6 +97,11 @@ public class LogFile {
}
String s = fileName.substring(fileNamePrefix.length() + 1, fileName.length()
- Constants.SUFFIX_LOG_FILE.length());
for (int i = 0; i < s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
return null;
}
}
int id = Integer.parseInt(s);
return new LogFile(log, id, fileNamePrefix);
}
......
......@@ -4,7 +4,6 @@
*/
package org.h2.message;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.math.BigDecimal;
......@@ -189,7 +188,7 @@ public class TraceObject {
e.printStackTrace(p);
p.close();
writer.close();
} catch (IOException e2) {
} catch (Exception e2) {
e2.printStackTrace();
}
}
......
......@@ -149,7 +149,7 @@ public class SecureSocketFactory {
}
}
if (needWrite) {
OutputStream out = FileUtils.openFileOutputStream(fileName);
OutputStream out = FileUtils.openFileOutputStream(fileName, false);
out.write(data);
out.close();
}
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public interface FileObject {
boolean exists();
boolean isDirectory();
boolean isFile();
boolean delete();
boolean mkdirs();
long lastModified();
boolean renameTo(FileObject fileNew);
void read(long skip, OutputStream out) throws IOException;
FileObject[] listFiles();
long length();
boolean canRead();
boolean canWrite();
String getName();
void write(InputStream in) throws IOException;
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class FileObjectDatabase implements FileObject {
static FileObjectDatabase get(FileSystemDatabase db, String name) {
return new FileObjectDatabase(db, name);
}
private FileSystemDatabase db;
private String fullName;
private FileObjectDatabase(FileSystemDatabase db, String fullName) {
this.db = db;
this.fullName = fullName;
}
public boolean canRead() {
return true;
}
public boolean canWrite() {
return true;
}
public boolean delete() {
db.delete(fullName);
return true;
}
public boolean exists() {
return db.exists(fullName);
}
public void read(long skip, OutputStream out) throws IOException {
db.read(fullName, skip, out);
}
public String getName() {
return db.getName(fullName);
}
public void write(InputStream in) throws IOException {
db.write(fullName, in);
}
public boolean isDirectory() {
return db.isDirectory(fullName);
}
public boolean isFile() {
return !db.isDirectory(fullName);
}
public long lastModified() {
return db.lastModified(fullName);
}
public long length() {
return db.length(fullName);
}
public FileObject[] listFiles() {
return db.listFiles(fullName);
}
public boolean mkdirs() {
db.mkdirs(fullName);
return true;
}
public boolean renameTo(FileObject fileNew) {
return db.renameTo(fullName, ((FileObjectDatabase) fileNew).fullName);
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.server.ftp;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
public class FileObjectNative implements FileObject {
private File file;
static FileObjectNative get(String name) {
name = FileUtils.translateFileName(name);
return new FileObjectNative(new File(name));
}
private FileObjectNative(File f) {
this.file = f;
}
public boolean exists() {
return file.exists();
}
public boolean isDirectory() {
return file.isDirectory();
}
public boolean canRead() {
return file.canRead();
}
public boolean canWrite() {
return file.canWrite();
}
public boolean delete() {
return file.delete();
}
public String getName() {
return file.getName();
}
public boolean isFile() {
return file.isFile();
}
public long lastModified() {
return file.lastModified();
}
public long length() {
return file.length();
}
public FileObject[] listFiles() {
File[] list = file.listFiles();
FileObject[] result = new FileObject[list.length];
for (int i = 0; i < list.length; i++) {
result[i] = get(list[i].getAbsolutePath());
}
return result;
}
public boolean mkdirs() {
return file.mkdirs();
}
public boolean renameTo(FileObject newFile) {
return file.renameTo(((FileObjectNative) newFile).file);
}
public void write(InputStream in) throws IOException {
try {
OutputStream out = FileUtils.openFileOutputStream(file.getAbsolutePath());
IOUtils.copyAndClose(in, out);
} catch (SQLException e) {
throw new IOException(e.getMessage());
}
}
public void read(long skip, OutputStream out) throws IOException {
InputStream in = FileUtils.openFileInputStream(file.getAbsolutePath());
IOUtils.skipFully(in, skip);
IOUtils.copyAndClose(in, out);
}
}
......@@ -10,6 +10,10 @@ import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.SQLException;
import org.h2.store.fs.FileSystem;
import org.h2.util.IOUtils;
public class FtpData extends Thread {
......@@ -58,22 +62,27 @@ public class FtpData extends Thread {
socket = null;
}
public synchronized void receive(FileObject file) throws IOException {
public synchronized void receive(FileSystem fs, String fileName) throws IOException, SQLException {
waitUntilConnected();
try {
InputStream in = socket.getInputStream();
file.write(in);
OutputStream out = fs.openFileOutputStream(fileName, false);
IOUtils.copy(in, out);
out.close();
} finally {
socket.close();
}
server.log("closed");
}
public synchronized void send(FileObject file, long skip) throws IOException {
public synchronized void send(FileSystem fs, String fileName, long skip) throws IOException {
waitUntilConnected();
try {
OutputStream out = socket.getOutputStream();
file.read(skip, out);
InputStream in = fs.openFileInputStream(fileName);
in.skip(skip);
IOUtils.copy(in, out);
in.close();
} finally {
socket.close();
}
......
......@@ -4,16 +4,12 @@
*/
package org.h2.server.ftp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
......@@ -21,9 +17,9 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Properties;
import org.h2.Driver;
import org.h2.engine.Constants;
import org.h2.server.Service;
import org.h2.store.fs.FileSystem;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.MathUtils;
......@@ -54,7 +50,7 @@ public class FtpServer implements Service {
private String readUserName = DEFAULT_READ;
private HashMap tasks = new HashMap();
private FileSystemDatabase db;
private FileSystem fs;
private boolean log;
private boolean allowTask;
static final String TASK_SUFFIX = ".task";
......@@ -87,18 +83,18 @@ public class FtpServer implements Service {
return dataSocket;
}
void appendFile(StringBuffer buff, FileObject f) {
buff.append(f.isDirectory() ? 'd' : '-');
buff.append(f.canRead() ? 'r' : '-');
buff.append(f.canWrite() ? 'w' : '-');
void appendFile(StringBuffer buff, String fileName) throws SQLException {
buff.append(fs.isDirectory(fileName) ? 'd' : '-');
buff.append('r');
buff.append(fs.canWrite(fileName) ? 'w' : '-');
buff.append("------- 1 owner group ");
String size = String.valueOf(f.length());
String size = String.valueOf(fs.length(fileName));
for (int i = size.length(); i < 15; i++) {
buff.append(' ');
}
buff.append(size);
buff.append(' ');
Date now = new Date(), mod = new Date(f.lastModified());
Date now = new Date(), mod = new Date(fs.getLastModified(fileName));
String date;
if (mod.after(now) || Math.abs((now.getTime() - mod.getTime()) / 1000 / 60 / 60 / 24) > 180) {
synchronized (dateFormatOld) {
......@@ -111,17 +107,21 @@ public class FtpServer implements Service {
}
buff.append(date);
buff.append(' ');
buff.append(f.getName());
buff.append(FileUtils.getFileName(fileName));
buff.append("\r\n");
}
String formatLastModified(FileObject file) {
String formatLastModified(String fileName) {
synchronized (dateFormat) {
return dateFormat.format(new Date(file.lastModified()));
return dateFormat.format(new Date(fs.getLastModified(fileName)));
}
}
FileObject getFile(String path) {
String getFileName(String path) {
return root + getPath(path);
}
String getPath(String path) {
if (path.indexOf("..") > 0) {
path = "/";
}
......@@ -131,21 +131,17 @@ public class FtpServer implements Service {
while (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
}
log("file: " + root + path);
if (db != null) {
return FileObjectDatabase.get(db, root + path);
} else {
return FileObjectNative.get(root + path);
}
log("path: " + path);
return path;
}
String getDirectoryListing(FileObject directory, boolean listDirectories) {
FileObject[] list = directory.listFiles();
String getDirectoryListing(String directory, boolean listDirectories) throws SQLException {
String[] list = fs.listFiles(directory);
StringBuffer buff = new StringBuffer();
for (int i = 0; list != null && i < list.length; i++) {
FileObject f = list[i];
if (f.isFile() || (f.isDirectory() && listDirectories)) {
appendFile(buff, f);
String fileName = list[i];
if (!fs.isDirectory(fileName) || (fs.isDirectory(fileName) && listDirectories)) {
appendFile(buff, fileName);
}
}
return buff.toString();
......@@ -164,7 +160,7 @@ public class FtpServer implements Service {
if ("-ftpPort".equals(args[i])) {
port = MathUtils.decodeInt(args[++i]);
} else if ("-ftpDir".equals(args[i])) {
root = FileUtils.translateFileName(args[++i]);
root = FileUtils.normalize(args[++i]);
} else if ("-ftpRead".equals(args[i])) {
readUserName = args[++i];
} else if ("-ftpWrite".equals(args[i])) {
......@@ -177,17 +173,8 @@ public class FtpServer implements Service {
allowTask = Boolean.valueOf(args[++i]).booleanValue();
}
}
if (root.startsWith("jdbc:")) {
Connection conn;
if (root.startsWith("jdbc:h2:")) {
// avoid using DriverManager if possible
conn = Driver.load().connect(root, new Properties());
} else {
conn = DriverManager.getConnection(root);
}
db = new FileSystemDatabase(conn, log);
root = "/";
}
fs = FileSystem.getInstance(root);
root = fs.normalize(root);
}
public String getURL() {
......@@ -195,7 +182,7 @@ public class FtpServer implements Service {
}
public void start() throws SQLException {
getFile("").mkdirs();
fs.mkdirs(root);
serverSocket = NetUtils.createServerSocket(port, false);
}
......@@ -245,31 +232,24 @@ public class FtpServer implements Service {
return allowTask;
}
void startTask(FileObject file) throws IOException {
stopTask(file);
String processName = file.getName();
if (file.getName().endsWith(".zip.task")) {
log("expand: " + file.getName());
Process p = Runtime.getRuntime().exec("jar -xf " + file.getName(), null, new File(root));
String processFile = root + "/" + processName;
new StreamRedirect(processFile, p.getInputStream(), null).start();
void startTask(String path) throws IOException {
stopTask(path);
if (path.endsWith(".zip.task")) {
log("expand: " + path);
Process p = Runtime.getRuntime().exec("jar -xf " + path, null, new File(root));
new StreamRedirect(path, p.getInputStream(), null).start();
return;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
file.read(0, out);
byte[] data = out.toByteArray();
Properties prop = new Properties();
prop.load(new ByteArrayInputStream(data));
Properties prop = FileUtils.loadProperties(path);
String command = prop.getProperty("command");
String outFile = processName.substring(0, processName.length() - TASK_SUFFIX.length());
String outFile = path.substring(0, path.length() - TASK_SUFFIX.length());
String errorFile = root + "/" + prop.getProperty("error", outFile + ".err.txt");
String outputFile = root + "/" + prop.getProperty("output", outFile + ".out.txt");
String processFile = root + "/" + processName;
log("start process: " + processName + " / " + command);
log("start process: " + path + " / " + command);
Process p = Runtime.getRuntime().exec(command, null, new File(root));
new StreamRedirect(processFile, p.getErrorStream(), errorFile).start();
new StreamRedirect(processFile, p.getInputStream(), outputFile).start();
tasks.put(processName, p);
new StreamRedirect(path, p.getErrorStream(), errorFile).start();
new StreamRedirect(path, p.getInputStream(), outputFile).start();
tasks.put(path, p);
}
private static class StreamRedirect extends Thread {
......@@ -287,7 +267,7 @@ public class FtpServer implements Service {
private void openOutput() {
if (outFile != null) {
try {
this.out = FileUtils.openFileOutputStream(outFile);
this.out = FileUtils.openFileOutputStream(outFile, false);
} catch (Exception e) {
// ignore
}
......@@ -316,8 +296,7 @@ public class FtpServer implements Service {
}
}
void stopTask(FileObject file) {
String processName = file.getName();
void stopTask(String processName) {
log("kill process: " + processName);
Process p = (Process) tasks.remove(processName);
if (p == null) {
......@@ -326,4 +305,8 @@ public class FtpServer implements Service {
p.destroy();
}
public FileSystem getFileSystem() {
return fs;
}
}
......@@ -143,7 +143,10 @@ public class PgServer implements Service {
PgServerThread c = (PgServerThread) list.get(i);
c.close();
try {
c.getThread().join(100);
Thread t = c.getThread();
if (t != null) {
t.join(100);
}
} catch (Exception e) {
// TODO log exception
e.printStackTrace();
......
......@@ -42,21 +42,19 @@ public class WebServer implements Service {
private static final String DEFAULT_LANGUAGE = "en";
/**
* Hungarian spec chars: &eacute;&#369;&aacute;&#337;&uacute;&ouml;&uuml;&oacute;&iacute;&Eacute;&Aacute;&#368;&#336;&Uacute;&Ouml;&Uuml;&Oacute;&Iacute;
*/
private static final String[][] LANGUAGES = {
{ "en", "English" },
{ "de", "Deutsch" },
{ "fr", "Fran\u00e7ais" },
{ "en", "English" },
{ "es", "Espa\u00f1ol" },
{ "zh_CN", "\u4E2D\u6587"},
{ "ja", "\u65e5\u672c\u8a9e"},
{ "fr", "Fran\u00e7ais" },
{ "hu", "Magyar"},
{ "in", "Indonesia"},
{ "pt_PT", "Portugu\u00eas (Europeu)"},
{ "pl", "Polski"},
{ "it", "Italiano"},
{ "ja", "\u65e5\u672c\u8a9e"},
{ "pl", "Polski"},
{ "pt_PT", "Portugu\u00eas (Europeu)"},
{ "ru", "\u0440\u0443\u0441\u0441\u043a\u0438\u0439"},
{ "zh_CN", "\u4E2D\u6587"},
};
private static final String[] GENERIC = new String[] {
......@@ -76,6 +74,18 @@ public class WebServer implements Service {
"Generic H2|org.h2.Driver|jdbc:h2:~/test|sa",
};
/*
String lang = new java.util.Locale("hu").getDisplayLanguage(new java.util.Locale("hu"));
java.util.Locale.CHINESE.getDisplayLanguage(
java.util.Locale.CHINESE);
for(int i=0; i<lang.length(); i++)
System.out.println(Integer.toHexString(lang.charAt(i))+" ");
*/
/**
* Hungarian spec chars: &eacute;&#369;&aacute;&#337;&uacute;&ouml;&uuml;&oacute;&iacute;&Eacute;&Aacute;&#368;&#336;&Uacute;&Ouml;&Uuml;&Oacute;&Iacute;
* Or use PropertiesToUTF8
*/
// private URLClassLoader urlClassLoader;
private String driverList;
private static int ticker;
......@@ -85,14 +95,6 @@ public class WebServer implements Service {
private boolean ssl;
private HashMap connInfoMap = new HashMap();
/*
String lang = new java.util.Locale("hu").getDisplayLanguage(new java.util.Locale("hu"));
java.util.Locale.CHINESE.getDisplayLanguage(
java.util.Locale.CHINESE);
for(int i=0; i<lang.length(); i++)
System.out.println(Integer.toHexString(lang.charAt(i))+" ");
*/
private static final long SESSION_TIMEOUT = 30 * 60 * 1000; // timeout is 30 min
private long lastTimeoutCheck;
private HashMap sessions = new HashMap();
......@@ -445,7 +447,7 @@ public class WebServer implements Service {
prop.setProperty(String.valueOf(len - i - 1), info.getString());
}
}
OutputStream out = FileUtils.openFileOutputStream(getPropertiesFileName());
OutputStream out = FileUtils.openFileOutputStream(getPropertiesFileName(), false);
prop.store(out, Constants.SERVER_PROPERTIES_TITLE);
out.close();
} catch (Exception e) {
......
......@@ -805,17 +805,22 @@ class WebThread extends Thread implements DatabaseEventListener {
}
private String getStackTrace(int id, Throwable e) {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String s = writer.toString();
s = PageParser.escapeHtml(s);
s = StringUtils.replaceAll(s, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
String message = PageParser.escapeHtml(e.getMessage());
s = "<a class=\"error\" href=\"#\" onclick=\"var x=document.getElementById('st" + id
+ "').style;x.display=x.display==''?'none':'';\">" + message
+ "</a><span style=\"display: none;\" id=\"st" + id + "\"><br />" + s + "</span>";
s = formatAsError(s);
return s;
try {
StringWriter writer = new StringWriter();
e.printStackTrace(new PrintWriter(writer));
String s = writer.toString();
s = PageParser.escapeHtml(s);
s = StringUtils.replaceAll(s, "\t", "&nbsp;&nbsp;&nbsp;&nbsp;");
String message = PageParser.escapeHtml(e.getMessage());
s = "<a class=\"error\" href=\"#\" onclick=\"var x=document.getElementById('st" + id
+ "').style;x.display=x.display==''?'none':'';\">" + message
+ "</a><span style=\"display: none;\" id=\"st" + id + "\"><br />" + s + "</span>";
s = formatAsError(s);
return s;
} catch (OutOfMemoryError e2) {
e.printStackTrace();
return e.toString();
}
}
private String formatAsError(String s) {
......
......@@ -4,7 +4,6 @@
*/
package org.h2.store;
import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
......@@ -35,12 +34,12 @@ public class FileLister {
* @throws SQLException
*/
public static ArrayList getDatabaseFiles(String dir, String db, boolean all) throws SQLException {
dir = FileUtils.translateFileName(dir);
dir = FileUtils.normalize(dir);
ArrayList files = new ArrayList();
if (dir == null || dir.equals("")) {
dir = ".";
}
String start = db == null ? null : FileUtils.normalize(dir + File.separator + db);
String start = db == null ? null : FileUtils.normalize(dir + "/" + db);
String[] list = FileUtils.listFiles(dir);
for (int i = 0; list != null && i < list.length; i++) {
String f = list[i];
......@@ -68,7 +67,7 @@ public class FileLister {
}
}
if (ok) {
if (db == null || FileUtils.fileStartsWith(f, start + ".") || FileUtils.isInMemory(dir)) {
if (db == null || FileUtils.fileStartsWith(f, start + ".")) {
String fileName = f;
files.add(fileName);
}
......
......@@ -21,6 +21,7 @@ import org.h2.jdbc.JdbcSQLException;
import org.h2.message.Message;
import org.h2.message.Trace;
import org.h2.message.TraceSystem;
import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.RandomUtils;
......@@ -46,6 +47,7 @@ public class FileLock {
private int sleep;
private long lastWrite;
private Properties properties;
private FileSystem fs;
private volatile String fileName;
private volatile ServerSocket socket;
private boolean locked;
......@@ -59,6 +61,7 @@ public class FileLock {
}
public synchronized void lock(String fileName, boolean allowSocket) throws SQLException {
this.fs = FileSystem.getInstance(fileName);
this.fileName = fileName;
if (locked) {
throw Message.getInternalError("already locked");
......@@ -95,7 +98,7 @@ public class FileLock {
try {
if (fileName != null) {
if (load().equals(properties)) {
FileUtils.delete(fileName);
fs.delete(fileName);
}
}
if (socket != null) {
......@@ -111,14 +114,14 @@ public class FileLock {
void save() throws SQLException {
try {
OutputStream out = FileUtils.openFileOutputStream(fileName);
OutputStream out = fs.openFileOutputStream(fileName, false);
try {
properties.setProperty("method", String.valueOf(method));
properties.store(out, MAGIC);
} finally {
out.close();
}
lastWrite = FileUtils.getLastModified(fileName);
lastWrite = fs.getLastModified(fileName);
trace.debug("save " + properties);
} catch (IOException e) {
throw getException(e);
......@@ -137,7 +140,7 @@ public class FileLock {
private void waitUntilOld() throws SQLException {
for (int i = 0; i < 10; i++) {
long last = FileUtils.getLastModified(fileName);
long last = fs.getLastModified(fileName);
long dist = System.currentTimeMillis() - last;
if (dist < -TIME_GRANULARITY) {
throw error("Lock file modified in the future: dist=" + dist);
......@@ -161,7 +164,7 @@ public class FileLock {
byte[] bytes = RandomUtils.getSecureBytes(RANDOM_BYTES);
String random = ByteUtils.convertBytesToString(bytes);
properties.setProperty("id", Long.toHexString(System.currentTimeMillis())+random);
if (!FileUtils.createNewFile(fileName)) {
if (!fs.createNewFile(fileName)) {
waitUntilOld();
String m2 = load().getProperty("method", FILE);
if (!m2.equals(FILE)) {
......@@ -172,8 +175,8 @@ public class FileLock {
if (!load().equals(properties)) {
throw error("Locked by another process");
}
FileUtils.delete(fileName);
if (!FileUtils.createNewFile(fileName)) {
fs.delete(fileName);
if (!fs.createNewFile(fileName)) {
throw error("Another process was faster");
}
}
......@@ -189,7 +192,7 @@ public class FileLock {
while (fileName != null) {
// trace.debug("watchdog check");
try {
if (!FileUtils.exists(fileName) || FileUtils.getLastModified(fileName) != lastWrite) {
if (!fs.exists(fileName) || fs.getLastModified(fileName) != lastWrite) {
save();
}
Thread.sleep(sleep);
......@@ -218,9 +221,9 @@ public class FileLock {
} catch (UnknownHostException e) {
throw getException(e);
}
if (!FileUtils.createNewFile(fileName)) {
if (!fs.createNewFile(fileName)) {
waitUntilOld();
long read = FileUtils.getLastModified(fileName);
long read = fs.getLastModified(fileName);
Properties p2 = load();
String m2 = p2.getProperty("method", SOCKET);
if (m2.equals(FILE)) {
......@@ -254,11 +257,11 @@ public class FileLock {
throw error("IOException");
}
}
if (read != FileUtils.getLastModified(fileName)) {
if (read != fs.getLastModified(fileName)) {
throw error("Concurrent update");
}
FileUtils.delete(fileName);
if (!FileUtils.createNewFile(fileName)) {
fs.delete(fileName);
if (!fs.createNewFile(fileName)) {
throw error("Another process was faster");
}
}
......
......@@ -5,7 +5,6 @@
package org.h2.store;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.ref.Reference;
import java.sql.SQLException;
......@@ -14,8 +13,9 @@ import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.message.Message;
import org.h2.security.SecureFileStore;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.TempFileDeleter;
/**
......@@ -31,7 +31,7 @@ public class FileStore {
protected String name;
protected DataHandler handler;
private byte[] magic;
private RandomAccessFile file;
private FileObject file;
private long filePos;
private long fileLength;
private Reference autoDeleteReference;
......@@ -50,9 +50,7 @@ public class FileStore {
public static FileStore open(DataHandler handler, String name, String mode, byte[] magic, String cipher,
byte[] key, int keyIterations) throws SQLException {
FileStore store;
if (FileUtils.isInMemory(name)) {
store = new MemoryFileStore(handler, name, magic);
} else if (cipher == null) {
if (cipher == null) {
store = new FileStore(handler, name, mode, magic);
} else {
store = new SecureFileStore(handler, name, mode, magic, cipher, key, keyIterations);
......@@ -61,17 +59,18 @@ public class FileStore {
}
protected FileStore(DataHandler handler, String name, String mode, byte[] magic) throws SQLException {
FileSystem fs = FileSystem.getInstance(name);
this.handler = handler;
this.name = name;
this.magic = magic;
this.mode = mode;
try {
FileUtils.createDirs(name);
if (FileUtils.exists(name) && !FileUtils.canWrite(name)) {
fs.createDirs(name);
if (fs.exists(name) && !fs.canWrite(name)) {
mode = "r";
this.mode = mode;
}
file = FileUtils.openRandomAccessFile(name, mode);
file = fs.openFileObject(name, mode);
if (mode.length() > 2) {
synchronousMode = true;
}
......@@ -124,7 +123,7 @@ public class FileStore {
write(magic, 0, len);
checkedWriting = true;
} else {
// write unencrypted
// read unencrypted
seek(0);
byte[] buff = new byte[len];
readFullyDirect(buff, 0, len);
......@@ -262,13 +261,13 @@ public class FileStore {
}
file.seek(pos);
} else {
FileUtils.setLength(file, newLength);
file.setLength(newLength);
}
fileLength = newLength;
} catch (IOException e) {
if (freeUpDiskSpace()) {
try {
FileUtils.setLength(file, newLength);
file.setLength(newLength);
} catch (IOException e2) {
throw Message.convertIOException(e2, name);
}
......@@ -289,7 +288,7 @@ public class FileStore {
}
if (SysProperties.CHECK2 && len % Constants.FILE_BLOCK_SIZE != 0) {
long newLength = len + Constants.FILE_BLOCK_SIZE - (len % Constants.FILE_BLOCK_SIZE);
FileUtils.setLength(file, newLength);
file.setLength(newLength);
fileLength = newLength;
throw Message.getInternalError("unaligned file length " + name + " len " + len);
}
......@@ -314,7 +313,7 @@ public class FileStore {
public void sync() {
try {
file.getFD().sync();
file.sync();
} catch (IOException e) {
// TODO log exception
}
......@@ -340,7 +339,7 @@ public class FileStore {
public void openFile() throws IOException {
if (file == null) {
file = FileUtils.openRandomAccessFile(name, mode);
file = FileSystem.getInstance(name).openFileObject(name, mode);
file.seek(filePos);
}
}
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.io.IOException;
import java.sql.SQLException;
import org.h2.util.FileUtils;
import org.h2.util.MemoryFile;
/**
* This class is an abstraction of an in-memory file.
* A {@link MemoryFile} contains the actual bytes.
*/
public class MemoryFileStore extends FileStore {
private MemoryFile memFile;
public MemoryFileStore(DataHandler handler, String name, byte[] magic) throws SQLException {
super(handler, magic);
this.name = name;
memFile = FileUtils.getMemoryFile(name);
memFile.setMagic(magic);
}
public void close() {
memFile.close();
}
public long getFilePointer() {
return memFile.getFilePointer();
}
public long length() {
return memFile.length();
}
public void readFully(byte[] b, int off, int len) throws SQLException {
checkPowerOff();
memFile.readFully(b, off, len);
}
public void seek(long pos) {
memFile.seek(pos);
}
public void setLength(long newLength) throws SQLException {
checkPowerOff();
memFile.setLength(newLength);
}
public void write(byte[] b, int off, int len) throws SQLException {
checkPowerOff();
memFile.write(b, off, len);
}
public void closeFile() throws IOException {
memFile.close();
}
public void openFile() throws IOException {
memFile.open();
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
import java.io.InputStream;
public class FileInputStream extends InputStream {
private FileObject file;
private byte[] buffer = new byte[1];
FileInputStream(FileObject file) {
this.file = file;
}
public int read() throws IOException {
if (file.getFilePointer() >= file.length()) {
return -1;
}
file.readFully(buffer, 0, 1);
return buffer[0];
}
private int todoWriteFtpTest;
private int todoReadBlock;
public void close() throws IOException {
file.close();
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
/**
* This interface represents a RandomAccessFile.
*/
public interface FileObject {
long length() throws IOException;
void close() throws IOException;
void readFully(byte[] b, int off, int len) throws IOException;
void seek(long pos) throws IOException;
void write(byte[] b, int off, int len) throws IOException;
long getFilePointer() throws IOException;
void sync() throws IOException;
void setLength(long newLength) throws IOException;
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
public class FileObjectDatabase implements FileObject {
private FileSystemDatabase db;
private String fileName;
private byte[] data;
private int pos, length;
private boolean changed;
FileObjectDatabase(FileSystemDatabase db, String fileName, byte[] data, boolean changed) {
this.db = db;
this.fileName = fileName;
this.data = data;
this.length = data.length;
this.changed = changed;
}
public void close() throws IOException {
sync();
}
public long getFilePointer() throws IOException {
return pos;
}
public long length() throws IOException {
return length;
}
public void readFully(byte[] b, int off, int len) throws IOException {
if (pos + len > length) {
throw new IOException("Can not read past EOF");
}
System.arraycopy(data, pos, b, off, len);
pos += len;
}
public void seek(long pos) throws IOException {
this.pos = (int) pos;
}
public void setLength(long newLength) throws IOException {
this.length = (int) newLength;
if (length != data.length) {
byte[] n = new byte[length];
System.arraycopy(data, 0, n, 0, Math.min(data.length, n.length));
data = n;
changed = true;
}
}
public void sync() throws IOException {
if (changed) {
db.write(fileName, data, length);
changed = false;
}
}
public void write(byte[] b, int off, int len) throws IOException {
if (pos + len > data.length) {
int newLen = Math.max(data.length * 2, 1024);
byte[] n = new byte[newLen];
System.arraycopy(data, 0, n, 0, length);
data = n;
}
System.arraycopy(b, off, data, pos, len);
pos += len;
length = Math.max(length, pos);
changed = true;
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
import java.io.RandomAccessFile;
import org.h2.util.FileUtils;
/**
* This class is wraps a RandomAccessFile.
*/
public class FileObjectDisk implements FileObject {
private RandomAccessFile file;
FileObjectDisk(RandomAccessFile file) {
this.file = file;
}
public long length() throws IOException {
return file.length();
}
public void close() throws IOException {
file.close();
}
public void readFully(byte[] b, int off, int len) throws IOException {
file.read(b, off, len);
}
public void seek(long pos) throws IOException {
file.seek(pos);
}
public void write(byte[] b, int off, int len) throws IOException {
file.write(b, off, len);
}
public long getFilePointer() throws IOException {
return file.getFilePointer();
}
public void sync() throws IOException {
file.getFD().sync();
}
public void setLength(long newLength) throws IOException {
FileUtils.setLength(file, newLength);
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
import java.io.OutputStream;
public class FileOutputStream extends OutputStream {
private FileObject file;
private byte[] buffer = new byte[1];
FileOutputStream(FileObject file, boolean append) throws IOException {
this.file = file;
if (append) {
file.seek(file.length());
} else {
file.seek(0);
file.setLength(0);
}
}
public void write(int b) throws IOException {
buffer[0] = (byte) b;
file.write(buffer, 0, 1);
}
private int todoWriteBlock;
public void close() throws IOException {
file.close();
}
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
public abstract class FileSystem {
public static final String MEMORY_PREFIX = "memFS:";
public static final String MEMORY_PREFIX_LZF = "memLZF:";
public static final String DB_PREFIX = "jdbc:";
public static FileSystem getInstance(String fileName) {
if (isInMemory(fileName)) {
return FileSystemMemory.getInstance();
} else if (fileName.startsWith(DB_PREFIX)) {
return FileSystemDatabase.getInstance(fileName);
}
return FileSystemDisk.getInstance();
}
private static boolean isInMemory(String fileName) {
return fileName != null && fileName.startsWith(MEMORY_PREFIX) || fileName.startsWith(MEMORY_PREFIX_LZF);
}
public abstract long length(String fileName);
public abstract void rename(String oldName, String newName) throws SQLException;
public abstract boolean createNewFile(String fileName) throws SQLException;
public abstract boolean exists(String fileName);
public abstract void delete(String fileName) throws SQLException;
public abstract boolean tryDelete(String fileName);
public abstract String createTempFile(String prefix, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException;
public abstract String[] listFiles(String path) throws SQLException;
public abstract void deleteRecursive(String fileName) throws SQLException;
public abstract boolean isReadOnly(String fileName);
public abstract String normalize(String fileName) throws SQLException;
public abstract String getParent(String fileName);
public abstract boolean isDirectory(String fileName);
public abstract boolean isAbsolute(String fileName);
public abstract String getAbsolutePath(String fileName);
public abstract long getLastModified(String fileName);
public abstract boolean canWrite(String fileName);
public abstract void copy(String original, String copy) throws SQLException;
public void mkdirs(String directoryName) throws SQLException {
createDirs(directoryName + "/x");
}
public abstract void createDirs(String fileName) throws SQLException;
public abstract String getFileName(String name) throws SQLException;
public abstract boolean fileStartsWith(String fileName, String prefix);
public abstract OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException;
public abstract FileObject openFileObject(String fileName, String mode) throws IOException;
public abstract InputStream openFileInputStream(String fileName) throws IOException;
}
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store.fs;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.HashMap;
import org.h2.message.Message;
public class FileSystemMemory extends FileSystem {
private static final FileSystemMemory INSTANCE = new FileSystemMemory();
private static final HashMap MEMORY_FILES = new HashMap();
public static FileSystemMemory getInstance() {
return INSTANCE;
}
private FileSystemMemory() {
}
public long length(String fileName) {
return getMemoryFile(fileName).length();
}
public void rename(String oldName, String newName) throws SQLException {
FileObjectMemory f = getMemoryFile(oldName);
f.setName(newName);
synchronized (MEMORY_FILES) {
MEMORY_FILES.put(newName, f);
}
}
public boolean createNewFile(String fileName) throws SQLException {
if (exists(fileName)) {
return false;
}
// creates the file (not thread safe)
getMemoryFile(fileName);
return true;
}
public boolean exists(String fileName) {
synchronized (MEMORY_FILES) {
return MEMORY_FILES.get(fileName) != null;
}
}
public void delete(String fileName) throws SQLException {
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
}
public boolean tryDelete(String fileName) {
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
return true;
}
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException {
name += ".";
for (int i = 0;; i++) {
String n = name + i + suffix;
if (!exists(n)) {
// creates the file (not thread safe)
getMemoryFile(n);
return n;
}
}
}
public String[] listFiles(String path) throws SQLException {
synchronized (MEMORY_FILES) {
String[] list = new String[MEMORY_FILES.size()];
FileObjectMemory[] l = new FileObjectMemory[MEMORY_FILES.size()];
MEMORY_FILES.values().toArray(l);
for (int i = 0; i < list.length; i++) {
list[i] = l[i].getName();
}
return list;
}
}
public void deleteRecursive(String fileName) throws SQLException {
throw Message.getUnsupportedException();
}
public boolean isReadOnly(String fileName) {
return false;
}
public String normalize(String fileName) throws SQLException {
return fileName;
}
public String getParent(String fileName) {
int idx = Math.max(fileName.indexOf(':'), fileName.lastIndexOf('/'));
return fileName.substring(0, idx);
}
public boolean isDirectory(String fileName) {
// TODO in memory file system currently doesn't support directories
return false;
}
public boolean isAbsolute(String fileName) {
// TODO relative files are not supported
return true;
}
public String getAbsolutePath(String fileName) {
// TODO relative files are not supported
return fileName;
}
public long getLastModified(String fileName) {
// TODO last modified is not supported
return 0;
}
public boolean canWrite(String fileName) {
return true;
}
public void copy(String original, String copy) throws SQLException {
// TODO support copying
throw Message.getUnsupportedException();
}
public void createDirs(String fileName) throws SQLException {
}
public String getFileName(String name) throws SQLException {
// TODO directories are not supported
return name;
}
public boolean fileStartsWith(String fileName, String prefix) {
return fileName.startsWith(prefix);
}
public OutputStream openFileOutputStream(String fileName, boolean append) throws SQLException {
try {
return new FileOutputStream(getMemoryFile(fileName), append);
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
}
}
public InputStream openFileInputStream(String fileName) throws IOException {
return new FileInputStream(getMemoryFile(fileName));
}
public FileObject openFileObject(String fileName, String mode) throws IOException {
return getMemoryFile(fileName);
}
private FileObjectMemory getMemoryFile(String fileName) {
synchronized (MEMORY_FILES) {
FileObjectMemory m = (FileObjectMemory) MEMORY_FILES.get(fileName);
if (m == null) {
boolean compress = fileName.startsWith(FileSystem.MEMORY_PREFIX_LZF);
m = new FileObjectMemory(fileName, compress);
MEMORY_FILES.put(fileName, m);
}
// TODO the memory file only supports one pointer
m.seek(0);
return m;
}
}
}
......@@ -88,13 +88,13 @@ public class Backup {
}
return;
}
zipFileName = FileUtils.translateFileName(zipFileName);
zipFileName = FileUtils.normalize(zipFileName);
if (FileUtils.exists(zipFileName)) {
FileUtils.delete(zipFileName);
}
OutputStream out = null;
try {
out = FileUtils.openFileOutputStream(zipFileName);
out = FileUtils.openFileOutputStream(zipFileName, false);
ZipOutputStream zipOut = new ZipOutputStream(out);
String base = "";
for (int i = 0; i < list.size(); i++) {
......
......@@ -71,7 +71,7 @@ public class ConvertTraceFile {
* @param javaClassName
* @throws IOException
*/
private void convertFile(String traceFileName, String javaClassName, String script) throws IOException {
private void convertFile(String traceFileName, String javaClassName, String script) throws IOException, SQLException {
LineNumberReader reader = new LineNumberReader(FileUtils.openFileReader(traceFileName));
PrintWriter javaWriter = new PrintWriter(FileUtils.openFileWriter(javaClassName + ".java", false));
PrintWriter scriptWriter = new PrintWriter(FileUtils.openFileWriter(script, false));
......
......@@ -26,6 +26,7 @@ import java.util.ArrayList;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
import org.h2.util.StringCache;
import org.h2.util.StringUtils;
/**
......@@ -337,6 +338,7 @@ public class Csv implements SimpleRowSource {
private String readValue() throws IOException {
endOfLine = false;
String value = null;
outer:
while (true) {
int ch = readChar();
if (ch < 0 || ch == '\r' || ch == '\n') {
......@@ -362,7 +364,8 @@ public class Csv implements SimpleRowSource {
while (true) {
ch = readChar();
if (ch < 0) {
return buff.toString();
value = buff.toString();
break outer;
} else if (ch == fieldDelimiter) {
ch = readChar();
if (ch == fieldDelimiter) {
......@@ -425,7 +428,8 @@ public class Csv implements SimpleRowSource {
break;
}
}
return value;
// save memory
return StringCache.get(value);
}
private String unEscape(String s) {
......
......@@ -271,7 +271,7 @@ public class Recover implements DataHandler {
}
}
private static PrintWriter getWriter(String fileName, String suffix) throws IOException {
private static PrintWriter getWriter(String fileName, String suffix) throws IOException, SQLException {
fileName = fileName.substring(0, fileName.length() - 3);
String outputFile = fileName + suffix;
System.out.println("Created file: " + outputFile);
......@@ -310,7 +310,7 @@ public class Recover implements DataHandler {
String n = fileName + (lobCompression ? ".comp" : "") + ".txt";
InputStream in = null;
try {
out = FileUtils.openFileOutputStream(n);
out = FileUtils.openFileOutputStream(n, false);
textStorage = Database.isTextStorage(fileName, false);
byte[] magic = Database.getMagic(textStorage);
store = FileStore.open(null, fileName, "r", magic);
......
......@@ -159,7 +159,7 @@ public class Restore {
if (copy) {
OutputStream out = null;
try {
out = FileUtils.openFileOutputStream(directory + File.separator + fileName);
out = FileUtils.openFileOutputStream(directory + File.separator + fileName, false);
IOUtils.copy(zipIn, out);
} finally {
IOUtils.closeSilently(out);
......
......@@ -5,7 +5,6 @@
package org.h2.tools;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.sql.Connection;
......@@ -14,7 +13,6 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.message.Message;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
import org.h2.util.JdbcUtils;
......@@ -143,8 +141,6 @@ public class Script {
writer.println(s + ";");
}
writer.close();
} catch (IOException e) {
throw Message.convertIOException(e, fileName);
} finally {
JdbcUtils.closeSilently(stat);
JdbcUtils.closeSilently(conn);
......
......@@ -4,13 +4,13 @@
*/
package org.h2.util;
import java.lang.ref.WeakReference;
import java.lang.ref.SoftReference;
import org.h2.constant.SysProperties;
public class StringCache {
private static final boolean ENABLED = true;
private static WeakReference weakCache = new WeakReference(null);
private static SoftReference softCache = new SoftReference(null);
// testing: cacheHit / miss are public!
// public static int cacheHit = 0, cacheMiss = 0;
......@@ -54,11 +54,11 @@ public class StringCache {
} else if (s.length() == 0) {
return "";
}
String[] cache = (String[]) weakCache.get();
String[] cache = (String[]) softCache.get();
int hash = s.hashCode();
if (cache == null) {
cache = new String[SysProperties.OBJECT_CACHE_SIZE];
weakCache = new WeakReference(cache);
softCache = new SoftReference(cache);
}
int index = hash & (SysProperties.OBJECT_CACHE_SIZE - 1);
String cached = cache[index];
......@@ -81,11 +81,11 @@ public class StringCache {
} else if (s.length() == 0) {
return "";
}
String[] cache = (String[]) weakCache.get();
String[] cache = (String[]) softCache.get();
int hash = s.hashCode();
if (cache == null) {
cache = new String[SysProperties.OBJECT_CACHE_SIZE];
weakCache = new WeakReference(cache);
softCache = new SoftReference(cache);
}
int index = hash & (SysProperties.OBJECT_CACHE_SIZE - 1);
String cached = cache[index];
......@@ -102,7 +102,7 @@ public class StringCache {
}
public static void clearCache() {
weakCache = new WeakReference(null);
softCache = new SoftReference(null);
}
}
......@@ -153,6 +153,18 @@ public class StringUtils {
case 'f':
buff.append('\f');
break;
case '#':
// for properties files
buff.append('#');
break;
case '=':
// for properties files
buff.append('=');
break;
case ':':
// for properties files
buff.append(':');
break;
case '"':
buff.append('"');
break;
......
......@@ -20,6 +20,7 @@ import org.h2.store.DataHandler;
import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream;
import org.h2.store.FileStoreOutputStream;
import org.h2.store.fs.FileSystem;
import org.h2.util.ByteUtils;
import org.h2.util.FileUtils;
import org.h2.util.IOUtils;
......@@ -621,7 +622,7 @@ public class ValueLob extends Value {
private void copyFile(DataHandler handler, String fileName, String live) throws SQLException {
synchronized (handler.getLobSyncObject()) {
FileUtils.copy(fileName, live);
FileSystem.getInstance(fileName).copy(fileName, live);
}
}
......
......@@ -8,6 +8,7 @@ import java.sql.SQLException;
import java.util.Properties;
import org.h2.server.TcpServer;
import org.h2.store.fs.FileSystemDisk;
import org.h2.test.db.TestAutoRecompile;
import org.h2.test.db.TestBackup;
import org.h2.test.db.TestBatchUpdates;
......@@ -77,6 +78,7 @@ import org.h2.test.unit.TestDataPage;
import org.h2.test.unit.TestExit;
import org.h2.test.unit.TestFile;
import org.h2.test.unit.TestFileLock;
import org.h2.test.unit.TestFileSystem;
import org.h2.test.unit.TestIntArray;
import org.h2.test.unit.TestIntIntHashMap;
import org.h2.test.unit.TestMultiThreadedKernel;
......@@ -93,7 +95,6 @@ import org.h2.test.unit.TestTools;
import org.h2.test.unit.TestValueHashMap;
import org.h2.tools.DeleteDbFiles;
import org.h2.tools.Server;
import org.h2.util.FileUtils;
import org.h2.util.StringUtils;
/**
......@@ -141,6 +142,19 @@ java org.h2.test.TestAll timer
/*
replicating file system
test DbStarter
TestFileSystem
create table test(id int, name varchar);
insert into test select x, '' from system_range(1, 10000);
-- fast
update test set name = 'y' where cast(id as varchar) like '1%';
-- slow
update test set name = 'x' where id in (select x from system_range(1, 10000) where cast(x as varchar) like '1%');
drop table test;
----
A file is sent although the Japanese translation has not been completed yet.
......@@ -484,6 +498,7 @@ write tests using the PostgreSQL JDBC driver
new TestExit().runTest(this);
new TestFile().runTest(this);
new TestFileLock().runTest(this);
new TestFileSystem().runTest(this);
new TestIntArray().runTest(this);
new TestIntIntHashMap().runTest(this);
new TestMultiThreadedKernel().runTest(this);
......@@ -575,7 +590,7 @@ write tests using the PostgreSQL JDBC driver
}
public void beforeTest() throws SQLException {
FileUtils.deleteRecursive("trace.db");
FileSystemDisk.getInstance().deleteRecursive("trace.db");
if (networked) {
TcpServer.logInternalErrors = true;
String[] args = ssl ? new String[] { "-tcpSSL", "true" } : new String[0];
......@@ -590,7 +605,7 @@ write tests using the PostgreSQL JDBC driver
}
public void afterTest() throws SQLException {
FileUtils.deleteRecursive("trace.db");
FileSystemDisk.getInstance().deleteRecursive("trace.db");
if (networked && server != null) {
server.stop();
}
......
......@@ -212,6 +212,10 @@ public class TestPowerOff extends TestBase {
if (config.networked) {
return;
}
if (config.cipher != null) {
// this would take too long (setLength uses individual writes, many thousand operations)
return;
}
deleteDb(dir, dbName);
// ((JdbcConnection)conn).setPowerOffCount(Integer.MAX_VALUE);
......
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.util.Random;
import org.h2.store.fs.FileObject;
import org.h2.store.fs.FileSystem;
import org.h2.store.fs.FileSystemMemory;
import org.h2.test.TestBase;
public class TestFileSystem extends TestBase {
public void test() throws Exception {
testFileSystem(FileSystem.getInstance(FileSystemMemory.MEMORY_PREFIX));
testFileSystem(FileSystem.getInstance(baseDir + "/fs"));
testFileSystem(FileSystem.getInstance(FileSystemMemory.MEMORY_PREFIX_LZF));
}
private void testFileSystem(FileSystem fs) throws Exception {
testTempFile(fs);
testRandomAccess(fs);
}
private void testRandomAccess(FileSystem fs) throws Exception {
String s = fs.createTempFile("temp", "tmp", false, false);
File file = new File(baseDir + "temp");
file.delete();
RandomAccessFile ra = new RandomAccessFile(file, "rw");
fs.delete(s);
FileObject f = fs.openFileObject(s, "rw");
Random random = new Random(1);
for (int i = 0; i < 200; i++) {
int pos = random.nextInt(10000);
switch(random.nextInt(7)) {
case 0: {
pos = (int) Math.min(pos, ra.length());
trace("seek " + pos);
f.seek(pos);
ra.seek(pos);
break;
}
case 1: {
byte[] buffer = new byte[random.nextInt(1000)];
random.nextBytes(buffer);
trace("write " + buffer.length);
f.write(buffer, 0, buffer.length);
ra.write(buffer, 0, buffer.length);
break;
}
case 2: {
f.setLength(pos);
ra.setLength(pos);
if (ra.getFilePointer() > pos) {
f.seek(0);
ra.seek(0);
}
trace("setLength " + pos);
break;
}
case 3: {
int len = random.nextInt(1000);
len = (int) Math.min(len, ra.length() - ra.getFilePointer());
byte[] b1 = new byte[len];
byte[] b2 = new byte[len];
f.readFully(b1, 0, len);
ra.readFully(b2, 0, len);
trace("readFully " + len);
check(b1, b2);
break;
}
case 4: {
trace("getFilePointer");
check(f.getFilePointer(), ra.getFilePointer());
break;
}
case 5: {
trace("length " + ra.length());
check(f.length(), ra.length());
break;
}
case 6: {
trace("reopen");
f.close();
ra.close();
ra = new RandomAccessFile(file, "rw");
f = fs.openFileObject(s, "rw");
check(f.length(), ra.length());
break;
}
}
}
f.close();
ra.close();
}
private void testTempFile(FileSystem fs) throws Exception {
String s = fs.createTempFile("temp", "tmp", false, false);
OutputStream out = fs.openFileOutputStream(s, false);
byte[] buffer = new byte[10000];
out.write(buffer);
out.close();
out = fs.openFileOutputStream(s, true);
out.write(1);
out.close();
InputStream in = fs.openFileInputStream(s);
for (int i = 0; i < 10000; i++) {
check(in.read(), 0);
}
check(in.read(), 1);
check(in.read(), -1);
}
}
......@@ -11,28 +11,55 @@ import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.h2.tools.Server;
import org.h2.util.StringUtils;
public class DbStarter implements ServletContextListener {
private Connection conn;
private Server server;
public void contextInitialized(ServletContextEvent servletContextEvent) {
try {
org.h2.Driver.load();
// You can also get the setting from a context-param in web.xml:
// This will get the setting from a context-param in web.xml if defined:
ServletContext servletContext = servletContextEvent.getServletContext();
// String url = servletContext.getInitParameter("db.url");
conn = DriverManager.getConnection("jdbc:h2:~/test", "sa", "");
String url = getParameter(servletContext, "db.url", "jdbc:h2:~/test");
String user = getParameter(servletContext, "db.user", "sa");
String password = getParameter(servletContext, "db.password", "sa");
conn = DriverManager.getConnection(url, user, password);
servletContext.setAttribute("connection", conn);
// Start the server if configured to do so
String serverParams = getParameter(servletContext, "db.tcpServer", null);
if (serverParams != null) {
String[] params = StringUtils.arraySplit(serverParams, ' ', true);
server = Server.createTcpServer(params);
}
// To access the database using the server, use the URL:
// jdbc:h2:tcp://localhost/~/test
} catch (Exception e) {
e.printStackTrace();
}
}
private String getParameter(ServletContext servletContext, String key, String defaultValue) {
String value = servletContext.getInitParameter(key);
return value == null ? defaultValue : value;
}
public Connection getConnection() {
return conn;
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
if (server != null) {
server.stop();
server = null;
}
try {
conn.close();
} catch (Exception e) {
......
......@@ -511,5 +511,5 @@ lumber thus taking repositories ago delegated mention leaks pgsql seeded felt ef
spfile svr pkey synced semicolon terminating
framework constructing architectural jmatter workgroup upgraded naked stopper skipping assumed
opensource atlassian hhh establish pawel nice italiano ucchino paolo italian pier shorter although
uklinux credential crypt kerberos redferni routine
uklinux credential crypt kerberos redferni routine reopen tmp configured replicating wraps
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论