898
void gcomm::evs::Proto::deliver_reg_view()
899
void gcomm::evs::Proto::deliver_reg_view(const InstallMessage& im,
900
const View& prev_view)
900
if (install_message_ == 0)
903
View view(im.install_view_id());
904
for (MessageNodeList::const_iterator i(im.node_list().begin());
905
i != im.node_list().end(); ++i)
903
<< "Protocol error: no install message in deliver reg view";
907
const UUID& uuid(MessageNodeList::key(i));
908
const MessageNode& mn(MessageNodeList::value(i));
910
// 1) Operational nodes will be members of new view
911
// 2) Operational nodes that were not present in previous
912
// view are going also to joined set
913
// 3) Leaving nodes go to left set
914
// 4) All other nodes present in previous view but not in
915
// member of left set are considered partitioned
916
if (mn.operational() == true)
918
view.add_member(uuid);
919
if (prev_view.is_member(uuid) == false)
921
view.add_joined(uuid);
924
else if (mn.leaving() == true)
930
// Partitioned set is constructed after this loop
906
if (previous_views_.size() == 0) gu_throw_fatal << "Zero-size view";
908
const View& prev_view (previous_view_);
909
View view (install_message_->install_view_id());
911
for (NodeMap::iterator i = known_.begin(); i != known_.end(); ++i)
934
// Loop over previous view and add each node not in new view
935
// member of left set as partitioned.
936
for (NodeList::const_iterator i(prev_view.members().begin());
937
i != prev_view.members().end(); ++i)
913
if (NodeMap::value(i).installed() == true)
915
view.add_member(NodeMap::key(i), "");
916
if (prev_view.members().find(NodeMap::key(i)) ==
917
prev_view.members().end())
919
view.add_joined(NodeMap::key(i), "");
922
else if (NodeMap::value(i).installed() == false)
924
const MessageNodeList& instances = install_message_->node_list();
925
MessageNodeList::const_iterator inst_i;
926
if ((inst_i = instances.find(NodeMap::key(i))) != instances.end())
928
if (MessageNodeList::value(inst_i).leaving() == true)
930
view.add_left(NodeMap::key(i), "");
934
view.add_partitioned(NodeMap::key(i), "");
937
gcomm_assert(NodeMap::key(i) != uuid());
938
gcomm_assert(NodeMap::value(i).operational() == false);
939
const UUID& uuid(NodeList::key(i));
940
if (view.is_member(uuid) == false &&
941
view.is_leaving(uuid) == false)
943
view.add_partitioned(uuid);
942
947
evs_log_info(I_VIEWS) << "delivering view " << view;
949
// This node must be a member of the view it delivers and
950
// view id UUID must be of one of the members.
951
gcomm_assert(view.is_member(uuid()) == true);
952
gcomm_assert(view.is_member(view.id().uuid()) == true)
953
<< "view id UUID " << view.id().uuid()
954
<< " not found from reg view members "
956
<< " must abort to avoid possibility of two groups "
957
<< "with the same view id";
944
959
set_stable_view(view);
945
960
ProtoUpMeta up_meta(UUID::nil(), ViewId(), &view);
946
961
send_up(Datagram(), up_meta);
949
void gcomm::evs::Proto::deliver_trans_view(bool local)
964
void gcomm::evs::Proto::deliver_trans_view(const InstallMessage& im,
965
const View& curr_view)
951
if (local == false && install_message_ == 0)
954
<< "Protocol error: no install message in deliver trans view";
968
// Trans view is intersection of members in curr_view
969
// and members going to be in the next view that come from
970
// curr_view according to install message
957
972
View view(ViewId(V_TRANS,
958
current_view_.id().uuid(),
959
current_view_.id().seq()));
973
curr_view.id().uuid(),
974
curr_view.id().seq()));
961
for (NodeMap::const_iterator i = known_.begin(); i != known_.end(); ++i)
976
for (MessageNodeList::const_iterator i(im.node_list().begin());
977
i != im.node_list().end(); ++i)
963
const UUID& uuid(NodeMap::key(i));
964
const Node& inst(NodeMap::value(i));
979
const UUID& uuid(MessageNodeList::key(i));
980
const MessageNode& mn(MessageNodeList::value(i));
966
if (inst.installed() == true &&
967
current_view_.members().find(uuid) !=
968
current_view_.members().end() &&
970
MessageNodeList::value(install_message_->node_list().find_checked(uuid)).view_id() == current_view_.id()))
972
view.add_member(NodeMap::key(i), "");
974
else if (inst.installed() == false)
978
const MessageNodeList& instances(install_message_->node_list());
979
MessageNodeList::const_iterator inst_i;
980
if ((inst_i = instances.find(NodeMap::key(i))) != instances.end())
982
if (MessageNodeList::value(inst_i).leaving())
984
view.add_left(NodeMap::key(i), "");
988
view.add_partitioned(NodeMap::key(i), "");
991
else if (current_view_.is_member(NodeMap::key(i)) == true)
993
view.add_partitioned(NodeMap::key(i), "");
982
if (curr_view.id() == mn.view_id() &&
983
curr_view.is_member(uuid) == true)
985
// 1) Operational nodes go to next view
986
// 2) Leaving nodes go to left set
987
// 3) All other nodes present in previous view but not in
988
// member of left set are considered partitioned
989
if (mn.operational() == true)
991
view.add_member(uuid);
993
else if (mn.leaving() == true)
998
// Just assume others have partitioned, it does not matter
999
// for leaving node anyway and it is not guaranteed if
1000
// the others get the leave message, so it is not safe
1001
// to assume then as left.
1002
view.add_partitioned(NodeMap::key(i), "");
999
// Partitioned set is constructed after this loop
1004
// Loop over current view and add each node not in new view
1005
// member of left set as partitioned.
1006
for (NodeList::const_iterator i(curr_view.members().begin());
1007
i != curr_view.members().end(); ++i)
1009
const UUID& uuid(NodeList::key(i));
1010
if (view.is_member(uuid) == false &&
1011
view.is_leaving(uuid) == false)
1007
// merging nodes, these won't be visible in trans view
1013
view.add_partitioned(uuid);
1017
// This node must be a member of the view it delivers and
1018
// if the view is the last transitional, view must have
1019
// exactly one member and no-one in left set.
1011
1020
gcomm_assert(view.is_member(uuid()) == true);
1013
1022
evs_log_info(I_VIEWS) << " delivering view " << view;
2289
2321
handle_stats_timer();
2323
// End of previous view
2325
// Construct new view and shift to S_OPERATIONAL before calling
2326
// deliver_reg_view(). Reg view delivery may trigger message
2327
// exchange on upper layer and operating view is needed to
2292
2330
previous_view_ = current_view_;
2293
2331
previous_views_.push_back(
2294
2332
std::make_pair(current_view_.id(), gu::datetime::Date::now()));
2296
const MessageNodeList& imap(install_message_->node_list());
2298
for (MessageNodeList::const_iterator i = imap.begin();
2299
i != imap.end(); ++i)
2334
current_view_ = View(install_message_->install_view_id());
2337
const MessageNodeList& imnl(install_message_->node_list());
2339
for (MessageNodeList::const_iterator i(imnl.begin());
2340
i != imnl.end(); ++i)
2342
const UUID& uuid(MessageNodeList::key(i));
2343
const MessageNode& n(MessageNodeList::value(i));
2345
// Collect list of previous view identifiers to filter out
2346
// delayed messages from previous views.
2301
2347
previous_views_.push_back(
2302
std::make_pair(MessageNodeList::value(i).view_id(),
2348
std::make_pair(n.view_id(),
2303
2349
gu::datetime::Date::now()));
2305
current_view_ = View(install_message_->install_view_id());
2307
for (NodeMap::iterator i = known_.begin(); i != known_.end(); ++i)
2309
if (NodeMap::value(i).installed() == true)
2351
// Add operational nodes to new view, assign input map index
2352
NodeMap::iterator nmi(known_.find(uuid));
2353
gcomm_assert(nmi != known_.end()) << "node " << uuid
2354
<< " not found from known map";
2355
if (n.operational() == true)
2311
gu_trace(current_view_.add_member(NodeMap::key(i), ""));
2312
NodeMap::value(i).set_index(idx++);
2357
current_view_.add_member(uuid);
2358
NodeMap::value(nmi).set_index(idx++);
2316
NodeMap::value(i).set_index(
2362
NodeMap::value(nmi).set_index(
2317
2363
std::numeric_limits<size_t>::max());
2321
2368
if (previous_view_.id().type() == V_REG &&