BCP_tmstorage.cpp
Go to the documentation of this file.
1 // Copyright (C) 2007, International Business Machines
2 // Corporation and others. All Rights Reserved.
3 
4 #include <cerrno>
5 
6 #include "BcpConfig.h"
7 #include "BCP_os.hpp"
8 #include "BCP_string.hpp"
9 #include "BCP_message_tag.hpp"
10 #include "BCP_main_fun.hpp"
11 #include "BCP_var.hpp"
12 #include "BCP_cut.hpp"
13 #include "BCP_tmstorage.hpp"
14 #include "BCP_problem_core.hpp"
15 #include "BCP_node_change.hpp"
16 
17 using std::make_pair;
18 
19 #define TS_MAX_HEAP_SIZE p.par.entry(BCP_ts_par::MaxHeapSize)
20 
21 //#############################################################################
22 
23 template <>
25 {
26  keys.push_back(make_pair(BCP_string("BCP_NiceLevel"),
28  NiceLevel)));
29  keys.push_back(make_pair(BCP_string("BCP_LogFileName"),
31  LogFileName)));
32  keys.push_back(make_pair(BCP_string("BCP_MaxHeapSize"),
34  MaxHeapSize)));
35 }
36 
37 //#############################################################################
38 
39 template <>
41 {
42  //-------------------------------------------------------------------------
43  set_entry(MessagePassingIsSerial, false);
44  set_entry(MaxHeapSize, 0);
45  set_entry(NiceLevel, 0);
46  set_entry(LogFileName,"");
47 }
48 
49 //#############################################################################
50 
52  USER_initialize* user_init,
53  int my_id, int parent, double ub)
54 {
55  // If we ever get here then the environment is parallel
56 
57  BCP_ts_prob p(my_id, parent);
58  p.msg_env = msg_env;
59 
61 
62  // wait for the message with the parameters and unpack it
63  p.msg_buf.clear();
64  msg_env->receive(parent /*tree_manager*/,
66  p.par.unpack(p.msg_buf);
67 
68  // Let us be nice
69  setpriority(PRIO_PROCESS, 0, p.par.entry(BCP_ts_par::NiceLevel));
70 
71  FILE* logfile = 0;
72 
74  if (! (p.par.entry(BCP_ts_par::LogFileName) == "")) {
75  int len = log.length();
76  char *logname = new char[len + 300];
77  memcpy(logname, log.c_str(), len);
78  memcpy(logname + len, "-ts-", 4);
79  len += 4;
80  gethostname(logname + len, 255);
81  len = strlen(logname);
82  logname[len++] = '-';
83  sprintf(logname + len, "%i", static_cast<int>(GETPID));
84  logfile = freopen(logname, "a", stdout);
85  if (logfile == 0) {
86  fprintf(stderr, "Error while redirecting stdout: %i\n", errno);
87  abort();
88  }
89  setvbuf(logfile, NULL, _IOLBF, 0); // make it line buffered
90  delete[] logname;
91  } else {
92  setvbuf(stdout, NULL, _IOLBF, 0); // make it line buffered
93  }
94 
95  // now create the user universe
96  p.user = user_init->ts_init(p);
97  if (p.user) {
99  }
100  p.packer = user_init->packer_init(p.user);
101  p.packer->user_class = p.user;
102 
103  // wait for the core description and process it
104  p.msg_buf.clear();
105  p.msg_env->receive(parent /*tree_manager*/,
107  p.core->unpack(p.msg_buf);
108 
109  // wait for the user info
110  p.msg_buf.clear();
111  msg_env->receive(parent /*tree_manager*/,
113  if (p.user) {
115  }
116 
117  // ok, we're all geared up to generate vars
118  // wait for messages and process them...
119  BCP_message_tag msgtag;
121  while (true) {
122  p.msg_buf.clear();
124  msgtag = p.msg_buf.msgtag();
125  if (msgtag == BCP_Msg_NoMessage) {
126  // test if the TM is still alive
127  if (! p.msg_env->alive(parent /*tree_manager*/)) {
128  throw BCP_fatal_error("VG: The TM has died -- VG exiting\n");
129  }
130  continue;
131  }
132  if (msgtag == BCP_Msg_ProcessType) {
133  p.msg_buf.unpack(ptype);
134  break;
135  }
136  p.process_message();
137  if (msgtag == BCP_Msg_FinishedBCP) {
138  break;
139  }
140  }
141  if (logfile) {
142  fclose(logfile);
143  }
144 
145  return ptype;
146 }
147 
148 //#############################################################################
149 
151 {
152  std::map<int, BCP_ts_node_data*>::iterator n;
153  for (n = nodes.begin(); n != nodes.end(); ++n) {
154  delete n->second->_desc;
155  delete n->second->_user;
156  delete n->second;
157  }
158  std::map<int, BCP_cut_algo*>::iterator c;
159  for (c = cuts.begin(); c != cuts.end(); ++c) {
160  delete c->second;
161  }
162  std::map<int, BCP_var_algo*>::iterator v;
163  for (v = vars.begin(); v != vars.end(); ++v) {
164  delete v->second;
165  }
166  delete core;
167  delete packer;
168  delete user;
169 }
170 
171 //#############################################################################
172 
174 {
175  int index;
176  int num = 0;
177  int fm = 0;
178  bool has_user_data = false;
179 
180  while (true) {
181  if (num % 10 == 0) {
182  fm = TS_MAX_HEAP_SIZE;
183  fm -= BCP_used_heap();
184  if (fm < 1<<23 /* 8M */ ) {
185  break;
186  }
187  }
188  buf.unpack(index);
189  if (index == -1) {
190  break;
191  }
192  assert(p.nodes.find(index) == p.nodes.end());
194  data->_desc = new BCP_node_change;
195  data->_desc->unpack(p.packer, false, buf);
196  buf.unpack(has_user_data);
197  data->_user = has_user_data ? p.packer->unpack_user_data(buf) : 0;
198  p.nodes[index] = data;
199  ++num;
200  }
202  buf.clear();
203  buf.pack(num);
204  buf.pack(fm);
206 }
207 
208 //-----------------------------------------------------------------------------
209 
211 {
212  int id;
213  buf.unpack(id);
214  BCP_vec<int>& nodelevels = p.positions;
215  buf.unpack(nodelevels);
216  const int num = nodelevels.size();
217  BCP_vec<int>& inds = p.indices;
218  buf.unpack(inds);
219  buf.clear();
220  buf.pack(id);
221  buf.pack(num);
222  for (int i = 0; i < num; ++i) {
223  std::map<int, BCP_ts_node_data*>::iterator n = p.nodes.find(inds[i]);
224  if (n == p.nodes.end()) {
225  throw BCP_fatal_error("TS: Requested node (%i) is not here\n",
226  inds[i]);
227  }
228  BCP_ts_node_data* data = n->second;
229  buf.pack(nodelevels[i]);
230  buf.pack(inds[i]);
231 
232  data->_desc->pack(p.packer, false, buf);
233  bool has_user_data = data->_user != 0;
234  buf.pack(has_user_data);
235  if (has_user_data) {
236  p.packer->pack_user_data(data->_user, buf);
237  }
238  }
240 }
241 
242 //-----------------------------------------------------------------------------
243 
245 {
246  BCP_vec<int>& inds = p.indices;
247  buf.unpack(inds);
248  const int num = inds.size();
249  for (int i = 0; i < num; ++i) {
250  std::map<int, BCP_ts_node_data*>::iterator n = p.nodes.find(inds[i]);
251  if (n == p.nodes.end()) {
252  throw BCP_fatal_error("TS: Node to be deleted (%i) is not here\n",
253  inds[i]);
254  }
255  delete n->second->_desc;
256  delete n->second->_user;
257  delete n->second;
258  p.nodes.erase(n);
259  }
260  buf.clear();
261  int fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
262  buf.pack(fm);
264 }
265 
266 //=============================================================================
267 
269 {
270  // FIXME This routine depends on writing the corresponding routine in TM
271  int num = 0 ;
272  int index;
273  int fm = 0;
274  while (true) {
275  if (num % 10 == 0) {
277  if (fm < 1<<23 /* 8M */ ) {
278  break;
279  }
280  }
281  buf.unpack(index);
282  if (index == -1) {
283  break;
284  }
285  p.cuts[index] = p.packer->unpack_cut_algo(buf);
286  ++num;
287  }
289  buf.clear();
290  buf.pack(num);
291  buf.pack(fm);
293 }
294 
295 //-----------------------------------------------------------------------------
296 
298 {
299  int id;
300  buf.unpack(id);
302  buf.unpack(pos);
303  const int num = pos.size();
304  BCP_vec<int>& inds = p.indices;
305  buf.unpack(inds);
306  buf.clear();
307  buf.pack(id);
308  buf.pack(num);
309  for (int i = 0; i < num; ++i) {
310  std::map<int, BCP_cut_algo*>::iterator c = p.cuts.find(inds[i]);
311  if (c == p.cuts.end()) {
312  throw BCP_fatal_error("TS: Requested cut (%i) is not here\n",
313  inds[i]);
314  }
315  buf.pack(pos[i]);
316  buf.pack(inds[i]);
317  p.packer->pack_cut_algo(c->second, buf);
318  }
320 }
321 
322 //-----------------------------------------------------------------------------
323 
325 {
326  // FIXME This routine depends on writing the corresponding routine in TM
327  BCP_vec<int>& inds = p.indices;
328  buf.unpack(inds);
329  const int num = inds.size();
330  for (int i = 0; i < num; ++i) {
331  std::map<int, BCP_cut_algo*>::iterator c = p.cuts.find(inds[i]);
332  if (c == p.cuts.end()) {
333  throw BCP_fatal_error("TS: cut to be deleted (%i) is not here\n",
334  inds[i]);
335  }
336  delete c->second;
337  p.cuts.erase(c);
338  }
339  buf.clear();
340  int fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
341  buf.pack(fm);
343 }
344 
345 //=============================================================================
346 
348 {
349  // FIXME This routine depends on writing the corresponding routine in TM
350  int num = 0 ;
351  int index;
352  int fm = 0;
353  while (true) {
354  if (num % 10 == 0) {
356  if (fm < 1<<23 /* 8M */ ) {
357  break;
358  }
359  }
360  buf.unpack(index);
361  if (index == -1) {
362  break;
363  }
364  p.vars[index] = p.packer->unpack_var_algo(buf);
365  ++num;
366  }
368  buf.clear();
369  buf.pack(num);
370  buf.pack(fm);
372 }
373 
374 //-----------------------------------------------------------------------------
375 
377 {
378  int id;
379  buf.unpack(id);
381  buf.unpack(pos);
382  const int num = pos.size();
383  BCP_vec<int>& inds = p.indices;
384  buf.unpack(inds);
385  buf.clear();
386  buf.pack(id);
387  buf.pack(num);
388  for (int i = 0; i < num; ++i) {
389  std::map<int, BCP_var_algo*>::iterator c = p.vars.find(inds[i]);
390  if (c == p.vars.end()) {
391  throw BCP_fatal_error("TS: Requested var (%i) is not here\n",
392  inds[i]);
393  }
394  buf.pack(pos[i]);
395  buf.pack(inds[i]);
396  p.packer->pack_var_algo(c->second, buf);
397  }
399 }
400 
401 //-----------------------------------------------------------------------------
402 
404 {
405  // FIXME This routine depends on writing the corresponding routine in TM
406  BCP_vec<int>& inds = p.indices;
407  buf.unpack(inds);
408  const int num = inds.size();
409  for (int i = 0; i < num; ++i) {
410  std::map<int, BCP_var_algo*>::iterator v = p.vars.find(inds[i]);
411  if (v == p.vars.end()) {
412  throw BCP_fatal_error("TS: var to be deleted (%i) is not here\n",
413  inds[i]);
414  }
415  delete v->second;
416  p.vars.erase(v);
417  }
418  buf.clear();
419  int fm = TS_MAX_HEAP_SIZE - BCP_used_heap();
420  buf.pack(fm);
422 }
423 
424 //#############################################################################
425 
426 void
428 {
429  switch (msg_buf.msgtag()){
431  throw BCP_fatal_error("\
432 TS: BCP_ts_prob::process_message(): BCP_Msg_InitialUserInfo arrived\n");
433 
434  case BCP_Msg_NodeList:
436  break;
437 
440  break;
441 
444  break;
445 
446  case BCP_Msg_CutList:
448  break;
449 
452  break;
453 
456  break;
457 
458  case BCP_Msg_VarList:
460  break;
461 
464  break;
465 
468  break;
469 
470  case BCP_Msg_UpperBound:
471  // A message that's sent' to everyone, but here we don't care...
472  break;
473 
474  case BCP_Msg_FinishedBCP:
475  break;
476 
477  default:
478  throw BCP_fatal_error("\
479 TS: BCP_ts_prob::process_message(): Unexpected message tag (%i) arrived\n",
480  msg_buf.msgtag());
481  }
482  msg_buf.clear();
483 
484 }
485 
486 //=============================================================================
487 
std::map< int, BCP_ts_node_data * > nodes
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
virtual void send(const int target, const BCP_message_tag tag)=0
Send an empty message (message tag only) to the process given by the frist argument.
BCP_node_change * _desc
void unpack(BCP_user_pack *packer, const bool def, BCP_buffer &buf)
BCP_buffer & pack(const T &value)
Pack a single object of type T.
Definition: BCP_buffer.hpp:177
BCP has finished.
Used when receiving, message with any message tag will be received.
Used to indicate that there is no message in the buffer of a process.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
Definition: BCP_buffer.hpp:186
void pack(BCP_user_pack *packer, const bool def, BCP_buffer &buf) const
void create_keyword_list()
Method for creating the list of keyword looked for in the parameter file.
virtual void receive(const int source, const BCP_message_tag tag, BCP_buffer &buf, const double timeout)=0
Blocking receive with timeout.
pos
position where the operator should be printed when printing the expression
const int BCP_AnyProcess
Definition: BCP_message.hpp:21
This is an abstract base class that describes the message passing environment.
Definition: BCP_message.hpp:30
static void process_Msg_CutListDelete(BCP_ts_prob &p, BCP_buffer &buf)
virtual BCP_cut_algo * unpack_cut_algo(BCP_buffer &buf)
Unpack an algorithmic cut.
Definition: BCP_USER.hpp:109
virtual BCP_user_data * unpack_user_data(BCP_buffer &buf)
Unpack an user data.
Definition: BCP_USER.hpp:126
BCP_process_t
This enumerative constant describes the various process types.
char entry(const chr_params key) const
const char * c_str() const
Definition: BCP_string.hpp:19
virtual BCP_user_pack * packer_init(BCP_user_class *p)
Definition: BCP_USER.hpp:225
The TM sends the description of the core formulation to the slave process.
BCP_ts_user * user
The TM sends the process type to the process (LP, Cut Generator, etc.)
BCP_process_t BCP_tmstorage_main(BCP_message_environment *msg_env, USER_initialize *user_init, int my_id, int parent, double ub)
void unpack(BCP_buffer &buf)
Unpack the contents of the core description from the buffer.
void set_default_entries()
Method for setting the default values for the parameters.
BCP_vec< std::pair< BCP_string, BCP_parameter > > keys
The keyword, parameter pairs.
#define setpriority(x, y, z)
Definition: BCP_os.hpp:13
This class is a very simple impelementation of a constant length string.
Definition: BCP_string.hpp:13
String parameter.
BCP_user_data * _user
static void process_Msg_CutList(BCP_ts_prob &p, BCP_buffer &buf)
void push_back(const_reference x)
Append x to the end of the vector.
virtual BCP_ts_user * ts_init(BCP_ts_prob &p)
Definition: BCP_USER.hpp:194
BCP_parameter_set< BCP_ts_par > par
BCP_user_pack * packer
void setTsProblemPointer(BCP_ts_prob *ptr)
Set the pointer.
BCP_vec< int > positions
positions in the TM of requested nodes/vars/cuts
virtual void pack_cut_algo(const BCP_cut_algo *cut, BCP_buffer &buf)
Pack an algorithmic cut.
Definition: BCP_USER.hpp:102
std::map< int, BCP_cut_algo * > cuts
This class is an abstract base class for the initializer class the user has to provide.
Definition: BCP_USER.hpp:160
#define GETPID
Definition: BCP_os.hpp:31
int length() const
Definition: BCP_string.hpp:16
BCP_vec< int > indices
a list of indices of nodes/vars/cuts that are requested/tobe deleted
std::map< int, BCP_var_algo * > vars
static long BCP_used_heap()
Definition: BCP_os.hpp:54
void set_entry(const chr_params key, const char val)
static void process_Msg_VarListRequest(BCP_ts_prob &p, BCP_buffer &buf)
BCP_user_class * user_class
A pointer ot the usr class of the process from which the methods of this class are invoked from...
Definition: BCP_USER.hpp:55
#define gethostname(x, y)
Definition: BCP_os.hpp:25
The TM sends the appropriate parameters to the slave process.
int get_parent() const
Definition: BCP_process.hpp:25
This parameter indeintifies a single parameter entry.
BCP_buffer msg_buf
The TM sends the initial user packed information to the slave process.
void clear()
Completely clear the buffer.
Definition: BCP_buffer.hpp:168
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
Definition: BCP_buffer.hpp:90
Currently there isn&#39;t any error handling in BCP.
Definition: BCP_error.hpp:20
static void process_Msg_VarListDelete(BCP_ts_prob &p, BCP_buffer &buf)
size_t size() const
Return the current number of entries.
Definition: BCP_vector.hpp:116
virtual BCP_var_algo * unpack_var_algo(BCP_buffer &buf)
Unpack an algorithmic variable.
Definition: BCP_USER.hpp:93
virtual ~BCP_ts_prob()
This class describes the message buffer used for all processes of BCP.
Definition: BCP_buffer.hpp:39
static void process_Msg_NodeListDelete(BCP_ts_prob &p, BCP_buffer &buf)
virtual void pack_var_algo(const BCP_var_algo *var, BCP_buffer &buf)
Pack an algorithmic variable.
Definition: BCP_USER.hpp:86
static void process_Msg_NodeList(BCP_ts_prob &p, BCP_buffer &buf)
BCP_message_environment * msg_env
void unpack(BCP_buffer &buf)
Unpack the parameter set from the buffer.
Integer parameter.
Any process to TM or TM to any process: a new upper bound found.
virtual bool alive(const int pid)=0
Test if the process given by the argument is alive or not.
static void process_Msg_VarList(BCP_ts_prob &p, BCP_buffer &buf)
virtual void pack_user_data(const BCP_user_data *ud, BCP_buffer &buf)
Pack an user data.
Definition: BCP_USER.hpp:119
void fint * n
BCP_problem_core * core
virtual void process_message()
virtual void unpack_module_data(BCP_buffer &buf)
Unpack the initial information sent to the LP process by the Tree Manager.
real c
static void process_Msg_NodeListRequest(BCP_ts_prob &p, BCP_buffer &buf)
Same as BCP_tm_node_data, just there&#39;s no need to use smart pointers in this process.
static void process_Msg_CutListRequest(BCP_ts_prob &p, BCP_buffer &buf)
#define TS_MAX_HEAP_SIZE
CouExpr & log(CouExpr &e)