Search in sources :

Example 6 with Predicate

use of herddb.model.Predicate in project herddb by diennea.

the class TableManager method accessTableData.

private void accessTableData(ScanStatement statement, StatementEvaluationContext context, ScanResultOperation consumer, Transaction transaction, boolean lockRequired, boolean forWrite) throws StatementExecutionException {
    statement.validateContext(context);
    Predicate predicate = statement.getPredicate();
    long _start = System.currentTimeMillis();
    boolean acquireLock = transaction != null || forWrite || lockRequired;
    LocalScanPageCache lastPageRead = acquireLock ? null : new LocalScanPageCache();
    try {
        IndexOperation indexOperation = predicate != null ? predicate.getIndexOperation() : null;
        boolean primaryIndexSeek = indexOperation instanceof PrimaryIndexSeek;
        AbstractIndexManager useIndex = getIndexForTbleAccess(indexOperation);
        BatchOrderedExecutor.Executor<Map.Entry<Bytes, Long>> scanExecutor = (List<Map.Entry<Bytes, Long>> batch) -> {
            for (Map.Entry<Bytes, Long> entry : batch) {
                Bytes key = entry.getKey();
                boolean keep_lock = false;
                boolean already_locked = transaction != null && transaction.lookupLock(table.name, key) != null;
                LockHandle lock = acquireLock ? (forWrite ? lockForWrite(key, transaction) : lockForRead(key, transaction)) : null;
                try {
                    if (transaction != null) {
                        if (transaction.recordDeleted(table.name, key)) {
                            // skip this record. inside current transaction it has been deleted
                            continue;
                        }
                        Record record = transaction.recordUpdated(table.name, key);
                        if (record != null) {
                            // use current transaction version of the record
                            if (predicate == null || predicate.evaluate(record, context)) {
                                consumer.accept(record);
                                keep_lock = true;
                            }
                            continue;
                        }
                    }
                    Long pageId = entry.getValue();
                    if (pageId != null) {
                        boolean pkFilterCompleteMatch = false;
                        if (!primaryIndexSeek && predicate != null) {
                            Predicate.PrimaryKeyMatchOutcome outcome = predicate.matchesRawPrimaryKey(key, context);
                            if (outcome == Predicate.PrimaryKeyMatchOutcome.FAILED) {
                                continue;
                            } else if (outcome == Predicate.PrimaryKeyMatchOutcome.FULL_CONDITION_VERIFIED) {
                                pkFilterCompleteMatch = true;
                            }
                        }
                        Record record = fetchRecord(key, pageId, lastPageRead);
                        if (record != null && (pkFilterCompleteMatch || predicate == null || predicate.evaluate(record, context))) {
                            consumer.accept(record);
                            keep_lock = true;
                        }
                    }
                } finally {
                    // release the lock on the key if it did not match scan criteria
                    if (transaction == null) {
                        if (lock != null) {
                            if (forWrite) {
                                locksManager.releaseWriteLockForKey(key, lock);
                            } else {
                                locksManager.releaseReadLockForKey(key, lock);
                            }
                        }
                    } else if (!keep_lock && !already_locked) {
                        transaction.releaseLockOnKey(table.name, key, locksManager);
                    }
                }
            }
        };
        BatchOrderedExecutor<Map.Entry<Bytes, Long>> executor = new BatchOrderedExecutor<>(SORTED_PAGE_ACCESS_WINDOW_SIZE, scanExecutor, SORTED_PAGE_ACCESS_COMPARATOR);
        Stream<Map.Entry<Bytes, Long>> scanner = keyToPage.scanner(indexOperation, context, tableContext, useIndex);
        boolean exit = false;
        try {
            scanner.forEach(executor);
            executor.finish();
        } catch (ExitLoop exitLoop) {
            exit = !exitLoop.continueWithTransactionData;
            if (LOGGER.isLoggable(Level.FINEST)) {
                LOGGER.log(Level.FINEST, "exit loop during scan {0}, started at {1}: {2}", new Object[] { statement, new java.sql.Timestamp(_start), exitLoop.toString() });
            }
        } catch (final HerdDBInternalException error) {
            LOGGER.log(Level.SEVERE, "error during scan", error);
            if (error.getCause() instanceof StatementExecutionException) {
                throw (StatementExecutionException) error.getCause();
            } else if (error.getCause() instanceof DataStorageManagerException) {
                throw (DataStorageManagerException) error.getCause();
            } else if (error instanceof StatementExecutionException) {
                throw (StatementExecutionException) error;
            } else if (error instanceof DataStorageManagerException) {
                throw (DataStorageManagerException) error;
            } else {
                throw new StatementExecutionException(error);
            }
        }
        if (!exit && transaction != null) {
            consumer.beginNewRecordsInTransactionBlock();
            Collection<Record> newRecordsForTable = transaction.getNewRecordsForTable(table.name);
            for (Record record : newRecordsForTable) {
                if (!transaction.recordDeleted(table.name, record.key) && (predicate == null || predicate.evaluate(record, context))) {
                    consumer.accept(record);
                }
            }
        }
    } catch (ExitLoop exitLoop) {
        if (LOGGER.isLoggable(Level.FINEST)) {
            LOGGER.log(Level.FINEST, "exit loop during scan {0}, started at {1}: {2}", new Object[] { statement, new java.sql.Timestamp(_start), exitLoop.toString() });
        }
    } catch (StatementExecutionException err) {
        LOGGER.log(Level.SEVERE, "error during scan {0}, started at {1}: {2}", new Object[] { statement, new java.sql.Timestamp(_start), err.toString() });
        throw err;
    } catch (HerdDBInternalException err) {
        LOGGER.log(Level.SEVERE, "error during scan {0}, started at {1}: {2}", new Object[] { statement, new java.sql.Timestamp(_start), err.toString() });
        throw new StatementExecutionException(err);
    }
}
Also used : DataStorageManagerException(herddb.storage.DataStorageManagerException) StatementExecutionException(herddb.model.StatementExecutionException) Predicate(herddb.model.Predicate) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) Bytes(herddb.utils.Bytes) Entry(java.util.Map.Entry) LogEntry(herddb.log.LogEntry) Record(herddb.model.Record) LockHandle(herddb.utils.LockHandle) BatchOrderedExecutor(herddb.utils.BatchOrderedExecutor) IndexOperation(herddb.index.IndexOperation) AtomicLong(java.util.concurrent.atomic.AtomicLong)

Example 7 with Predicate

use of herddb.model.Predicate in project herddb by diennea.

the class AbstractSystemTableManager method scan.

@Override
public DataScanner scan(ScanStatement statement, StatementEvaluationContext context, Transaction transaction, boolean lockRequired, boolean forWrite) throws StatementExecutionException {
    Predicate predicate = statement.getPredicate();
    MaterializedRecordSet recordSet = tableSpaceManager.getDbmanager().getRecordSetFactory().createRecordSet(table.columnNames, table.columns);
    for (Record record : buildVirtualRecordList()) {
        if (predicate == null || predicate.evaluate(record, context)) {
            recordSet.add(record.getDataAccessor(table));
        }
    }
    recordSet.writeFinished();
    recordSet.sort(statement.getComparator());
    recordSet.applyLimits(statement.getLimits(), context);
    recordSet.applyProjection(statement.getProjection(), context);
    return new SimpleDataScanner(transaction != null ? transaction.transactionId : 0, recordSet);
}
Also used : MaterializedRecordSet(herddb.core.MaterializedRecordSet) Record(herddb.model.Record) SimpleDataScanner(herddb.core.SimpleDataScanner) Predicate(herddb.model.Predicate)

Example 8 with Predicate

use of herddb.model.Predicate in project herddb by diennea.

the class TableManager method streamTableData.

private Stream<Record> streamTableData(ScanStatement statement, StatementEvaluationContext context, Transaction transaction, boolean lockRequired, boolean forWrite) throws StatementExecutionException {
    statement.validateContext(context);
    Predicate predicate = statement.getPredicate();
    boolean acquireLock = transaction != null || forWrite || lockRequired;
    LocalScanPageCache lastPageRead = acquireLock ? null : new LocalScanPageCache();
    IndexOperation indexOperation = predicate != null ? predicate.getIndexOperation() : null;
    boolean primaryIndexSeek = indexOperation instanceof PrimaryIndexSeek;
    AbstractIndexManager useIndex = getIndexForTbleAccess(indexOperation);
    Stream<Map.Entry<Bytes, Long>> scanner = keyToPage.scanner(indexOperation, context, tableContext, useIndex);
    Stream<Record> resultFromTable = scanner.map(entry -> {
        return accessRecord(entry, predicate, context, transaction, lastPageRead, primaryIndexSeek, forWrite, acquireLock);
    }).filter(r -> r != null);
    return resultFromTable;
}
Also used : UpdateStatement(herddb.model.commands.UpdateStatement) Table(herddb.model.Table) TruncateTableStatement(herddb.model.commands.TruncateTableStatement) TupleComparator(herddb.model.TupleComparator) DuplicatePrimaryKeyException(herddb.model.DuplicatePrimaryKeyException) TableStatus(herddb.storage.TableStatus) ServerConfiguration(herddb.server.ServerConfiguration) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) RecordTooBigException(herddb.model.RecordTooBigException) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) LocalLockManager(herddb.utils.LocalLockManager) DataStorageManagerException(herddb.storage.DataStorageManagerException) Index(herddb.model.Index) DataAccessor(herddb.utils.DataAccessor) LogNotAvailableException(herddb.log.LogNotAvailableException) InsertStatement(herddb.model.commands.InsertStatement) DataScanner(herddb.model.DataScanner) CommitLogResult(herddb.log.CommitLogResult) DDLException(herddb.model.DDLException) RecordFunction(herddb.model.RecordFunction) StatementExecutionException(herddb.model.StatementExecutionException) TableContext(herddb.model.TableContext) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) LogSequenceNumber(herddb.log.LogSequenceNumber) Logger(java.util.logging.Logger) Collectors(java.util.stream.Collectors) RecordSerializer(herddb.codec.RecordSerializer) DataPageMetaData(herddb.core.PageSet.DataPageMetaData) ScanStatement(herddb.model.commands.ScanStatement) List(java.util.List) Stream(java.util.stream.Stream) FullTableScanConsumer(herddb.storage.FullTableScanConsumer) GetStatement(herddb.model.commands.GetStatement) Entry(java.util.Map.Entry) Statement(herddb.model.Statement) Bytes(herddb.utils.Bytes) LongAdder(java.util.concurrent.atomic.LongAdder) Holder(herddb.utils.Holder) LockHandle(herddb.utils.LockHandle) LogEntry(herddb.log.LogEntry) GetResult(herddb.model.GetResult) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) Function(java.util.function.Function) ArrayList(java.util.ArrayList) ConcurrentMap(java.util.concurrent.ConcurrentMap) Level(java.util.logging.Level) BatchOrderedExecutor(herddb.utils.BatchOrderedExecutor) Transaction(herddb.model.Transaction) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Projection(herddb.model.Projection) EnsureLongIncrementAccumulator(herddb.utils.EnsureLongIncrementAccumulator) LogEntryType(herddb.log.LogEntryType) ScanLimits(herddb.model.ScanLimits) DeleteStatement(herddb.model.commands.DeleteStatement) Iterator(java.util.Iterator) ReentrantLock(java.util.concurrent.locks.ReentrantLock) Record(herddb.model.Record) Semaphore(java.util.concurrent.Semaphore) DataPageDoesNotExistException(herddb.storage.DataPageDoesNotExistException) LogEntryFactory(herddb.log.LogEntryFactory) StatementExecutionResult(herddb.model.StatementExecutionResult) KeyToPageIndex(herddb.index.KeyToPageIndex) DataStorageManager(herddb.storage.DataStorageManager) ColumnTypes(herddb.model.ColumnTypes) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) Lock(java.util.concurrent.locks.Lock) CommitLog(herddb.log.CommitLog) IndexOperation(herddb.index.IndexOperation) Predicate(herddb.model.Predicate) Column(herddb.model.Column) StatementEvaluationContext(herddb.model.StatementEvaluationContext) Comparator(java.util.Comparator) Collections(java.util.Collections) SECONDS(java.util.concurrent.TimeUnit.SECONDS) StampedLock(java.util.concurrent.locks.StampedLock) TableManagerStats(herddb.core.stats.TableManagerStats) SystemProperties(herddb.utils.SystemProperties) IndexOperation(herddb.index.IndexOperation) PrimaryIndexSeek(herddb.index.PrimaryIndexSeek) Entry(java.util.Map.Entry) LogEntry(herddb.log.LogEntry) Record(herddb.model.Record) Predicate(herddb.model.Predicate)

Example 9 with Predicate

use of herddb.model.Predicate in project herddb by diennea.

the class TableManager method executeGet.

private StatementExecutionResult executeGet(GetStatement get, Transaction transaction, StatementEvaluationContext context) throws StatementExecutionException, DataStorageManagerException {
    Bytes key = new Bytes(get.getKey().computeNewValue(null, context, tableContext));
    Predicate predicate = get.getPredicate();
    boolean requireLock = get.isRequireLock();
    long transactionId = transaction != null ? transaction.transactionId : 0;
    LockHandle lock = (transaction != null || requireLock) ? lockForRead(key, transaction) : null;
    try {
        if (transaction != null) {
            if (transaction.recordDeleted(table.name, key)) {
                return GetResult.NOT_FOUND(transactionId);
            }
            Record loadedInTransaction = transaction.recordUpdated(table.name, key);
            if (loadedInTransaction != null) {
                if (predicate != null && !predicate.evaluate(loadedInTransaction, context)) {
                    return GetResult.NOT_FOUND(transactionId);
                }
                return new GetResult(transactionId, loadedInTransaction, table);
            }
            loadedInTransaction = transaction.recordInserted(table.name, key);
            if (loadedInTransaction != null) {
                if (predicate != null && !predicate.evaluate(loadedInTransaction, context)) {
                    return GetResult.NOT_FOUND(transactionId);
                }
                return new GetResult(transactionId, loadedInTransaction, table);
            }
        }
        Long pageId = keyToPage.get(key);
        if (pageId == null) {
            return GetResult.NOT_FOUND(transactionId);
        }
        Record loaded = fetchRecord(key, pageId, null);
        if (loaded == null || (predicate != null && !predicate.evaluate(loaded, context))) {
            return GetResult.NOT_FOUND(transactionId);
        }
        return new GetResult(transactionId, loaded, table);
    } finally {
        if (transaction == null && lock != null) {
            locksManager.releaseReadLockForKey(key, lock);
        }
    }
}
Also used : Bytes(herddb.utils.Bytes) LockHandle(herddb.utils.LockHandle) GetResult(herddb.model.GetResult) AtomicLong(java.util.concurrent.atomic.AtomicLong) Record(herddb.model.Record) Predicate(herddb.model.Predicate)

Example 10 with Predicate

use of herddb.model.Predicate in project herddb by diennea.

the class TableManager method executeUpdate.

private StatementExecutionResult executeUpdate(UpdateStatement update, Transaction transaction, StatementEvaluationContext context) throws StatementExecutionException, DataStorageManagerException {
    AtomicInteger updateCount = new AtomicInteger();
    Holder<Bytes> lastKey = new Holder<>();
    Holder<byte[]> lastValue = new Holder<>();
    /*
         an update can succeed only if the row is valid, the key is contains in the "keys" structure
         the update will simply override the value of the row, assigning a null page to the row
         the update can have a 'where' predicate which is to be evaluated against the decoded row, the update will be executed only if the predicate returns boolean 'true' value  (CAS operation)
         locks: the update  uses a lock on the the key
         */
    RecordFunction function = update.getFunction();
    long transactionId = transaction != null ? transaction.transactionId : 0;
    Predicate predicate = update.getPredicate();
    ScanStatement scan = new ScanStatement(table.tablespace, table, predicate);
    accessTableData(scan, context, new ScanResultOperation() {

        @Override
        public void accept(Record actual) throws StatementExecutionException, LogNotAvailableException, DataStorageManagerException {
            byte[] newValue = function.computeNewValue(actual, context, tableContext);
            final long size = DataPage.estimateEntrySize(actual.key, newValue);
            if (size > maxLogicalPageSize) {
                throw new RecordTooBigException("New version of record " + actual.key + " is to big to be update: new size " + size + ", actual size " + DataPage.estimateEntrySize(actual) + ", max size " + maxLogicalPageSize);
            }
            LogEntry entry = LogEntryFactory.update(table, actual.key.data, newValue, transaction);
            CommitLogResult pos = log.log(entry, entry.transactionId <= 0);
            apply(pos, entry, false);
            lastKey.value = actual.key;
            lastValue.value = newValue;
            updateCount.incrementAndGet();
        }
    }, transaction, true, true);
    return new DMLStatementExecutionResult(transactionId, updateCount.get(), lastKey.value, update.isReturnValues() ? (lastValue.value != null ? Bytes.from_array(lastValue.value) : null) : null);
}
Also used : DataStorageManagerException(herddb.storage.DataStorageManagerException) Holder(herddb.utils.Holder) CommitLogResult(herddb.log.CommitLogResult) RecordTooBigException(herddb.model.RecordTooBigException) StatementExecutionException(herddb.model.StatementExecutionException) Predicate(herddb.model.Predicate) Bytes(herddb.utils.Bytes) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) Record(herddb.model.Record) RecordFunction(herddb.model.RecordFunction) LogEntry(herddb.log.LogEntry) ScanStatement(herddb.model.commands.ScanStatement) LogNotAvailableException(herddb.log.LogNotAvailableException)

Aggregations

Predicate (herddb.model.Predicate)14 Record (herddb.model.Record)10 ScanStatement (herddb.model.commands.ScanStatement)8 StatementExecutionException (herddb.model.StatementExecutionException)7 Bytes (herddb.utils.Bytes)7 Table (herddb.model.Table)6 DataScanner (herddb.model.DataScanner)5 LogEntry (herddb.log.LogEntry)4 StatementEvaluationContext (herddb.model.StatementEvaluationContext)4 DeleteStatement (herddb.model.commands.DeleteStatement)4 InsertStatement (herddb.model.commands.InsertStatement)4 DataStorageManagerException (herddb.storage.DataStorageManagerException)4 LockHandle (herddb.utils.LockHandle)4 HashMap (java.util.HashMap)4 List (java.util.List)4 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 AtomicLong (java.util.concurrent.atomic.AtomicLong)4 DMLStatementExecutionResult (herddb.model.DMLStatementExecutionResult)3 RecordFunction (herddb.model.RecordFunction)3 UpdateStatement (herddb.model.commands.UpdateStatement)3