@@ -349,17 +349,81 @@ class SvBaseDir(object):
349349 if not sv .ro and not opts .dry_run :
350350 prop_set_ro (newpath , False )
351351
352- def parents_getter (subvols ):
353- lookup = { x .uuid : x for x in subvols }
354- def _getter (x ):
355- while x .parent_uuid is not None :
356- try :
357- x = lookup [x .parent_uuid ]
358- except KeyError :
359- return
352+ class SubvolSet (object ):
353+
354+ def __init__ (self , subvols ):
355+ self .subvols = subvols
356+ self .lookup = { x .uuid : x for x in subvols }
357+
358+ def parents_getter (self ):
359+ def _getter (x ):
360+ while x .parent_uuid is not None :
361+ try :
362+ x = self .lookup [x .parent_uuid ]
363+ except KeyError :
364+ return
365+ else :
366+ yield x
367+ return _getter
368+
369+ def get_parents (self , x ):
370+ return self .parents_getter ()(x )
371+
372+ def get_parent (self , x ):
373+ if x .parent_uuid is not None and x .parent_uuid in self .lookup :
374+ return self .lookup [x .parent_uuid ]
375+ return None
376+
377+ def siblings_getter (self ):
378+ def _getter (x ):
379+ return (y for y in self .subvols if x .parent_uuid == y .parent_uuid
380+ and y .uuid != x .uuid )
381+ return _getter
382+
383+ def get_siblings (self , x ):
384+ return self .siblings_getter ()(x )
385+
386+ def children_getter (self ):
387+ def _getter (uuid ):
388+ return (y for y in self .subvols if y .parent_uuid == uuid )
389+ return _getter
390+
391+ def get_children (self , x ):
392+ return self .children_getter ()(x )
393+
394+ def descendants_getter (self ):
395+ def _getter (uuid ):
396+ children = self .get_children (uuid )
397+ for c in children :
398+ yield c
399+ for x in (y for y in _getter (c .uuid )):
400+ yield x
401+ return _getter
402+
403+ def get_descendants (self , x ):
404+ return self .descendants_getter ()(x )
405+
406+ def relatives_getter (self ):
407+ def _getter (sv ):
408+ parents = list (self .get_parents (sv ))
409+ if parents :
410+ grandpa = parents [- 1 ]
360411 else :
412+ grandpa = sv
413+ if grandpa .parent_uuid is not None :
414+ # oldest ancestor is not in subvols
415+ uuid = grandpa .parent_uuid
416+ else :
417+ uuid = grandpa .uuid
418+ if uuid != sv .uuid :
419+ yield grandpa
420+ for x in (y for y in self .get_descendants (uuid )):
361421 yield x
362- return _getter
422+ return _getter
423+
424+ def get_relatives (self , x ):
425+ return self .relatives_getter ()(x )
426+
363427
364428class Strategy (object ):
365429
@@ -379,7 +443,8 @@ class Strategy(object):
379443
380444 def prepare_subvols (self ):
381445 self .subvols = get_subvols (self .old )
382- self .get_parents = parents_getter (self .subvols )
446+ self .svset = SubvolSet (self .subvols )
447+ self .get_parents = self .svset .parents_getter ()
383448 self .subvols .sort (key = self .sort_key )
384449
385450 atexit .register (set_all_ro , False , self .subvols , self .old )
@@ -427,6 +492,15 @@ class ParentStrategy(Strategy):
427492 def _done (self , sv ):
428493 sv .set_ro (False , self .new )
429494
495+ class BruteStrategy (ParentStrategy ):
496+
497+ def send_subvol (self , sv ):
498+ relatives = (y for y in self .svset .get_relatives (sv ) if y .ogen < sv .ogen )
499+ flags = self .build_flags (relatives , self .svset .get_parent (sv ))
500+ do_send_recv (sv .get_path (self .old ),
501+ os .path .dirname (sv .get_path (self .new )),
502+ flags )
503+
430504class _FlatStrategy (Strategy ):
431505
432506 def strategy (self ):
@@ -690,14 +764,15 @@ class GenerationStrategy(_FlatStrategy):
690764 def _done (self , sv ):
691765 self .done = [sv ] + self .done
692766
767+ _strategies = {
768+ "parent" : ParentStrategy ,
769+ "snapshot" : SnapStrategy ,
770+ "chronological" : ChronoStrategy ,
771+ "generation" : GenerationStrategy ,
772+ "bruteforce" : BruteStrategy ,
773+ }
693774
694775def get_strategy ():
695- _strategies = {
696- "parent" : ParentStrategy ,
697- "snapshot" : SnapStrategy ,
698- "chronological" : ChronoStrategy ,
699- "generation" : GenerationStrategy ,
700- }
701776 return _strategies [opts .strategy ]
702777
703778def make_args ():
@@ -707,8 +782,7 @@ def make_args():
707782 ps .add_argument ("-f" , "--force" , action = 'store_true' )
708783 ps .add_argument ("-n" , "--dry-run" , action = 'store_true' )
709784 ps .add_argument ("-s" , "--strategy" , default = "generation" ,
710- choices = ["parent" , "snapshot" , "chronological" ,
711- "generation" ])
785+ choices = _strategies .keys ())
712786 ps .add_argument ("--snap-base" )
713787 ps .add_argument ("--no-unshare" , action = 'store_true' )
714788 ps .add_argument ("-t" , "--toplevel" , action = 'store_false' ,
0 commit comments