120 likes | 235 Views
Bud Causal Delivery. Implémentation. L ’existant…. module DeliveryProtocol state do interface input , : pipe_in , [ : dst , : src , : ident ] => [ :payload ] interface output , : pipe_sent , [ :dst , : src , : ident ] => [ : payload ]
E N D
Bud Causal Delivery Implémentation
L’existant… moduleDeliveryProtocol state do interface input, :pipe_in,[:dst, :src, :ident]=>[:payload] interface output, :pipe_sent,[:dst, :src, :ident]=>[:payload] interface output, :pipe_out,[:dst, :src, :ident]=>[:payload] end end moduleCausalDelivery includeDeliveryProtocol state do channel :chn,[:@dst, :src, :ident]=>[:payload, :clock, :ord_buf] lmap :my_vc lmap :next_vc lmap :ord_buf table :recv_buf,chn.schema scratch :buf_chosen,recv_buf.schema end bootstrapdo my_vc<={ip_port=>Bud::MaxLattice.new(0)} end
L’existant… bloom :update_vcdo next_vc<=my_vc next_vc<=pipe_in{{ip_port=> my_vc.at(ip_port)+1}} next_vc<=buf_chosen{{ip_port=> my_vc.at(ip_port)+1}} next_vc<=buf_chosen{|m|m.clock} my_vc<+next_vc end bloom :outbound_msgdo chn<~pipe_in{|p|[p.dst, p.src,p.ident,p.payload,next_vc,ord_buf]} ord_buf<+pipe_in{|p|{p.dst =>next_vc}} pipe_sent<=pipe_in end bloom :inbound_msgdo recv_buf<=chn buf_chosen<=recv_buf{|m| m.ord_buf.at(ip_port,Bud::MapLattice).lt_eq(my_vc).when_true{ m }} recv_buf<-buf_chosen pipe_out<=buf_chosen{|m|[m.dst, m.src,m.ident,m.payload]} ord_buf<+buf_chosen{|m| m.ord_buf} end end
Modifications à effectuer • Fonction de hachage • [n° processus] => [ entrées dans le VC] • Incrémentation des horloges à la réception • Sous condition • Incrémentation des horloges à l’envoi • Inconditionnel • Affichage des messages • Doublement conditionné
Utilitaires • Pour sérialiser des BudTable moduleVCTableSerializeModule defto_a @v end defto_s @v.inspect end end classVCTableSerialize includeVCTableSerializeModule definitialize(vc) raise "VCTableSerialize.initialize : first parameter must be a Bud::BudTable" if notvc.is_a?(Bud::BudTable) tmp= vc.map do|item| [ item[0], item[1]] end tmp.sort! {|x, y| x[0]<=> y[0]} @v = tmp.map do|item| item[1] end end end
Utilitaires • Pour réaliser des tests sur les VC moduleVCTestModule attr_reader :v deffirst_test(vc, entries) raise "VCTestModule.first_test : first parameter must be a VCTest" if notvc.is_a?(VCTest) raise "VCTestModule.first_test : second parameter must be an Array" if notentries.is_a?(Array) isSuccess=true for e in entries isSuccess=isSuccessand(@v[e]-1<=vc.v[e]) end returnisSuccess end defsecond_test(vc,forbidEntries) raise "VCTestModule.second_test : first parameter must be a VCTest" if notvc.is_a?(VCTest) raise "VCTestModule.second_test : second parameter must be an Array" if notforbidEntries.is_a?(Array) j=0 result=[] for i in(0..vc.v.length-1) ifforbidEntries.index(i)==nil result[j]= i j = j+1 end end isSuccess=true for e inresult isSuccess=isSuccessand(@v[e]<=vc.v[e]) end returnisSuccess end
Utilitaires defthird_test(vc, entries) raise "VCTestModule.third_test : first parameter must be a VCTest" if notvc.is_a?(VCTest) raise "VCTestModule.third_test : second parameter must be an Array" if notentries.is_a?(Array) isSuccess=true for e in entries isSuccess=isSuccessand(@v[e]-1==vc.v[e]) end returnisSuccess end End classVCTest includeVCTestModule definitialize(vc) raise "VCTest.initialize : first parameter must be an Array" if notvc.is_a?(Array) @v =vc end end
Fonction de hachage • Simulée par une Map • Fixée pour 5 processus @fi ={1=>[0,2], 2=>[1,3], 3=>[2,4], 4=>[0,3], 5=>[1,4]}
Incrémentation des horloges - Réception • Définition de deux nouveaux scratch scratch :chn_tmp,chn.schema scratch :next_vc_tmp,next_vc.schema • Quand un message arrive, on se prépare à l’afficher, même si les conditions d’affichage ne sont pas validées • Incrémentation d’horloges provisoires • Si le message est réellement affiché, application des modifications à l’horloge du processus
Incrémentation des horloges - Réception chn_tmp<=chn{|c|Bud::BoolLattice.new(VCTest.new(c.clock).third_test(VCTest.new( VCTableSerialize.new(my_vc).to_a@fi[c.src])).when_true{ c }} next_vc_tmp<=chn_tmp.flat_mapdo|t| @fi[t.src].map {|e| [e,VCTableSerialize.new(my_vc).to_a[e]+1]} end next_vc<=pipe_out.flat_mapdo|p| next_vc_tmp.map {|i|[ i[0], i[1]]} end next_vc<=pipe_out.flat_mapdo|p| my_vc.map {|i| Bud::BoolLattice.new(@fi[p.src].index(i[0])==nil).when_true {[i[0],i[1]]}} end
Incrémentation des horloges - Envoi • Incrémentation dès qu’un message est en demande d’envoi next_vc<=pipe_in.flat_mapdo|p| my_vc.map {|i| Bud::BoolLattice.new(@fi[@src].index(i[0])!=nil) .when_true{[i[0],i[1]+1]}} end next_vc<=pipe_in.flat_mapdo|p| my_vc.map {|i| Bud::BoolLattice.new(@fi[@src].index(i[0])==nil) .when_true{[i[0],i[1]]}} end
Affichage des messages bloom :inbound_msgdo recv_buf<=chn buf_chosen_first<=recv_buf{|m|Bud::BoolLattice.new(VCTest.new(m.clock).first_test( VCTest.new(VCTableSerialize.new(my_vc).to_a),@fi[m.src])) .when_true{ m }} buf_chosen_second<=buf_chosen_first{|m|Bud::BoolLattice.new(VCTest.new(m.clock).second_test( VCTest.new(VCTableSerialize.new(my_vc).to_a), @fi[m.src]+ @fi[@src])) .when_true{ m }} recv_buf<-buf_chosen_second pipe_out<=buf_chosen_second{|m|[m.dst, m.src,m.content]} end