LobStorageBackend
This class stores LOB objects in the database, in tables. This is the
back-end i.e. the server side of the LOB storage.
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.
| Methods |
| static void |
assertHoldsLock(Object lock)
Check whether this thread has synchronized on this object.
|
| static void |
assertHoldsLock(Object lock)
Check whether this thread has synchronized on this object.
Parameters:
lock - the object
|
| ValueLobDb |
copyLob(ValueLobDb old, int tableId, long length)
|
| ValueLobDb |
copyLob(ValueLobDb old, int tableId, long length)
|
| Value |
createBlob(InputStream in, long maxLength)
|
| Value |
createBlob(InputStream in, long maxLength)
|
| Value |
createClob(Reader reader, long maxLength)
|
| Value |
createClob(Reader reader, long maxLength)
|
| InputStream |
getInputStream(ValueLobDb lob, byte[] hmac, long byteCount)
|
| InputStream |
getInputStream(ValueLobDb lob, byte[] hmac, long byteCount) throws IOException
|
| void |
init()
|
| void |
init()
|
| boolean |
isReadOnly()
|
| boolean |
isReadOnly()
|
| PreparedStatement |
prepare(String sql)
Create a prepared statement, or re-use an existing one.
|
| PreparedStatement |
prepare(String sql) throws SQLException
Create a prepared statement, or re-use an existing one.
Parameters:
sql - the SQL statement
Returns:
the prepared statement
|
| byte[] |
readBlock(long block)
Read a block of data from the given LOB.
|
| byte[] |
readBlock(long block) throws SQLException
Read a block of data from the given LOB.
Parameters:
block - the block number
Returns:
the block (expanded if stored compressed)
|
| void |
removeAllForTable(int tableId)
|
| void |
removeAllForTable(int tableId)
|
| void |
removeLob(ValueLobDb lob)
|
| void |
removeLob(ValueLobDb lob)
|
| void |
reuse(String sql, PreparedStatement prep)
Allow to re-use the prepared statement.
|
| void |
reuse(String sql, PreparedStatement prep)
Allow to re-use the prepared statement.
Parameters:
sql - the SQL statement
prep - the prepared statement
|
| void |
storeBlock(long lobId, int seq, long pos, byte[] b, String compressAlgorithm)
Store a block in the LOB storage.
|
| void |
storeBlock(long lobId, int seq, long pos, byte[] b, String compressAlgorithm) throws SQLException
Store a block in the LOB storage.
Parameters:
lobId - the lob id
seq - the sequence number
pos - the position within the lob
b - the data
compressAlgorithm - the compression algorithm (may be null)
|
|