@@ -20,13 +20,13 @@ class Log::Metadata
20
20
# When the metadata is defragmented max_total_size will be updated with size
21
21
protected getter max_total_size : Int32
22
22
@max_total_size = uninitialized Int32
23
- # How many entries are potentially overridden from parent (ie: initial entries.size)
24
- @overridden_size = uninitialized Int32
25
23
# How many entries are stored from @first.
26
- # Initially are @overridden_size, the one explicitly overridden in entries argument.
27
24
# When the metadata is defragmented @size will be increased up to
28
25
# the actual number of entries resulting from merging the parent
29
26
@size = uninitialized Int32
27
+ # Numer of parent elements we've copied on defrag
28
+ @parent_size = uninitialized Int32
29
+
30
30
# @first needs to be the last ivar of Metadata. The entries are allocated together with self
31
31
@first = uninitialized Entry
32
32
@@ -42,18 +42,18 @@ class Log::Metadata
42
42
end
43
43
44
44
protected def setup (@parent : Metadata ?, entries : NamedTuple | Hash )
45
- @size = @overridden_size = entries.size
45
+ @size = entries.size
46
+ @parent_size = 0
46
47
parent_size = (@parent .try(& .max_total_size) || 0 )
47
48
@max_total_size = @size + parent_size
48
49
ptr_entries = pointerof (@first )
49
50
50
- # Use parent_size as offset to make room for parent entries when defragging
51
51
if entries.is_a?(NamedTuple )
52
- entries.each_with_index(parent_size) do |key , value , i |
52
+ entries.each_with_index do |key , value , i |
53
53
ptr_entries[i] = {key: key, value: Value .to_metadata_value(value)}
54
54
end
55
55
else
56
- entries.each_with_index(parent_size) do |(key , value ), i |
56
+ entries.each_with_index do |(key , value ), i |
57
57
ptr_entries[i] = {key: key, value: Value .to_metadata_value(value)}
58
58
end
59
59
end
@@ -93,57 +93,51 @@ class Log::Metadata
93
93
# will be recomputed, but the result should be the same.
94
94
#
95
95
# * @parent.nil? signals if the defrag is needed/done
96
- # * The values of @overridden_size, pointerof(@first) are never changed
96
+ # * The value of pointerof(@first) are never changed
97
97
# * @parent is set at the very end of the method
98
98
protected def defrag
99
99
parent = @parent
100
100
return if parent.nil?
101
101
102
102
ptr_entries = pointerof (@first )
103
- next_free_entry = ptr_entries
104
- # Math to get @size from end
105
- my_entries = ptr_entries + (@max_total_size - @size )
103
+ next_free_entry = ptr_entries + @size
104
+ total_size = @size
106
105
107
- # Copy all parent entries to the beginning of "our" entries
106
+ # Copy parent entries that ain't overwritten
108
107
parent_size = 0
109
- parent.each_with_index do |(key , value ), i |
110
- next_free_entry.value = {key: key, value: value}
111
- next_free_entry += 1
112
- parent_size += 1
113
- end
114
-
115
- total_size = parent_size
116
-
117
- # Move all of "our" entries, but overwrite parent if exists
118
- @size .times do |i |
119
- entry = my_entries[i]
120
-
108
+ parent.each do |(key , value )|
121
109
overwritten = false
122
- parent_size.times do |j |
123
- if ptr_entries[j][:key ] == entry[:key ]
124
- # Overwrite parent entry with our entry
125
- ptr_entries[j] = {key: entry[:key ], value: entry[:value ]}
110
+ @size .times do |i |
111
+ if ptr_entries[i][:key ] == key
126
112
overwritten = true
127
113
break
128
114
end
129
115
end
130
116
next if overwritten
131
-
132
- next_free_entry.value = { key: entry[ :key ], value: entry[ :value ]}
117
+ next_free_entry.value = { key: key, value: value}
118
+ parent_size += 1
133
119
next_free_entry += 1
134
120
total_size += 1
135
121
end
136
122
137
123
@size = total_size
138
124
@max_total_size = total_size
125
+ @parent_size = parent_size
139
126
@parent = nil
140
127
end
141
128
142
129
def each (& : {Symbol , Value } - > )
143
130
defrag
144
131
ptr_entries = pointerof (@first )
132
+ parent_size = @parent_size
133
+ local_size = @size - parent_size
134
+
135
+ parent_size.times do |i |
136
+ entry = ptr_entries[i + local_size]
137
+ yield ({entry[:key ], entry[:value ]})
138
+ end
145
139
146
- @size .times do |i |
140
+ local_size .times do |i |
147
141
entry = ptr_entries[i]
148
142
yield ({entry[:key ], entry[:value ]})
149
143
end
@@ -171,9 +165,9 @@ class Log::Metadata
171
165
172
166
ptr_entries = pointerof (@first )
173
167
# Math to get @size from end
174
- my_entries = ptr_entries + (@max_total_size - @size )
175
- @size .times do |i |
176
- return my_entries [i] if my_entries [i][:key ] == key
168
+ # my_entries = ptr_entries + (@max_total_size - @size)
169
+ ( @size - @parent_size ) .times do |i |
170
+ return ptr_entries [i] if ptr_entries [i][:key ] == key
177
171
end
178
172
179
173
return parent.find_entry(key) if parent
0 commit comments