public class LobStorageBackend extends java.lang.Object implements LobStorageInterface
Using the system session
Why do we use the system session to store the data? Some LOB operations can take a very long time. If we did them on a normal session, we would be locking the LOB tables for long periods of time, which is extremely detrimental to the rest of the system. Perhaps when we shift to the MVStore engine, we can revisit this design decision (using the StreamStore, that is, no connection at all).
Locking
Normally, the locking order in H2 is: first lock the Session object, then lock the Database object. However, in the case of the LOB data, we are using the system session to store the data. If we locked the normal way, we see deadlocks caused by the following pattern:
Thread 1:
locks normal session
locks database
waiting to lock system session
Thread 2:
locks system session
waiting to lock database.
So, in this class alone, we do two things: we have our very own dedicated
session, the LOB session, and we take the locks in this order: first the
Database object, and then the LOB session. Since we own the LOB session,
no-one else can lock on it, and we are safe.| Modifier and Type | Class and Description |
|---|---|
class |
LobStorageBackend.LobInputStream
An input stream that reads from a LOB.
|
| Modifier and Type | Field and Description |
|---|---|
static java.lang.String |
LOB_DATA_TABLE
The name of the lob data table.
|
| Constructor and Description |
|---|
LobStorageBackend(Database database) |
| Modifier and Type | Method and Description |
|---|---|
ValueLobDb |
copyLob(ValueLobDb old,
int tableId,
long length)
Copy a lob.
|
Value |
createBlob(java.io.InputStream in,
long maxLength)
Create a BLOB object.
|
Value |
createClob(java.io.Reader reader,
long maxLength)
Create a CLOB object.
|
java.io.InputStream |
getInputStream(ValueLobDb lob,
byte[] hmac,
long byteCount)
Get the input stream for the given lob.
|
void |
init()
Initialize the lob storage.
|
boolean |
isReadOnly()
Whether the storage is read-only
|
void |
removeAllForTable(int tableId)
Remove all LOBs for this table.
|
void |
removeLob(ValueLobDb lob)
Delete a LOB (from the database, if it is stored there).
|
public static final java.lang.String LOB_DATA_TABLE
public LobStorageBackend(Database database)
public void init()
LobStorageInterfaceinit in interface LobStorageInterfacepublic void removeAllForTable(int tableId)
LobStorageInterfaceremoveAllForTable in interface LobStorageInterfacetableId - the table idpublic void removeLob(ValueLobDb lob)
LobStorageInterfaceremoveLob in interface LobStorageInterfacelob - the lobpublic java.io.InputStream getInputStream(ValueLobDb lob, byte[] hmac, long byteCount) throws java.io.IOException
LobStorageInterfacegetInputStream in interface LobStorageInterfacelob - the lob idhmac - the message authentication code (for remote input streams)byteCount - the number of bytes to read, or -1 if not knownjava.io.IOExceptionpublic boolean isReadOnly()
LobStorageInterfaceisReadOnly in interface LobStorageInterfacepublic ValueLobDb copyLob(ValueLobDb old, int tableId, long length)
LobStorageInterfacecopyLob in interface LobStorageInterfaceold - the old lobtableId - the new table idlength - the lengthpublic Value createBlob(java.io.InputStream in, long maxLength)
LobStorageInterfacecreateBlob in interface LobStorageInterfacein - the input streammaxLength - the maximum length (-1 if not known)public Value createClob(java.io.Reader reader, long maxLength)
LobStorageInterfacecreateClob in interface LobStorageInterfacereader - the readermaxLength - the maximum length (-1 if not known)