00001
00002
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
00178
00179 break;
00180 case BCP_ProcessType_VP:
00181
00182
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
00267
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
00279
00280
00281
00282
00283
00284 static int msg_count = 0;
00285
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);
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
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
00496 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00497 if (! param(BCP_tm_par::MessagePassingIsSerial) &&
00498 msg_count % test_frequency == 0) {
00499
00500
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
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
00528 return true;
00529
00530 int dead_pid = *dead_process_i;
00531 bool continue_testing = true;
00532
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
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
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
00612
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
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
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
00676 #if 0
00677
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
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
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
00744
00745 #if ! defined(BCP_ONLY_LP_PROCESS_HANDLING_WORKS)
00746
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
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
00829 p.msg_env->send(sender, BCP_CONFIG_OK);
00830 #endif
00831 }