use of herddb.utils.Bytes in project herddb by diennea.
the class TableManager method onTransactionCommit.
@Override
public void onTransactionCommit(Transaction transaction, boolean recovery) throws DataStorageManagerException {
if (transaction == null) {
throw new DataStorageManagerException("transaction cannot be null");
}
boolean forceFlushTableData = false;
if (createdInTransaction > 0) {
if (transaction.transactionId != createdInTransaction) {
throw new DataStorageManagerException("table " + table.tablespace + "." + table.name + " is available only on transaction " + createdInTransaction);
}
createdInTransaction = 0;
forceFlushTableData = true;
}
if (!transaction.lastSequenceNumber.after(bootSequenceNumber)) {
if (recovery) {
LOGGER.log(Level.FINER, "ignoring transaction {0} commit on recovery, {1}.{2} data is newer: transaction {3}, table {4}", new Object[] { transaction.transactionId, table.tablespace, table.name, transaction.lastSequenceNumber, bootSequenceNumber });
return;
} else {
throw new DataStorageManagerException("corrupted commit log " + table.tablespace + "." + table.name + " data is newer than transaction " + transaction.transactionId + " transaction " + transaction.lastSequenceNumber + " table " + bootSequenceNumber);
}
}
boolean lockAcquired;
try {
lockAcquired = checkpointLock.asReadLock().tryLock(CHECKPOINT_LOCK_READ_TIMEOUT, SECONDS);
} catch (InterruptedException err) {
throw new DataStorageManagerException("interrupted while acquiring checkpoint lock during a commit", err);
}
if (!lockAcquired) {
throw new DataStorageManagerException("timed out while acquiring checkpoint lock during a commit");
}
try {
Map<Bytes, Record> changedRecords = transaction.changedRecords.get(table.name);
// transaction is still holding locks on each record, so we can change records
Map<Bytes, Record> newRecords = transaction.newRecords.get(table.name);
if (newRecords != null) {
for (Record record : newRecords.values()) {
applyInsert(record.key, record.value, true);
}
}
if (changedRecords != null) {
for (Record r : changedRecords.values()) {
applyUpdate(r.key, r.value);
}
}
Set<Bytes> deletedRecords = transaction.deletedRecords.get(table.name);
if (deletedRecords != null) {
for (Bytes key : deletedRecords) {
applyDelete(key);
}
}
} finally {
checkpointLock.asReadLock().unlock();
}
transaction.releaseLocksOnTable(table.name, locksManager);
if (forceFlushTableData) {
LOGGER.log(Level.FINE, "forcing local checkpoint, table " + table.name + " will be visible to all transactions now");
checkpoint(false);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class TableManager method rebuildNextPrimaryKeyValue.
private void rebuildNextPrimaryKeyValue() throws DataStorageManagerException {
LOGGER.log(Level.INFO, "rebuildNextPrimaryKeyValue");
try {
Stream<Entry<Bytes, Long>> scanner = keyToPage.scanner(null, StatementEvaluationContext.DEFAULT_EVALUATION_CONTEXT(), tableContext, null);
scanner.forEach((Entry<Bytes, Long> t) -> {
Bytes key = t.getKey();
long pk_logical_value;
if (table.getColumn(table.primaryKey[0]).type == ColumnTypes.INTEGER || table.getColumn(table.primaryKey[0]).type == ColumnTypes.NOTNULL_INTEGER) {
pk_logical_value = key.to_int();
} else {
pk_logical_value = key.to_long();
}
nextPrimaryKeyValue.accumulateAndGet(pk_logical_value + 1, EnsureLongIncrementAccumulator.INSTANCE);
});
LOGGER.log(Level.INFO, "rebuildNextPrimaryKeyValue, newPkValue : " + nextPrimaryKeyValue.get());
} catch (StatementExecutionException impossible) {
throw new DataStorageManagerException(impossible);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class RecordSerializer method deserializeMultiColumnPrimaryKey.
private static void deserializeMultiColumnPrimaryKey(Bytes data, Table table, Map<String, Object> res) {
try (ByteArrayCursor din = data.newCursor()) {
for (String primaryKeyColumn : table.primaryKey) {
Bytes value = din.readBytesNoCopy();
res.put(primaryKeyColumn, deserialize(value, table.getColumn(primaryKeyColumn).type));
}
} catch (IOException err) {
throw new IllegalArgumentException("malformed record", err);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class RecordSerializer method deserializeMultiColumnPrimaryKey.
@SuppressFBWarnings("RV_RETURN_VALUE_IGNORED")
private static void deserializeMultiColumnPrimaryKey(Bytes data, Table table, ImmutableMap.Builder<String, Object> res) {
try (ByteArrayCursor din = data.newCursor()) {
for (String primaryKeyColumn : table.primaryKey) {
Bytes value = din.readBytesNoCopy();
res.put(primaryKeyColumn, deserialize(value, table.getColumn(primaryKeyColumn).type));
}
} catch (IOException err) {
throw new IllegalArgumentException("malformed record", err);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class ConcurrentMapKeyToPageIndex method scanner.
@Override
public Stream<Map.Entry<Bytes, Long>> scanner(IndexOperation operation, StatementEvaluationContext context, TableContext tableContext, herddb.core.AbstractIndexManager index) throws DataStorageManagerException {
if (operation instanceof PrimaryIndexSeek) {
PrimaryIndexSeek seek = (PrimaryIndexSeek) operation;
byte[] seekValue;
try {
seekValue = seek.value.computeNewValue(null, context, tableContext);
} catch (InvalidNullValueForKeyException nullKey) {
seekValue = null;
}
if (seekValue == null) {
return Stream.empty();
}
Bytes key = Bytes.from_array(seekValue);
Long pageId = map.get(key);
if (pageId == null) {
return Stream.empty();
}
return Stream.of(new AbstractMap.SimpleImmutableEntry<>(key, pageId));
}
// every predicate (WHEREs...) will always be evaluated anyway on every record, in order to guarantee correctness
if (index != null) {
return index.recordSetScanner(operation, context, tableContext, this);
}
if (operation == null) {
Stream<Map.Entry<Bytes, Long>> baseStream = map.entrySet().stream();
return baseStream;
} else if (operation instanceof PrimaryIndexPrefixScan) {
PrimaryIndexPrefixScan scan = (PrimaryIndexPrefixScan) operation;
byte[] prefix;
try {
prefix = scan.value.computeNewValue(null, context, tableContext);
} catch (InvalidNullValueForKeyException err) {
return Stream.empty();
} catch (StatementExecutionException err) {
throw new RuntimeException(err);
}
Predicate<Map.Entry<Bytes, Long>> predicate = (Map.Entry<Bytes, Long> t) -> {
Bytes fullrecordKey = t.getKey();
return fullrecordKey.startsWith(prefix.length, prefix);
};
Stream<Map.Entry<Bytes, Long>> baseStream = map.entrySet().stream();
return baseStream.filter(predicate);
} else if (operation instanceof PrimaryIndexRangeScan) {
Bytes refminvalue;
PrimaryIndexRangeScan sis = (PrimaryIndexRangeScan) operation;
SQLRecordKeyFunction minKey = sis.minValue;
if (minKey != null) {
refminvalue = Bytes.from_nullable_array(minKey.computeNewValue(null, context, tableContext));
} else {
refminvalue = null;
}
Bytes refmaxvalue;
SQLRecordKeyFunction maxKey = sis.maxValue;
if (maxKey != null) {
refmaxvalue = Bytes.from_nullable_array(maxKey.computeNewValue(null, context, tableContext));
} else {
refmaxvalue = null;
}
Predicate<Map.Entry<Bytes, Long>> predicate;
if (refminvalue != null && refmaxvalue == null) {
predicate = (Map.Entry<Bytes, Long> entry) -> {
Bytes datum = entry.getKey();
return datum.compareTo(refminvalue) >= 0;
};
} else if (refminvalue == null && refmaxvalue != null) {
predicate = (Map.Entry<Bytes, Long> entry) -> {
Bytes datum = entry.getKey();
return datum.compareTo(refmaxvalue) <= 0;
};
} else if (refminvalue != null && refmaxvalue != null) {
predicate = (Map.Entry<Bytes, Long> entry) -> {
Bytes datum = entry.getKey();
return datum.compareTo(refmaxvalue) <= 0 && datum.compareTo(refminvalue) >= 0;
};
} else {
predicate = (Map.Entry<Bytes, Long> entry) -> {
return true;
};
}
Stream<Map.Entry<Bytes, Long>> baseStream = map.entrySet().stream();
return baseStream.filter(predicate);
} else {
throw new DataStorageManagerException("operation " + operation + " not implemented on " + this.getClass());
}
}
Aggregations