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

--no commit message

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