Skip to content

Commit e31e905

Browse files
committed
python3/qcow2-to-stdout: Implement Interval for checking sparse cluster allocation
Instead of using a set with every individual allocated cluster index as a member, use a sorted list of intervals to verify if cluster is allocated - this uses much less memory and directly follows from the JSON format qcow-stream-tool and vhd-tool output now. Signed-off-by: Andrii Sultanov <andriy.sultanov@vates.tech>
1 parent c6184d1 commit e31e905

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

python3/libexec/qcow2-to-stdout.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,65 @@ def write_features(cluster, offset, data_file_name):
9191
offset += 48
9292

9393

94+
class Interval:
95+
"""
96+
Represents the allocated virtual cluster intervals in a sparse file
97+
"""
98+
def __init__(self, lst):
99+
self.intervals = lst
100+
self.intervals.sort(key=lambda x: x[0])
101+
102+
103+
def __contains__(self, cluster):
104+
"""
105+
Checks if cluster is in one of the intervals, removes it from the
106+
interval if true
107+
"""
108+
# Check if cluster is within [min, max]
109+
if (len(self.intervals) == 0 or
110+
(self.intervals[-1][1] < cluster or self.intervals[0][0] > cluster)):
111+
return False
112+
113+
# Binary search for the interval that could contain the cluster
114+
l = 0
115+
h = len(self.intervals) - 1
116+
while l <= h:
117+
mid = (l + h) // 2
118+
current = self.intervals[mid]
119+
120+
if cluster >= current[0] and cluster <= current[1]:
121+
if cluster == current[0] and cluster == current[1]:
122+
# Remove the cluster from the interval
123+
del self.intervals[mid]
124+
return True
125+
126+
if cluster == current[0]:
127+
# Shrink interval from the left
128+
left = current[0] + 1
129+
right = current[1]
130+
elif cluster == current[1]:
131+
# Shrink interval from the right
132+
left = current[0]
133+
right = current[1] - 1
134+
else:
135+
# Split the original interval into two
136+
left = current[0]
137+
right = cluster
138+
self.intervals.insert(mid+1, [cluster+1, current[1]])
139+
140+
self.intervals[mid] = [left, right]
141+
return True
142+
elif cluster < current[0]:
143+
h = mid - 1
144+
elif cluster > current[1]:
145+
l = mid + 1
146+
147+
return False
148+
149+
def __iter__(self):
150+
return self.intervals.__iter__()
151+
152+
94153
def write_qcow2_content(input_file, cluster_size, refcount_bits,
95154
data_file_name, data_file_raw, diff_file_name,
96155
virtual_size, nonzero_clusters,

0 commit comments

Comments
 (0)