use of org.h2.value.lob.LobData in project h2database by h2database.
the class LobStorageMap method init.
@Override
public void init() {
if (init) {
return;
}
init = true;
Store s = database.getMvStore();
MVStore mvStore;
if (s == null) {
// in-memory database
mvStore = MVStore.open(null);
} else {
mvStore = s.getStore();
}
lobMap = mvStore.openMap("lobMap");
refMap = mvStore.openMap("lobRef");
dataMap = mvStore.openMap("lobData");
streamStore = new StreamStore(dataMap);
// garbage collection of the last blocks
if (database.isReadOnly()) {
return;
}
if (dataMap.isEmpty()) {
return;
}
// search for the last block
// (in theory, only the latest lob can have unreferenced blocks,
// but the latest lob could be a copy of another one, and
// we don't know that, so we iterate over all lobs)
long lastUsedKey = -1;
for (Entry<Long, Object[]> e : lobMap.entrySet()) {
long lobId = e.getKey();
Object[] v = e.getValue();
byte[] id = (byte[]) v[0];
long max = streamStore.getMaxBlockKey(id);
// a lob may not have a referenced blocks if data is kept inline
if (max != -1 && max > lastUsedKey) {
lastUsedKey = max;
if (TRACE) {
trace("lob " + lobId + " lastUsedKey=" + lastUsedKey);
}
}
}
if (TRACE) {
trace("lastUsedKey=" + lastUsedKey);
}
// delete all blocks that are newer
while (true) {
Long last = dataMap.lastKey();
if (last == null || last <= lastUsedKey) {
break;
}
if (TRACE) {
trace("gc " + last);
}
dataMap.remove(last);
}
// don't re-use block ids, except at the very end
Long last = dataMap.lastKey();
if (last != null) {
streamStore.setNextKey(last + 1);
}
}
use of org.h2.value.lob.LobData in project h2database by h2database.
the class LobStorageMap method createClob.
@Override
public ValueClob createClob(Reader reader, long maxLength) {
MVStore.TxCounter txCounter = mvStore.registerVersionUsage();
try {
// we multiple by 3 here to get the worst-case size in bytes
if (maxLength != -1 && maxLength * 3 <= database.getMaxLengthInplaceLob()) {
char[] small = new char[(int) maxLength];
int len = IOUtils.readFully(reader, small, (int) maxLength);
if (len > maxLength) {
throw new IllegalStateException("len > blobLength, " + len + " > " + maxLength);
}
byte[] utf8 = new String(small, 0, len).getBytes(StandardCharsets.UTF_8);
if (utf8.length > database.getMaxLengthInplaceLob()) {
throw new IllegalStateException("len > maxinplace, " + utf8.length + " > " + database.getMaxLengthInplaceLob());
}
return ValueClob.createSmall(utf8, len);
}
if (maxLength < 0) {
maxLength = Long.MAX_VALUE;
}
CountingReaderInputStream in = new CountingReaderInputStream(reader, maxLength);
ValueBlob blob = createBlob(in);
LobData lobData = blob.getLobData();
return new ValueClob(lobData, blob.octetLength(), in.getLength());
} catch (IllegalStateException e) {
throw DbException.get(ErrorCode.OBJECT_CLOSED, e);
} catch (IOException e) {
throw DbException.convertIOException(e, null);
} finally {
mvStore.deregisterVersionUsage(txCounter);
}
}
use of org.h2.value.lob.LobData in project h2database by h2database.
the class LobStorageMap method copyLob.
@Override
public ValueLob copyLob(ValueLob old, int tableId) {
MVStore.TxCounter txCounter = mvStore.registerVersionUsage();
try {
final LobDataDatabase lobData = (LobDataDatabase) old.getLobData();
final int type = old.getValueType();
final long oldLobId = lobData.getLobId();
long octetLength = old.octetLength();
// get source lob
final byte[] streamStoreId;
if (isTemporaryLob(lobData.getTableId())) {
streamStoreId = tempLobMap.get(oldLobId);
} else {
BlobMeta value = lobMap.get(oldLobId);
streamStoreId = value.streamStoreId;
}
// create destination lob
final long newLobId = generateLobId();
if (isTemporaryLob(tableId)) {
tempLobMap.put(newLobId, streamStoreId);
} else {
BlobMeta value = new BlobMeta(streamStoreId, tableId, type == Value.CLOB ? old.charLength() : octetLength, 0);
lobMap.put(newLobId, value);
}
BlobReference refMapKey = new BlobReference(streamStoreId, newLobId);
refMap.put(refMapKey, ValueNull.INSTANCE);
LobDataDatabase newLobData = new LobDataDatabase(database, tableId, newLobId);
ValueLob lob = type == Value.BLOB ? new ValueBlob(newLobData, octetLength) : new ValueClob(newLobData, octetLength, old.charLength());
if (TRACE) {
trace("copy " + lobData.getTableId() + "/" + lobData.getLobId() + " > " + tableId + "/" + newLobId);
}
return lob;
} finally {
mvStore.deregisterVersionUsage(txCounter);
}
}
use of org.h2.value.lob.LobData in project h2database by h2database.
the class ValueDataType method readLobDataDatabase.
private LobDataDatabase readLobDataDatabase(ByteBuffer buff) {
int tableId = readVarInt(buff);
long lobId = readVarLong(buff);
LobDataDatabase lobData = new LobDataDatabase(handler, tableId, lobId);
return lobData;
}
use of org.h2.value.lob.LobData in project h2database by h2database.
the class ValueClob method copy.
@Override
public ValueLob copy(DataHandler database, int tableId) {
if (lobData instanceof LobDataInMemory) {
byte[] small = ((LobDataInMemory) lobData).getSmall();
if (small.length > database.getMaxLengthInplaceLob()) {
LobStorageInterface s = database.getLobStorage();
ValueClob v = s.createClob(getReader(), charLength);
ValueLob v2 = v.copy(database, tableId);
v.remove();
return v2;
}
return this;
} else if (lobData instanceof LobDataDatabase) {
return database.getLobStorage().copyLob(this, tableId);
} else {
throw new UnsupportedOperationException();
}
}
Aggregations