Search in sources :

Example 1 with OCacheEntry

use of com.orientechnologies.orient.core.storage.cache.OCacheEntry in project orientdb by orientechnologies.

the class OClusterPositionMap method resurrect.

public void resurrect(final long clusterPosition, final OClusterPositionMapBucket.PositionEntry entry) throws IOException {
    startOperation();
    try {
        OAtomicOperation atomicOperation = startAtomicOperation(true);
        acquireExclusiveLock();
        try {
            final long pageIndex = clusterPosition / OClusterPositionMapBucket.MAX_ENTRIES;
            final int index = (int) (clusterPosition % OClusterPositionMapBucket.MAX_ENTRIES);
            if (pageIndex >= getFilledUpTo(atomicOperation, fileId))
                throw new OClusterPositionMapException("Passed in cluster position " + clusterPosition + " is outside of range of cluster-position map", this);
            final OCacheEntry cacheEntry = loadPage(atomicOperation, fileId, pageIndex, false, 1);
            cacheEntry.acquireExclusiveLock();
            try {
                final OClusterPositionMapBucket bucket = new OClusterPositionMapBucket(cacheEntry, getChanges(atomicOperation, cacheEntry));
                bucket.resurrect(index, entry);
            } finally {
                cacheEntry.releaseExclusiveLock();
                releasePage(atomicOperation, cacheEntry);
            }
            endAtomicOperation(false, null);
        } catch (IOException e) {
            endAtomicOperation(true, e);
            throw OException.wrapException(new OClusterPositionMapException("Error of resurrecting mapping between logical and physical record position", this), e);
        } catch (RuntimeException e) {
            endAtomicOperation(true, e);
            throw OException.wrapException(new OClusterPositionMapException("Error of resurrecting mapping between logical and physical record position", this), e);
        } finally {
            releaseExclusiveLock();
        }
    } finally {
        completeOperation();
    }
}
Also used : OAtomicOperation(com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation) OClusterPositionMapException(com.orientechnologies.orient.core.exception.OClusterPositionMapException) OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry) IOException(java.io.IOException)

Example 2 with OCacheEntry

use of com.orientechnologies.orient.core.storage.cache.OCacheEntry in project orientdb by orientechnologies.

the class OLocalHashTable20 method load.

@Override
public void load(String name, OType[] keyTypes, boolean nullKeyIsSupported) {
    acquireExclusiveLock();
    try {
        if (keyTypes != null)
            this.keyTypes = Arrays.copyOf(keyTypes, keyTypes.length);
        else
            this.keyTypes = null;
        this.nullKeyIsSupported = nullKeyIsSupported;
        OAtomicOperation atomicOperation = atomicOperationsManager.getCurrentOperation();
        fileStateId = openFile(atomicOperation, name + metadataConfigurationFileExtension);
        final OCacheEntry hashStateEntry = loadPage(atomicOperation, fileStateId, 0, true);
        hashStateEntryIndex = hashStateEntry.getPageIndex();
        directory = new OHashTableDirectory(treeStateFileExtension, name, getFullName(), durableInNonTxMode, storage);
        directory.open();
        pinPage(atomicOperation, hashStateEntry);
        try {
            OHashIndexFileLevelMetadataPage page = new OHashIndexFileLevelMetadataPage(hashStateEntry, getChanges(atomicOperation, hashStateEntry), false);
            keySerializer = (OBinarySerializer<K>) storage.getComponentsFactory().binarySerializerFactory.getObjectSerializer(page.getKeySerializerId());
            valueSerializer = (OBinarySerializer<V>) storage.getComponentsFactory().binarySerializerFactory.getObjectSerializer(page.getValueSerializerId());
        } finally {
            releasePage(atomicOperation, hashStateEntry);
        }
        if (nullKeyIsSupported)
            nullBucketFileId = openFile(atomicOperation, name + nullBucketFileExtension);
    } catch (IOException e) {
        throw OException.wrapException(new OIndexException("Exception during hash table loading"), e);
    } finally {
        releaseExclusiveLock();
    }
}
Also used : OAtomicOperation(com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation) OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry) OIndexException(com.orientechnologies.orient.core.index.OIndexException) IOException(java.io.IOException)

Example 3 with OCacheEntry

use of com.orientechnologies.orient.core.storage.cache.OCacheEntry in project orientdb by orientechnologies.

the class OSBTree method put.

@SuppressWarnings("unchecked")
private boolean put(K key, V value, OIndexEngine.Validator<K, V> validator) {
    final OSessionStoragePerformanceStatistic statistic = performanceStatisticManager.getSessionPerformanceStatistic();
    startOperation();
    if (statistic != null)
        statistic.startIndexEntryUpdateTimer();
    try {
        final OAtomicOperation atomicOperation;
        try {
            atomicOperation = startAtomicOperation(true);
        } catch (IOException e) {
            throw OException.wrapException(new OSBTreeException("Error during sbtree entrie put", this), e);
        }
        acquireExclusiveLock();
        try {
            checkNullSupport(key);
            if (key != null) {
                final int keySize = keySerializer.getObjectSize(key, (Object[]) keyTypes);
                final int valueSize = valueSerializer.getObjectSize(value);
                if (keySize > MAX_KEY_SIZE)
                    throw new OTooBigIndexKeyException("Key size is more than allowed, operation was canceled. Current key size " + keySize + ", allowed  " + MAX_KEY_SIZE, getName());
                final boolean createLinkToTheValue = valueSize > MAX_EMBEDDED_VALUE_SIZE;
                key = keySerializer.preprocess(key, (Object[]) keyTypes);
                long valueLink = -1;
                if (createLinkToTheValue)
                    valueLink = createLinkToTheValue(value, atomicOperation);
                final OSBTreeValue<V> treeValue = new OSBTreeValue<V>(createLinkToTheValue, valueLink, createLinkToTheValue ? null : value);
                BucketSearchResult bucketSearchResult = findBucket(key, atomicOperation);
                OCacheEntry keyBucketCacheEntry = loadPage(atomicOperation, fileId, bucketSearchResult.getLastPathItem(), false);
                keyBucketCacheEntry.acquireExclusiveLock();
                OSBTreeBucket<K, V> keyBucket = new OSBTreeBucket<K, V>(keyBucketCacheEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, keyBucketCacheEntry));
                if (validator != null) {
                    // assuming validation throws by default
                    boolean failure = true;
                    boolean ignored = false;
                    try {
                        final V oldValue = bucketSearchResult.itemIndex > -1 ? readValue(keyBucket.getValue(bucketSearchResult.itemIndex), atomicOperation) : null;
                        final Object result = validator.validate(key, oldValue, value);
                        if (result == OIndexEngine.Validator.IGNORE) {
                            ignored = true;
                            failure = false;
                            return false;
                        }
                        value = (V) result;
                        failure = false;
                    } finally {
                        if (failure || ignored) {
                            keyBucketCacheEntry.releaseExclusiveLock();
                            releasePage(atomicOperation, keyBucketCacheEntry);
                        }
                        if (// in case of a failure atomic operation will be ended in a usual way below
                        ignored)
                            endAtomicOperation(false, null);
                    }
                }
                int insertionIndex;
                int sizeDiff;
                if (bucketSearchResult.itemIndex >= 0) {
                    int updateResult = keyBucket.updateValue(bucketSearchResult.itemIndex, treeValue);
                    if (updateResult >= 0) {
                        keyBucketCacheEntry.releaseExclusiveLock();
                        releasePage(atomicOperation, keyBucketCacheEntry);
                        endAtomicOperation(false, null);
                        return true;
                    } else {
                        assert updateResult == -1;
                        long removedLinkedValue = keyBucket.remove(bucketSearchResult.itemIndex);
                        if (removedLinkedValue >= 0)
                            removeLinkedValue(removedLinkedValue, atomicOperation);
                        insertionIndex = bucketSearchResult.itemIndex;
                        sizeDiff = 0;
                    }
                } else {
                    insertionIndex = -bucketSearchResult.itemIndex - 1;
                    sizeDiff = 1;
                }
                while (!keyBucket.addEntry(insertionIndex, new OSBTreeBucket.SBTreeEntry<K, V>(-1, -1, key, treeValue), true)) {
                    keyBucketCacheEntry.releaseExclusiveLock();
                    releasePage(atomicOperation, keyBucketCacheEntry);
                    bucketSearchResult = splitBucket(bucketSearchResult.path, insertionIndex, key, atomicOperation);
                    insertionIndex = bucketSearchResult.itemIndex;
                    keyBucketCacheEntry = loadPage(atomicOperation, fileId, bucketSearchResult.getLastPathItem(), false);
                    keyBucketCacheEntry.acquireExclusiveLock();
                    keyBucket = new OSBTreeBucket<K, V>(keyBucketCacheEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, keyBucketCacheEntry));
                }
                keyBucketCacheEntry.releaseExclusiveLock();
                releasePage(atomicOperation, keyBucketCacheEntry);
                if (sizeDiff != 0)
                    setSize(size() + sizeDiff, atomicOperation);
            } else {
                OCacheEntry cacheEntry;
                boolean isNew = false;
                if (getFilledUpTo(atomicOperation, nullBucketFileId) == 0) {
                    cacheEntry = addPage(atomicOperation, nullBucketFileId);
                    isNew = true;
                } else
                    cacheEntry = loadPage(atomicOperation, nullBucketFileId, 0, false);
                final int valueSize = valueSerializer.getObjectSize(value);
                final boolean createLinkToTheValue = valueSize > MAX_EMBEDDED_VALUE_SIZE;
                long valueLink = -1;
                if (createLinkToTheValue)
                    valueLink = createLinkToTheValue(value, atomicOperation);
                final OSBTreeValue<V> treeValue = new OSBTreeValue<V>(createLinkToTheValue, valueLink, createLinkToTheValue ? null : value);
                int sizeDiff = 0;
                boolean ignored = false;
                cacheEntry.acquireExclusiveLock();
                try {
                    final ONullBucket<V> nullBucket = new ONullBucket<V>(cacheEntry, getChanges(atomicOperation, cacheEntry), valueSerializer, isNew);
                    final OSBTreeValue<V> oldValue = nullBucket.getValue();
                    if (validator != null) {
                        final V oldValueValue = oldValue == null ? null : readValue(oldValue, atomicOperation);
                        final Object result = validator.validate(null, oldValueValue, value);
                        if (result == OIndexEngine.Validator.IGNORE) {
                            ignored = true;
                            return false;
                        }
                        value = (V) result;
                    }
                    if (oldValue != null)
                        sizeDiff = -1;
                    nullBucket.setValue(treeValue);
                } finally {
                    cacheEntry.releaseExclusiveLock();
                    releasePage(atomicOperation, cacheEntry);
                    if (ignored)
                        endAtomicOperation(false, null);
                }
                sizeDiff++;
                setSize(size() + sizeDiff, atomicOperation);
            }
            endAtomicOperation(false, null);
            return true;
        } catch (IOException e) {
            rollback(e);
            throw OException.wrapException(new OSBTreeException("Error during index update with key " + key + " and value " + value, this), e);
        } catch (RuntimeException e) {
            rollback(e);
            throw e;
        } finally {
            releaseExclusiveLock();
        }
    } finally {
        if (statistic != null)
            statistic.stopIndexEntryUpdateTimer();
        completeOperation();
    }
}
Also used : OAtomicOperation(com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation) IOException(java.io.IOException) OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry) OSessionStoragePerformanceStatistic(com.orientechnologies.orient.core.storage.impl.local.statistic.OSessionStoragePerformanceStatistic) OTooBigIndexKeyException(com.orientechnologies.orient.core.exception.OTooBigIndexKeyException)

Example 4 with OCacheEntry

use of com.orientechnologies.orient.core.storage.cache.OCacheEntry in project orientdb by orientechnologies.

the class OSBTree method lastItem.

private BucketSearchResult lastItem(OAtomicOperation atomicOperation) throws IOException {
    LinkedList<PagePathItemUnit> path = new LinkedList<PagePathItemUnit>();
    long bucketIndex = ROOT_INDEX;
    OCacheEntry cacheEntry = loadPage(atomicOperation, fileId, bucketIndex, false);
    cacheEntry.acquireSharedLock();
    OSBTreeBucket<K, V> bucket = new OSBTreeBucket<K, V>(cacheEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, cacheEntry));
    int itemIndex = bucket.size() - 1;
    try {
        while (true) {
            if (!bucket.isLeaf()) {
                if (itemIndex < -1) {
                    if (!path.isEmpty()) {
                        PagePathItemUnit pagePathItemUnit = path.removeLast();
                        bucketIndex = pagePathItemUnit.pageIndex;
                        itemIndex = pagePathItemUnit.itemIndex - 1;
                    } else
                        return null;
                } else {
                    path.add(new PagePathItemUnit(bucketIndex, itemIndex));
                    if (itemIndex > -1) {
                        OSBTreeBucket.SBTreeEntry<K, V> entry = bucket.getEntry(itemIndex);
                        bucketIndex = entry.rightChild;
                    } else {
                        OSBTreeBucket.SBTreeEntry<K, V> entry = bucket.getEntry(0);
                        bucketIndex = entry.leftChild;
                    }
                    itemIndex = OSBTreeBucket.MAX_PAGE_SIZE_BYTES + 1;
                }
            } else {
                if (bucket.isEmpty()) {
                    if (!path.isEmpty()) {
                        PagePathItemUnit pagePathItemUnit = path.removeLast();
                        bucketIndex = pagePathItemUnit.pageIndex;
                        itemIndex = pagePathItemUnit.itemIndex - 1;
                    } else
                        return null;
                } else {
                    final ArrayList<Long> resultPath = new ArrayList<Long>(path.size() + 1);
                    for (PagePathItemUnit pathItemUnit : path) resultPath.add(pathItemUnit.pageIndex);
                    resultPath.add(bucketIndex);
                    return new BucketSearchResult(bucket.size() - 1, resultPath);
                }
            }
            cacheEntry.releaseSharedLock();
            releasePage(atomicOperation, cacheEntry);
            cacheEntry = loadPage(atomicOperation, fileId, bucketIndex, false);
            cacheEntry.acquireSharedLock();
            bucket = new OSBTreeBucket<K, V>(cacheEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, cacheEntry));
            if (itemIndex == OSBTreeBucket.MAX_PAGE_SIZE_BYTES + 1)
                itemIndex = bucket.size() - 1;
        }
    } finally {
        cacheEntry.releaseSharedLock();
        releasePage(atomicOperation, cacheEntry);
    }
}
Also used : OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry)

Example 5 with OCacheEntry

use of com.orientechnologies.orient.core.storage.cache.OCacheEntry in project orientdb by orientechnologies.

the class OSBTree method splitNonRootBucket.

private BucketSearchResult splitNonRootBucket(List<Long> path, int keyIndex, K keyToInsert, long pageIndex, OSBTreeBucket<K, V> bucketToSplit, boolean splitLeaf, int indexToSplit, K separationKey, List<OSBTreeBucket.SBTreeEntry<K, V>> rightEntries, OAtomicOperation atomicOperation) throws IOException {
    OCacheEntry rightBucketEntry = addPage(atomicOperation, fileId);
    rightBucketEntry.acquireExclusiveLock();
    try {
        OSBTreeBucket<K, V> newRightBucket = new OSBTreeBucket<K, V>(rightBucketEntry, splitLeaf, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, rightBucketEntry));
        newRightBucket.addAll(rightEntries);
        bucketToSplit.shrink(indexToSplit);
        if (splitLeaf) {
            long rightSiblingPageIndex = bucketToSplit.getRightSibling();
            newRightBucket.setRightSibling(rightSiblingPageIndex);
            newRightBucket.setLeftSibling(pageIndex);
            bucketToSplit.setRightSibling(rightBucketEntry.getPageIndex());
            if (rightSiblingPageIndex >= 0) {
                final OCacheEntry rightSiblingBucketEntry = loadPage(atomicOperation, fileId, rightSiblingPageIndex, false);
                rightSiblingBucketEntry.acquireExclusiveLock();
                OSBTreeBucket<K, V> rightSiblingBucket = new OSBTreeBucket<K, V>(rightSiblingBucketEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, rightSiblingBucketEntry));
                try {
                    rightSiblingBucket.setLeftSibling(rightBucketEntry.getPageIndex());
                } finally {
                    rightSiblingBucketEntry.releaseExclusiveLock();
                    releasePage(atomicOperation, rightSiblingBucketEntry);
                }
            }
        }
        long parentIndex = path.get(path.size() - 2);
        OCacheEntry parentCacheEntry = loadPage(atomicOperation, fileId, parentIndex, false);
        parentCacheEntry.acquireExclusiveLock();
        try {
            OSBTreeBucket<K, V> parentBucket = new OSBTreeBucket<K, V>(parentCacheEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, parentCacheEntry));
            OSBTreeBucket.SBTreeEntry<K, V> parentEntry = new OSBTreeBucket.SBTreeEntry<K, V>(pageIndex, rightBucketEntry.getPageIndex(), separationKey, null);
            int insertionIndex = parentBucket.find(separationKey);
            assert insertionIndex < 0;
            insertionIndex = -insertionIndex - 1;
            while (!parentBucket.addEntry(insertionIndex, parentEntry, true)) {
                parentCacheEntry.releaseExclusiveLock();
                releasePage(atomicOperation, parentCacheEntry);
                BucketSearchResult bucketSearchResult = splitBucket(path.subList(0, path.size() - 1), insertionIndex, separationKey, atomicOperation);
                parentIndex = bucketSearchResult.getLastPathItem();
                parentCacheEntry = loadPage(atomicOperation, fileId, parentIndex, false);
                parentCacheEntry.acquireExclusiveLock();
                insertionIndex = bucketSearchResult.itemIndex;
                parentBucket = new OSBTreeBucket<K, V>(parentCacheEntry, keySerializer, keyTypes, valueSerializer, getChanges(atomicOperation, parentCacheEntry));
            }
        } finally {
            parentCacheEntry.releaseExclusiveLock();
            releasePage(atomicOperation, parentCacheEntry);
        }
    } finally {
        rightBucketEntry.releaseExclusiveLock();
        releasePage(atomicOperation, rightBucketEntry);
    }
    ArrayList<Long> resultPath = new ArrayList<Long>(path.subList(0, path.size() - 1));
    if (comparator.compare(keyToInsert, separationKey) < 0) {
        resultPath.add(pageIndex);
        return new BucketSearchResult(keyIndex, resultPath);
    }
    resultPath.add(rightBucketEntry.getPageIndex());
    if (splitLeaf) {
        return new BucketSearchResult(keyIndex - indexToSplit, resultPath);
    }
    resultPath.add(rightBucketEntry.getPageIndex());
    return new BucketSearchResult(keyIndex - indexToSplit - 1, resultPath);
}
Also used : OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry)

Aggregations

OCacheEntry (com.orientechnologies.orient.core.storage.cache.OCacheEntry)210 OAtomicOperation (com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation)77 ByteBuffer (java.nio.ByteBuffer)77 OLogSequenceNumber (com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OLogSequenceNumber)74 OByteBufferPool (com.orientechnologies.common.directmemory.OByteBufferPool)69 OCachePointer (com.orientechnologies.orient.core.storage.cache.OCachePointer)65 IOException (java.io.IOException)62 OIndexException (com.orientechnologies.orient.core.index.OIndexException)23 OIdentifiable (com.orientechnologies.orient.core.db.record.OIdentifiable)20 OSessionStoragePerformanceStatistic (com.orientechnologies.orient.core.storage.impl.local.statistic.OSessionStoragePerformanceStatistic)20 OWALChangesTree (com.orientechnologies.orient.core.storage.impl.local.paginated.wal.OWALChangesTree)19 OException (com.orientechnologies.common.exception.OException)17 Test (org.testng.annotations.Test)17 ORecordId (com.orientechnologies.orient.core.id.ORecordId)14 OStorageException (com.orientechnologies.orient.core.exception.OStorageException)13 OLocalHashTableException (com.orientechnologies.orient.core.exception.OLocalHashTableException)12 OSBTreeBonsaiLocalException (com.orientechnologies.orient.core.exception.OSBTreeBonsaiLocalException)11 Lock (java.util.concurrent.locks.Lock)11 Random (java.util.Random)9 HashMap (java.util.HashMap)8