/home/coin/SVN-release/OS-2.0.1/Bcp/src/TM/BCP_tm_msgproc.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #include "CoinTime.hpp"
00004 
00005 #include "BCP_math.hpp"
00006 #include "BCP_node_change.hpp"
00007 #include "BCP_tm.hpp"
00008 #include "BCP_lp.hpp"
00009 #include "BCP_tm_functions.hpp"
00010 #include "BCP_problem_core.hpp"
00011 #include "BCP_solution.hpp"
00012 #include "BCP_tm_user.hpp"
00013 
00014 static void
00015 BCP_tm_change_config(BCP_tm_prob& p, BCP_buffer& buf);
00016 
00017 //#############################################################################
00018 
00019 void BCP_tm_idle_processes(BCP_tm_prob& p)
00020 {
00021     p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
00022                          BCP_Msg_FinishedBCP);
00023 }
00024 
00025 //#############################################################################
00026 
00027 void BCP_tm_stop_processes(BCP_tm_prob& p)
00028 {
00029     p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
00030                          BCP_Msg_FinishedBCP);
00031 }
00032 
00033 //#############################################################################
00034 
00035 void BCP_tm_start_processes(BCP_tm_prob& p)
00036 {
00037     const BCP_string& exe = p.param(BCP_tm_par::ExecutableName);
00038 
00039     if (p.param(BCP_tm_par::LpProcessNum) > 0) {
00040         const bool debug = p.param(BCP_tm_par::DebugLpProcesses) != 0;
00041         const int  num = p.param(BCP_tm_par::LpProcessNum);
00042         const BCP_vec<BCP_string>& machines = p.param(BCP_tm_par::LpMachines);
00043         p.lp_procs.insert(p.lp_procs.end(), num, -1);
00044         bool success = machines.size() == 0 ?
00045           p.msg_env->start_processes(exe, num, debug, &p.lp_procs[0]) :
00046           p.msg_env->start_processes(exe, num, machines, debug, &p.lp_procs[0]);
00047         if (! success) {
00048           throw BCP_fatal_error("Failed to start up the LP processes\n");
00049         }
00050         p.lp_scheduler.add_free_ids(p.lp_procs.size(), &p.lp_procs[0]);
00051     }
00052 
00053 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00054     if (p.param(BCP_tm_par::CgProcessNum) > 0) {
00055         const bool debug = p.param(BCP_tm_par::DebugCgProcesses) != 0;
00056         const int  num = p.param(BCP_tm_par::CgProcessNum);
00057         const BCP_vec<BCP_string>& machines = p.param(BCP_tm_par::CgMachines);
00058         if (machines.size() == 0) {
00059             p.slaves.cg= p.msg_env->start_processes(exe, num, debug);
00060         } else {
00061             p.slaves.cg= p.msg_env->start_processes(exe, num, machines, debug);
00062         }
00063         p.slaves.all->add_procs(p.slaves.cg->procs().begin(),
00064                                 p.slaves.cg->procs().end());
00065     }
00066 
00067     if (p.param(BCP_tm_par::VgProcessNum) > 0) {
00068         const bool debug = p.param(BCP_tm_par::DebugVgProcesses) != 0;
00069         const int  num = p.param(BCP_tm_par::VgProcessNum);
00070         const BCP_vec<BCP_string>& machines = p.param(BCP_tm_par::VgMachines);
00071         if (machines.size() == 0) {
00072             p.slaves.vg= p.msg_env->start_processes(exe, num, debug);
00073         } else {
00074             p.slaves.vg= p.msg_env->start_processes(exe, num, machines, debug);
00075         }
00076         p.slaves.all->add_procs(p.slaves.vg->procs().begin(),
00077                                 p.slaves.vg->procs().end());
00078     }
00079 
00080     if (p.param(BCP_tm_par::CpProcessNum) > 0) {
00081         const bool debug = p.param(BCP_tm_par::DebugCpProcesses) != 0;
00082         const int  num = p.param(BCP_tm_par::CpProcessNum);
00083         const BCP_vec<BCP_string>& machines = p.param(BCP_tm_par::CpMachines);
00084         if (machines.size() == 0) {
00085             p.slaves.cp= p.msg_env->start_processes(exe, num, debug);
00086         } else {
00087             p.slaves.cp= p.msg_env->start_processes(exe, num, machines, debug);
00088         }
00089         p.slaves.all->add_procs(p.slaves.cp->procs().begin(),
00090                                 p.slaves.cp->procs().end());
00091     }
00092 
00093     if (p.param(BCP_tm_par::VpProcessNum) > 0) {
00094         const bool debug = p.param(BCP_tm_par::DebugVpProcesses) != 0;
00095         const int  num = p.param(BCP_tm_par::VpProcessNum);
00096         const BCP_vec<BCP_string>& machines = p.param(BCP_tm_par::VpMachines);
00097         if (machines.size() == 0) {
00098             p.slaves.vp= p.msg_env->start_processes(exe, num, debug);
00099         } else {
00100             p.slaves.vp= p.msg_env->start_processes(exe, num, machines, debug);
00101         }
00102         p.slaves.all->add_procs(p.slaves.vp->procs().begin(),
00103                                 p.slaves.vp->procs().end());
00104     }
00105 #endif
00106 }
00107 
00108 //#############################################################################
00109 
00110 void BCP_tm_notify_about_new_phase(BCP_tm_prob& p)
00111 {
00112   p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
00113                        BCP_Msg_NextPhaseStarts);
00114 }
00115 
00116 //#############################################################################
00117 
00118 template <typename T> void
00119 BCP_tm_initialize_process_type(BCP_tm_prob& p,
00120                                BCP_process_t ptype,
00121                                BCP_parameter_set<T>& par,
00122                                int num, const int* pids)
00123 {
00124     if (num == 0) {
00125         return;
00126     }
00127 
00128     p.msg_buf.clear();
00129     p.msg_buf.pack(ptype);
00130     p.msg_buf.pack(p.ub());
00131     p.msg_env->multicast(num, pids, BCP_Msg_ProcessType, p.msg_buf);
00132 
00133     p.msg_buf.clear();
00134     par.pack(p.msg_buf);
00135     const double wallclockInit = CoinWallclockTime(-1);
00136     p.msg_buf.pack(wallclockInit);
00137     p.msg_buf.pack(p.start_time);
00138     p.msg_env->multicast(num, pids, BCP_Msg_ProcessParameters, p.msg_buf);
00139 
00140     p.msg_buf.clear();
00141     p.core->pack(p.msg_buf);
00142     p.msg_env->multicast(num, pids, BCP_Msg_CoreDescription, p.msg_buf);
00143 
00144     p.msg_buf.clear();
00145     p.user->pack_module_data(p.msg_buf, ptype);
00146     p.msg_env->multicast(num, pids, BCP_Msg_InitialUserInfo, p.msg_buf);
00147 }
00148 
00149 //-----------------------------------------------------------------------------
00150 
00151 template <typename T> void
00152 BCP_tm_initialize_process_type(BCP_tm_prob& p,
00153                                BCP_process_t ptype,
00154                                BCP_parameter_set<T>& par,
00155                                const std::vector<int>& pids)
00156 {
00157   BCP_tm_initialize_process_type(p, ptype, par, pids.size(), &pids[0]);
00158 }
00159 
00160 //#############################################################################
00161 
00162 void
00163 BCP_tm_notify_process_type(BCP_tm_prob& p, BCP_process_t ptype,
00164                            int num, const int* pids)
00165 {
00166     switch (ptype) {
00167     case BCP_ProcessType_LP:
00168         BCP_tm_initialize_process_type(p, BCP_ProcessType_LP, p.slave_pars.lp,
00169                                        num, pids);
00170         break;
00171     case BCP_ProcessType_TS:
00172         BCP_tm_initialize_process_type(p, BCP_ProcessType_TS, p.slave_pars.ts,
00173                                        num, pids);
00174         break;
00175 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00176     case BCP_ProcessType_CP:
00177 //      BCP_tm_initialize_process_type(p, BCP_ProcessType_CP, p.slave_pars.cp,
00178 //                                     procs ? *procs : p.slaves.cp->procs());
00179         break;
00180     case BCP_ProcessType_VP:
00181 //      BCP_tm_initialize_process_type(p, BCP_ProcessType_VP, p.slave_pars.vp,
00182 //                                     procs ? *procs : p.slaves.vp->procs());
00183         break;
00184     case BCP_ProcessType_CG:
00185         BCP_tm_initialize_process_type(p, BCP_ProcessType_CG, p.slave_pars.cg,
00186                                        procs ? *procs : p.slaves.cg->procs());
00187         break;
00188     case BCP_ProcessType_VG:
00189         BCP_tm_initialize_process_type(p, BCP_ProcessType_VG, p.slave_pars.vg,
00190                                        procs ? *procs : p.slaves.vg->procs());
00191         break;
00192 #endif
00193     default:
00194         throw BCP_fatal_error("Trying to notify bad process type\n");
00195     }
00196 }
00197 
00198 //-----------------------------------------------------------------------------
00199 
00200 void
00201 BCP_tm_notify_process_type(BCP_tm_prob& p, BCP_process_t ptype,
00202                            const std::vector<int>& pids)
00203 {
00204   BCP_tm_notify_process_type(p, ptype, pids.size(), &pids[0]);
00205 }
00206   
00207 //#############################################################################
00208 
00209 void
00210 BCP_tm_notify_processes(BCP_tm_prob& p)
00211 {
00212     BCP_tm_notify_process_type(p, BCP_ProcessType_LP, p.lp_procs);
00213 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00214     BCP_tm_notify_process_type(p, BCP_ProcessType_CG, &p.slaves.cg->procs());
00215     BCP_tm_notify_process_type(p, BCP_ProcessType_VG, &p.slaves.vg->procs());
00216     BCP_tm_notify_process_type(p, BCP_ProcessType_CP, &p.slaves.cp->procs());
00217     BCP_tm_notify_process_type(p, BCP_ProcessType_VP, &p.slaves.vp->procs());
00218 #endif
00219 }
00220 
00221 //#############################################################################
00222 
00223 void
00224 BCP_tm_broadcast_ub(BCP_tm_prob& p)
00225 {
00226   p.msg_buf.clear();
00227   p.msg_buf.pack(p.ub());
00228   p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
00229                        BCP_Msg_UpperBound, p.msg_buf);
00230 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00231 #endif
00232 }
00233 
00234 //#############################################################################
00235 
00236 void
00237 BCP_tm_rebroadcast_root_warmstart(BCP_tm_prob& p)
00238 {
00239   BCP_warmstart* ws = p.packer->unpack_warmstart(p.msg_buf);
00240   p.msg_buf.clear();
00241   p.packer->pack_warmstart(ws, p.msg_buf);
00242   p.msg_env->multicast(p.lp_procs.size(), &p.lp_procs[0],
00243                        BCP_Msg_WarmstartRoot, p.msg_buf);
00244 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00245 #endif
00246   delete ws;
00247 }
00248 
00249 //#############################################################################
00250 
00251 void
00252 BCP_tm_provide_SB_processes(BCP_tm_prob& p)
00253 {
00254   int sender = p.msg_buf.sender();
00255   int branchNum;
00256   p.msg_buf.unpack(branchNum);
00257   int * pids = new int[branchNum];
00258   int numIds = p.lp_scheduler.request_sb_ids(branchNum, pids);
00259   p.msg_buf.clear();
00260   p.msg_buf.pack(pids, numIds);
00261   p.msg_env->send(sender, BCP_Msg_ProcessList, p.msg_buf);
00262   delete[] pids;
00263 }
00264 
00265 //#############################################################################
00266 // This function returns T/F depending on whether an LP process was freed up
00267 // or not.
00268 
00269 void
00270 BCP_tm_prob::process_message()
00271 {
00272     BCP_tm_node* node;
00273     int sender;
00274     int id;
00275     std::map<int, BCP_tm_node_to_send*>::iterator index__node;
00276     BCP_tm_node_to_send* node_to_send;
00277 
00278     // msg_counter counts the number of incoming messages. Every so often
00279     // (always when there's no message in the buffer) we check that every
00280     // processor is alive and well. If any has died then appropriate process
00281     // list gets shrunk, tree nodes put back on the list, etc.
00282     // Of course, this makes sense only if the computing environment in NOT
00283     // serial.
00284     static int msg_count = 0;
00285     // static const int test_frequency = 1;
00286 
00287     ++msg_count;
00288 
00289     switch (msg_buf.msgtag()){
00290     case BCP_Msg_User:
00291         user->process_message(msg_buf);
00292         break;
00293 
00294     case BCP_Msg_NoMessage:
00295         msg_count = 0;
00296         break;
00297 
00298     case BCP_Msg_UpperBound:
00299         throw BCP_fatal_error("TM: Got BCP_Msg_UpperBound message!\n");
00300         break;
00301 
00302     case BCP_Msg_NodeDescription_OverUB:
00303         node = BCP_tm_unpack_node_no_branching_info(*this, msg_buf);
00304         next_phase_nodes.push_back(node);
00305         node->status = BCP_NextPhaseNode_OverUB;
00306         break;
00307 
00308     case BCP_Msg_NodeDescription_Infeas:
00309         node = BCP_tm_unpack_node_no_branching_info(*this, msg_buf);
00310         next_phase_nodes.push_back(node);
00311         node->status = BCP_NextPhaseNode_Infeas;
00312         break;
00313 
00314     case BCP_Msg_NodeDescription_Discarded:
00315     case BCP_Msg_NodeDescription_OverUB_Pruned:
00316     case BCP_Msg_NodeDescription_Infeas_Pruned:
00317         node = BCP_tm_unpack_node_no_branching_info(*this, msg_buf);
00318         if (msg_buf.msgtag() == BCP_Msg_NodeDescription_OverUB_Pruned) {
00319             node->status = BCP_PrunedNode_OverUB;
00320         } else if (msg_buf.msgtag() == BCP_Msg_NodeDescription_Infeas_Pruned) {
00321             node->status = BCP_PrunedNode_Infeas;
00322         } else {
00323             node->status = BCP_PrunedNode_Discarded;
00324         }
00325         nodes_to_free.push_back(node);
00326         break;
00327 
00328     case BCP_Msg_NodeDescriptionWithBranchingInfo:
00329         BCP_tm_unpack_node_with_branching_info(*this, msg_buf);
00330         break;
00331 
00332     case BCP_Msg_FeasibleSolution:
00333         {
00334             BCP_solution *new_sol = user->unpack_feasible_solution(msg_buf);
00335             if (new_sol) {
00336                 const bool allval =
00337                     param(BCP_tm_par::TmVerb_AllFeasibleSolutionValue);
00338                 const bool allsol =
00339                     param(BCP_tm_par::TmVerb_AllFeasibleSolution);
00340                 const bool betterval =
00341                     param(BCP_tm_par::TmVerb_BetterFeasibleSolutionValue);
00342                 const bool bettersol =
00343                     param(BCP_tm_par::TmVerb_BetterFeasibleSolution);
00344                 bool better;
00345                 if (upper_bound > new_sol->objective_value() + 1e-6) {
00346                     better = true;
00347                 } else if (upper_bound > new_sol->objective_value() - 1e-6) {
00348                     better = user->replace_solution(feas_sol, new_sol);
00349                 } else {
00350                     better = false;
00351                 }
00352 
00353                 if (allval || allsol || ((betterval || bettersol) && better)) {
00354                     if (param(BCP_tm_par::TmVerb_TimeOfImprovingSolution)) {
00355                         printf("TM: Solution found at %.3f sec.\n",
00356                                CoinCpuTime() - start_time);
00357                     }
00358                     const int tree_size = search_tree.size();
00359                     const int tree_proc = search_tree.processed();
00360                     const int cand_list_size = candidate_list.size();
00361                     const int cand_list_ins = candidate_list.numInserted();
00362                     char bdstr[1000];
00363                     
00364                     if (upper_bound > BCP_DBL_MAX/10) {
00365                       sprintf(bdstr, "infinity");
00366                     } else {
00367                       sprintf(bdstr, "%f", upper_bound);
00368                     }
00369                     sender = msg_buf.sender();
00370                     printf("TM %.3f: Sol from proc: %i  val: %f (prev best: %s)  tree size/procd: %i/%i  cand list ins/size: %i/%i\n",
00371                            CoinWallclockTime() - start_time, sender,
00372                            new_sol->objective_value(), bdstr,
00373                            tree_size, tree_proc,
00374                            cand_list_ins, cand_list_size);
00375                     if (allsol || (bettersol && better)) {
00376                         user->display_feasible_solution(new_sol);
00377                     }
00378                 }
00379                 if (better) {
00380                     user->change_candidate_heap(candidate_list, true);
00381                     ub(new_sol->objective_value());
00382                     delete feas_sol;
00383                     feas_sol = new_sol;
00384                     BCP_tm_broadcast_ub(*this);
00385                 } else {
00386                     delete new_sol;
00387                 }
00388             }
00389         }
00390         break;
00391 
00392     case BCP_Msg_RequestProcessList:
00393         BCP_tm_provide_SB_processes(*this);
00394         break;
00395         
00396     case BCP_Msg_SBnodeFinished:
00397         sender = msg_buf.sender();
00398         lp_scheduler.release_sb_id(sender);
00399         break;
00400 
00401     case BCP_Msg_WarmstartRoot:
00402         BCP_tm_rebroadcast_root_warmstart(*this);
00403         break;
00404 
00405     case BCP_Msg_RequestCutIndexSet:
00406         sender = msg_buf.sender();
00407         msg_buf.clear();
00408         msg_buf.pack(next_cut_index_set_start);
00409         next_cut_index_set_start += 10000;
00410         msg_buf.pack(next_cut_index_set_start);
00411         msg_env->send(sender, BCP_Msg_CutIndexSet, msg_buf);
00412         break;
00413       
00414     case BCP_Msg_RequestVarIndexSet:
00415         sender = msg_buf.sender();
00416         msg_buf.clear();
00417         msg_buf.pack(next_var_index_set_start);
00418         next_var_index_set_start += 10000;
00419         msg_buf.pack(next_var_index_set_start);
00420         msg_env->send(sender, BCP_Msg_VarIndexSet, msg_buf);
00421         break;
00422 
00423     case BCP_Msg_NodeListRequestReply:
00424       msg_buf.unpack(id);
00425       index__node = BCP_tm_node_to_send::waiting.find(id);
00426       if (index__node == BCP_tm_node_to_send::waiting.end()) {
00427         throw BCP_fatal_error("TM: node data from TMS for node not waiting.\n");
00428       }
00429       node_to_send = index__node->second;
00430       if (node_to_send->receive_node_desc(msg_buf)) {
00431         delete node_to_send;
00432         BCP_tm_node_to_send::waiting.erase(index__node);
00433       }
00434       break;
00435 
00436     case BCP_Msg_VarListRequestReply:
00437       msg_buf.unpack(id);
00438       index__node = BCP_tm_node_to_send::waiting.find(id);
00439       if (index__node == BCP_tm_node_to_send::waiting.end()) {
00440         throw BCP_fatal_error("TM: var list from TMS for node not waiting.\n");
00441       }
00442       node_to_send = index__node->second;
00443       if (node_to_send->receive_vars(msg_buf)) {
00444         delete node_to_send;
00445         BCP_tm_node_to_send::waiting.erase(index__node);
00446       }
00447       break;
00448 
00449     case BCP_Msg_CutListRequestReply:
00450       msg_buf.unpack(id);
00451       index__node = BCP_tm_node_to_send::waiting.find(id);
00452       if (index__node == BCP_tm_node_to_send::waiting.end()) {
00453         throw BCP_fatal_error("TM: cut list from TMS for node not waiting.\n");
00454       }
00455       node_to_send = index__node->second;
00456       if (node_to_send->receive_cuts(msg_buf)) {
00457         delete node_to_send;
00458         BCP_tm_node_to_send::waiting.erase(index__node);
00459       }
00460       break;
00461 
00462     case BCP_Msg_NodeListDeleteReply:
00463     case BCP_Msg_VarListDeleteReply:
00464     case BCP_Msg_CutListDeleteReply:
00465         sender = msg_buf.sender();
00466         msg_buf.unpack(id); // just reuse an int variable...
00467         ts_space[msg_buf.sender()] = id;
00468         break;
00469         
00470     case BCP_Msg_LpStatistics:
00471         throw BCP_fatal_error("\
00472 Unexpected BCP_Msg_LpStatistics message in BCP_tm_prob::process_message.\n");
00473 
00474     case BCP_Msg_SomethingDied:
00475         // *FIXME-NOW* : what to do when something has died?
00476         break;
00477 
00478     case BCP_ARE_YOU_TREEMANAGER:
00479         msg_env->send(msg_buf.sender(), BCP_I_AM_TREEMANAGER);
00480         break;
00481 
00482     case BCP_CONFIG_CHANGE:
00483         BCP_tm_change_config(*this, msg_buf);
00484         break;
00485 
00486     default:
00487         throw BCP_fatal_error("\
00488 Unknown message in BCP_tm_prob::process_message.\n");
00489     }
00490     msg_buf.clear();
00491 
00492     const double t = CoinCpuTime() - start_time;
00493     const bool time_is_over = t > param(BCP_tm_par::MaxRunTime);
00494 
00495     /* FIXME: for now we disable testing the machine... */
00496 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00497     if (! param(BCP_tm_par::MessagePassingIsSerial) &&
00498         msg_count % test_frequency == 0) {
00499         // run the machine testing while it returns false (i.e., it did not
00500         // check out, it had to delete something)
00501         while (! BCP_tm_test_machine(*this));
00502         if (slaves.lp->procs().size() == 0)
00503             throw BCP_fatal_error("TM: No LP process left to compute with.\n");
00504     }
00505 #endif
00506 
00507     if (time_is_over) {
00508         const double lb = search_tree.true_lower_bound(search_tree.root());
00509         BCP_fatal_error::abort_on_error = false;
00510         throw BCP_fatal_error("\
00511 TM: Time has ran out.\n\
00512 TM: Best lower bound in this phase: %f\n", lb);
00513     }
00514 }
00515 
00516 //#############################################################################
00517 
00518 /* FIXME: for now we disable testing the machine... */
00519 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00520 bool
00521 BCP_tm_test_machine(BCP_tm_prob& p)
00522 {
00523     BCP_vec<int>::const_iterator dead_process_i =
00524         p.msg_env->alive(*p.slaves.all);
00525 
00526     if (dead_process_i == p.slaves.all->procs().end())
00527         // everything is fine
00528         return true;
00529 
00530     int dead_pid = *dead_process_i;
00531     bool continue_testing = true;
00532     // Oops, something has died, must write it off.
00533 
00534     if (continue_testing) {
00535       printf("TM: Removing dead LP (pid: %i).\n", dead_pid);
00536       BCP_tm_remove_lp(p, dead_pid);
00537       continue_testing = false;
00538     }
00539 
00540 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00541     int i;
00542     if (continue_testing && p.slaves.cg) {
00543         i = p.slaves.cg->index_of_proc(dead_process);
00544         if (i >= 0) {
00545             printf("TM: CG #%i is dead. Removing the LP/CG/VG/triplet.\n", i);
00546             BCP_tm_remove_cg(p, i);
00547             continue_testing = false;
00548         }
00549     }
00550 
00551     if (continue_testing && p.slaves.vg) {
00552         i = p.slaves.vg->index_of_proc(dead_process);
00553         if (i >= 0) {
00554             printf("TM: VG #%i is dead. Removing the LP/CG/VG/triplet.\n", i);
00555             BCP_tm_remove_vg(p, i);
00556             continue_testing = false;
00557         }
00558     }
00559 #endif
00560 
00561     p.slaves.all->delete_proc(dead_pid);
00562 
00563     return false;
00564 }
00565 #endif
00566 
00567 //#############################################################################
00568 
00569 void BCP_tm_modify_pool_counters(BCP_tm_prob& p, BCP_tm_node* node)
00570 {
00571 /* FIXME: we don't have pools anyway... */
00572 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00573     if (node->cp != -1) {
00574         BCP_vec< std::pair<int, int> >::iterator proc =
00575             BCP_tm_identify_process(p.leaves_per_cp, node->cp);
00576 #ifdef BCP_DEBUG
00577         if (proc == p.leaves_per_cp.end())
00578             throw BCP_fatal_error("\
00579 TM: non-existing CP was assigned to a just pruned node.\n");
00580 #endif
00581         if (--proc->second == 0)
00582             p.slaves.cp->set_proc_free(proc->first);
00583     }
00584     if (node->vp != -1) {
00585         BCP_vec< std::pair<int, int> >::iterator proc =
00586             BCP_tm_identify_process(p.leaves_per_vp, node->vp);
00587 #ifdef BCP_DEBUG
00588         if (proc == p.leaves_per_vp.end())
00589             throw BCP_fatal_error("\
00590 TM: non-existing VP was assigned to a just pruned node.\n");
00591 #endif
00592         if (--proc->second == 0)
00593             p.slaves.vp->set_proc_free(proc->first);
00594     }
00595 #endif
00596 }
00597 
00598 //#############################################################################
00599 
00600 /* FIXME: for now we disable testing the machine... */
00601 void
00602 BCP_tm_remove_lp(BCP_tm_prob& p, const int dead_pid)
00603 {
00604   printf("For now we can't remove dead processes...\n");
00605   abort();
00606 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00607     BCP_tm_node* node = p.active_nodes[dead_pid];
00608     if (node) {
00609         if (node->lp != dead_pid)
00610             throw BCP_fatal_error("TM: messed up active nodes... :-(.\n");
00611         // Got to put back the search tree node onto the candidate list.
00612         // fix the CP/VP fields
00613         if (node->cp != -1) {
00614             BCP_vec< std::pair<int, int> >::iterator proc =
00615                 BCP_tm_identify_process(p.leaves_per_cp, node->cp);
00616             if (proc == p.leaves_per_cp.end()) {
00617                 node->cp = -1; 
00618             }
00619         }
00620         if (node->vp != -1) {
00621             BCP_vec< std::pair<int, int> >::iterator proc =
00622                 BCP_tm_identify_process(p.leaves_per_vp, node->vp);
00623             if (proc == p.leaves_per_vp.end()) {
00624                 node->vp = -1; 
00625             }
00626         }
00627         p.active_nodes.erase(dead_pid);
00628 
00629         node->lp = node->cg = node->vg = -1;
00630         node->status = BCP_CandidateNode;
00631         p.candidate_list.push(node, false);
00632     }
00633 
00634 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00635     int proc;
00636     if (p.slaves.cg) {
00637         proc = p.slaves.cg->procs()[index];
00638         p.slaves.cg->delete_proc(index);
00639         p.slaves.all->delete_proc(p.slaves.all->index_of_proc(proc));
00640     }
00641     if (p.slaves.vg) {
00642         proc = p.slaves.vg->procs()[index];
00643         p.slaves.vg->delete_proc(index);
00644         p.slaves.all->delete_proc(p.slaves.all->index_of_proc(proc));
00645     }
00646 #endif
00647 
00648     p.slaves.lp->delete_proc(dead_pid);
00649     p.slaves.all->delete_proc(dead_pid);
00650 #endif
00651 }
00652 
00653 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00654 void
00655 BCP_tm_remove_cg(BCP_tm_prob& p, const int index)
00656 {
00657     // for now this just removes the lp
00658     BCP_tm_remove_lp(p, index);
00659 }
00660 
00661 void
00662 BCP_tm_remove_vg(BCP_tm_prob& p, const int index)
00663 {
00664     // for now this just removes the lp
00665     BCP_tm_remove_lp(p, index);
00666 }
00667 #endif
00668 
00669 //#############################################################################
00670 
00671 void
00672 BCP_tm_unpack_priced_root(BCP_tm_prob& p, BCP_buffer& buf)
00673 {
00674     abort();
00675     // BROKEN: multistage is BROKEN
00676 #if 0
00677     // only a BCP_named_pricing_list is sent over, unpack it.
00678     BCP_tm_node* root = p.search_tree.root();
00679 
00680     p.flags.root_pricing_unpacked = true;
00681 
00682     BCP_tm_free_procs_of_node(p, root);
00683     p.active_nodes.erase(root->lp);
00684 #endif
00685 }
00686 
00687 //#############################################################################
00688 
00689 void
00690 BCP_tm_free_procs_of_node(BCP_tm_prob& p, BCP_tm_node* node)
00691 {
00692   p.lp_scheduler.release_node_id(node->lp);
00693 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00694     if (node->cg != -1)
00695         p.slaves.cg->set_proc_free(node->cg);
00696     if (node->vg != -1)
00697         p.slaves.vg->set_proc_free(node->vg);
00698 #endif
00699     // node's pointers are 0'd out (not deleted!)
00700     node->lp = node->cg = node->vg = -1;
00701 }
00702 
00703 //#############################################################################
00704 
00705 static void
00706 BCP_tm_change_config(BCP_tm_prob& p, BCP_buffer& buf)
00707 {
00708   /* FIXME: Do not allow config change for now */
00709 #if 0
00710     int i;
00711     int sender = buf.sender();
00712 
00713     int lp_num = 0;
00714     buf.unpack(lp_num);
00715     BCP_vec<BCP_string> lp(lp_num, "");
00716     for (i = 0; i < lp_num; ++i)
00717         buf.unpack(lp[i]);
00718 
00719     int cg_num = 0;
00720     buf.unpack(cg_num);
00721     BCP_vec<BCP_string> cg(cg_num, "");
00722     for (i = 0; i < cg_num; ++i)
00723         buf.unpack(cg[i]);
00724 
00725     int vg_num = 0;
00726     buf.unpack(vg_num);
00727     BCP_vec<BCP_string> vg(vg_num, "");
00728     for (i = 0; i < vg_num; ++i)
00729         buf.unpack(vg[i]);
00730 
00731     int cp_num = 0;
00732     buf.unpack(cp_num);
00733     BCP_vec<BCP_string> cp(cp_num, "");
00734     for (i = 0; i < cp_num; ++i)
00735         buf.unpack(cp[i]);
00736 
00737     int vp_num = 0;
00738     buf.unpack(vp_num);
00739     BCP_vec<BCP_string> vp(vp_num, "");
00740     for (i = 0; i < vp_num; ++i)
00741         buf.unpack(vp[i]);
00742 
00743     // Check that everything works out fine
00744 
00745 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00746     // At least for now cg_num/vg_num must be the same as lp_num or must be 0
00747     if (p.slaves.cg->size() > 0) {
00748         if (cg_num != lp_num) {
00749             printf("\
00750 BCP: config change: CG's are running thus the number of new CG's must be\
00751      the same as the number of new LP's. Not changing anything.\n");
00752             p.msg_env->send(sender, BCP_CONFIG_ERROR);
00753             return;
00754         }
00755     } else {
00756         if (cg_num != 0) {
00757             printf("\
00758 BCP: config change: CG's are not running thus no new CG's can be started.\
00759      Not changing anything.\n");
00760             p.msg_env->send(sender, BCP_CONFIG_ERROR);
00761             return;
00762         }
00763     }
00764     if (p.slaves.vg->size() > 0) {
00765         if (vg_num != lp_num) {
00766             printf("\
00767 BCP: config change: VG's are running thus the number of new VG's must be\
00768      the same as the number of new LP's. Not changing anything.\n");
00769             p.msg_env->send(sender, BCP_CONFIG_ERROR);
00770             return;
00771         }
00772     } else {
00773         if (vg_num != 0) {
00774             printf("\
00775 BCP: config change: VG's are not running thus no new VG's can be started.\
00776      Not changing anything.\n");
00777             p.msg_env->send(sender, BCP_CONFIG_ERROR);
00778             return;
00779         }
00780     }
00781 #endif
00782 
00783     // Spawn the jobs
00784     const BCP_string& exe = p.param(BCP_tm_par::ExecutableName);
00785     if (lp_num > 0) {
00786         const bool debug = p.param(BCP_tm_par::DebugLpProcesses) != 0;
00787         BCP_proc_array* new_lps =
00788             p.msg_env->start_processes(exe, lp_num, lp, debug);
00789         p.slaves.lp->add_procs(new_lps->procs().begin(),
00790                                new_lps->procs().end());
00791         BCP_tm_notify_process_type(p, BCP_ProcessType_LP, &new_lps->procs());
00792     }
00793 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00794     if (cg_num > 0) {
00795         const bool debug = p.param(BCP_tm_par::DebugCgProcesses) != 0;
00796         BCP_proc_array* new_cgs =
00797             p.msg_env->start_processes(exe, cg_num, cg, debug);
00798         p.slaves.cg->add_procs(new_cgs->procs().begin(),
00799                                new_cgs->procs().end());
00800         BCP_tm_notify_process_type(p, BCP_ProcessType_CG, &new_cgs->procs());
00801     }
00802     if (vg_num > 0) {
00803         const bool debug = p.param(BCP_tm_par::DebugVgProcesses) != 0;
00804         BCP_proc_array* new_vgs =
00805             p.msg_env->start_processes(exe, vg_num, vg, debug);
00806         p.slaves.vg->add_procs(new_vgs->procs().begin(),
00807                                new_vgs->procs().end());
00808         BCP_tm_notify_process_type(p, BCP_ProcessType_VG, &new_vgs->procs());
00809     }
00810     if (cp_num > 0) {
00811         const bool debug = p.param(BCP_tm_par::DebugCpProcesses) != 0;
00812         BCP_proc_array* new_cps =
00813             p.msg_env->start_processes(exe, cp_num, cp, debug);
00814         p.slaves.cp->add_procs(new_cps->procs().begin(),
00815                                new_cps->procs().end());
00816         BCP_tm_notify_process_type(p, BCP_ProcessType_CP, &new_cps->procs());
00817     }
00818     if (vp_num > 0) {
00819         const bool debug = p.param(BCP_tm_par::DebugVpProcesses) != 0;
00820         BCP_proc_array* new_vps =
00821             p.msg_env->start_processes(exe, vp_num, vp, debug);
00822         p.slaves.vp->add_procs(new_vps->procs().begin(),
00823                                new_vps->procs().end());
00824         BCP_tm_notify_process_type(p, BCP_ProcessType_VP, &new_vps->procs());
00825     }
00826 #endif
00827 
00828     // Signal back that everything is OK.
00829     p.msg_env->send(sender, BCP_CONFIG_OK);
00830 #endif
00831 }

Generated on Thu Oct 8 03:02:52 2009 by  doxygen 1.4.7