/// <summary> /// We will loop over all external updates once to add them to the tree. This is done without checking any uniqueness. /// If index is a uniqueness index we will then loop over external updates again and for each ADD or CHANGED update /// we will verify that those entries are unique in the tree and throw as soon as we find a duplicate. </summary> /// <exception cref="IOException"> If something goes wrong while reading from index. </exception> /// <exception cref="IndexEntryConflictException"> If a duplicate is found. </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private void writeExternalUpdatesToTree(RecordingConflictDetector<KEY,VALUE> recordingConflictDetector) throws java.io.IOException, org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException private void WriteExternalUpdatesToTree(RecordingConflictDetector <KEY, VALUE> recordingConflictDetector) { using (Writer <KEY, VALUE> writer = tree.writer(), IndexUpdateCursor <KEY, VALUE> updates = _externalUpdates.reader()) { while (updates.Next() && !_cancellation.cancelled()) { switch (updates.UpdateMode()) { case ADDED: WriteToTree(writer, recordingConflictDetector, updates.Key(), updates.Value()); break; case REMOVED: writer.Remove(updates.Key()); break; case CHANGED: writer.Remove(updates.Key()); WriteToTree(writer, recordingConflictDetector, updates.Key2(), updates.Value()); break; default: throw new System.ArgumentException("Unknown update mode " + updates.UpdateMode()); } _numberOfAppliedExternalUpdates++; } } }
//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++; } } } }
/// <summary> /// Will check if recording conflict detector saw a conflict. If it did, that conflict has been recorded and we will verify uniqueness for this /// value later on. But for now we try and insert conflicting value again but with a relaxed uniqueness constraint. Insert is done with a throwing /// conflict checker which means it will throw if we see same value AND same id in one key. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private void handleMergeConflict(org.neo4j.index.internal.gbptree.Writer<KEY,VALUE> writer, RecordingConflictDetector<KEY,VALUE> recordingConflictDetector, KEY key, VALUE value) throws org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException private void HandleMergeConflict(Writer <KEY, VALUE> writer, RecordingConflictDetector <KEY, VALUE> recordingConflictDetector, KEY key, VALUE value) { if (recordingConflictDetector.wasConflicting()) { // Report conflict KEY copy = layout.newKey(); layout.copyKey(key, copy); recordingConflictDetector.reportConflict(copy); // Insert and overwrite with relaxed uniqueness constraint recordingConflictDetector.RelaxUniqueness(key); writer.Put(key, value); } }
/// <summary> /// Write key and value to tree and record duplicates if any. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: private void writeToTree(org.neo4j.index.internal.gbptree.Writer<KEY,VALUE> writer, RecordingConflictDetector<KEY,VALUE> recordingConflictDetector, KEY key, VALUE value) throws org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException private void WriteToTree(Writer <KEY, VALUE> writer, RecordingConflictDetector <KEY, VALUE> recordingConflictDetector, KEY key, VALUE value) { recordingConflictDetector.controlConflictDetection(key); writer.Merge(key, value, recordingConflictDetector); HandleMergeConflict(writer, recordingConflictDetector, key, value); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: //ORIGINAL LINE: public void scanCompleted(org.neo4j.kernel.impl.api.index.PhaseTracker phaseTracker) throws org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException public override void ScanCompleted(PhaseTracker phaseTracker) { if (!MarkMergeStarted()) { // This populator has already been closed, either from an external cancel or drop call. // Either way we're not supposed to do this merge. return; } try { phaseTracker.EnterPhase(Org.Neo4j.Kernel.Impl.Api.index.PhaseTracker_Phase.Merge); if (_allScanUpdates.Count > 0) { MergeScanUpdates(); } _externalUpdates.doneAdding(); // don't merge and sort the external updates // Build the tree from the scan updates if (_cancellation.cancelled()) { // Do one additional check before starting to write to the tree return; } phaseTracker.EnterPhase(Org.Neo4j.Kernel.Impl.Api.index.PhaseTracker_Phase.Build); File duplicatesFile = new File(storeFile.ParentFile, storeFile.Name + ".dup"); int readBufferSize = SmallerBufferSize(); using (Allocator allocator = _bufferFactory.newLocalAllocator(), IndexKeyStorage <KEY> indexKeyStorage = new IndexKeyStorage <KEY>(fileSystem, duplicatesFile, allocator, readBufferSize, layout)) { RecordingConflictDetector <KEY, VALUE> recordingConflictDetector = new RecordingConflictDetector <KEY, VALUE>(!descriptor.Unique, indexKeyStorage); WriteScanUpdatesToTree(recordingConflictDetector, allocator, readBufferSize); // Apply the external updates phaseTracker.EnterPhase(Org.Neo4j.Kernel.Impl.Api.index.PhaseTracker_Phase.ApplyExternal); WriteExternalUpdatesToTree(recordingConflictDetector); // Verify uniqueness if (descriptor.Unique) { using (IndexKeyStorage.KeyEntryCursor <KEY> allConflictingKeys = recordingConflictDetector.AllConflicts()) { VerifyUniqueKeys(allConflictingKeys); } } } } catch (IOException e) { throw new UncheckedIOException(e); } catch (InterruptedException e) { Thread.CurrentThread.Interrupt(); throw new Exception("Got interrupted, so merge not completed", e); } catch (ExecutionException e) { // Propagating merge exception from other thread Exception executionException = e.InnerException; if (executionException is Exception) { throw ( Exception )executionException; } throw new Exception(executionException); } finally { _mergeOngoingLatch.Signal(); } }