Пример #1
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);
                }
            }
        }
Пример #2
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private static <KEY, VALUE> long writeEntries(org.neo4j.io.fs.StoreChannel targetChannel, ByteBuffer byteBuffer, org.neo4j.index.internal.gbptree.Layout<KEY,VALUE> layout, BlockEntryCursor<KEY,VALUE> blockEntryCursor, Cancellation cancellation, System.Action<int> entryCountReporter) throws java.io.IOException
        private static long WriteEntries <KEY, VALUE>(StoreChannel targetChannel, ByteBuffer byteBuffer, Layout <KEY, VALUE> layout, BlockEntryCursor <KEY, VALUE> blockEntryCursor, Cancellation cancellation, System.Action <int> entryCountReporter)
        {
            // Loop over block entries
            long actualDataSize            = BlockHeaderSize;
            ByteArrayPageCursor pageCursor = new ByteArrayPageCursor(byteBuffer);
            int entryCountToReport         = 0;

            while (blockEntryCursor.Next())
            {
                KEY   key       = blockEntryCursor.Key();
                VALUE value     = blockEntryCursor.Value();
                int   entrySize = BlockEntry.EntrySize(layout, key, value);
                actualDataSize += entrySize;
                entryCountToReport++;

                if (byteBuffer.remaining() < entrySize)
                {
                    // First check if this merge have been cancelled, if so just break here, it's fine.
                    if (cancellation.Cancelled())
                    {
                        break;
                    }

                    // flush and reset + DON'T PAD!!!
                    byteBuffer.flip();
                    targetChannel.WriteAll(byteBuffer);
                    byteBuffer.clear();
                    entryCountReporter(entryCountToReport);
                    entryCountToReport = 0;
                }

                BlockEntry.Write(pageCursor, layout, key, value);
            }
            if (entryCountToReport > 0)
            {
                entryCountReporter(entryCountToReport);
            }
            return(actualDataSize);
        }