use of herddb.utils.Bytes in project herddb by diennea.
the class BRINIndexManager method checkpoint.
@Override
public List<PostCheckpointAction> checkpoint(LogSequenceNumber sequenceNumber, boolean pin) throws DataStorageManagerException {
try {
BlockRangeIndexMetadata<Bytes> metadata = data.checkpoint();
/* Checks metadata consistency with actual data structure */
if (VALIDATE_CHECKPOINT_METADATA) {
boolean invalid = false;
/*
* Metadata are saved/recovered in reverse order so "next" block has been already created
*/
Long nextID = null;
for (BlockRangeIndexMetadata.BlockMetadata<Bytes> blockData : metadata.getBlocksMetadata()) {
/* Medatada safety check (do not trust blindly ordering) */
if (blockData.nextBlockId != null) {
if (nextID == null) {
LOGGER.log(Level.WARNING, "Wrong next block on index {0}, expected notingh but {0} found", new Object[] { index.name, blockData.nextBlockId });
invalid = true;
} else if (nextID != blockData.nextBlockId.longValue()) {
LOGGER.log(Level.WARNING, "Wrong next block on index {0}, expected {1} but {2} found", new Object[] { index.name, nextID, blockData.nextBlockId });
invalid = true;
}
} else {
if (nextID != null) {
LOGGER.log(Level.WARNING, "Wrong next block on index {0}, expected {1} but nothing found", new Object[] { index.name, nextID });
invalid = true;
}
}
nextID = blockData.blockId;
}
if (invalid) {
LOGGER.log(Level.WARNING, data.generateDetailedInternalStatus());
}
}
PageContents page = new PageContents();
page.type = PageContents.TYPE_METADATA;
page.metadata = metadata.getBlocksMetadata();
byte[] contents = page.serialize();
Set<Long> activePages = new HashSet<>();
page.metadata.forEach(b -> {
activePages.add(b.pageId);
});
IndexStatus indexStatus = new IndexStatus(index.name, sequenceNumber, newPageId.get(), activePages, contents);
List<PostCheckpointAction> result = new ArrayList<>();
result.addAll(dataStorageManager.indexCheckpoint(tableSpaceUUID, index.uuid, indexStatus, pin));
LOGGER.log(Level.INFO, "checkpoint index {0} finished: logpos {1}, {2} blocks", new Object[] { index.name, sequenceNumber, Integer.toString(page.metadata.size()) });
LOGGER.log(Level.FINE, "checkpoint index {0} finished: logpos {1}, pages {2}", new Object[] { index.name, sequenceNumber, activePages });
return result;
} catch (IOException err) {
throw new DataStorageManagerException(err);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class MemoryHashIndexManager method scanner.
@Override
public Stream<Bytes> scanner(IndexOperation operation, StatementEvaluationContext context, TableContext tableContext) throws StatementExecutionException {
if (operation instanceof SecondaryIndexSeek) {
SecondaryIndexSeek sis = (SecondaryIndexSeek) operation;
SQLRecordKeyFunction value = sis.value;
byte[] refvalue = value.computeNewValue(null, context, tableContext);
List<Bytes> result = data.get(Bytes.from_array(refvalue));
if (result != null) {
return result.stream();
} else {
return Stream.empty();
}
} else if (operation instanceof SecondaryIndexPrefixScan) {
SecondaryIndexPrefixScan sis = (SecondaryIndexPrefixScan) operation;
SQLRecordKeyFunction value = sis.value;
byte[] refvalue = value.computeNewValue(null, context, tableContext);
Predicate<Map.Entry<Bytes, List<Bytes>>> predicate = (Map.Entry<Bytes, List<Bytes>> entry) -> {
Bytes recordValue = entry.getKey();
return recordValue.startsWith(refvalue.length, refvalue);
};
return data.entrySet().stream().filter(predicate).map(entry -> entry.getValue()).flatMap(l -> l.stream());
} else if (operation instanceof SecondaryIndexRangeScan) {
Bytes refminvalue;
SecondaryIndexRangeScan sis = (SecondaryIndexRangeScan) 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, List<Bytes>>> predicate;
if (refminvalue != null && refmaxvalue == null) {
predicate = (Map.Entry<Bytes, List<Bytes>> entry) -> {
Bytes datum = entry.getKey();
return datum.compareTo(refminvalue) >= 0;
};
} else if (refminvalue == null && refmaxvalue != null) {
predicate = (Map.Entry<Bytes, List<Bytes>> entry) -> {
Bytes datum = entry.getKey();
return datum.compareTo(refmaxvalue) <= 0;
};
} else if (refminvalue != null && refmaxvalue != null) {
predicate = (Map.Entry<Bytes, List<Bytes>> entry) -> {
Bytes datum = entry.getKey();
return datum.compareTo(refmaxvalue) <= 0 && datum.compareTo(refminvalue) >= 0;
};
} else {
predicate = (Map.Entry<Bytes, List<Bytes>> entry) -> {
return true;
};
}
return data.entrySet().stream().filter(predicate).map(entry -> entry.getValue()).flatMap(l -> l.stream());
} else {
throw new UnsupportedOperationException("unsuppported index access type " + operation);
}
}
use of herddb.utils.Bytes in project herddb by diennea.
the class MemoryHashIndexManager method checkpoint.
@Override
public List<PostCheckpointAction> checkpoint(LogSequenceNumber sequenceNumber, boolean pin) throws DataStorageManagerException {
if (createdInTransaction > 0) {
LOGGER.log(Level.INFO, "checkpoint for index " + index.name + " skipped, this index is created on transaction " + createdInTransaction + " which is not committed");
return Collections.emptyList();
}
List<PostCheckpointAction> result = new ArrayList<>();
LOGGER.log(Level.INFO, "flush index {0}", new Object[] { index.name });
long pageId = newPageId.getAndIncrement();
Holder<Long> count = new Holder<>();
dataStorageManager.writeIndexPage(tableSpaceUUID, index.uuid, pageId, (out) -> {
long entries = 0;
// version
out.writeVLong(1);
// flags for future implementations
out.writeVLong(0);
out.writeVInt(data.size());
for (Map.Entry<Bytes, List<Bytes>> entry : data.entrySet()) {
out.writeArray(entry.getKey());
List<Bytes> entrydata = entry.getValue();
out.writeVInt(entrydata.size());
for (Bytes v : entrydata) {
out.writeArray(v);
++entries;
}
}
count.value = entries;
});
IndexStatus indexStatus = new IndexStatus(index.name, sequenceNumber, newPageId.get(), Collections.singleton(pageId), null);
result.addAll(dataStorageManager.indexCheckpoint(tableSpaceUUID, index.uuid, indexStatus, pin));
LOGGER.log(Level.INFO, "checkpoint index {0} finished: logpos {1}, {2} entries, page {3}", new Object[] { index.name, sequenceNumber, Long.toString(count.value), Long.toString(pageId) });
return result;
}
use of herddb.utils.Bytes in project herddb by diennea.
the class MemoryHashIndexManager method rebuild.
@Override
public void rebuild() throws DataStorageManagerException {
long _start = System.currentTimeMillis();
LOGGER.log(Level.INFO, "building index {0}", index.name);
dataStorageManager.initIndex(tableSpaceUUID, index.uuid);
data.clear();
Table table = tableManager.getTable();
tableManager.scanForIndexRebuild(r -> {
DataAccessor values = r.getDataAccessor(table);
Bytes key = RecordSerializer.serializeIndexKey(values, table, table.primaryKey);
Bytes indexKey = RecordSerializer.serializeIndexKey(values, index, index.columnNames);
// LOGGER.log(Level.SEVERE, "adding " + key + " -> " + values);
recordInserted(key, indexKey);
});
long _stop = System.currentTimeMillis();
LOGGER.log(Level.INFO, "building index {0} took {1}", new Object[] { index.name, (_stop - _start) + " ms" });
}
use of herddb.utils.Bytes in project herddb by diennea.
the class DeleteOp method executeAsync.
@Override
public CompletableFuture<StatementExecutionResult> executeAsync(TableSpaceManager tableSpaceManager, TransactionContext transactionContext, StatementEvaluationContext context, boolean lockRequired, boolean forWrite) {
// not supported for deletes
final boolean returnValues = false;
StatementExecutionResult input = this.input.execute(tableSpaceManager, transactionContext, context, true, true);
ScanResult downstreamScanResult = (ScanResult) input;
final Table table = tableSpaceManager.getTableManager(tableName).getTable();
long transactionId = transactionContext.transactionId;
List<DMLStatement> statements = new ArrayList<>();
try (DataScanner inputScanner = downstreamScanResult.dataScanner) {
while (inputScanner.hasNext()) {
DataAccessor row = inputScanner.next();
long transactionIdFromScanner = inputScanner.getTransactionId();
if (transactionIdFromScanner > 0 && transactionIdFromScanner != transactionId) {
transactionId = transactionIdFromScanner;
transactionContext = new TransactionContext(transactionId);
}
Bytes key = RecordSerializer.serializeIndexKey(row, table, table.getPrimaryKey());
DMLStatement deleteStatement = new DeleteStatement(tableSpace, tableName, null, new RawKeyEquals(key));
statements.add(deleteStatement);
}
if (statements.isEmpty()) {
return CompletableFuture.completedFuture(new DMLStatementExecutionResult(transactionId, 0, null, null));
}
if (statements.size() == 1) {
return tableSpaceManager.executeStatementAsync(statements.get(0), context, transactionContext);
}
CompletableFuture<StatementExecutionResult> finalResult = new CompletableFuture<>();
AtomicInteger updateCounts = new AtomicInteger();
AtomicReference<Bytes> lastKey = new AtomicReference<>();
AtomicReference<Bytes> lastNewValue = new AtomicReference<>();
class ComputeNext implements BiConsumer<StatementExecutionResult, Throwable> {
int current;
public ComputeNext(int current) {
this.current = current;
}
@Override
public void accept(StatementExecutionResult res, Throwable error) {
if (error != null) {
finalResult.completeExceptionally(error);
return;
}
DMLStatementExecutionResult dml = (DMLStatementExecutionResult) res;
updateCounts.addAndGet(dml.getUpdateCount());
if (returnValues) {
lastKey.set(dml.getKey());
lastNewValue.set(dml.getNewvalue());
}
long newTransactionId = res.transactionId;
if (current == statements.size()) {
DMLStatementExecutionResult finalDMLResult = new DMLStatementExecutionResult(newTransactionId, updateCounts.get(), lastKey.get(), lastNewValue.get());
finalResult.complete(finalDMLResult);
return;
}
DMLStatement nextStatement = statements.get(current);
TransactionContext transactionContext = new TransactionContext(newTransactionId);
CompletableFuture<StatementExecutionResult> nextPromise = tableSpaceManager.executeStatementAsync(nextStatement, context, transactionContext);
nextPromise.whenComplete(new ComputeNext(current + 1));
}
}
DMLStatement firstStatement = statements.get(0);
tableSpaceManager.executeStatementAsync(firstStatement, context, transactionContext).whenComplete(new ComputeNext(1));
return finalResult;
} catch (DataScannerException err) {
throw new StatementExecutionException(err);
}
}
Aggregations