00001
00002
00003
00004 #include <cerrno>
00005
00006 #include "BcpConfig.h"
00007 #include "BCP_os.hpp"
00008 #include "BCP_string.hpp"
00009 #include "BCP_message_tag.hpp"
00010 #include "BCP_main_fun.hpp"
00011 #include "BCP_var.hpp"
00012 #include "BCP_cut.hpp"
00013 #include "BCP_tmstorage.hpp"
00014 #include "BCP_problem_core.hpp"
00015 #include "BCP_node_change.hpp"
00016
00017 using std::make_pair;
00018
00019 #define TS_MAX_HEAP_SIZE p.par.entry(BCP_ts_par::MaxHeapSize)
00020
00021
00022
00023 template <>
00024 void BCP_parameter_set<BCP_ts_par>::create_keyword_list()
00025 {
00026 keys.push_back(make_pair(BCP_string("BCP_NiceLevel"),
00027 BCP_parameter(BCP_IntPar,
00028 NiceLevel)));
00029 keys.push_back(make_pair(BCP_string("BCP_LogFileName"),
00030 BCP_parameter(BCP_StringPar,
00031 LogFileName)));
00032 keys.push_back(make_pair(BCP_string("BCP_MaxHeapSize"),
00033 BCP_parameter(BCP_IntPar,
00034 MaxHeapSize)));
00035 }
00036
00037
00038
00039 template <>
00040 void BCP_parameter_set<BCP_ts_par>::set_default_entries()
00041 {
00042
00043 set_entry(MessagePassingIsSerial, false);
00044 set_entry(MaxHeapSize, 0);
00045 set_entry(NiceLevel, 0);
00046 set_entry(LogFileName,"");
00047 }
00048
00049
00050
00051 BCP_process_t BCP_tmstorage_main(BCP_message_environment* msg_env,
00052 USER_initialize* user_init,
00053 int my_id, int parent, double ub)
00054 {
00055
00056
00057 BCP_ts_prob p(my_id, parent);
00058 p.msg_env = msg_env;
00059
00060 p.par.set_entry(BCP_ts_par::MessagePassingIsSerial, false);
00061
00062
00063 p.msg_buf.clear();
00064 msg_env->receive(parent ,
00065 BCP_Msg_ProcessParameters, p.msg_buf, -1);
00066 p.par.unpack(p.msg_buf);
00067
00068
00069 setpriority(PRIO_PROCESS, 0, p.par.entry(BCP_ts_par::NiceLevel));
00070
00071 FILE* logfile = 0;
00072
00073 const BCP_string& log = p.par.entry(BCP_ts_par::LogFileName);
00074 if (! (p.par.entry(BCP_ts_par::LogFileName) == "")) {
00075 int len = log.length();
00076 char *logname = new char[len + 300];
00077 memcpy(logname, log.c_str(), len);
00078 memcpy(logname + len, "-ts-", 4);
00079 len += 4;
00080 gethostname(logname + len, 255);
00081 len = strlen(logname);
00082 logname[len++] = '-';
00083 sprintf(logname + len, "%i", static_cast<int>(GETPID));
00084 logfile = freopen(logname, "a", stdout);
00085 if (logfile == 0) {
00086 fprintf(stderr, "Error while redirecting stdout: %i\n", errno);
00087 abort();
00088 }
00089 setvbuf(logfile, NULL, _IOLBF, 0);
00090 delete[] logname;
00091 } else {
00092 setvbuf(stdout, NULL, _IOLBF, 0);
00093 }
00094
00095
00096 p.user = user_init->ts_init(p);
00097 if (p.user) {
00098 p.user->setTsProblemPointer(&p);
00099 }
00100 p.packer = user_init->packer_init(p.user);
00101 p.packer->user_class = p.user;
00102
00103
00104 p.msg_buf.clear();
00105 p.msg_env->receive(parent ,
00106 BCP_Msg_CoreDescription, p.msg_buf, -1);
00107 p.core->unpack(p.msg_buf);
00108
00109
00110 p.msg_buf.clear();
00111 msg_env->receive(parent ,
00112 BCP_Msg_InitialUserInfo, p.msg_buf, -1);
00113 if (p.user) {
00114 p.user->unpack_module_data(p.msg_buf);
00115 }
00116
00117
00118
00119 BCP_message_tag msgtag;
00120 BCP_process_t ptype = BCP_ProcessType_EndProcess;
00121 while (true) {
00122 p.msg_buf.clear();
00123 msg_env->receive(BCP_AnyProcess, BCP_Msg_AnyMessage, p.msg_buf, 15);
00124 msgtag = p.msg_buf.msgtag();
00125 if (msgtag == BCP_Msg_NoMessage) {
00126
00127 if (! p.msg_env->alive(parent )) {
00128 throw BCP_fatal_error("VG: The TM has died -- VG exiting\n");
00129 }
00130 continue;
00131 }
00132 if (msgtag == BCP_Msg_ProcessType) {
00133 p.msg_buf.unpack(ptype);
00134 break;
00135 }
00136 p.process_message();
00137 if (msgtag == BCP_Msg_FinishedBCP) {
00138 break;
00139 }
00140 }
00141 if (logfile) {
00142 fclose(logfile);
00143 }
00144
00145 return ptype;
00146 }
00147
00148
00149
00150 BCP_ts_prob::~BCP_ts_prob()
00151 {
00152 std::map<int, BCP_ts_node_data*>::iterator n;
00153 for (n = nodes.begin(); n != nodes.end(); ++n) {
00154 delete n->second->_desc;
00155 delete n->second->_user;
00156 delete n->second;
00157 }
00158 std::map<int, BCP_cut_algo*>::iterator c;
00159 for (c = cuts.begin(); c != cuts.end(); ++c) {
00160 delete c->second;
00161 }
00162 std::map<int, BCP_var_algo*>::iterator v;
00163 for (v = vars.begin(); v != vars.end(); ++v) {
00164 delete v->second;
00165 }
00166 delete core;
00167 delete packer;
00168 delete user;
00169 }
00170
00171
00172
00173 static void process_Msg_NodeList(BCP_ts_prob& p, BCP_buffer& buf)
00174 {
00175 int index;
00176 int num = 0;
00177 int fm = 0;
00178 bool has_user_data = false;
00179
00180 while (true) {
00181 if (num % 10 == 0) {
00182 fm = TS_MAX_HEAP_SIZE;
00183 fm -= BCP_used_heap();
00184 if (fm < 1<<23 ) {
00185 break;
00186 }
00187 }
00188 buf.unpack(index);
00189 if (index == -1) {
00190 break;
00191 }
00192 assert(p.nodes.find(index) == p.nodes.end());
00193 BCP_ts_node_data* data = new BCP_ts_node_data;
00194 data->_desc = new BCP_node_change;
00195 data->_desc->unpack(p.packer, false, buf);
00196 buf.unpack(has_user_data);
00197 data->_user = has_user_data ? p.packer->unpack_user_data(buf) : 0;
00198 p.nodes[index] = data;
00199 ++num;
00200 }
00201 fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00202 buf.clear();
00203 buf.pack(num);
00204 buf.pack(fm);
00205 p.msg_env->send(p.get_parent(), BCP_Msg_NodeListReply, buf);
00206 }
00207
00208
00209
00210 static void process_Msg_NodeListRequest(BCP_ts_prob& p, BCP_buffer& buf)
00211 {
00212 int id;
00213 buf.unpack(id);
00214 BCP_vec<int>& nodelevels = p.positions;
00215 buf.unpack(nodelevels);
00216 const int num = nodelevels.size();
00217 BCP_vec<int>& inds = p.indices;
00218 buf.unpack(inds);
00219 buf.clear();
00220 buf.pack(id);
00221 buf.pack(num);
00222 for (int i = 0; i < num; ++i) {
00223 std::map<int, BCP_ts_node_data*>::iterator n = p.nodes.find(inds[i]);
00224 if (n == p.nodes.end()) {
00225 throw BCP_fatal_error("TS: Requested node (%i) is not here\n",
00226 inds[i]);
00227 }
00228 BCP_ts_node_data* data = n->second;
00229 buf.pack(nodelevels[i]);
00230 buf.pack(inds[i]);
00231
00232 data->_desc->pack(p.packer, false, buf);
00233 bool has_user_data = data->_user != 0;
00234 buf.pack(has_user_data);
00235 if (has_user_data) {
00236 p.packer->pack_user_data(data->_user, buf);
00237 }
00238 }
00239 p.msg_env->send(p.get_parent(), BCP_Msg_NodeListRequestReply, buf);
00240 }
00241
00242
00243
00244 static void process_Msg_NodeListDelete(BCP_ts_prob& p, BCP_buffer& buf)
00245 {
00246 BCP_vec<int>& inds = p.indices;
00247 buf.unpack(inds);
00248 const int num = inds.size();
00249 for (int i = 0; i < num; ++i) {
00250 std::map<int, BCP_ts_node_data*>::iterator n = p.nodes.find(inds[i]);
00251 if (n == p.nodes.end()) {
00252 throw BCP_fatal_error("TS: Node to be deleted (%i) is not here\n",
00253 inds[i]);
00254 }
00255 delete n->second->_desc;
00256 delete n->second->_user;
00257 delete n->second;
00258 p.nodes.erase(n);
00259 }
00260 buf.clear();
00261 int fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00262 buf.pack(fm);
00263 p.msg_env->send(p.get_parent(), BCP_Msg_NodeListDeleteReply, buf);
00264 }
00265
00266
00267
00268 static void process_Msg_CutList(BCP_ts_prob& p, BCP_buffer& buf)
00269 {
00270
00271 int num = 0 ;
00272 int index;
00273 int fm = 0;
00274 while (true) {
00275 if (num % 10 == 0) {
00276 fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00277 if (fm < 1<<23 ) {
00278 break;
00279 }
00280 }
00281 buf.unpack(index);
00282 if (index == -1) {
00283 break;
00284 }
00285 p.cuts[index] = p.packer->unpack_cut_algo(buf);
00286 ++num;
00287 }
00288 fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00289 buf.clear();
00290 buf.pack(num);
00291 buf.pack(fm);
00292 p.msg_env->send(p.get_parent(), BCP_Msg_CutListReply, buf);
00293 }
00294
00295
00296
00297 static void process_Msg_CutListRequest(BCP_ts_prob& p, BCP_buffer& buf)
00298 {
00299 int id;
00300 buf.unpack(id);
00301 BCP_vec<int>& pos = p.positions;
00302 buf.unpack(pos);
00303 const int num = pos.size();
00304 BCP_vec<int>& inds = p.indices;
00305 buf.unpack(inds);
00306 buf.clear();
00307 buf.pack(id);
00308 buf.pack(num);
00309 for (int i = 0; i < num; ++i) {
00310 std::map<int, BCP_cut_algo*>::iterator c = p.cuts.find(inds[i]);
00311 if (c == p.cuts.end()) {
00312 throw BCP_fatal_error("TS: Requested cut (%i) is not here\n",
00313 inds[i]);
00314 }
00315 buf.pack(pos[i]);
00316 buf.pack(inds[i]);
00317 p.packer->pack_cut_algo(c->second, buf);
00318 }
00319 p.msg_env->send(p.get_parent(), BCP_Msg_CutListRequestReply, buf);
00320 }
00321
00322
00323
00324 static void process_Msg_CutListDelete(BCP_ts_prob& p, BCP_buffer& buf)
00325 {
00326
00327 BCP_vec<int>& inds = p.indices;
00328 buf.unpack(inds);
00329 const int num = inds.size();
00330 for (int i = 0; i < num; ++i) {
00331 std::map<int, BCP_cut_algo*>::iterator c = p.cuts.find(inds[i]);
00332 if (c == p.cuts.end()) {
00333 throw BCP_fatal_error("TS: cut to be deleted (%i) is not here\n",
00334 inds[i]);
00335 }
00336 delete c->second;
00337 p.cuts.erase(c);
00338 }
00339 buf.clear();
00340 int fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00341 buf.pack(fm);
00342 p.msg_env->send(p.get_parent(), BCP_Msg_CutListDeleteReply, buf);
00343 }
00344
00345
00346
00347 static void process_Msg_VarList(BCP_ts_prob& p, BCP_buffer& buf)
00348 {
00349
00350 int num = 0 ;
00351 int index;
00352 int fm = 0;
00353 while (true) {
00354 if (num % 10 == 0) {
00355 fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00356 if (fm < 1<<23 ) {
00357 break;
00358 }
00359 }
00360 buf.unpack(index);
00361 if (index == -1) {
00362 break;
00363 }
00364 p.vars[index] = p.packer->unpack_var_algo(buf);
00365 ++num;
00366 }
00367 fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00368 buf.clear();
00369 buf.pack(num);
00370 buf.pack(fm);
00371 p.msg_env->send(p.get_parent(), BCP_Msg_VarListReply, buf);
00372 }
00373
00374
00375
00376 static void process_Msg_VarListRequest(BCP_ts_prob& p, BCP_buffer& buf)
00377 {
00378 int id;
00379 buf.unpack(id);
00380 BCP_vec<int>& pos = p.positions;
00381 buf.unpack(pos);
00382 const int num = pos.size();
00383 BCP_vec<int>& inds = p.indices;
00384 buf.unpack(inds);
00385 buf.clear();
00386 buf.pack(id);
00387 buf.pack(num);
00388 for (int i = 0; i < num; ++i) {
00389 std::map<int, BCP_var_algo*>::iterator c = p.vars.find(inds[i]);
00390 if (c == p.vars.end()) {
00391 throw BCP_fatal_error("TS: Requested var (%i) is not here\n",
00392 inds[i]);
00393 }
00394 buf.pack(pos[i]);
00395 buf.pack(inds[i]);
00396 p.packer->pack_var_algo(c->second, buf);
00397 }
00398 p.msg_env->send(p.get_parent(), BCP_Msg_VarListRequestReply, buf);
00399 }
00400
00401
00402
00403 static void process_Msg_VarListDelete(BCP_ts_prob& p, BCP_buffer& buf)
00404 {
00405
00406 BCP_vec<int>& inds = p.indices;
00407 buf.unpack(inds);
00408 const int num = inds.size();
00409 for (int i = 0; i < num; ++i) {
00410 std::map<int, BCP_var_algo*>::iterator v = p.vars.find(inds[i]);
00411 if (v == p.vars.end()) {
00412 throw BCP_fatal_error("TS: var to be deleted (%i) is not here\n",
00413 inds[i]);
00414 }
00415 delete v->second;
00416 p.vars.erase(v);
00417 }
00418 buf.clear();
00419 int fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
00420 buf.pack(fm);
00421 p.msg_env->send(p.get_parent(), BCP_Msg_VarListDeleteReply, buf);
00422 }
00423
00424
00425
00426 void
00427 BCP_ts_prob::process_message()
00428 {
00429 switch (msg_buf.msgtag()){
00430 case BCP_Msg_InitialUserInfo:
00431 throw BCP_fatal_error("\
00432 TS: BCP_ts_prob::process_message(): BCP_Msg_InitialUserInfo arrived\n");
00433
00434 case BCP_Msg_NodeList:
00435 process_Msg_NodeList(*this, msg_buf);
00436 break;
00437
00438 case BCP_Msg_NodeListRequest:
00439 process_Msg_NodeListRequest(*this, msg_buf);
00440 break;
00441
00442 case BCP_Msg_NodeListDelete:
00443 process_Msg_NodeListDelete(*this, msg_buf);
00444 break;
00445
00446 case BCP_Msg_CutList:
00447 process_Msg_CutList(*this, msg_buf);
00448 break;
00449
00450 case BCP_Msg_CutListRequest:
00451 process_Msg_CutListRequest(*this, msg_buf);
00452 break;
00453
00454 case BCP_Msg_CutListDelete:
00455 process_Msg_CutListDelete(*this, msg_buf);
00456 break;
00457
00458 case BCP_Msg_VarList:
00459 process_Msg_VarList(*this, msg_buf);
00460 break;
00461
00462 case BCP_Msg_VarListRequest:
00463 process_Msg_VarListRequest(*this, msg_buf);
00464 break;
00465
00466 case BCP_Msg_VarListDelete:
00467 process_Msg_VarListDelete(*this, msg_buf);
00468 break;
00469
00470 case BCP_Msg_UpperBound:
00471
00472 break;
00473
00474 case BCP_Msg_FinishedBCP:
00475 break;
00476
00477 default:
00478 throw BCP_fatal_error("\
00479 TS: BCP_ts_prob::process_message(): Unexpected message tag (%i) arrived\n",
00480 msg_buf.msgtag());
00481 }
00482 msg_buf.clear();
00483
00484 }
00485
00486
00487