提交 8fd3db60 authored 作者: noelgrandin's avatar noelgrandin

Split the LobStorage class into client-side and server-side code.

This is a cleanup targetted at allowing us to fix a deadlock issue.
上级 9ed50ccb
...@@ -25,7 +25,7 @@ import org.h2.store.DataHandler; ...@@ -25,7 +25,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.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.tools.CompressTool; import org.h2.tools.CompressTool;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
...@@ -232,7 +232,7 @@ abstract class ScriptBase extends Prepared implements DataHandler { ...@@ -232,7 +232,7 @@ abstract class ScriptBase extends Prepared implements DataHandler {
return null; return null;
} }
public LobStorage getLobStorage() { public LobStorageBackend getLobStorage() {
return null; return null;
} }
......
...@@ -40,7 +40,7 @@ import org.h2.store.DataHandler; ...@@ -40,7 +40,7 @@ import org.h2.store.DataHandler;
import org.h2.store.FileLock; import org.h2.store.FileLock;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.InDoubtTransaction; import org.h2.store.InDoubtTransaction;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.PageStore; import org.h2.store.PageStore;
import org.h2.store.WriterThread; import org.h2.store.WriterThread;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
...@@ -167,7 +167,7 @@ public class Database implements DataHandler { ...@@ -167,7 +167,7 @@ public class Database implements DataHandler {
private SourceCompiler compiler; private SourceCompiler compiler;
private volatile boolean metaTablesInitialized; private volatile boolean metaTablesInitialized;
private boolean flushOnEachCommit; private boolean flushOnEachCommit;
private LobStorage lobStorage; private LobStorageBackend lobStorage;
private final int pageSize; private final int pageSize;
private int defaultTableType = Table.TYPE_CACHED; private int defaultTableType = Table.TYPE_CACHED;
private final DbSettings dbSettings; private final DbSettings dbSettings;
...@@ -1102,11 +1102,11 @@ public class Database implements DataHandler { ...@@ -1102,11 +1102,11 @@ public class Database implements DataHandler {
} }
// remove all session variables // remove all session variables
if (persistent) { if (persistent) {
boolean lobStorageIsUsed = infoSchema.findTableOrView(systemSession, LobStorage.LOB_DATA_TABLE) != null; boolean lobStorageIsUsed = infoSchema.findTableOrView(systemSession, LobStorageBackend.LOB_DATA_TABLE) != null;
if (lobStorageIsUsed) { if (lobStorageIsUsed) {
try { try {
getLobStorage(); getLobStorage();
lobStorage.removeAllForTable(LobStorage.TABLE_ID_SESSION_VARIABLE); lobStorage.removeAllForTable(LobStorageBackend.TABLE_ID_SESSION_VARIABLE);
} catch (DbException e) { } catch (DbException e) {
trace.error(e, "close"); trace.error(e, "close");
} }
...@@ -2314,9 +2314,9 @@ public class Database implements DataHandler { ...@@ -2314,9 +2314,9 @@ public class Database implements DataHandler {
return compiler; return compiler;
} }
public LobStorage getLobStorage() { public LobStorageBackend getLobStorage() {
if (lobStorage == null) { if (lobStorage == null) {
lobStorage = new LobStorage(this); lobStorage = new LobStorageBackend(this);
} }
return lobStorage; return lobStorage;
} }
......
...@@ -30,7 +30,7 @@ import org.h2.result.Row; ...@@ -30,7 +30,7 @@ import org.h2.result.Row;
import org.h2.schema.Schema; import org.h2.schema.Schema;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.InDoubtTransaction; import org.h2.store.InDoubtTransaction;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.table.Table; import org.h2.table.Table;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -145,7 +145,7 @@ public class Session extends SessionWithState { ...@@ -145,7 +145,7 @@ public class Session extends SessionWithState {
old = variables.remove(name); old = variables.remove(name);
} else { } else {
// link LOB values, to make sure we have our own object // link LOB values, to make sure we have our own object
value = value.link(database, LobStorage.TABLE_ID_SESSION_VARIABLE); value = value.link(database, LobStorageBackend.TABLE_ID_SESSION_VARIABLE);
old = variables.put(name, value); old = variables.put(name, value);
} }
if (old != null) { if (old != null) {
...@@ -967,6 +967,10 @@ public class Session extends SessionWithState { ...@@ -967,6 +967,10 @@ public class Session extends SessionWithState {
return database; return database;
} }
public LobStorageBackend getLobStorageBackend() {
return database.getLobStorage();
}
/** /**
* Remember that the given LOB value must be un-linked (disconnected from * Remember that the given LOB value must be un-linked (disconnected from
* the table) at commit. * the table) at commit.
......
...@@ -22,7 +22,8 @@ import org.h2.message.Trace; ...@@ -22,7 +22,8 @@ import org.h2.message.Trace;
import org.h2.message.TraceSystem; import org.h2.message.TraceSystem;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage; import org.h2.store.LobStorageFrontend;
import org.h2.store.LobStorageInterface;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.NetUtils; import org.h2.util.NetUtils;
...@@ -82,7 +83,7 @@ public class SessionRemote extends SessionWithState implements DataHandler { ...@@ -82,7 +83,7 @@ public class SessionRemote extends SessionWithState implements DataHandler {
private int lastReconnect; private int lastReconnect;
private SessionInterface embedded; private SessionInterface embedded;
private DatabaseEventListener eventListener; private DatabaseEventListener eventListener;
private LobStorage lobStorage; private LobStorageFrontend lobStorage;
private boolean cluster; private boolean cluster;
public SessionRemote(ConnectionInfo ci) { public SessionRemote(ConnectionInfo ci) {
...@@ -681,9 +682,9 @@ public class SessionRemote extends SessionWithState implements DataHandler { ...@@ -681,9 +682,9 @@ public class SessionRemote extends SessionWithState implements DataHandler {
// nothing to do // nothing to do
} }
public LobStorage getLobStorage() { public LobStorageInterface getLobStorage() {
if (lobStorage == null) { if (lobStorage == null) {
lobStorage = new LobStorage(this); lobStorage = new LobStorageFrontend(this);
} }
return lobStorage; return lobStorage;
} }
......
...@@ -23,7 +23,8 @@ import org.h2.mvstore.type.DataType; ...@@ -23,7 +23,8 @@ import org.h2.mvstore.type.DataType;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageInterface;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
...@@ -592,12 +593,12 @@ public class ValueDataType implements DataType { ...@@ -592,12 +593,12 @@ public class ValueDataType implements DataType {
if (smallLen >= 0) { if (smallLen >= 0) {
byte[] small = DataUtils.newBytes(smallLen); byte[] small = DataUtils.newBytes(smallLen);
buff.get(small, 0, smallLen); buff.get(small, 0, smallLen);
return LobStorage.createSmallLob(type, small); return LobStorageBackend.createSmallLob(type, small);
} else if (smallLen == -3) { } else if (smallLen == -3) {
int tableId = readVarInt(buff); int tableId = readVarInt(buff);
long lobId = readVarLong(buff); long lobId = readVarLong(buff);
long precision = readVarLong(buff); long precision = readVarLong(buff);
LobStorage lobStorage = handler.getLobStorage(); LobStorageInterface lobStorage = handler.getLobStorage();
ValueLobDb lob = ValueLobDb.create(type, lobStorage, tableId, lobId, null, precision); ValueLobDb lob = ValueLobDb.create(type, lobStorage, tableId, lobId, null, precision);
return lob; return lob;
} else { } else {
......
...@@ -30,7 +30,7 @@ import org.h2.jdbc.JdbcSQLException; ...@@ -30,7 +30,7 @@ import org.h2.jdbc.JdbcSQLException;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.result.ResultColumn; import org.h2.result.ResultColumn;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.store.LobStorage; import org.h2.store.LobStorageInterface;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
import org.h2.util.SmallMap; import org.h2.util.SmallMap;
...@@ -427,7 +427,7 @@ public class TcpServerThread implements Runnable { ...@@ -427,7 +427,7 @@ public class TcpServerThread implements Runnable {
} }
long offset = transfer.readLong(); long offset = transfer.readLong();
if (in.getPos() != offset) { if (in.getPos() != offset) {
LobStorage lobStorage = session.getDataHandler().getLobStorage(); LobStorageInterface lobStorage = session.getDataHandler().getLobStorage();
InputStream lobIn = lobStorage.getInputStream(lobId, hmac, -1); InputStream lobIn = lobStorage.getInputStream(lobId, hmac, -1);
in = new CachedInputStream(lobIn); in = new CachedInputStream(lobIn);
lobs.put(lobId, in); lobs.put(lobId, in);
......
...@@ -787,12 +787,12 @@ public class Data { ...@@ -787,12 +787,12 @@ public class Data {
if (smallLen >= 0) { if (smallLen >= 0) {
byte[] small = DataUtils.newBytes(smallLen); byte[] small = DataUtils.newBytes(smallLen);
read(small, 0, smallLen); read(small, 0, smallLen);
return LobStorage.createSmallLob(type, small); return LobStorageBackend.createSmallLob(type, small);
} else if (smallLen == -3) { } else if (smallLen == -3) {
int tableId = readVarInt(); int tableId = readVarInt();
long lobId = readVarLong(); long lobId = readVarLong();
long precision = readVarLong(); long precision = readVarLong();
LobStorage lobStorage = handler.getLobStorage(); LobStorageInterface lobStorage = handler.getLobStorage();
ValueLobDb lob = ValueLobDb.create(type, lobStorage, tableId, lobId, null, precision); ValueLobDb lob = ValueLobDb.create(type, lobStorage, tableId, lobId, null, precision);
return lob; return lob;
} else { } else {
......
...@@ -90,7 +90,7 @@ public interface DataHandler { ...@@ -90,7 +90,7 @@ public interface DataHandler {
* *
* @return the lob storage mechanism * @return the lob storage mechanism
*/ */
LobStorage getLobStorage(); LobStorageInterface getLobStorage();
/** /**
* Get a database connection to be used for LOB access. * Get a database connection to be used for LOB access.
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
*/ */
package org.h2.store; package org.h2.store;
import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
...@@ -18,7 +17,6 @@ import java.sql.Statement; ...@@ -18,7 +17,6 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import org.h2.constant.ErrorCode; import org.h2.constant.ErrorCode;
import org.h2.constant.SysProperties; import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
...@@ -34,8 +32,9 @@ import org.h2.value.ValueLobDb; ...@@ -34,8 +32,9 @@ import org.h2.value.ValueLobDb;
/** /**
* This class stores LOB objects in the database. * This class stores LOB objects in the database.
* This is the back-end i.e. the server side of the LOB storage.
*/ */
public class LobStorage { public class LobStorageBackend implements LobStorageInterface {
/** /**
* The table id for session variables (LOBs not assigned to a table). * The table id for session variables (LOBs not assigned to a table).
...@@ -75,7 +74,7 @@ public class LobStorage { ...@@ -75,7 +74,7 @@ public class LobStorage {
private final DataHandler handler; private final DataHandler handler;
private boolean init; private boolean init;
public LobStorage(DataHandler handler) { public LobStorageBackend(DataHandler handler) {
this.handler = handler; this.handler = handler;
} }
...@@ -89,9 +88,6 @@ public class LobStorage { ...@@ -89,9 +88,6 @@ public class LobStorage {
synchronized (handler) { synchronized (handler) {
conn = handler.getLobConnection(); conn = handler.getLobConnection();
init = true; init = true;
if (conn == null) {
return;
}
try { try {
Statement stat = conn.createStatement(); Statement stat = conn.createStatement();
// stat.execute("SET UNDO_LOG 0"); // stat.execute("SET UNDO_LOG 0");
...@@ -266,75 +262,6 @@ public class LobStorage { ...@@ -266,75 +262,6 @@ public class LobStorage {
} }
} }
/**
* An input stream that reads from a remote LOB.
*/
public static class RemoteInputStream extends InputStream {
/**
* The data handler.
*/
private final DataHandler handler;
/**
* The lob id.
*/
private final long lob;
private final byte[] hmac;
/**
* The position.
*/
private long pos;
/**
* The remaining bytes in the lob.
*/
private long remainingBytes;
public RemoteInputStream(DataHandler handler, long lob, byte[] hmac, long byteCount) {
this.handler = handler;
this.lob = lob;
this.hmac = hmac;
remainingBytes = byteCount;
}
public int read() throws IOException {
byte[] buff = new byte[1];
int len = read(buff, 0, 1);
return len < 0 ? len : (buff[0] & 255);
}
public int read(byte[] buff) throws IOException {
return read(buff, 0, buff.length);
}
public int read(byte[] buff, int off, int length) throws IOException {
if (length == 0) {
return 0;
}
length = (int) Math.min(length, remainingBytes);
if (length == 0) {
return -1;
}
length = handler.readLob(lob, hmac, pos, buff, off, length);
remainingBytes -= length;
if (length == 0) {
return -1;
}
pos += length;
return length;
}
public long skip(long n) {
remainingBytes -= n;
pos += n;
return n;
}
}
/** /**
* An input stream that reads from a LOB. * An input stream that reads from a LOB.
*/ */
...@@ -499,9 +426,6 @@ public class LobStorage { ...@@ -499,9 +426,6 @@ public class LobStorage {
public void removeLob(long lob) { public void removeLob(long lob) {
try { try {
synchronized (handler) { synchronized (handler) {
if (conn == null) {
return;
}
String sql = "SELECT BLOCK, HASH FROM " + LOB_MAP + " D WHERE D.LOB = ? " + String sql = "SELECT BLOCK, HASH FROM " + LOB_MAP + " D WHERE D.LOB = ? " +
"AND NOT EXISTS(SELECT 1 FROM " + LOB_MAP + " O " + "AND NOT EXISTS(SELECT 1 FROM " + LOB_MAP + " O " +
"WHERE O.BLOCK = D.BLOCK AND O.LOB <> ?)"; "WHERE O.BLOCK = D.BLOCK AND O.LOB <> ?)";
...@@ -552,12 +476,6 @@ public class LobStorage { ...@@ -552,12 +476,6 @@ public class LobStorage {
*/ */
public InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException { public InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException {
init(); init();
if (conn == null) {
if (byteCount < 0) {
byteCount = Long.MAX_VALUE;
}
return new BufferedInputStream(new RemoteInputStream(handler, lobId, hmac, byteCount));
}
if (byteCount == -1) { if (byteCount == -1) {
synchronized (handler) { synchronized (handler) {
try { try {
...@@ -861,13 +779,6 @@ public class LobStorage { ...@@ -861,13 +779,6 @@ public class LobStorage {
public Value createBlob(InputStream in, long maxLength) { public Value createBlob(InputStream in, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) { if (SysProperties.LOB_IN_DATABASE) {
init(); init();
if (conn == null) {
// remote connections:
// need to use a temp file, because the input stream could come from
// the same database, which would create a weird situation (trying
// to read a block while write something)
return ValueLobDb.createTempBlob(in, maxLength, handler);
}
return addLob(in, maxLength, Value.BLOB); return addLob(in, maxLength, Value.BLOB);
} }
return ValueLob.createBlob(in, maxLength, handler); return ValueLob.createBlob(in, maxLength, handler);
...@@ -883,13 +794,6 @@ public class LobStorage { ...@@ -883,13 +794,6 @@ public class LobStorage {
public Value createClob(Reader reader, long maxLength) { public Value createClob(Reader reader, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) { if (SysProperties.LOB_IN_DATABASE) {
init(); init();
if (conn == null) {
// remote connections:
// need to use a temp file, because the input stream could come from
// the same database, which would create a weird situation (trying
// to read a block while write something)
return ValueLobDb.createTempClob(reader, maxLength, handler);
}
long max = maxLength == -1 ? Long.MAX_VALUE : maxLength; long max = maxLength == -1 ? Long.MAX_VALUE : maxLength;
CountingReaderInputStream in = new CountingReaderInputStream(reader, max); CountingReaderInputStream in = new CountingReaderInputStream(reader, max);
ValueLobDb lob = addLob(in, Long.MAX_VALUE, Value.CLOB); ValueLobDb lob = addLob(in, Long.MAX_VALUE, Value.CLOB);
......
/*
* Copyright 2004-2013 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.store;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import org.h2.constant.SysProperties;
import org.h2.engine.Constants;
import org.h2.value.Value;
import org.h2.value.ValueLob;
import org.h2.value.ValueLobDb;
/**
* This class stores LOB objects in the database.
* This is the front-end i.e. the client side of the LOB storage.
*/
public class LobStorageFrontend implements LobStorageInterface {
private final DataHandler handler;
public LobStorageFrontend(DataHandler handler) {
this.handler = handler;
}
/**
* Create a LOB object that fits in memory.
*
* @param type the value type
* @param small the byte array
* @return the LOB
*/
public static Value createSmallLob(int type, byte[] small) {
if (SysProperties.LOB_IN_DATABASE) {
int precision;
if (type == Value.CLOB) {
precision = new String(small, Constants.UTF8).length();
} else {
precision = small.length;
}
return ValueLobDb.createSmallLob(type, small, precision);
}
return ValueLob.createSmallLob(type, small);
}
/**
* Delete a LOB from the database.
*
* @param lob the lob id
*/
public void removeLob(long lob) {
// TODO ideally, this should not be called at all, but that's a refactoring for another day
}
/**
* Get the input stream for the given lob.
*
* @param lobId the lob id
* @param hmac the message authentication code (for remote input streams)
* @param byteCount the number of bytes to read, or -1 if not known
* @return the stream
*/
public InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException {
if (byteCount < 0) {
byteCount = Long.MAX_VALUE;
}
return new BufferedInputStream(new LobStorageRemoteInputStream(handler, lobId, hmac, byteCount));
}
/**
* Copy a lob.
*
* @param type the type
* @param oldLobId the old lob id
* @param tableId the new table id
* @param length the length
* @return the new lob
*/
public ValueLobDb copyLob(int type, long oldLobId, int tableId, long length) {
// TODO ideally, this should not be called at all, but that's a refactoring for another day
// this should never be called
throw new UnsupportedOperationException();
}
/**
* Create a BLOB object.
*
* @param in the input stream
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
public Value createBlob(InputStream in, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) {
// need to use a temp file, because the input stream could come from
// the same database, which would create a weird situation (trying
// to read a block while write something)
return ValueLobDb.createTempBlob(in, maxLength, handler);
}
return ValueLob.createBlob(in, maxLength, handler);
}
/**
* Create a CLOB object.
*
* @param reader the reader
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
public Value createClob(Reader reader, long maxLength) {
if (SysProperties.LOB_IN_DATABASE) {
// need to use a temp file, because the input stream could come from
// the same database, which would create a weird situation (trying
// to read a block while write something)
return ValueLobDb.createTempClob(reader, maxLength, handler);
}
return ValueLob.createClob(reader, maxLength, handler);
}
/**
* Set the table reference of this lob.
*
* @param lobId the lob
* @param table the table
*/
public void setTable(long lobId, int table) {
// TODO ideally, this should not be called at all, but that's a refactoring for another day
// this should never be called
throw new UnsupportedOperationException();
}
}
package org.h2.store;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import org.h2.value.Value;
import org.h2.value.ValueLobDb;
public interface LobStorageInterface {
/**
* Create a CLOB object.
*
* @param reader the reader
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
Value createClob(Reader reader, long maxLength);
/**
* Create a BLOB object.
*
* @param in the input stream
* @param maxLength the maximum length (-1 if not known)
* @return the LOB
*/
Value createBlob(InputStream in, long maxLength);
/**
* Set the table reference of this lob.
*
* @param lobId the lob
* @param table the table
*/
void setTable(long lobId, int table);
/**
* Copy a lob.
*
* @param type the type
* @param oldLobId the old lob id
* @param tableId the new table id
* @param length the length
* @return the new lob
*/
ValueLobDb copyLob(int type, long oldLobId, int tableId, long length);
/**
* Get the input stream for the given lob.
*
* @param lobId the lob id
* @param hmac the message authentication code (for remote input streams)
* @param byteCount the number of bytes to read, or -1 if not known
* @return the stream
*/
InputStream getInputStream(long lobId, byte[] hmac, long byteCount) throws IOException;
/**
* Delete a LOB from the database.
*
* @param lob the lob id
*/
void removeLob(long lob);
}
package org.h2.store;
import java.io.IOException;
import java.io.InputStream;
/**
* An input stream that reads from a remote LOB.
*/
class LobStorageRemoteInputStream extends InputStream {
/**
* The data handler.
*/
private final DataHandler handler;
/**
* The lob id.
*/
private final long lob;
private final byte[] hmac;
/**
* The position.
*/
private long pos;
/**
* The remaining bytes in the lob.
*/
private long remainingBytes;
public LobStorageRemoteInputStream(DataHandler handler, long lob, byte[] hmac, long byteCount) {
this.handler = handler;
this.lob = lob;
this.hmac = hmac;
remainingBytes = byteCount;
}
public int read() throws IOException {
byte[] buff = new byte[1];
int len = read(buff, 0, 1);
return len < 0 ? len : (buff[0] & 255);
}
public int read(byte[] buff) throws IOException {
return read(buff, 0, buff.length);
}
public int read(byte[] buff, int off, int length) throws IOException {
if (length == 0) {
return 0;
}
length = (int) Math.min(length, remainingBytes);
if (length == 0) {
return -1;
}
length = handler.readLob(lob, hmac, pos, buff, off, length);
remainingBytes -= length;
if (length == 0) {
return -1;
}
pos += length;
return length;
}
public long skip(long n) {
remainingBytes -= n;
pos += n;
return n;
}
}
\ No newline at end of file
...@@ -38,7 +38,8 @@ import org.h2.store.DataReader; ...@@ -38,7 +38,8 @@ import org.h2.store.DataReader;
import org.h2.store.FileLister; import org.h2.store.FileLister;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.FileStoreInputStream; import org.h2.store.FileStoreInputStream;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageInterface;
import org.h2.store.Page; import org.h2.store.Page;
import org.h2.store.PageFreeList; import org.h2.store.PageFreeList;
import org.h2.store.PageLog; import org.h2.store.PageLog;
...@@ -192,8 +193,8 @@ public class Recover extends Tool implements DataHandler { ...@@ -192,8 +193,8 @@ public class Recover extends Tool implements DataHandler {
*/ */
public static Value.ValueBlob readBlobDb(Connection conn, long lobId, long precision) { public static Value.ValueBlob readBlobDb(Connection conn, long lobId, long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
LobStorage lobStorage = h.getLobStorage(); LobStorageInterface lobStorage = h.getLobStorage();
return ValueLobDb.create(Value.BLOB, lobStorage, LobStorage.TABLE_TEMP, lobId, null, precision); return ValueLobDb.create(Value.BLOB, lobStorage, LobStorageBackend.TABLE_TEMP, lobId, null, precision);
} }
/** /**
...@@ -201,8 +202,8 @@ public class Recover extends Tool implements DataHandler { ...@@ -201,8 +202,8 @@ public class Recover extends Tool implements DataHandler {
*/ */
public static Value.ValueClob readClobDb(Connection conn, long lobId, long precision) { public static Value.ValueClob readClobDb(Connection conn, long lobId, long precision) {
DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler(); DataHandler h = ((JdbcConnection) conn).getSession().getDataHandler();
LobStorage lobStorage = h.getLobStorage(); LobStorageInterface lobStorage = h.getLobStorage();
return ValueLobDb.create(Value.CLOB, lobStorage, LobStorage.TABLE_TEMP, lobId, null, precision); return ValueLobDb.create(Value.CLOB, lobStorage, LobStorageBackend.TABLE_TEMP, lobId, null, precision);
} }
private void trace(String message) { private void trace(String message) {
...@@ -1229,7 +1230,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1229,7 +1230,7 @@ public class Recover extends Tool implements DataHandler {
writer.println("DELETE FROM " + name + ";"); writer.println("DELETE FROM " + name + ";");
writer.println("INSERT INTO " + name + " SELECT * FROM " + storageName + ";"); writer.println("INSERT INTO " + name + " SELECT * FROM " + storageName + ";");
if (name.startsWith("INFORMATION_SCHEMA.LOBS")) { if (name.startsWith("INFORMATION_SCHEMA.LOBS")) {
writer.println("UPDATE " + name + " SET TABLE = " + LobStorage.TABLE_TEMP + ";"); writer.println("UPDATE " + name + " SET TABLE = " + LobStorageBackend.TABLE_TEMP + ";");
deleteLobs = true; deleteLobs = true;
} }
} }
...@@ -1255,7 +1256,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1255,7 +1256,7 @@ public class Recover extends Tool implements DataHandler {
writer.println("DROP ALIAS READ_BLOB_DB;"); writer.println("DROP ALIAS READ_BLOB_DB;");
writer.println("DROP ALIAS READ_CLOB_DB;"); writer.println("DROP ALIAS READ_CLOB_DB;");
if (deleteLobs) { if (deleteLobs) {
writer.println("DELETE FROM INFORMATION_SCHEMA.LOBS WHERE TABLE = " + LobStorage.TABLE_TEMP + ";"); writer.println("DELETE FROM INFORMATION_SCHEMA.LOBS WHERE TABLE = " + LobStorageBackend.TABLE_TEMP + ";");
} }
for (MetaRecord m : schema) { for (MetaRecord m : schema) {
if (isSchemaObjectTypeDelayed(m)) { if (isSchemaObjectTypeDelayed(m)) {
...@@ -1409,7 +1410,7 @@ public class Recover extends Tool implements DataHandler { ...@@ -1409,7 +1410,7 @@ public class Recover extends Tool implements DataHandler {
/** /**
* INTERNAL * INTERNAL
*/ */
public LobStorage getLobStorage() { public LobStorageBackend getLobStorage() {
return null; return null;
} }
......
...@@ -31,7 +31,7 @@ import org.h2.jdbc.JdbcBlob; ...@@ -31,7 +31,7 @@ import org.h2.jdbc.JdbcBlob;
import org.h2.jdbc.JdbcClob; import org.h2.jdbc.JdbcClob;
import org.h2.jdbc.JdbcConnection; import org.h2.jdbc.JdbcConnection;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.Utils; import org.h2.util.Utils;
...@@ -540,7 +540,7 @@ public class DataType { ...@@ -540,7 +540,7 @@ public class DataType {
} }
case Value.CLOB: { case Value.CLOB: {
if (session == null) { if (session == null) {
v = LobStorage.createSmallLob(Value.CLOB, rs.getString(columnIndex).getBytes(Constants.UTF8)); v = LobStorageBackend.createSmallLob(Value.CLOB, rs.getString(columnIndex).getBytes(Constants.UTF8));
} else { } else {
Reader in = rs.getCharacterStream(columnIndex); Reader in = rs.getCharacterStream(columnIndex);
if (in == null) { if (in == null) {
...@@ -553,7 +553,7 @@ public class DataType { ...@@ -553,7 +553,7 @@ public class DataType {
} }
case Value.BLOB: { case Value.BLOB: {
if (session == null) { if (session == null) {
v = LobStorage.createSmallLob(Value.BLOB, rs.getBytes(columnIndex)); v = LobStorageBackend.createSmallLob(Value.BLOB, rs.getBytes(columnIndex));
} else { } else {
InputStream in = rs.getBinaryStream(columnIndex); InputStream in = rs.getBinaryStream(columnIndex);
v = (in == null) ? (Value) ValueNull.INSTANCE : session.getDataHandler().getLobStorage().createBlob(in, -1); v = (in == null) ? (Value) ValueNull.INSTANCE : session.getDataHandler().getLobStorage().createBlob(in, -1);
......
...@@ -25,7 +25,7 @@ import org.h2.constant.SysProperties; ...@@ -25,7 +25,7 @@ import org.h2.constant.SysProperties;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -771,7 +771,7 @@ public abstract class Value { ...@@ -771,7 +771,7 @@ public abstract class Value {
switch(getType()) { switch(getType()) {
case BYTES: case BYTES:
return LobStorage.createSmallLob(Value.BLOB, getBytesNoCopy()); return LobStorageBackend.createSmallLob(Value.BLOB, getBytesNoCopy());
} }
break; break;
} }
...@@ -834,9 +834,9 @@ public abstract class Value { ...@@ -834,9 +834,9 @@ public abstract class Value {
case FLOAT: case FLOAT:
return ValueFloat.get(Float.parseFloat(s.trim())); return ValueFloat.get(Float.parseFloat(s.trim()));
case CLOB: case CLOB:
return LobStorage.createSmallLob(CLOB, s.getBytes(Constants.UTF8)); return LobStorageBackend.createSmallLob(CLOB, s.getBytes(Constants.UTF8));
case BLOB: case BLOB:
return LobStorage.createSmallLob(BLOB, StringUtils.convertHexToBytes(s.trim())); return LobStorageBackend.createSmallLob(BLOB, StringUtils.convertHexToBytes(s.trim()));
case ARRAY: case ARRAY:
return ValueArray.get(new Value[]{ValueString.get(s)}); return ValueArray.get(new Value[]{ValueString.get(s)});
case RESULT_SET: { case RESULT_SET: {
......
...@@ -21,7 +21,8 @@ import org.h2.store.DataHandler; ...@@ -21,7 +21,8 @@ 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.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageInterface;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -38,7 +39,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -38,7 +39,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
private int tableId; private int tableId;
private int hash; private int hash;
private LobStorage lobStorage; private LobStorageInterface lobStorage;
private final long lobId; private final long lobId;
private final byte[] hmac; private final byte[] hmac;
...@@ -48,7 +49,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -48,7 +49,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
private FileStore tempFile; private FileStore tempFile;
private String fileName; private String fileName;
private ValueLobDb(int type, LobStorage lobStorage, int tableId, long lobId, byte[] hmac, long precision) { private ValueLobDb(int type, LobStorageInterface lobStorage, int tableId, long lobId, byte[] hmac, long precision) {
this.type = type; this.type = type;
this.lobStorage = lobStorage; this.lobStorage = lobStorage;
this.tableId = tableId; this.tableId = tableId;
...@@ -76,7 +77,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -76,7 +77,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
* @param precision the precision (number of bytes / characters) * @param precision the precision (number of bytes / characters)
* @return the value * @return the value
*/ */
public static ValueLobDb create(int type, LobStorage lobStorage, public static ValueLobDb create(int type, LobStorageInterface lobStorage,
int tableId, long id, byte[] hmac, long precision) { int tableId, long id, byte[] hmac, long precision) {
return new ValueLobDb(type, lobStorage, tableId, id, hmac, precision); return new ValueLobDb(type, lobStorage, tableId, id, hmac, precision);
} }
...@@ -108,21 +109,21 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -108,21 +109,21 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
Value copy = lobStorage.createClob(getReader(), -1); Value copy = lobStorage.createClob(getReader(), -1);
return copy; return copy;
} else if (small != null) { } else if (small != null) {
return LobStorage.createSmallLob(t, small); return LobStorageBackend.createSmallLob(t, small);
} }
} else if (t == Value.BLOB) { } else if (t == Value.BLOB) {
if (lobStorage != null) { if (lobStorage != null) {
Value copy = lobStorage.createBlob(getInputStream(), -1); Value copy = lobStorage.createBlob(getInputStream(), -1);
return copy; return copy;
} else if (small != null) { } else if (small != null) {
return LobStorage.createSmallLob(t, small); return LobStorageBackend.createSmallLob(t, small);
} }
} }
return super.convertTo(t); return super.convertTo(t);
} }
public boolean isLinked() { public boolean isLinked() {
return tableId != LobStorage.TABLE_ID_SESSION_VARIABLE && small == null; return tableId != LobStorageBackend.TABLE_ID_SESSION_VARIABLE && small == null;
} }
public boolean isStored() { public boolean isStored() {
...@@ -147,22 +148,22 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo ...@@ -147,22 +148,22 @@ public class ValueLobDb extends Value implements Value.ValueClob, Value.ValueBlo
} }
public void unlink() { public void unlink() {
if (small == null && tableId != LobStorage.TABLE_ID_SESSION_VARIABLE) { if (small == null && tableId != LobStorageBackend.TABLE_ID_SESSION_VARIABLE) {
lobStorage.setTable(lobId, LobStorage.TABLE_ID_SESSION_VARIABLE); lobStorage.setTable(lobId, LobStorageBackend.TABLE_ID_SESSION_VARIABLE);
tableId = LobStorage.TABLE_ID_SESSION_VARIABLE; tableId = LobStorageBackend.TABLE_ID_SESSION_VARIABLE;
} }
} }
public Value link(DataHandler h, int tabId) { public Value link(DataHandler h, int tabId) {
if (small == null) { if (small == null) {
if (tableId == LobStorage.TABLE_TEMP) { if (tableId == LobStorageBackend.TABLE_TEMP) {
lobStorage.setTable(lobId, tabId); lobStorage.setTable(lobId, tabId);
this.tableId = tabId; this.tableId = tabId;
} else { } else {
return lobStorage.copyLob(type, lobId, tabId, getPrecision()); return lobStorage.copyLob(type, lobId, tabId, getPrecision());
} }
} else if (small.length > h.getMaxLengthInplaceLob()) { } else if (small.length > h.getMaxLengthInplaceLob()) {
LobStorage s = h.getLobStorage(); LobStorageInterface s = h.getLobStorage();
Value v; Value v;
if (type == Value.BLOB) { if (type == Value.BLOB) {
v = s.createBlob(getInputStream(), getPrecision()); v = s.createBlob(getInputStream(), getPrecision());
......
...@@ -15,7 +15,7 @@ import java.sql.Types; ...@@ -15,7 +15,7 @@ import java.sql.Types;
import org.h2.store.Data; import org.h2.store.Data;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -315,7 +315,7 @@ public class TestDataPage extends TestBase implements DataHandler { ...@@ -315,7 +315,7 @@ public class TestDataPage extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() { public LobStorageBackend getLobStorage() {
return null; return null;
} }
......
...@@ -10,7 +10,7 @@ import java.sql.Connection; ...@@ -10,7 +10,7 @@ import java.sql.Connection;
import java.util.Random; import java.util.Random;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -169,7 +169,7 @@ public class TestFile extends TestBase implements DataHandler { ...@@ -169,7 +169,7 @@ public class TestFile extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() { public LobStorageBackend getLobStorage() {
return null; return null;
} }
......
...@@ -14,7 +14,7 @@ import java.util.HashMap; ...@@ -14,7 +14,7 @@ import java.util.HashMap;
import java.util.Random; import java.util.Random;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -145,7 +145,7 @@ public class TestValueHashMap extends TestBase implements DataHandler { ...@@ -145,7 +145,7 @@ public class TestValueHashMap extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() { public LobStorageBackend getLobStorage() {
return null; return null;
} }
......
...@@ -17,7 +17,8 @@ import java.util.Random; ...@@ -17,7 +17,8 @@ import java.util.Random;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.store.FileStore; import org.h2.store.FileStore;
import org.h2.store.LobStorage; import org.h2.store.LobStorageBackend;
import org.h2.store.LobStorageFrontend;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.test.utils.MemoryFootprint; import org.h2.test.utils.MemoryFootprint;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
...@@ -54,7 +55,7 @@ public class TestValueMemory extends TestBase implements DataHandler { ...@@ -54,7 +55,7 @@ public class TestValueMemory extends TestBase implements DataHandler {
private final Random random = new Random(1); private final Random random = new Random(1);
private final SmallLRUCache<String, String[]> lobFileListCache = SmallLRUCache.newInstance(128); private final SmallLRUCache<String, String[]> lobFileListCache = SmallLRUCache.newInstance(128);
private LobStorage lobStorage; private LobStorageFrontend lobStorage;
/** /**
* Run just this test. * Run just this test.
...@@ -246,9 +247,9 @@ public class TestValueMemory extends TestBase implements DataHandler { ...@@ -246,9 +247,9 @@ public class TestValueMemory extends TestBase implements DataHandler {
return TempFileDeleter.getInstance(); return TempFileDeleter.getInstance();
} }
public LobStorage getLobStorage() { public LobStorageFrontend getLobStorage() {
if (lobStorage == null) { if (lobStorage == null) {
lobStorage = new LobStorage(this); lobStorage = new LobStorageFrontend(this);
} }
return lobStorage; return lobStorage;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论