… | |
… | |
24 | package AnyEvent::MP::Kernel; |
24 | package AnyEvent::MP::Kernel; |
25 | |
25 | |
26 | use common::sense; |
26 | use common::sense; |
27 | use POSIX (); |
27 | use POSIX (); |
28 | use Carp (); |
28 | use Carp (); |
29 | use MIME::Base64 (); |
|
|
30 | |
29 | |
31 | use AE (); |
30 | use AE (); |
32 | |
31 | |
33 | use AnyEvent::MP::Node; |
32 | use AnyEvent::MP::Node; |
34 | use AnyEvent::MP::Transport; |
33 | use AnyEvent::MP::Transport; |
… | |
… | |
113 | } |
112 | } |
114 | |
113 | |
115 | \&$func |
114 | \&$func |
116 | } |
115 | } |
117 | |
116 | |
|
|
117 | my @alnum = ('0' .. '9', 'A' .. 'Z', 'a' .. 'z'); |
|
|
118 | |
118 | sub nonce($) { |
119 | sub nonce($) { |
119 | my $nonce; |
|
|
120 | |
|
|
121 | if (open my $fh, "</dev/urandom") { |
|
|
122 | sysread $fh, $nonce, $_[0]; |
|
|
123 | } else { |
|
|
124 | # shit... |
|
|
125 | $nonce = join "", map +(chr rand 256), 1 .. $_[0] |
120 | join "", map chr rand 256, 1 .. $_[0] |
126 | } |
|
|
127 | |
|
|
128 | $nonce |
|
|
129 | } |
121 | } |
130 | |
122 | |
131 | # binary to alphanumeric |
123 | sub nonce62($) { |
132 | sub alnumbits($) { |
124 | join "", map $alnum[rand 62], 1 .. $_[0] |
133 | (my $data = MIME::Base64::encode_base64 $_[0], "") =~ y%+/=%-_%d; |
|
|
134 | $data |
|
|
135 | } |
125 | } |
136 | |
126 | |
137 | sub gen_uniq { |
127 | sub gen_uniq { |
138 | # 48 bits happen to fit perfectly into 8 chars |
128 | my $now = AE::now; |
139 | # we add one more char to get 54 bits. |
129 | (join "", |
140 | substr +(alnumbits pack "nna*", $$ & 0xffff, time & 0xffff, nonce 3), 0, 9 |
130 | map $alnum[$_], |
|
|
131 | $$ / 62 % 62, |
|
|
132 | $$ % 62, |
|
|
133 | (int $now ) % 62, |
|
|
134 | (int $now * 100) % 62, |
|
|
135 | (int $now * 10000) % 62, |
|
|
136 | ) . nonce62 4; |
141 | } |
137 | } |
142 | |
138 | |
143 | our $CONFIG; # this node's configuration |
139 | our $CONFIG; # this node's configuration |
144 | |
140 | |
145 | our $RUNIQ; # remote uniq value |
141 | our $RUNIQ; # remote uniq value |
… | |
… | |
158 | our $LISTENER; # our listeners, as arrayref |
154 | our $LISTENER; # our listeners, as arrayref |
159 | |
155 | |
160 | our $SRCNODE; # holds the sending node _object_ during _inject |
156 | our $SRCNODE; # holds the sending node _object_ during _inject |
161 | |
157 | |
162 | sub _init_names { |
158 | sub _init_names { |
|
|
159 | # ~54 bits, for local port names, lowercase $ID appended |
163 | $UNIQ = gen_uniq; |
160 | $UNIQ = gen_uniq; |
164 | $RUNIQ = substr +(alnumbits nonce 64/8), 0, 10; # for remote port names &c, should be longer than $UNIQ |
161 | |
|
|
162 | # ~59 bits, for remote port names, one longer than $UNIQ and uppercase at the end to avoid clashes |
|
|
163 | $RUNIQ = nonce62 10; |
|
|
164 | $RUNIQ =~ s/(.)$/\U$1/; |
|
|
165 | |
165 | $NODE = "anon/$RUNIQ"; |
166 | $NODE = "anon/$RUNIQ"; |
166 | } |
167 | } |
167 | |
168 | |
168 | _init_names; |
169 | _init_names; |
169 | |
170 | |
170 | sub NODE() { |
171 | sub NODE() { |
… | |
… | |
597 | # "'g" -> node -> undef |
598 | # "'g" -> node -> undef |
598 | # ... |
599 | # ... |
599 | # |
600 | # |
600 | |
601 | |
601 | # used on all nodes: |
602 | # used on all nodes: |
602 | our $MASTER; # the global node we bind ourselves to, unless we are global ourselves |
603 | our $MASTER; # the global node we bind ourselves to, unless we are global ourselves |
603 | our $GLOBAL_MON; |
604 | our $MASTER_MON; |
604 | our $GLOBAL_TIMER; |
|
|
605 | our %LOCAL_DB; # this node database |
605 | our %LOCAL_DB; # this node database |
606 | |
606 | |
607 | # used on global nodes: |
|
|
608 | our %GLOBAL_DB; # all local databases, merged |
607 | our %GLOBAL_DB; # all local databases, merged - empty on non-global nodes |
609 | our %LOCAL_DBS; # local databases of all global nodes |
|
|
610 | our %GLOBAL_DBS; # global db |
|
|
611 | our %GLOBAL_SLAVE; # nodes that are our slaves |
|
|
612 | |
608 | |
613 | #our $sv_ne_json = JSON::XS->new->canonical; |
609 | #our $sv_ne_json = JSON::XS->new->canonical; |
614 | # |
610 | # |
615 | #sub sv_ne($$) { |
611 | #sub sv_ne($$) { |
616 | # $sv_ne_json->encode ($_[0]) ne $sv_ne_json->encode ($_[1]) |
612 | # $sv_ne_json->encode ($_[0]) ne $sv_ne_json->encode ($_[1]) |
617 | #} |
613 | #} |
618 | |
|
|
619 | # should be only on globals, but... |
|
|
620 | $node_req{g_global} = sub { |
|
|
621 | if ($GLOBAL) { |
|
|
622 | &g_clr ($SRCNODE->{id}); |
|
|
623 | $SRCNODE->{transport}{remote_greeting}{global} = 1; |
|
|
624 | delete $GLOBAL_SLAVE{$SRCNODE->{id}}; |
|
|
625 | snd $SRCNODE->{id}, g_set => \%LOCAL_DB; |
|
|
626 | } |
|
|
627 | }; |
|
|
628 | |
|
|
629 | sub other_globals() { |
|
|
630 | grep $_ ne $NODE && node_is_up $_, keys %{ $GLOBAL_DB{"'g"} } |
|
|
631 | } |
|
|
632 | |
614 | |
633 | # local database management |
615 | # local database management |
634 | sub ldb_set($$;$) { |
616 | sub ldb_set($$;$) { |
635 | warn "ldb_set<@_>\n";#d# |
617 | warn "ldb_set<@_>\n";#d# |
636 | if (@_ > 2) { |
618 | if (@_ > 2) { |
… | |
… | |
698 | master_set $_; |
680 | master_set $_; |
699 | return; |
681 | return; |
700 | } |
682 | } |
701 | } |
683 | } |
702 | |
684 | |
703 | $GLOBAL_MON = mon_nodes sub { |
685 | $MASTER_MON = mon_nodes sub { |
704 | return unless $_[1]; # we are only interested in node-ups |
686 | return unless $_[1]; # we are only interested in node-ups |
705 | return unless $NODE_SEED{$_[0]}; # we are only interested in seed nodes |
687 | return unless $NODE_SEED{$_[0]}; # we are only interested in seed nodes |
706 | |
688 | |
707 | master_set $_[0]; |
689 | master_set $_[0]; |
708 | |
690 | |
709 | $GLOBAL_MON = mon_nodes sub { |
691 | $MASTER_MON = mon_nodes sub { |
710 | if ($_[0] eq $MASTER && !$_[1]) { |
692 | if ($_[0] eq $MASTER && !$_[1]) { |
711 | undef $MASTER; |
693 | undef $MASTER; |
712 | master_search (); |
694 | master_search (); |
713 | } |
695 | } |
714 | }; |
696 | }; |