Skip to content

Commit 2e19424

Browse files
committed
New Frame uses a distinct type to express the different mode of operation. This is clean enough to get going
1 parent e814fda commit 2e19424

File tree

1 file changed

+62
-23
lines changed

1 file changed

+62
-23
lines changed

fun.py

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,13 @@ def delta_list_apply(dcl, bbuf, write, lbound_offset=0, size=0):
237237

238238

239239
class DeltaChunkList(list):
240-
"""List with special functionality to deal with DeltaChunks"""
240+
"""List with special functionality to deal with DeltaChunks.
241+
There are two types of lists we represent. The one was created bottom-up, working
242+
towards the latest delta, the other kind was created top-down, working from the
243+
latest delta down to the earliest ancestor. This attribute is queryable
244+
after all processing with is_reversed."""
245+
246+
__slots__ = tuple()
241247

242248
def rbound(self):
243249
""":return: rightmost extend in bytes, absolute"""
@@ -255,24 +261,18 @@ def size(self):
255261
""":return: size of bytes as measured by our delta chunks"""
256262
return self.rbound() - self.lbound()
257263

258-
def connect_with(self, bdcl, tdcl):
264+
def connect_with(self, bdcl):
259265
"""Connect this instance's delta chunks virtually with the given base.
260266
This means that all copy deltas will simply apply to the given region
261267
of the given base. Afterwards, the base is optimized so that add-deltas
262268
will be truncated to the region actually used, or removed completely where
263269
adequate. This way, memory usage is reduced.
264-
:param bdcl: DeltaChunkList to serve as base
265-
:param tdcl: topmost delta chunk list. If set, reverse order is assumed
266-
and the list is connected more efficiently"""
267-
if tdcl is None:
268-
for dc in self:
269-
if not dc.has_data():
270-
dc.set_copy_chunklist(bdcl[dc.so:dc.ts])
271-
# END handle overlap
272-
# END for each dc
273-
else:
274-
raise NotImplementedError("todo")
275-
# END handle order
270+
:param bdcl: DeltaChunkList to serve as base"""
271+
for dc in self:
272+
if not dc.has_data():
273+
dc.set_copy_chunklist(bdcl[dc.so:dc.ts])
274+
# END handle overlap
275+
# END for each dc
276276

277277
def apply(self, bbuf, write, lbound_offset=0, size=0):
278278
"""Only used by public clients, internally we only use the global routines
@@ -396,8 +396,37 @@ def __getslice__(self, absofs, size):
396396

397397
# ndcl.check_integrity()
398398
return ndcl
399-
400-
399+
400+
401+
class TopdownDeltaChunkList(DeltaChunkList):
402+
"""Represents a list which is generated by feeding its ancestor streams one by
403+
one"""
404+
__slots__ = ('frozen', ) # if True, the list is frozen and can reproduce all data
405+
# Will only be set in lists which where processed top-down
406+
407+
def __init__(self):
408+
self.frozen = False
409+
410+
def connect_with_next_base(self, bdcl):
411+
"""Connect this chain with the next level of our base delta chunklist.
412+
The goal in this game is to mark as many of our chunks rigid, hence they
413+
cannot be changed by any of the upcoming bases anymore. Once all our
414+
chunks are marked like that, we can stop all processing
415+
:param bdcl: data chunk list being one of our bases. They must be fed in
416+
consequtively and in order, towards the earliest ancestor delta
417+
:return: True if processing was done. Use it to abort processing of
418+
remaining streams"""
419+
if self.frozen == 1:
420+
# Can that ever be hit ?
421+
return False
422+
# END early abort
423+
# mark us so that the is_reversed method returns True, without us thinking
424+
# we are frozen
425+
self.frozen = -1
426+
427+
raise NotImplementedError("todo")
428+
return True
429+
401430

402431
#} END structures
403432

@@ -540,8 +569,14 @@ def connect_deltas(dstreams, reverse):
540569
If True, deltas are ordered so that the one to be applied last comes first.
541570
:return: DeltaChunkList, containing all operations to apply"""
542571
bdcl = None # data chunk list for initial base
543-
dcl = DeltaChunkList()
544572
tdcl = None # topmost dcl, only effective if reverse is True
573+
574+
if reverse:
575+
dcl = tdcl = TopdownDeltaChunkList()
576+
else:
577+
dcl = DeltaChunkList()
578+
# END handle type of first chunk list
579+
545580
for dsi, ds in enumerate(dstreams):
546581
# print "Stream", dsi
547582
db = ds.read()
@@ -603,13 +638,14 @@ def connect_deltas(dstreams, reverse):
603638

604639
dcl.compress()
605640

606-
if reverse and tdcl is None:
607-
tdcl = dcl
608-
# END handle reverse
609-
610641
# merge the lists !
611642
if bdcl is not None:
612-
dcl.connect_with(bdcl, tdcl)
643+
if tdcl:
644+
if not tdcl.connect_with_next_base(dcl):
645+
break
646+
# END early abort
647+
else:
648+
dcl.connect_with(bdcl)
613649
# END handle merge
614650

615651
# dcl.check_integrity()
@@ -619,7 +655,10 @@ def connect_deltas(dstreams, reverse):
619655
dcl = DeltaChunkList()
620656
# END for each delta stream
621657

622-
return bdcl
658+
if tdcl:
659+
return tdcl
660+
else:
661+
return bdcl
623662

624663

625664
def apply_delta_data(src_buf, src_buf_size, delta_buf, delta_buf_size, write):

0 commit comments

Comments
 (0)