| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 1 | package Krawfish::Query::Base::Sorted; |
| 2 | use parent 'Krawfish::Query'; |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 3 | use Krawfish::Log; |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 4 | use strict; |
| 5 | use warnings; |
| 6 | |
| Akron | 1273619 | 2017-03-08 20:31:58 +0100 | [diff] [blame] | 7 | use constant DEBUG => 0; |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 8 | |
| 9 | # TODO: |
| Akron | 15fc197 | 2017-07-20 22:53:00 +0200 | [diff] [blame] | 10 | # Implement using Krawfish::Util::Heap |
| 11 | |
| 12 | # TODO: |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 13 | # Implement as an overwriting ring buffer (FIFO) with |
| 14 | # byte precision. |
| 15 | # |
| 16 | # The recent element indicates the last freed element, |
| 17 | # to know, whenever a sorting fails (i.e. an element has |
| 18 | # an ordering earlier then the earliest element. |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 19 | # |
| 20 | # TODO: |
| 21 | # 0 points to the last bubbled element. That means, if an element |
| 22 | # tries to be buffered that needs to be before this element, a warning |
| 23 | # should be issued, that the buffer was exceeded! |
| 24 | |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 25 | # Elements have: |
| 26 | # <size><data> |
| 27 | |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 28 | sub new { |
| 29 | my $class = shift; |
| 30 | bless { |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 31 | span => shift, |
| 32 | capacity => shift, # The size of the buffer, in the future given in bytes |
| 33 | offset => 0, # The numerical offset for numbered access |
| 34 | size => 0, # The number of elements in the buffer |
| 35 | recent => 0, # Pointer to the last freed element in the buffer |
| 36 | first => 0, # Pointer to the first element in the buffer |
| 37 | last => 0, # Pointer to the last element in the buffer |
| 38 | buffer => [] # Array holding all elements in the buffer |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 39 | }, $class; |
| 40 | }; |
| 41 | |
| 42 | |
| 43 | # Next sorted element |
| 44 | sub next { |
| 45 | my $self = shift; |
| 46 | |
| 47 | while ($self->{span}->next) { |
| 48 | my $next_post = $self->{span}->current; |
| 49 | |
| 50 | # Sort buffer |
| 51 | my $last_index = $self->buffer_last; |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 52 | |
| 53 | print_log('sortbuf', "Last position in buffer is $last_index") if DEBUG; |
| 54 | |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 55 | my $buffer_post = $self->buffer_get($last_index); |
| 56 | |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 57 | if (DEBUG) { |
| 58 | print_log( |
| 59 | 'sortbuf', |
| 60 | 'Last buffer element is ' . ($buffer_post ? '' : 'not') . ' given' |
| 61 | ); |
| 62 | }; |
| 63 | |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 64 | # Compare next posting with last element in buffer |
| 65 | while ($next_post->compare($buffer_post) == -1) { |
| 66 | $last_index--; |
| 67 | |
| 68 | if ($last_index == 0) { |
| 69 | # todo! Add at beginning! |
| 70 | ... |
| 71 | }; |
| 72 | |
| 73 | # Get last buffer post |
| 74 | $buffer_post = $self->buffer_get($last_index); |
| 75 | }; |
| 76 | |
| 77 | # Insert posting at the correct position in the buffered stream |
| 78 | $self->buffer_insert_after($last_index, $next_post); |
| 79 | |
| 80 | # The buffer has reached its limit |
| 81 | if ($self->buffer_length >= $self->capacity) { |
| 82 | return $self->buffer_shift; |
| 83 | }; |
| 84 | }; |
| 85 | |
| 86 | return $self->buffer_shift; |
| 87 | }; |
| 88 | |
| 89 | # Return index to last added element |
| Akron | 290f59f | 2017-08-17 21:55:07 +0200 | [diff] [blame] | 90 | sub buffer_last { |
| 91 | ... |
| 92 | }; |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 93 | |
| 94 | # Points to the latest freed element in the buffer |
| 95 | # (normally this is -1 to first) |
| 96 | sub buffer_recent { |
| 97 | return $_[0]->{recent}; |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 98 | }; |
| 99 | |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 100 | |
| 101 | # Points to the first accessible element in the buffer |
| 102 | sub buffer_first { |
| 103 | return $_[0]->{first}; |
| 104 | }; |
| 105 | |
| 106 | # sub buffer_push; |
| Akron | 290f59f | 2017-08-17 21:55:07 +0200 | [diff] [blame] | 107 | sub buffer_shift { |
| 108 | ... |
| 109 | }; |
| 110 | |
| 111 | sub buffer_get { |
| 112 | ... |
| 113 | }; |
| 114 | |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 115 | sub buffer_insert_after { |
| 116 | my ($self, $index, $element) = @_; |
| Akron | 6ff7b48 | 2017-02-09 01:29:29 +0100 | [diff] [blame] | 117 | }; |
| Akron | d8540bd | 2017-02-06 15:05:26 +0100 | [diff] [blame] | 118 | |
| 119 | 1; |