6 def first_block(data_locators, range_start, range_size, debug=False):
9 # range_start/block_start is the inclusive lower bound
10 # range_end/block_end is the exclusive upper bound
12 hi = len(data_locators)
14 i = int((hi + lo) / 2)
15 block_size = data_locators[i][BLOCKSIZE]
16 block_start = data_locators[i][OFFSET]
17 block_end = block_start + block_size
20 # perform a binary search for the first block
21 # assumes that all of the blocks are contigious, so range_start is guaranteed
22 # to either fall into the range of a block or be outside the block range entirely
23 while not (range_start >= block_start and range_start < block_end):
25 # must be out of range, fail
27 if range_start > block_start:
31 i = int((hi + lo) / 2)
32 if debug: print lo, i, hi
33 block_size = data_locators[i][BLOCKSIZE]
34 block_start = data_locators[i][OFFSET]
35 block_end = block_start + block_size
39 def locators_and_ranges(data_locators, range_start, range_size, debug=False):
41 Get blocks that are covered by the range
42 data_locators: list of [locator, block_size, block_start], assumes that blocks are in order and contigous
43 range_start: start of range
44 range_size: size of range
45 returns list of [block locator, blocksize, segment offset, segment size] that satisfies the range
50 range_start = long(range_start)
51 range_size = long(range_size)
52 range_end = range_start + range_size
54 i = first_block(data_locators, range_start, range_size, debug)
58 while i < len(data_locators):
59 locator, block_size, block_start = data_locators[i]
60 block_end = block_start + block_size
62 print locator, "range_start", range_start, "block_start", block_start, "range_end", range_end, "block_end", block_end
63 if range_end <= block_start:
64 # range ends before this block starts, so don't look at any more locators
67 #if range_start >= block_end:
68 # range starts after this block ends, so go to next block
69 # we should always start at the first block due to the binary above, so this test is redundant
72 if range_start >= block_start and range_end <= block_end:
73 # range starts and ends in this block
74 resp.append([locator, block_size, range_start - block_start, range_size])
75 elif range_start >= block_start and range_end > block_end:
76 # range starts in this block
77 resp.append([locator, block_size, range_start - block_start, block_end - range_start])
78 elif range_start < block_start and range_end > block_end:
79 # range starts in a previous block and extends to further blocks
80 resp.append([locator, block_size, 0L, block_size])
81 elif range_start < block_start and range_end <= block_end:
82 # range starts in a previous block and ends in this block
83 resp.append([locator, block_size, 0L, range_end - block_start])
84 block_start = block_end
88 def replace_range(data_locators, range_start, range_size, new_locator, debug=False):
90 Replace a file segment range with a new segment.
91 data_locators: list of [locator, segment_size, segment_start], assumes that segments are in order and contigous
92 range_start: start of range
93 range_size: size of range
94 new_locator: locator for new segment to be inserted
95 !!! data_locators will be updated in place !!!
100 range_start = long(range_start)
101 range_size = long(range_size)
102 range_end = range_start + range_size
104 last = data_locators[-1]
105 if (last[OFFSET]+last[BLOCKSIZE]) == range_start:
106 # extend last segment
107 last[BLOCKSIZE] += range_size
110 i = first_block(data_locators, range_start, range_size, debug)
114 while i < len(data_locators):
115 locator, segment_size, segment_start = data_locators[i]
116 segment_end = segment_start + segment_size
118 print locator, "range_start", range_start, "segment_start", segment_start, "range_end", range_end, "segment_end", segment_end
119 if range_end <= segment_start:
120 # range ends before this segment starts, so don't look at any more locators
123 #if range_start >= segment_end:
124 # range starts after this segment ends, so go to next segment
125 # we should always start at the first segment due to the binary above, so this test is redundant
128 if range_start >= segment_start and range_end <= segment_end:
129 # range starts and ends in this segment
130 # split segment into 3 pieces
131 if (range_start-segment_start) > 0:
132 data_locators[i] = [locator, (range_start-segment_start), segment_start]
133 data_locators.insert(i+1, [new_locator, range_size, range_start])
135 data_locators[i] = [new_locator, range_size, range_start]
137 if (segment_end-range_end) > 0:
138 data_locators.insert(i+2, [(locator + (range_start-segment_start) + range_size), (segment_end-range_end), range_end])
140 elif range_start >= segment_start and range_end > segment_end:
141 # range starts in this segment
142 # split segment into 2 pieces
143 data_locators[i] = [locator, (range_start-segment_start), segment_start]
144 data_locators.insert(i+1, [new_locator, range_size, range_start])
146 elif range_start < segment_start and range_end > segment_end:
147 # range starts in a previous segment and extends to further segments
148 # delete this segment
151 elif range_start < segment_start and range_end <= segment_end:
152 # range starts in a previous segment and ends in this segment
153 # move the starting point of this segment up, and shrink it.
154 data_locators[i] = [locator+(range_end-segment_start), (segment_end-range_end), range_end]
156 segment_start = segment_end