/// <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); } } }
//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); }