~codership/galera/2.x

« back to all changes in this revision

Viewing changes to gcomm/src/evs_proto.cpp

  • Committer: Alexey Yurchenko
  • Date: 2014-01-29 14:43:26 UTC
  • mto: This revision was merged to the branch mainline in revision 167.
  • Revision ID: alexey.yurchenko@codership.com-20140129144326-aa70nhzofl0smkm8
Fixes:
* provider pause() is fixed to avoid potential deadlock with replicating threads.
* lp:1099478 - handle own address in the address list properly (do not throw exception)
* lp:1259952 - fixed allocation of multiple of pages when posix_fallocate() is unavailable
* lp:1261996 - fixed compilation on Solaris 11
* lp:1232747 - fixed group remerge after partitioning event

Synced with SVN r3450

Show diffs side-by-side

added added

removed removed

Lines of Context:
849
849
}
850
850
 
851
851
 
852
 
void gcomm::evs::Proto::cleanup_unoperational()
 
852
void gcomm::evs::Proto::cleanup_foreign(const InstallMessage& im)
853
853
{
854
854
    NodeMap::iterator i, i_next;
855
855
    for (i = known_.begin(); i != known_.end(); i = i_next)
856
856
    {
 
857
        const UUID& uuid(NodeMap::key(i));
857
858
        i_next = i, ++i_next;
858
 
        if (NodeMap::value(i).installed() == false)
 
859
        const MessageNodeList::const_iterator mni(im.node_list().find(uuid));
 
860
        if (mni == im.node_list().end() ||
 
861
            MessageNodeList::value(mni).operational() == false)
859
862
        {
860
 
            evs_log_debug(D_STATE) << "erasing " << NodeMap::key(i);
861
863
            known_.erase(i);
862
864
        }
863
865
    }
864
866
}
865
867
 
866
 
 
867
868
void gcomm::evs::Proto::cleanup_views()
868
869
{
869
870
    gu::datetime::Date now(gu::datetime::Date::now());
895
896
    return ret;
896
897
}
897
898
 
898
 
void gcomm::evs::Proto::deliver_reg_view()
 
899
void gcomm::evs::Proto::deliver_reg_view(const InstallMessage& im,
 
900
                                         const View& prev_view)
899
901
{
900
 
    if (install_message_ == 0)
 
902
 
 
903
    View view(im.install_view_id());
 
904
    for (MessageNodeList::const_iterator i(im.node_list().begin());
 
905
         i != im.node_list().end(); ++i)
901
906
    {
902
 
        gu_throw_fatal
903
 
            << "Protocol error: no install message in deliver reg view";
 
907
        const UUID& uuid(MessageNodeList::key(i));
 
908
        const MessageNode& mn(MessageNodeList::value(i));
 
909
 
 
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)
 
917
        {
 
918
            view.add_member(uuid);
 
919
            if (prev_view.is_member(uuid) == false)
 
920
            {
 
921
                view.add_joined(uuid);
 
922
            }
 
923
        }
 
924
        else if (mn.leaving() == true)
 
925
        {
 
926
            view.add_left(uuid);
 
927
        }
 
928
        else
 
929
        {
 
930
            // Partitioned set is constructed after this loop
 
931
        }
904
932
    }
905
933
 
906
 
    if (previous_views_.size() == 0) gu_throw_fatal << "Zero-size view";
907
 
 
908
 
    const View& prev_view (previous_view_);
909
 
    View view (install_message_->install_view_id());
910
 
 
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)
912
938
    {
913
 
        if (NodeMap::value(i).installed() == true)
914
 
        {
915
 
            view.add_member(NodeMap::key(i), "");
916
 
            if (prev_view.members().find(NodeMap::key(i)) ==
917
 
                prev_view.members().end())
918
 
            {
919
 
                view.add_joined(NodeMap::key(i), "");
920
 
            }
921
 
        }
922
 
        else if (NodeMap::value(i).installed() == false)
923
 
        {
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())
927
 
            {
928
 
                if (MessageNodeList::value(inst_i).leaving() == true)
929
 
                {
930
 
                    view.add_left(NodeMap::key(i), "");
931
 
                }
932
 
                else
933
 
                {
934
 
                    view.add_partitioned(NodeMap::key(i), "");
935
 
                }
936
 
            }
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)
 
942
        {
 
943
            view.add_partitioned(uuid);
939
944
        }
940
945
    }
941
946
 
942
947
    evs_log_info(I_VIEWS) << "delivering view " << view;
943
948
 
 
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 "
 
955
        << view.members()
 
956
        << " must abort to avoid possibility of two groups "
 
957
        << "with the same view id";
 
958
 
944
959
    set_stable_view(view);
945
960
    ProtoUpMeta up_meta(UUID::nil(), ViewId(), &view);
946
961
    send_up(Datagram(), up_meta);
947
962
}
948
963
 
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)
950
966
{
951
 
    if (local == false && install_message_ == 0)
952
 
    {
953
 
        gu_throw_fatal
954
 
            << "Protocol error: no install message in deliver trans view";
955
 
    }
 
967
 
 
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
956
971
 
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()));
960
975
 
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)
962
978
    {
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));
965
981
 
966
 
        if (inst.installed() == true &&
967
 
            current_view_.members().find(uuid) !=
968
 
            current_view_.members().end() &&
969
 
            (local == true ||
970
 
             MessageNodeList::value(install_message_->node_list().find_checked(uuid)).view_id() == current_view_.id()))
971
 
        {
972
 
            view.add_member(NodeMap::key(i), "");
973
 
        }
974
 
        else if (inst.installed() == false)
975
 
        {
976
 
            if (local == false)
977
 
            {
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())
981
 
                {
982
 
                    if (MessageNodeList::value(inst_i).leaving())
983
 
                    {
984
 
                        view.add_left(NodeMap::key(i), "");
985
 
                    }
986
 
                    else
987
 
                    {
988
 
                        view.add_partitioned(NodeMap::key(i), "");
989
 
                    }
990
 
                }
991
 
                else if (current_view_.is_member(NodeMap::key(i)) == true)
992
 
                {
993
 
                    view.add_partitioned(NodeMap::key(i), "");
994
 
                }
 
982
        if (curr_view.id()            == mn.view_id() &&
 
983
            curr_view.is_member(uuid) == true)
 
984
        {
 
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)
 
990
            {
 
991
                view.add_member(uuid);
 
992
            }
 
993
            else if (mn.leaving() == true)
 
994
            {
 
995
                view.add_left(uuid);
995
996
            }
996
997
            else
997
998
            {
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
1003
1000
            }
1004
1001
        }
1005
 
        else
 
1002
    }
 
1003
 
 
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)
 
1008
    {
 
1009
        const UUID& uuid(NodeList::key(i));
 
1010
        if (view.is_member(uuid)  == false &&
 
1011
            view.is_leaving(uuid) == false)
1006
1012
        {
1007
 
            // merging nodes, these won't be visible in trans view
 
1013
            view.add_partitioned(uuid);
1008
1014
        }
1009
1015
    }
1010
1016
 
 
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);
1012
1021
 
1013
1022
    evs_log_info(I_VIEWS) << " delivering view " << view;
2193
2202
    }
2194
2203
    switch (s) {
2195
2204
    case S_CLOSED:
 
2205
    {
2196
2206
        gcomm_assert(state() == S_LEAVING);
2197
2207
        gu_trace(deliver());
2198
2208
        gu_trace(deliver_local());
2199
2209
        setall_installed(false);
2200
2210
        NodeMap::value(self_i_).set_installed(true);
2201
 
        gu_trace(deliver_trans_view(true));
 
2211
        // Construct install message containing only one node for
 
2212
        // last trans view.
 
2213
        MessageNodeList node_list;
 
2214
        (void)node_list.insert_unique(
 
2215
            std::make_pair(uuid(),
 
2216
                           MessageNode(true,
 
2217
                                       false,
 
2218
                                       -1,
 
2219
                                       current_view_.id(),
 
2220
                                       input_map_->safe_seq(
 
2221
                                           NodeMap::value(self_i_).index()),
 
2222
                                       input_map_->range(
 
2223
                                           NodeMap::value(self_i_).index()))));
 
2224
        InstallMessage im(version_,
 
2225
                          uuid(),
 
2226
                          current_view_.id(),
 
2227
                          ViewId(V_REG, uuid(), current_view_.id().seq() + 1),
 
2228
                          input_map_->safe_seq(),
 
2229
                          input_map_->aru_seq(),
 
2230
                          ++fifo_seq_,
 
2231
                          node_list);
 
2232
        gu_trace(deliver_trans_view(im, current_view_));
2202
2233
        gu_trace(deliver_trans());
2203
2234
        gu_trace(deliver_local(true));
2204
2235
        gcomm_assert(causal_queue_.empty() == true);
2207
2238
            handle_stats_timer();
2208
2239
        }
2209
2240
        gu_trace(deliver_empty_view());
2210
 
        cleanup_unoperational();
 
2241
        cleanup_foreign(im);
2211
2242
        cleanup_views();
2212
2243
        timers_.clear();
2213
2244
        state_ = S_CLOSED;
2214
2245
        break;
 
2246
    }
2215
2247
    case S_JOINING:
2216
2248
        state_ = S_JOINING;
2217
2249
        break;
2279
2311
        gcomm_assert(is_all_installed() == true);
2280
2312
        gu_trace(deliver());
2281
2313
        gu_trace(deliver_local());
2282
 
        gu_trace(deliver_trans_view(false));
 
2314
        gu_trace(deliver_trans_view(*install_message_, current_view_));
2283
2315
        gu_trace(deliver_trans());
2284
2316
        gu_trace(deliver_local(true));
2285
2317
        gcomm_assert(causal_queue_.empty() == true);
2288
2320
        {
2289
2321
            handle_stats_timer();
2290
2322
        }
 
2323
        // End of previous view
 
2324
 
 
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
 
2328
        // handle messages.
2291
2329
 
2292
2330
        previous_view_ = current_view_;
2293
2331
        previous_views_.push_back(
2294
2332
            std::make_pair(current_view_.id(), gu::datetime::Date::now()));
2295
2333
 
2296
 
        const MessageNodeList& imap(install_message_->node_list());
2297
 
 
2298
 
        for (MessageNodeList::const_iterator i = imap.begin();
2299
 
             i != imap.end(); ++i)
 
2334
        current_view_ = View(install_message_->install_view_id());
 
2335
        size_t idx = 0;
 
2336
 
 
2337
        const MessageNodeList& imnl(install_message_->node_list());
 
2338
 
 
2339
        for (MessageNodeList::const_iterator i(imnl.begin());
 
2340
             i != imnl.end(); ++i)
2300
2341
        {
 
2342
            const UUID& uuid(MessageNodeList::key(i));
 
2343
            const MessageNode& n(MessageNodeList::value(i));
 
2344
 
 
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()));
2304
 
        }
2305
 
        current_view_ = View(install_message_->install_view_id());
2306
 
        size_t idx = 0;
2307
 
        for (NodeMap::iterator i = known_.begin(); i != known_.end(); ++i)
2308
 
        {
2309
 
            if (NodeMap::value(i).installed() == true)
 
2350
 
 
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)
2310
2356
            {
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++);
2313
2359
            }
2314
2360
            else
2315
2361
            {
2316
 
                NodeMap::value(i).set_index(
 
2362
                NodeMap::value(nmi).set_index(
2317
2363
                    std::numeric_limits<size_t>::max());
2318
2364
            }
 
2365
 
2319
2366
        }
2320
2367
 
2321
2368
        if (previous_view_.id().type() == V_REG &&
2328
2375
        input_map_->reset(current_view_.members().size());
2329
2376
        last_sent_ = -1;
2330
2377
        state_ = S_OPERATIONAL;
2331
 
        deliver_reg_view();
 
2378
        deliver_reg_view(*install_message_, previous_view_);
2332
2379
 
2333
 
        cleanup_unoperational();
 
2380
        cleanup_foreign(*install_message_);
2334
2381
        cleanup_views();
2335
2382
        cleanup_joins();
2336
2383