use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class Session method rollbackTo.
/**
* Partially roll back the current transaction.
*
* @param savepoint the savepoint to which should be rolled back
* @param trimToSize if the list should be trimmed
*/
public void rollbackTo(Savepoint savepoint, boolean trimToSize) {
int index = savepoint == null ? 0 : savepoint.logIndex;
while (undoLog.size() > index) {
UndoLogRecord entry = undoLog.getLast();
entry.undo(this);
undoLog.removeLast(trimToSize);
}
if (transaction != null) {
long savepointId = savepoint == null ? 0 : savepoint.transactionSavepoint;
HashMap<String, MVTable> tableMap = database.getMvStore().getTables();
Iterator<Change> it = transaction.getChanges(savepointId);
while (it.hasNext()) {
Change c = it.next();
MVTable t = tableMap.get(c.mapName);
if (t != null) {
long key = ((ValueLong) c.key).getLong();
ValueArray value = (ValueArray) c.value;
short op;
Row row;
if (value == null) {
op = UndoLogRecord.INSERT;
row = t.getRow(this, key);
} else {
op = UndoLogRecord.DELETE;
row = createRow(value.getList(), Row.MEMORY_CALCULATE);
}
row.setKey(key);
UndoLogRecord log = new UndoLogRecord(t, op, row);
log.undo(this);
}
}
}
if (savepoints != null) {
String[] names = savepoints.keySet().toArray(new String[savepoints.size()]);
for (String name : names) {
Savepoint sp = savepoints.get(name);
int savepointIndex = sp.logIndex;
if (savepointIndex > index) {
savepoints.remove(name);
}
}
}
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class PageBtreeNode method remove.
@Override
SearchRow remove(SearchRow row) {
int at = find(row, false, false, true);
// merge is not implemented to allow concurrent usage
// TODO maybe implement merge
PageBtree page = index.getPage(childPageIds[at]);
SearchRow last = page.remove(row);
index.getPageStore().logUndo(this, data);
updateRowCount(-1);
written = false;
changeCount = index.getPageStore().getChangeCount();
if (last == null) {
// the last row didn't change - nothing to do
return null;
} else if (last == row) {
// this child is now empty
index.getPageStore().free(page.getPos());
if (entryCount < 1) {
// no more children - this page is empty as well
return row;
}
if (at == entryCount) {
// removing the last child
last = getRow(at - 1);
} else {
last = null;
}
removeChild(at);
index.getPageStore().update(this);
return last;
}
// the last row is in the last child
if (at == entryCount) {
return last;
}
int child = childPageIds[at];
removeChild(at);
// TODO this can mean only the position is now stored
// should split at the next possible moment
addChild(at, child, last);
// remove and add swapped two children, fix that
int temp = childPageIds[at];
childPageIds[at] = childPageIds[at + 1];
childPageIds[at + 1] = temp;
index.getPageStore().update(this);
return null;
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class MVSecondaryIndex method addBufferedRows.
@Override
public void addBufferedRows(List<String> bufferNames) {
ArrayList<String> mapNames = new ArrayList<>(bufferNames);
CompareMode compareMode = database.getCompareMode();
int buffersCount = bufferNames.size();
Queue<Source> queue = new PriorityQueue<>(buffersCount, new Source.Comparator(compareMode));
for (String bufferName : bufferNames) {
Iterator<ValueArray> iter = openMap(bufferName).keyIterator(null);
if (iter.hasNext()) {
queue.add(new Source(iter));
}
}
try {
while (!queue.isEmpty()) {
Source s = queue.remove();
ValueArray rowData = s.next();
if (indexType.isUnique()) {
Value[] array = rowData.getList();
// don't change the original value
array = array.clone();
array[keyColumns - 1] = ValueLong.MIN;
ValueArray unique = ValueArray.get(array);
SearchRow row = convertToSearchRow(rowData);
if (!mayHaveNullDuplicates(row)) {
requireUnique(row, dataMap, unique);
}
}
dataMap.putCommitted(rowData, ValueNull.INSTANCE);
if (s.hasNext()) {
queue.offer(s);
}
}
} finally {
for (String tempMapName : mapNames) {
MVMap<ValueArray, Value> map = openMap(tempMapName);
map.getStore().removeMap(map);
}
}
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class MVTable method rebuildIndexBlockMerge.
private void rebuildIndexBlockMerge(Session session, MVIndex index) {
if (index instanceof MVSpatialIndex) {
// the spatial index doesn't support multi-way merge sort
rebuildIndexBuffered(session, index);
}
// Read entries in memory, sort them, write to a new map (in sorted
// order); repeat (using a new map for every block of 1 MB) until all
// record are read. Merge all maps to the target (using merge sort;
// duplicates are detected in the target). For randomly ordered data,
// this should use relatively few write operations.
// A possible optimization is: change the buffer size from "row count"
// to "amount of memory", and buffer index keys instead of rows.
Index scan = getScanIndex(session);
long remaining = scan.getRowCount(session);
long total = remaining;
Cursor cursor = scan.find(session, null, null);
long i = 0;
Store store = session.getDatabase().getMvStore();
int bufferSize = database.getMaxMemoryRows() / 2;
ArrayList<Row> buffer = new ArrayList<>(bufferSize);
String n = getName() + ":" + index.getName();
int t = MathUtils.convertLongToInt(total);
ArrayList<String> bufferNames = New.arrayList();
while (cursor.next()) {
Row row = cursor.get();
buffer.add(row);
database.setProgress(DatabaseEventListener.STATE_CREATE_INDEX, n, MathUtils.convertLongToInt(i++), t);
if (buffer.size() >= bufferSize) {
sortRows(buffer, index);
String mapName = store.nextTemporaryMapName();
index.addRowsToBuffer(buffer, mapName);
bufferNames.add(mapName);
buffer.clear();
}
remaining--;
}
sortRows(buffer, index);
if (!bufferNames.isEmpty()) {
String mapName = store.nextTemporaryMapName();
index.addRowsToBuffer(buffer, mapName);
bufferNames.add(mapName);
buffer.clear();
index.addBufferedRows(bufferNames);
} else {
addRowsToIndex(session, buffer, index);
}
if (SysProperties.CHECK && remaining != 0) {
DbException.throwInternalError("rowcount remaining=" + remaining + " " + getName());
}
}
use of org.h2.mvstore.db.TransactionStore.Change in project h2database by h2database.
the class CipherFactory method setKeystore.
private static void setKeystore() throws IOException {
Properties p = System.getProperties();
if (p.getProperty(KEYSTORE_KEY) == null) {
String fileName = KEYSTORE;
byte[] data = getKeyStoreBytes(getKeyStore(KEYSTORE_PASSWORD), KEYSTORE_PASSWORD);
boolean needWrite = true;
if (FileUtils.exists(fileName) && FileUtils.size(fileName) == data.length) {
// don't need to overwrite the file if it did not change
InputStream fin = FileUtils.newInputStream(fileName);
byte[] now = IOUtils.readBytesAndClose(fin, 0);
if (now != null && Arrays.equals(data, now)) {
needWrite = false;
}
}
if (needWrite) {
try {
OutputStream out = FileUtils.newOutputStream(fileName, false);
out.write(data);
out.close();
} catch (Exception e) {
throw DbException.convertToIOException(e);
}
}
String absolutePath = FileUtils.toRealPath(fileName);
System.setProperty(KEYSTORE_KEY, absolutePath);
}
if (p.getProperty(KEYSTORE_PASSWORD_KEY) == null) {
System.setProperty(KEYSTORE_PASSWORD_KEY, KEYSTORE_PASSWORD);
}
}
Aggregations