Search in sources :

Example 26 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 27 with OCacheEntry

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

the class OSBTreeBonsaiLocal method reuseBucketFromFreeList.

private AllocationResult reuseBucketFromFreeList(OSysBucket sysBucket, OAtomicOperation atomicOperation) throws IOException {
    final OBonsaiBucketPointer oldFreeListHead = sysBucket.getFreeListHead();
    assert oldFreeListHead.isValid();
    OCacheEntry cacheEntry = loadPage(atomicOperation, fileId, oldFreeListHead.getPageIndex(), false);
    cacheEntry.acquireExclusiveLock();
    try {
        final OSBTreeBonsaiBucket<K, V> bucket = new OSBTreeBonsaiBucket<K, V>(cacheEntry, oldFreeListHead.getPageOffset(), keySerializer, valueSerializer, getChanges(atomicOperation, cacheEntry), this);
        sysBucket.setFreeListHead(bucket.getFreeListPointer());
        sysBucket.setFreeListLength(sysBucket.freeListLength() - 1);
    } finally {
        cacheEntry.releaseExclusiveLock();
    }
    return new AllocationResult(oldFreeListHead, cacheEntry);
}
Also used : OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry)

Example 28 with OCacheEntry

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

the class OSBTreeBonsaiLocal method splitBucket.

private BucketSearchResult splitBucket(List<OBonsaiBucketPointer> path, int keyIndex, K keyToInsert, OAtomicOperation atomicOperation) throws IOException {
    final OBonsaiBucketPointer bucketPointer = path.get(path.size() - 1);
    OCacheEntry bucketEntry = loadPage(atomicOperation, fileId, bucketPointer.getPageIndex(), false);
    bucketEntry.acquireExclusiveLock();
    try {
        OSBTreeBonsaiBucket<K, V> bucketToSplit = new OSBTreeBonsaiBucket<K, V>(bucketEntry, bucketPointer.getPageOffset(), keySerializer, valueSerializer, getChanges(atomicOperation, bucketEntry), this);
        final boolean splitLeaf = bucketToSplit.isLeaf();
        final int bucketSize = bucketToSplit.size();
        int indexToSplit = bucketSize >>> 1;
        final K separationKey = bucketToSplit.getKey(indexToSplit);
        final List<OSBTreeBonsaiBucket.SBTreeEntry<K, V>> rightEntries = new ArrayList<OSBTreeBonsaiBucket.SBTreeEntry<K, V>>(indexToSplit);
        final int startRightIndex = splitLeaf ? indexToSplit : indexToSplit + 1;
        for (int i = startRightIndex; i < bucketSize; i++) rightEntries.add(bucketToSplit.getEntry(i));
        if (!bucketPointer.equals(rootBucketPointer)) {
            final AllocationResult allocationResult = allocateBucket(atomicOperation);
            OCacheEntry rightBucketEntry = allocationResult.getCacheEntry();
            final OBonsaiBucketPointer rightBucketPointer = allocationResult.getPointer();
            rightBucketEntry.acquireExclusiveLock();
            try {
                OSBTreeBonsaiBucket<K, V> newRightBucket = new OSBTreeBonsaiBucket<K, V>(rightBucketEntry, rightBucketPointer.getPageOffset(), splitLeaf, keySerializer, valueSerializer, getChanges(atomicOperation, rightBucketEntry), this);
                newRightBucket.addAll(rightEntries);
                bucketToSplit.shrink(indexToSplit);
                if (splitLeaf) {
                    OBonsaiBucketPointer rightSiblingBucketPointer = bucketToSplit.getRightSibling();
                    newRightBucket.setRightSibling(rightSiblingBucketPointer);
                    newRightBucket.setLeftSibling(bucketPointer);
                    bucketToSplit.setRightSibling(rightBucketPointer);
                    if (rightSiblingBucketPointer.isValid()) {
                        final OCacheEntry rightSiblingBucketEntry = loadPage(atomicOperation, fileId, rightSiblingBucketPointer.getPageIndex(), false);
                        rightSiblingBucketEntry.acquireExclusiveLock();
                        OSBTreeBonsaiBucket<K, V> rightSiblingBucket = new OSBTreeBonsaiBucket<K, V>(rightSiblingBucketEntry, rightSiblingBucketPointer.getPageOffset(), keySerializer, valueSerializer, getChanges(atomicOperation, rightSiblingBucketEntry), this);
                        try {
                            rightSiblingBucket.setLeftSibling(rightBucketPointer);
                        } finally {
                            rightSiblingBucketEntry.releaseExclusiveLock();
                            releasePage(atomicOperation, rightSiblingBucketEntry);
                        }
                    }
                }
                OBonsaiBucketPointer parentBucketPointer = path.get(path.size() - 2);
                OCacheEntry parentCacheEntry = loadPage(atomicOperation, fileId, parentBucketPointer.getPageIndex(), false);
                parentCacheEntry.acquireExclusiveLock();
                try {
                    OSBTreeBonsaiBucket<K, V> parentBucket = new OSBTreeBonsaiBucket<K, V>(parentCacheEntry, parentBucketPointer.getPageOffset(), keySerializer, valueSerializer, getChanges(atomicOperation, parentCacheEntry), this);
                    OSBTreeBonsaiBucket.SBTreeEntry<K, V> parentEntry = new OSBTreeBonsaiBucket.SBTreeEntry<K, V>(bucketPointer, rightBucketPointer, 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);
                        parentBucketPointer = bucketSearchResult.getLastPathItem();
                        parentCacheEntry = loadPage(atomicOperation, fileId, parentBucketPointer.getPageIndex(), false);
                        parentCacheEntry.acquireExclusiveLock();
                        insertionIndex = bucketSearchResult.itemIndex;
                        parentBucket = new OSBTreeBonsaiBucket<K, V>(parentCacheEntry, parentBucketPointer.getPageOffset(), keySerializer, valueSerializer, getChanges(atomicOperation, parentCacheEntry), this);
                    }
                } finally {
                    parentCacheEntry.releaseExclusiveLock();
                    releasePage(atomicOperation, parentCacheEntry);
                }
            } finally {
                rightBucketEntry.releaseExclusiveLock();
                releasePage(atomicOperation, rightBucketEntry);
            }
            ArrayList<OBonsaiBucketPointer> resultPath = new ArrayList<OBonsaiBucketPointer>(path.subList(0, path.size() - 1));
            if (comparator.compare(keyToInsert, separationKey) < 0) {
                resultPath.add(bucketPointer);
                return new BucketSearchResult(keyIndex, resultPath);
            }
            resultPath.add(rightBucketPointer);
            if (splitLeaf) {
                return new BucketSearchResult(keyIndex - indexToSplit, resultPath);
            }
            return new BucketSearchResult(keyIndex - indexToSplit - 1, resultPath);
        } else {
            long treeSize = bucketToSplit.getTreeSize();
            final List<OSBTreeBonsaiBucket.SBTreeEntry<K, V>> leftEntries = new ArrayList<OSBTreeBonsaiBucket.SBTreeEntry<K, V>>(indexToSplit);
            for (int i = 0; i < indexToSplit; i++) leftEntries.add(bucketToSplit.getEntry(i));
            final AllocationResult leftAllocationResult = allocateBucket(atomicOperation);
            OCacheEntry leftBucketEntry = leftAllocationResult.getCacheEntry();
            OBonsaiBucketPointer leftBucketPointer = leftAllocationResult.getPointer();
            final AllocationResult rightAllocationResult = allocateBucket(atomicOperation);
            OCacheEntry rightBucketEntry = rightAllocationResult.getCacheEntry();
            OBonsaiBucketPointer rightBucketPointer = rightAllocationResult.getPointer();
            leftBucketEntry.acquireExclusiveLock();
            try {
                OSBTreeBonsaiBucket<K, V> newLeftBucket = new OSBTreeBonsaiBucket<K, V>(leftBucketEntry, leftBucketPointer.getPageOffset(), splitLeaf, keySerializer, valueSerializer, getChanges(atomicOperation, leftBucketEntry), this);
                newLeftBucket.addAll(leftEntries);
                if (splitLeaf)
                    newLeftBucket.setRightSibling(rightBucketPointer);
            } finally {
                leftBucketEntry.releaseExclusiveLock();
                releasePage(atomicOperation, leftBucketEntry);
            }
            rightBucketEntry.acquireExclusiveLock();
            try {
                OSBTreeBonsaiBucket<K, V> newRightBucket = new OSBTreeBonsaiBucket<K, V>(rightBucketEntry, rightBucketPointer.getPageOffset(), splitLeaf, keySerializer, valueSerializer, getChanges(atomicOperation, rightBucketEntry), this);
                newRightBucket.addAll(rightEntries);
                if (splitLeaf)
                    newRightBucket.setLeftSibling(leftBucketPointer);
            } finally {
                rightBucketEntry.releaseExclusiveLock();
                releasePage(atomicOperation, rightBucketEntry);
            }
            bucketToSplit = new OSBTreeBonsaiBucket<K, V>(bucketEntry, bucketPointer.getPageOffset(), false, keySerializer, valueSerializer, getChanges(atomicOperation, bucketEntry), this);
            bucketToSplit.setTreeSize(treeSize);
            bucketToSplit.addEntry(0, new OSBTreeBonsaiBucket.SBTreeEntry<K, V>(leftBucketPointer, rightBucketPointer, separationKey, null), true);
            ArrayList<OBonsaiBucketPointer> resultPath = new ArrayList<OBonsaiBucketPointer>(path.subList(0, path.size() - 1));
            if (comparator.compare(keyToInsert, separationKey) < 0) {
                resultPath.add(leftBucketPointer);
                return new BucketSearchResult(keyIndex, resultPath);
            }
            resultPath.add(rightBucketPointer);
            if (splitLeaf)
                return new BucketSearchResult(keyIndex - indexToSplit, resultPath);
            return new BucketSearchResult(keyIndex - indexToSplit - 1, resultPath);
        }
    } finally {
        bucketEntry.releaseExclusiveLock();
        releasePage(atomicOperation, bucketEntry);
    }
}
Also used : OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry)

Example 29 with OCacheEntry

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

the class OSBTreeBonsaiLocal method loadEntriesBetween.

@Override
public void loadEntriesBetween(K keyFrom, boolean fromInclusive, K keyTo, boolean toInclusive, RangeResultListener<K, V> listener) {
    final OSessionStoragePerformanceStatistic statistic = performanceStatisticManager.getSessionPerformanceStatistic();
    int readEntries = 0;
    startOperation();
    if (statistic != null)
        statistic.startRidBagEntryReadTimer();
    try {
        atomicOperationsManager.acquireReadLock(this);
        try {
            final Lock lock = FILE_LOCK_MANAGER.acquireSharedLock(fileId);
            try {
                OAtomicOperation atomicOperation = atomicOperationsManager.getCurrentOperation();
                BucketSearchResult bucketSearchResultFrom = findBucket(keyFrom, atomicOperation);
                OBonsaiBucketPointer bucketPointerFrom = bucketSearchResultFrom.getLastPathItem();
                int indexFrom;
                if (bucketSearchResultFrom.itemIndex >= 0) {
                    indexFrom = fromInclusive ? bucketSearchResultFrom.itemIndex : bucketSearchResultFrom.itemIndex + 1;
                } else {
                    indexFrom = -bucketSearchResultFrom.itemIndex - 1;
                }
                BucketSearchResult bucketSearchResultTo = findBucket(keyTo, atomicOperation);
                OBonsaiBucketPointer bucketPointerTo = bucketSearchResultTo.getLastPathItem();
                int indexTo;
                if (bucketSearchResultTo.itemIndex >= 0) {
                    indexTo = toInclusive ? bucketSearchResultTo.itemIndex : bucketSearchResultTo.itemIndex - 1;
                } else {
                    indexTo = -bucketSearchResultTo.itemIndex - 2;
                }
                int startIndex = indexFrom;
                int endIndex;
                OBonsaiBucketPointer bucketPointer = bucketPointerFrom;
                resultsLoop: while (true) {
                    final OCacheEntry cacheEntry = loadPage(atomicOperation, fileId, bucketPointer.getPageIndex(), false);
                    cacheEntry.acquireSharedLock();
                    try {
                        OSBTreeBonsaiBucket<K, V> bucket = new OSBTreeBonsaiBucket<K, V>(cacheEntry, bucketPointer.getPageOffset(), keySerializer, valueSerializer, getChanges(atomicOperation, cacheEntry), this);
                        if (!bucketPointer.equals(bucketPointerTo))
                            endIndex = bucket.size() - 1;
                        else
                            endIndex = indexTo;
                        for (int i = startIndex; i <= endIndex; i++) {
                            if (!listener.addResult(bucket.getEntry(i))) {
                                readEntries++;
                                break resultsLoop;
                            }
                        }
                        if (bucketPointer.equals(bucketPointerTo))
                            break;
                        bucketPointer = bucket.getRightSibling();
                        if (bucketPointer.getPageIndex() < 0)
                            break;
                    } finally {
                        cacheEntry.releaseSharedLock();
                        releasePage(atomicOperation, cacheEntry);
                    }
                    startIndex = 0;
                }
            } finally {
                lock.unlock();
            }
        } catch (IOException ioe) {
            throw OException.wrapException(new OSBTreeBonsaiLocalException("Error during fetch of values between key " + keyFrom + " and key " + keyTo + " in sbtree " + getName(), this), ioe);
        } finally {
            atomicOperationsManager.releaseReadLock(this);
        }
    } finally {
        if (statistic != null)
            statistic.stopRidBagEntryReadTimer(readEntries);
        completeOperation();
    }
}
Also used : OAtomicOperation(com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation) OSBTreeBonsaiLocalException(com.orientechnologies.orient.core.exception.OSBTreeBonsaiLocalException) IOException(java.io.IOException) Lock(java.util.concurrent.locks.Lock) OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry) OSessionStoragePerformanceStatistic(com.orientechnologies.orient.core.storage.impl.local.statistic.OSessionStoragePerformanceStatistic)

Example 30 with OCacheEntry

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

the class OSBTreeBonsaiLocal method initAfterCreate.

private void initAfterCreate(OAtomicOperation atomicOperation) throws IOException {
    initSysBucket(atomicOperation);
    final AllocationResult allocationResult = allocateBucket(atomicOperation);
    OCacheEntry rootCacheEntry = allocationResult.getCacheEntry();
    this.rootBucketPointer = allocationResult.getPointer();
    rootCacheEntry.acquireExclusiveLock();
    try {
        OSBTreeBonsaiBucket<K, V> rootBucket = new OSBTreeBonsaiBucket<K, V>(rootCacheEntry, this.rootBucketPointer.getPageOffset(), true, keySerializer, valueSerializer, getChanges(atomicOperation, rootCacheEntry), this);
        rootBucket.setTreeSize(0);
    } finally {
        rootCacheEntry.releaseExclusiveLock();
        releasePage(atomicOperation, rootCacheEntry);
    }
}
Also used : OCacheEntry(com.orientechnologies.orient.core.storage.cache.OCacheEntry)

Aggregations

OCacheEntry (com.orientechnologies.orient.core.storage.cache.OCacheEntry)209 ByteBuffer (java.nio.ByteBuffer)77 OAtomicOperation (com.orientechnologies.orient.core.storage.impl.local.paginated.atomicoperations.OAtomicOperation)76 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)61 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