Search in sources :

Example 16 with Bytes

use of herddb.utils.Bytes in project herddb by diennea.

the class TableManager method executeInsert.

private StatementExecutionResult executeInsert(InsertStatement insert, Transaction transaction, StatementEvaluationContext context) throws StatementExecutionException, DataStorageManagerException {
    /*
         an insert can succeed only if the row is valid and the "keys" structure  does not contain the requested key
         the insert will add the row in the 'buffer' without assigning a page to it
         locks: the insert uses global 'insert' lock on the table
         the insert will update the 'maxKey' for auto_increment primary keys
         */
    Bytes key = new Bytes(insert.getKeyFunction().computeNewValue(null, context, tableContext));
    byte[] value = insert.getValuesFunction().computeNewValue(new Record(key, null), context, tableContext);
    final long size = DataPage.estimateEntrySize(key, value);
    if (size > maxLogicalPageSize) {
        throw new RecordTooBigException("New record " + key + " is to big to be inserted: size " + size + ", max size " + maxLogicalPageSize);
    }
    LockHandle lock = lockForWrite(key, transaction);
    try {
        if (transaction != null) {
            if (transaction.recordDeleted(table.name, key)) {
            // OK, INSERT on a DELETED record inside this transaction
            } else if (transaction.recordInserted(table.name, key) != null) {
                // ERROR, INSERT on a INSERTED record inside this transaction
                throw new DuplicatePrimaryKeyException(key, "key " + key + ", decoded as " + RecordSerializer.deserializePrimaryKey(key.data, table) + ", already exists in table " + table.name + " inside transaction " + transaction.transactionId);
            } else if (keyToPage.containsKey(key)) {
                throw new DuplicatePrimaryKeyException(key, "key " + key + ", decoded as " + RecordSerializer.deserializePrimaryKey(key.data, table) + ", already exists in table " + table.name + " during transaction " + transaction.transactionId);
            }
        } else if (keyToPage.containsKey(key)) {
            throw new DuplicatePrimaryKeyException(key, "key " + key + ", decoded as " + RecordSerializer.deserializePrimaryKey(key.data, table) + ", already exists in table " + table.name);
        }
        LogEntry entry = LogEntryFactory.insert(table, key.data, value, transaction);
        CommitLogResult pos = log.log(entry, entry.transactionId <= 0);
        apply(pos, entry, false);
        return new DMLStatementExecutionResult(entry.transactionId, 1, key, insert.isReturnValues() ? Bytes.from_array(value) : null);
    } catch (LogNotAvailableException err) {
        throw new StatementExecutionException(err);
    } finally {
        if (transaction == null) {
            locksManager.releaseWriteLockForKey(key, lock);
        }
    }
}
Also used : Bytes(herddb.utils.Bytes) LockHandle(herddb.utils.LockHandle) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) DuplicatePrimaryKeyException(herddb.model.DuplicatePrimaryKeyException) Record(herddb.model.Record) CommitLogResult(herddb.log.CommitLogResult) RecordTooBigException(herddb.model.RecordTooBigException) LogEntry(herddb.log.LogEntry) StatementExecutionException(herddb.model.StatementExecutionException) LogNotAvailableException(herddb.log.LogNotAvailableException)

Example 17 with Bytes

use of herddb.utils.Bytes in project herddb by diennea.

the class TableManager method createImmutablePage.

/**
 * Create a new page with given data, save it and update keyToPage records
 * <p>
 * Will not place any lock, this method should be invoked at startup time or during checkpoint: <b>during
 * "stop-the-world" procedures!</b>
 * </p>
 */
private long createImmutablePage(Map<Bytes, Record> newPage, long newPageSize) throws DataStorageManagerException {
    final Long pageId = nextPageId++;
    final DataPage dataPage = buildImmutableDataPage(pageId, newPage, newPageSize);
    LOGGER.log(Level.FINER, "createNewPage table {0}, pageId={1} with {2} records, {3} logical page size", new Object[] { table.name, pageId, newPage.size(), newPageSize });
    dataStorageManager.writePage(tableSpaceUUID, table.uuid, pageId, newPage.values());
    pageSet.pageCreated(pageId, dataPage);
    pages.put(pageId, dataPage);
    /* We mustn't update currentDirtyRecordsPage. This page isn't created to host live dirty data */
    final Page.Metadata unload = pageReplacementPolicy.add(dataPage);
    if (unload != null) {
        unload.owner.unload(unload.pageId);
    }
    for (Bytes key : newPage.keySet()) {
        keyToPage.put(key, pageId);
    }
    return pageId;
}
Also used : Bytes(herddb.utils.Bytes) AtomicLong(java.util.concurrent.atomic.AtomicLong)

Example 18 with Bytes

use of herddb.utils.Bytes 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 19 with Bytes

use of herddb.utils.Bytes in project herddb by diennea.

the class TableManager method executeGetAsync.

private CompletableFuture<StatementExecutionResult> executeGetAsync(GetStatement get, Transaction transaction, StatementEvaluationContext context) {
    Bytes key;
    try {
        key = Bytes.from_nullable_array(get.getKey().computeNewValue(null, context, tableContext));
    } catch (StatementExecutionException validationError) {
        return Futures.exception(validationError);
    }
    Predicate predicate = get.getPredicate();
    boolean requireLock = get.isRequireLock();
    boolean useWriteLock = requireLock && context.isForceAcquireWriteLock();
    long transactionId = transaction != null ? transaction.transactionId : 0;
    LockHandle lock = (transaction != null || requireLock) ? (useWriteLock ? lockForWrite(key, transaction) : lockForRead(key, transaction)) : null;
    CompletableFuture<StatementExecutionResult> res = null;
    try {
        if (transaction != null) {
            if (transaction.recordDeleted(table.name, key)) {
                res = CompletableFuture.completedFuture(GetResult.NOT_FOUND(transactionId));
            } else {
                Record loadedInTransaction = transaction.recordUpdated(table.name, key);
                if (loadedInTransaction != null) {
                    if (predicate != null && !predicate.evaluate(loadedInTransaction, context)) {
                        res = CompletableFuture.completedFuture(GetResult.NOT_FOUND(transactionId));
                    } else {
                        res = CompletableFuture.completedFuture(new GetResult(transactionId, loadedInTransaction, table));
                    }
                } else {
                    loadedInTransaction = transaction.recordInserted(table.name, key);
                    if (loadedInTransaction != null) {
                        if (predicate != null && !predicate.evaluate(loadedInTransaction, context)) {
                            res = CompletableFuture.completedFuture(GetResult.NOT_FOUND(transactionId));
                        } else {
                            res = CompletableFuture.completedFuture(new GetResult(transactionId, loadedInTransaction, table));
                        }
                    }
                }
            }
        }
        if (res == null) {
            Long pageId = keyToPage.get(key);
            if (pageId == null) {
                res = CompletableFuture.completedFuture(GetResult.NOT_FOUND(transactionId));
            } else {
                Record loaded = fetchRecord(key, pageId, null);
                if (loaded == null || (predicate != null && !predicate.evaluate(loaded, context))) {
                    res = CompletableFuture.completedFuture(GetResult.NOT_FOUND(transactionId));
                } else {
                    res = CompletableFuture.completedFuture(new GetResult(transactionId, loaded, table));
                }
            }
        }
        if (lock != null) {
            if (transaction == null) {
                res.whenComplete((r, e) -> {
                    locksManager.releaseReadLock(lock);
                });
            } else if (!context.isForceRetainReadLock() && !lock.write) {
                transaction.releaseLockOnKey(table.name, key, locksManager);
            }
        }
        return res;
    } catch (HerdDBInternalException err) {
        return Futures.exception(err);
    }
}
Also used : Bytes(herddb.utils.Bytes) LockHandle(herddb.utils.LockHandle) GetResult(herddb.model.GetResult) DMLStatementExecutionResult(herddb.model.DMLStatementExecutionResult) StatementExecutionResult(herddb.model.StatementExecutionResult) AtomicLong(java.util.concurrent.atomic.AtomicLong) Record(herddb.model.Record) StatementExecutionException(herddb.model.StatementExecutionException) Predicate(herddb.model.Predicate)

Example 20 with Bytes

use of herddb.utils.Bytes in project herddb by diennea.

the class TableManager method applyDelete.

private void applyDelete(Bytes key) throws DataStorageManagerException {
    /* This could be a normal or a temporary modifiable page */
    final Long pageId = keyToPage.remove(key);
    if (pageId == null) {
        throw new IllegalStateException("corrupted transaction log: key " + key + " is not present in table " + table.tablespace + "." + table.name);
    }
    if (LOGGER.isLoggable(Level.FINEST)) {
        LOGGER.log(Level.FINEST, "Deleted key " + key + " from page " + pageId + " from table " + table.tablespace + "." + table.name);
    }
    /*
         * We'll try to remove the record if in a writable page, otherwise we'll simply set the old page
         * as dirty.
         */
    final Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(table.name);
    /*
         * When index is enabled we need the old value to update them, we'll force the page load only if that
         * record is really needed.
         */
    final DataPage page;
    final Record previous;
    if (indexes == null) {
        /* We don't need the page if isn't loaded or isn't a mutable new page */
        page = newPages.get(pageId);
        if (page != null) {
            pageReplacementPolicy.pageHit(page);
            previous = page.get(key);
            if (previous == null) {
                throw new IllegalStateException("corrupted PK: old page " + pageId + " for deleted record at " + key + " was not found in table " + table.tablespace + "." + table.name);
            }
        } else {
            previous = null;
        }
    } else {
        /* We really need the page for update index old values */
        page = loadPageToMemory(pageId, false);
        previous = page.get(key);
        if (previous == null) {
            throw new IllegalStateException("corrupted PK: old page " + pageId + " for deleted record at " + key + " was not found in table " + table.tablespace + "." + table.name);
        }
    }
    if (page == null || page.immutable) {
        /* Unloaded or immutable, set it as dirty */
        pageSet.setPageDirty(pageId, previous);
    } else {
        /* Mutable page, need to check if still modifiable or already unloaded */
        final Lock lock = page.pageLock.readLock();
        lock.lock();
        try {
            if (page.writable) {
                /* We can modify the page directly */
                page.remove(key);
            } else {
                /* Unfortunately is not writable (anymore), set it as dirty */
                pageSet.setPageDirty(pageId, previous);
            }
        } finally {
            lock.unlock();
        }
    }
    if (indexes != null) {
        /* If there are indexes e have already forced a page load and previous record has been loaded */
        DataAccessor values = previous.getDataAccessor(table);
        for (AbstractIndexManager index : indexes.values()) {
            Bytes indexKey = RecordSerializer.serializeIndexKey(values, index.getIndex(), index.getColumnNames());
            index.recordDeleted(key, indexKey);
        }
    }
}
Also used : Bytes(herddb.utils.Bytes) DataAccessor(herddb.utils.DataAccessor) AtomicLong(java.util.concurrent.atomic.AtomicLong) Record(herddb.model.Record) Lock(java.util.concurrent.locks.Lock) StampedLock(java.util.concurrent.locks.StampedLock) ReentrantLock(java.util.concurrent.locks.ReentrantLock)

Aggregations

Bytes (herddb.utils.Bytes)139 Record (herddb.model.Record)77 Test (org.junit.Test)71 Table (herddb.model.Table)68 TransactionContext (herddb.model.TransactionContext)62 InsertStatement (herddb.model.commands.InsertStatement)61 GetResult (herddb.model.GetResult)53 GetStatement (herddb.model.commands.GetStatement)51 CreateTableStatement (herddb.model.commands.CreateTableStatement)50 CreateTableSpaceStatement (herddb.model.commands.CreateTableSpaceStatement)49 Path (java.nio.file.Path)34 TransactionResult (herddb.model.TransactionResult)28 BeginTransactionStatement (herddb.model.commands.BeginTransactionStatement)28 CommitTransactionStatement (herddb.model.commands.CommitTransactionStatement)28 DataStorageManagerException (herddb.storage.DataStorageManagerException)28 DataScanner (herddb.model.DataScanner)26 DeleteStatement (herddb.model.commands.DeleteStatement)24 UpdateStatement (herddb.model.commands.UpdateStatement)24 DMLStatementExecutionResult (herddb.model.DMLStatementExecutionResult)23 ArrayList (java.util.ArrayList)23