Skip to content

Commit 85f6b58

Browse files
committed
Less cursors are needed for iteration.
1 parent 7399f3f commit 85f6b58

File tree

1 file changed

+93
-75
lines changed

1 file changed

+93
-75
lines changed

BTDB/ODBLayer/RelationEnumerator.cs

+93-75
Original file line numberDiff line numberDiff line change
@@ -587,8 +587,7 @@ public class RelationAdvancedEnumerator<T> : IEnumerator<T>, ICollection<T>
587587
protected readonly RelationInfo.ItemLoaderInfo ItemLoader;
588588
readonly IInternalObjectDBTransaction _tr;
589589
readonly IKeyValueDBTransaction _keyValueTr;
590-
IKeyValueDBCursor? _startCursor;
591-
IKeyValueDBCursor? _endCursor;
590+
IKeyValueDBCursor? _untilCursor;
592591
IKeyValueDBCursor? _cursor;
593592
bool _seekNeeded;
594593
readonly bool _ascending;
@@ -628,85 +627,106 @@ public RelationAdvancedEnumerator(
628627

629628
void CreateCursors()
630629
{
631-
_startCursor = _keyValueTr.CreateCursor();
632-
if (_startKeyProposition == KeyProposition.Ignored)
630+
IKeyValueDBCursor? startCursor = null;
631+
IKeyValueDBCursor? endCursor = null;
632+
try
633633
{
634-
if (!_startCursor.FindFirstKey(_keyBytes))
634+
startCursor = _keyValueTr.CreateCursor();
635+
if (_startKeyProposition == KeyProposition.Ignored)
635636
{
636-
return;
637+
if (!startCursor.FindFirstKey(_keyBytes))
638+
{
639+
return;
640+
}
637641
}
638-
}
639-
else
640-
{
641-
switch (_startCursor.Find(_startKeyBytes, (uint)_keyBytes.Length))
642+
else
642643
{
643-
case FindResult.Exact:
644-
if (_startKeyProposition == KeyProposition.Excluded)
645-
{
646-
if (!_startCursor.FindNextKey(_keyBytes)) return;
647-
}
644+
switch (startCursor.Find(_startKeyBytes, (uint)_keyBytes.Length))
645+
{
646+
case FindResult.Exact:
647+
if (_startKeyProposition == KeyProposition.Excluded)
648+
{
649+
if (!startCursor.FindNextKey(_keyBytes)) return;
650+
}
648651

649-
break;
650-
case FindResult.Previous:
651-
if (!_startCursor.FindNextKey(_keyBytes)) return;
652-
if (_startKeyProposition == KeyProposition.Excluded)
653-
{
654-
if (!_startCursor.FindNextKey(_keyBytes)) return;
655-
}
652+
break;
653+
case FindResult.Previous:
654+
if (!startCursor.FindNextKey(_keyBytes)) return;
655+
if (_startKeyProposition == KeyProposition.Excluded)
656+
{
657+
if (!startCursor.FindNextKey(_keyBytes)) return;
658+
}
656659

657-
break;
658-
case FindResult.Next:
659-
if (_startKeyProposition == KeyProposition.Excluded && _startCursor.KeyHasPrefix(_startKeyBytes))
660-
{
661-
if (!_startCursor.FindNextKey(_keyBytes)) return;
662-
}
660+
break;
661+
case FindResult.Next:
662+
if (_startKeyProposition == KeyProposition.Excluded && startCursor.KeyHasPrefix(_startKeyBytes))
663+
{
664+
if (!startCursor.FindNextKey(_keyBytes)) return;
665+
}
663666

664-
break;
665-
case FindResult.NotFound:
666-
return;
667-
default:
668-
throw new ArgumentOutOfRangeException();
667+
break;
668+
case FindResult.NotFound:
669+
return;
670+
default:
671+
throw new ArgumentOutOfRangeException();
672+
}
669673
}
670-
}
671674

672-
_endCursor = _keyValueTr.CreateCursor();
673-
var realEndKeyBytes = new ReadOnlySpan<byte>(_endKeyBytes);
674-
if (_endKeyProposition == KeyProposition.Included)
675-
realEndKeyBytes = FindLastKeyWithPrefix(_endKeyBytes.AsSpan(), _endCursor);
675+
endCursor = _keyValueTr.CreateCursor();
676+
var realEndKeyBytes = new ReadOnlySpan<byte>(_endKeyBytes);
677+
if (_endKeyProposition == KeyProposition.Included)
678+
realEndKeyBytes = FindLastKeyWithPrefix(_endKeyBytes.AsSpan(), endCursor);
676679

677-
if (_endKeyProposition == KeyProposition.Ignored)
678-
{
679-
if (!_endCursor.FindLastKey(_keyBytes)) return;
680-
}
681-
else
682-
{
683-
switch (_endCursor.Find(realEndKeyBytes, (uint)_keyBytes.Length))
680+
if (_endKeyProposition == KeyProposition.Ignored)
684681
{
685-
case FindResult.Exact:
686-
if (_endKeyProposition == KeyProposition.Excluded)
687-
{
688-
if (!_endCursor.FindPreviousKey(_keyBytes)) return;
689-
}
682+
if (!endCursor.FindLastKey(_keyBytes)) return;
683+
}
684+
else
685+
{
686+
switch (endCursor.Find(realEndKeyBytes, (uint)_keyBytes.Length))
687+
{
688+
case FindResult.Exact:
689+
if (_endKeyProposition == KeyProposition.Excluded)
690+
{
691+
if (!endCursor.FindPreviousKey(_keyBytes)) return;
692+
}
690693

691-
break;
692-
case FindResult.Previous:
693-
break;
694-
case FindResult.Next:
695-
if (!_endCursor.FindPreviousKey(_keyBytes)) return;
696-
break;
697-
case FindResult.NotFound:
698-
return;
699-
default:
700-
throw new ArgumentOutOfRangeException();
694+
break;
695+
case FindResult.Previous:
696+
break;
697+
case FindResult.Next:
698+
if (!endCursor.FindPreviousKey(_keyBytes)) return;
699+
break;
700+
case FindResult.NotFound:
701+
return;
702+
default:
703+
throw new ArgumentOutOfRangeException();
704+
}
701705
}
702-
}
703706

704-
var startIndex = _startCursor.GetKeyIndex();
705-
var endIndex = _endCursor.GetKeyIndex();
706-
if (startIndex > endIndex) return;
707-
_cursor = _keyValueTr.CreateCursor();
708-
_cursor.FindKeyIndex(_ascending ? startIndex : endIndex);
709-
_seekNeeded = true;
707+
var startIndex = startCursor.GetKeyIndex();
708+
var endIndex = endCursor.GetKeyIndex();
709+
if (startIndex > endIndex) return;
710+
if (_ascending)
711+
{
712+
_cursor = startCursor;
713+
_untilCursor = endCursor;
714+
}
715+
else
716+
{
717+
_cursor = endCursor;
718+
_untilCursor = startCursor;
719+
}
720+
721+
startCursor = null;
722+
endCursor = null;
723+
_seekNeeded = true;
724+
}
725+
finally
726+
{
727+
startCursor?.Dispose();
728+
endCursor?.Dispose();
729+
}
710730
}
711731

712732
public RelationAdvancedEnumerator(
@@ -754,7 +774,7 @@ public bool MoveNext()
754774
return false;
755775
}
756776

757-
if (_cursor.GetKeyIndex() > _endCursor!.GetKeyIndex())
777+
if (_cursor.GetKeyIndex() > _untilCursor!.GetKeyIndex())
758778
{
759779
return false;
760780
}
@@ -766,7 +786,7 @@ public bool MoveNext()
766786
return false;
767787
}
768788

769-
if (_cursor.GetKeyIndex() < _startCursor!.GetKeyIndex())
789+
if (_cursor.GetKeyIndex() < _untilCursor!.GetKeyIndex())
770790
{
771791
return false;
772792
}
@@ -809,10 +829,8 @@ public byte[] GetKeyBytes()
809829

810830
public void Dispose()
811831
{
812-
_startCursor?.Dispose();
813-
_startCursor = null;
814-
_endCursor?.Dispose();
815-
_endCursor = null;
832+
_untilCursor?.Dispose();
833+
_untilCursor = null;
816834
_cursor?.Dispose();
817835
_cursor = null;
818836
}
@@ -848,7 +866,7 @@ public void CopyTo(T[] array, int arrayIndex)
848866
CreateCursors();
849867
try
850868
{
851-
var count = _endCursor == null ? 0 : (int)(_endCursor.GetKeyIndex() - _startCursor!.GetKeyIndex() + 1);
869+
var count = _cursor == null ? 0 : (int)(Math.Abs(_cursor.GetKeyIndex() - _untilCursor!.GetKeyIndex()) + 1);
852870
if (count == 0) return;
853871
if (array.Length - arrayIndex < count) throw new ArgumentException("Array too small");
854872
while (MoveNext())
@@ -874,7 +892,7 @@ public int Count
874892
try
875893
{
876894
CreateCursors();
877-
return _endCursor == null ? 0 : (int)(_endCursor.GetKeyIndex() - _startCursor!.GetKeyIndex() + 1);
895+
return _cursor == null ? 0 : (int)(Math.Abs(_cursor.GetKeyIndex() - _untilCursor!.GetKeyIndex()) + 1);
878896
}
879897
finally
880898
{

0 commit comments

Comments
 (0)