Ejemplo n.º 1
0
        /// <summary>
        /// Merge some number of blocks, how many is decided by mergeFactor, into a single sorted block. This is done by opening <seealso cref="BlockEntryReader"/> on each
        /// block that we want to merge and give them to a <seealso cref="MergingBlockEntryReader"/>. The <seealso cref="BlockEntryReader"/>s are pulled from a <seealso cref="BlockReader"/>
        /// that iterate over Blocks in file in sequential order.
        ///
        /// <seealso cref="MergingBlockEntryReader"/> pull head from each <seealso cref="BlockEntryReader"/> and hand them out in sorted order, making the multiple entry readers look
        /// like a single large and sorted entry reader.
        ///
        /// The large block resulting from the merge is written down to targetChannel by calling
        /// <seealso cref="writeBlock(StoreChannel, BlockEntryCursor, long, long, Cancellation, IntConsumer, ByteBuffer)"/>.
        /// </summary>
        /// <param name="mergeFactor"> How many blocks to merge at the same time. Influence how much memory will be used because each merge block will have it's own
        /// <seealso cref="ByteBuffer"/> that they read from. </param>
        /// <param name="reader"> The <seealso cref="BlockReader"/> to pull blocks / <seealso cref="BlockEntryReader"/>s from. </param>
        /// <param name="targetChannel"> The <seealso cref="StoreChannel"/> to write the merge result to. Result will be appended to current position. </param>
        /// <param name="cancellation"> Injected so that this merge can be cancelled, if an external request to do that comes in. </param>
        /// <param name="readBuffers"> buffers for all block readers. </param>
        /// <param name="writeBuffer"> buffer for writing merged blocks. </param>
        /// <returns> The number of blocks that where merged, most often this will be equal to mergeFactor but can be less if there are fewer blocks left in source. </returns>
        /// <exception cref="IOException"> If something goes wrong when reading from file. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private int performSingleMerge(int mergeFactor, BlockReader<KEY,VALUE> reader, org.neo4j.io.fs.StoreChannel targetChannel, Cancellation cancellation, ByteBuffer[] readBuffers, ByteBuffer writeBuffer) throws java.io.IOException
        private int PerformSingleMerge(int mergeFactor, BlockReader <KEY, VALUE> reader, StoreChannel targetChannel, Cancellation cancellation, ByteBuffer[] readBuffers, ByteBuffer writeBuffer)
        {
            using (MergingBlockEntryReader <KEY, VALUE> merger = new MergingBlockEntryReader <KEY, VALUE>(_layout))
            {
                long blockSize    = 0;
                long entryCount   = 0;
                int  blocksMerged = 0;
                for (int i = 0; i < mergeFactor; i++)
                {
                    readBuffers[i].clear();
                    BlockEntryReader <KEY, VALUE> source = reader.NextBlock(readBuffers[i]);
                    if (source != null)
                    {
                        blockSize  += source.BlockSize();
                        entryCount += source.EntryCount();
                        blocksMerged++;
                        merger.AddSource(source);
                    }
                    else
                    {
                        break;
                    }
                }

                writeBuffer.clear();
                WriteBlock(targetChannel, merger, blockSize, entryCount, cancellation, _monitor.entriesMerged, writeBuffer);
                _monitor.mergedBlocks(blockSize, entryCount, blocksMerged);
                return(blocksMerged);
            }
        }
Ejemplo n.º 2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void writeScanUpdatesToTree(RecordingConflictDetector<KEY,VALUE> recordingConflictDetector, org.neo4j.kernel.impl.index.schema.ByteBufferFactory.Allocator allocator, int bufferSize) throws java.io.IOException, org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException
        private void WriteScanUpdatesToTree(RecordingConflictDetector <KEY, VALUE> recordingConflictDetector, Allocator allocator, int bufferSize)
        {
            using (MergingBlockEntryReader <KEY, VALUE> allEntries = new MergingBlockEntryReader <KEY, VALUE>(layout))
            {
                ByteBuffer singleBlockAssertionBuffer = allocator.Allocate(( int )kibiBytes(8));
                foreach (ThreadLocalBlockStorage part in _allScanUpdates)
                {
                    using (BlockReader <KEY, VALUE> reader = part.BlockStorage.reader())
                    {
                        BlockEntryReader <KEY, VALUE> singleMergedBlock = reader.NextBlock(allocator.Allocate(bufferSize));
                        if (singleMergedBlock != null)
                        {
                            allEntries.AddSource(singleMergedBlock);
                            // Pass in some sort of ByteBuffer here. The point is that there should be no more data to read,
                            // if there is then it's due to a bug in the code and must be fixed.
                            if (reader.NextBlock(singleBlockAssertionBuffer) != null)
                            {
                                throw new System.InvalidOperationException("Final BlockStorage had multiple blocks");
                            }
                        }
                    }
                }

                int asMuchAsPossibleToTheLeft = 1;
                using (Writer <KEY, VALUE> writer = tree.writer(asMuchAsPossibleToTheLeft))
                {
                    while (allEntries.Next() && !_cancellation.cancelled())
                    {
                        WriteToTree(writer, recordingConflictDetector, allEntries.Key(), allEntries.Value());
                        _numberOfAppliedScanUpdates++;
                    }
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// There are two files: sourceFile and targetFile. Blocks are merged, mergeFactor at the time, from source to target. When all blocks from source have
        /// been merged into a larger block one merge iteration is done and source and target are flipped. As long as source contain more than a single block more
        /// merge iterations are needed and we start over again.
        /// When source only contain a single block we are finished and the extra file is deleted and <seealso cref="blockFile"/> contains the result with a single sorted
        /// block.
        ///
        /// See <seealso cref="performSingleMerge(int, BlockReader, StoreChannel, Cancellation, ByteBuffer[], ByteBuffer)"/> for further details.
        /// </summary>
        /// <param name="mergeFactor"> See <seealso cref="performSingleMerge(int, BlockReader, StoreChannel, Cancellation, ByteBuffer[], ByteBuffer)"/>. </param>
        /// <param name="cancellation"> Injected so that this merge can be cancelled, if an external request to do that comes in.
        /// A cancelled merge will leave the same end state file/channel-wise, just not quite completed, which is fine because the merge
        /// was cancelled meaning that the result will not be used for anything other than deletion. </param>
        /// <exception cref="IOException"> If something goes wrong when reading from file. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public void merge(int mergeFactor, Cancellation cancellation) throws java.io.IOException
        public virtual void Merge(int mergeFactor, Cancellation cancellation)
        {
            _monitor.mergeStarted(_entryCount, CalculateNumberOfEntriesWrittenDuringMerges(_entryCount, _numberOfBlocksInCurrentFile, mergeFactor));
            File sourceFile = _blockFile;
            File tempFile   = new File(_blockFile.Parent, _blockFile.Name + ".b");

            try
            {
                using (Allocator mergeBufferAllocator = _bufferFactory.newLocalAllocator())
                {
                    File targetFile = tempFile;

                    // Allocate all buffers that will be used and reused for all merge iterations
                    ByteBuffer   writeBuffer = mergeBufferAllocator.Allocate(_bufferFactory.bufferSize());
                    ByteBuffer[] readBuffers = new ByteBuffer[mergeFactor];
                    for (int i = 0; i < readBuffers.Length; i++)
                    {
                        readBuffers[i] = mergeBufferAllocator.Allocate(_bufferFactory.bufferSize());
                    }

                    while (_numberOfBlocksInCurrentFile > 1)
                    {
                        // Perform one complete merge iteration, merging all blocks from source into target.
                        // After this step, target will contain fewer blocks than source, but may need another merge iteration.
                        using (BlockReader <KEY, VALUE> reader = reader(sourceFile), StoreChannel targetChannel = _fs.open(targetFile, OpenMode.READ_WRITE))
                        {
                            long blocksMergedSoFar  = 0;
                            long blocksInMergedFile = 0;
                            while (!cancellation.Cancelled() && blocksMergedSoFar < _numberOfBlocksInCurrentFile)
                            {
                                blocksMergedSoFar += PerformSingleMerge(mergeFactor, reader, targetChannel, cancellation, readBuffers, writeBuffer);
                                blocksInMergedFile++;
                            }
                            _numberOfBlocksInCurrentFile = blocksInMergedFile;
                            _monitor.mergeIterationFinished(blocksMergedSoFar, blocksInMergedFile);
                        }

                        // Flip and restore the channels
                        File tmpSourceFile = sourceFile;
                        sourceFile = targetFile;
                        targetFile = tmpSourceFile;
                    }
                }
            }
            finally
            {
                if (sourceFile == _blockFile)
                {
                    _fs.deleteFile(tempFile);
                }
                else
                {
                    _fs.deleteFile(_blockFile);
                    _fs.renameFile(tempFile, _blockFile);
                }
            }
        }
Ejemplo n.º 4
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void assertContents(org.neo4j.index.internal.gbptree.SimpleLongLayout layout, BlockStorage<org.apache.commons.lang3.mutable.MutableLong,org.apache.commons.lang3.mutable.MutableLong> storage, Iterable<java.util.List<BlockEntry<org.apache.commons.lang3.mutable.MutableLong,org.apache.commons.lang3.mutable.MutableLong>>> expectedBlocks) throws java.io.IOException
        private void AssertContents(SimpleLongLayout layout, BlockStorage <MutableLong, MutableLong> storage, IEnumerable <IList <BlockEntry <MutableLong, MutableLong> > > expectedBlocks)
        {
            using (BlockReader <MutableLong, MutableLong> reader = storage.Reader())
            {
                foreach (IList <BlockEntry <MutableLong, MutableLong> > expectedBlock in expectedBlocks)
                {
                    using (BlockEntryReader <MutableLong, MutableLong> block = reader.NextBlock(HEAP_ALLOCATOR.allocate(1024)))
                    {
                        assertNotNull(block);
                        assertEquals(expectedBlock.Count, block.EntryCount());
                        foreach (BlockEntry <MutableLong, MutableLong> expectedEntry in expectedBlock)
                        {
                            assertTrue(block.Next());
                            assertEquals(0, layout.Compare(expectedEntry.Key(), block.Key()));
                            assertEquals(expectedEntry.Value(), block.Value());
                        }
                    }
                }
            }
        }