/home/coin/SVN-release/OS-2.4.0/Bcp/src/TM/BCP_tmstorage.cpp

Go to the documentation of this file.
00001 // Copyright (C) 2007, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
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     // If we ever get here then the environment is parallel
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     // wait for the message with the parameters and unpack it
00063     p.msg_buf.clear();
00064     msg_env->receive(parent /*tree_manager*/,
00065                      BCP_Msg_ProcessParameters, p.msg_buf, -1);
00066     p.par.unpack(p.msg_buf);
00067 
00068     // Let us be nice
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); // make it line buffered
00090         delete[] logname;
00091     } else {
00092         setvbuf(stdout, NULL, _IOLBF, 0); // make it line buffered
00093     }
00094 
00095     // now create the user universe
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     // wait for the core description and process it
00104     p.msg_buf.clear();
00105     p.msg_env->receive(parent /*tree_manager*/,
00106                        BCP_Msg_CoreDescription, p.msg_buf, -1);
00107     p.core->unpack(p.msg_buf);
00108 
00109     // wait for the user info
00110     p.msg_buf.clear();
00111     msg_env->receive(parent /*tree_manager*/,
00112                      BCP_Msg_InitialUserInfo, p.msg_buf, -1);
00113     if (p.user) {
00114       p.user->unpack_module_data(p.msg_buf);
00115     }
00116 
00117     // ok, we're all geared up to generate vars
00118     // wait for messages and process them...
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         // test if the TM is still alive
00127         if (! p.msg_env->alive(parent /*tree_manager*/)) {
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 /* 8M */ ) {
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     // FIXME This routine depends on writing the corresponding routine in TM
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 /* 8M */ ) {
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     // FIXME This routine depends on writing the corresponding routine in TM
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     // FIXME This routine depends on writing the corresponding routine in TM
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 /* 8M */ ) {
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     // FIXME This routine depends on writing the corresponding routine in TM
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         // A message that's sent' to everyone, but here we don't care...
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 

Generated on Thu Sep 22 03:05:53 2011 by  doxygen 1.4.7