ARB
AP_main.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : AP_main.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include "ap_main.hxx"
12 #include <aw_msg.hxx>
13 #include <map>
14 
15 using namespace std;
16 
17 // ----------------
18 // AP_main
19 
20 GB_ERROR AP_main::open(const char *db_server) {
22  gb_main = GB_open(db_server, "rwt");
23  if (!gb_main) error = GB_await_error();
24  return error;
25 }
26 
28  user_frames.push(new UserFrame(frameLevel));
29  remember();
30 }
31 
33  if (user_frames.empty()) {
34  aw_message("No user-pop possible");
35  }
36  else {
37  UserFrame *wanted = user_frames.pop();
38  if (frameLevel<=wanted->get_level()) {
39  aw_message("Wanted user_frame not available");
40  }
41  else {
42  while (frameLevel>wanted->get_level()) {
43  revert();
44  }
45  }
46  delete wanted;
47  }
48 }
49 
55  frameLevel ++;
56  if (currFrame) frames.push(currFrame);
57  currFrame = new NodeStack(frameData);
58  ap_assert(!frameData);
59  frameData = new StackFrameData;
60 
61 #if defined(CHECK_ROOT_POPS)
62  currFrame->root_at_create = DOWNCAST(AP_tree_nlen*, get_tree_root()->get_root_node());
63 #endif
64 }
65 
70  if (!currFrame) GBK_terminate("AP_main::pop on empty stack");
71 
72  bool rootPopped = false;
73  {
74  AP_tree_nlen *node;
75  while ((node = currFrame->pop())) {
76  if (frameLevel != node->last_remembered_frame()) {
77  cerr << "Main frame level=" << frameLevel << " node frame level=" << node->last_remembered_frame() << endl;
78  GBK_terminate("AP_main::pop: main/node frame-level inconsistency");
79  }
80  node->revertToPreviousState(frameLevel, rootPopped);
81  }
82  }
83 
84  ap_assert(rootPopped == frameData->root_pushed);
85 #if defined(CHECK_ROOT_POPS)
86  ap_assert(currFrame->root_at_create == get_tree_root()->get_root_node()); // root has been restored!
87 #endif
88 
89  currFrame->revert_resources(frameData);
90  delete frameData;
91  frameData = currFrame->take_previous_frame_data();
92 
93  delete currFrame;
94  currFrame = frames.pop();
95  frameLevel --;
96 }
97 
100  HasLevelSmallerThan(Level level_) : level(level_) {}
101  bool operator()(const NodeState *state) const { return state->frameNr < level; }
102 };
103 
104 void AP_main::push_nodes_changed_since(Level wanted_frameLevel) {
105  // does not consider currFrame (because we push_nodes to currFrame)
106  Level frame_level = frameLevel-1;
107  ap_assert(frame_level == frames.count_elements());
108 
109  typedef map<AP_tree_nlen*,int> NodeCounter;
110  NodeCounter pops2skip; // specifies how many pops to skip for each node
111 
112  AP_tree_nlen *oldRoot = get_root_node();
113 
114  push_node(oldRoot, ROOT);
115 
116  for (FrameStack::const_iterator f = frames.begin(); f != frames.end(); ++f, --frame_level) {
117  if (frame_level == wanted_frameLevel) break;
118  ap_assert(frame_level>wanted_frameLevel);
119 
120  const NodeStack *frame = *f;
121  HasLevelSmallerThan hasWantedLevel(frame_level);
122 
123  for (NodeStack::const_iterator n = frame->begin(); n != frame->end(); ++n) {
124  AP_tree_nlen *node = *n;
125  if (node == oldRoot) continue;
126 
127  NodeCounter::iterator skipCounter = pops2skip.find(node);
128  int skip = skipCounter == pops2skip.end() ? 0 : skipCounter->second;
129  const StateStack& states = node->get_states();
130  StateStack::const_iterator toPush = states.begin();
131 
132  if (skip>0) advance(toPush, skip);
133 
134  ap_assert(toPush != states.end()); // otherwise node should not be listed in 'frame'
135  ap_assert(hasWantedLevel(*toPush));
136 
137  const NodeState *prevState = *toPush;
138  ap_assert(prevState->frameNr < frame_level);
139 
140  AP_STACK_MODE mode = prevState->mode;
141  if (mode == ROOT || node->is_root_node()) {
142  mode = BOTH;
143  }
144 #if defined(ASSERTION_USED)
145  Level lold = states.count_elements();
146 #endif
147  int pushed = push_node(node, mode);
148 
149  ap_assert(states.count_elements() == lold+pushed);
150 
151  pops2skip[node] = skip+1+pushed;
152  }
153  }
154 }
155 
156 void AP_main::rollback_to(Level wanted_frameLevel) {
157  // does not consider currFrame
158  // (assumes tree state is identical to state before last push())
159  Level frame_level = frameLevel-1;
160  ap_assert(frame_level == frames.count_elements());
161 
162  typedef map<AP_tree_nlen*,int> NodeCounter;
163  NodeCounter pops2skip; // specifies how many pops to skip for each node
164 
165  // skip pushes done by push_nodes_changed_since()
166  for (NodeStack::const_iterator n = currFrame->begin(); n != currFrame->end(); ++n) {
167  AP_tree_nlen *node = *n;
168  pops2skip[node] = 1;
169  }
170 
171  for (FrameStack::const_iterator f = frames.begin(); f != frames.end(); ++f, --frame_level) {
172  if (frame_level == wanted_frameLevel) break;
173  ap_assert(frame_level>wanted_frameLevel);
174 
175  const NodeStack *frame = *f;
176 #if defined(ASSERTION_USED)
177  HasLevelSmallerThan hasWantedLevel(frame_level);
178 #endif
179 
180  for (NodeStack::const_iterator n = frame->begin(); n != frame->end(); ++n) {
181  AP_tree_nlen *node = *n;
182  NodeCounter::iterator skipCounter = pops2skip.find(node);
183  int skip = skipCounter == pops2skip.end() ? 0 : skipCounter->second;
184  const StateStack& states = node->get_states();
185  StateStack::const_iterator toRestore = states.begin();
186 
187  if (skip>0) advance(toRestore, skip);
188 
189  ap_assert(toRestore != states.end()); // otherwise node should not be listed in 'frame'
190  ap_assert(hasWantedLevel(*toRestore));
191 
192  const NodeState *prevState = *toRestore;
193  ap_assert(prevState->frameNr < frame_level);
194  node->restore_nondestructive(*prevState);
195 
196  pops2skip[node] = skip+1;
197  }
198 
199 #if defined(CHECK_ROOT_POPS)
200  ap_assert(frame->root_at_create == get_tree_root()->get_root_node()); // root has been restored!
201 #endif
202  }
203 }
204 
210  if (!currFrame) GBK_terminate("AP_main::accept on empty stack");
211  ap_assert(frameData);
212 
213  AP_tree_nlen *node;
214 
215  NodeStack *prev_frame = frames.pop();
216 
217  // detect nodes (and edges) created AND destroyed inside currently accepted stack frame
218  ResourceStack *common = NULp;
219  if (prev_frame) {
220  common = new ResourceStack;
221  frameData->extract_common_to(*common);
222  }
223 
224  while ((node = currFrame->pop())) {
225  if (node->acceptCurrentState(frameLevel) != true) {
226  // stored node state was not discarded (because it was not stored for the previous stack frame).
227  // if revert() gets called for previous stack frane, it is necessary to revert
228  // the current change as well -> move into previous frame
229  if (prev_frame) {
230  if (common->has_node(node)) {
231  // do NOT push nodes which get destroyed by accept_resources() below!
232  ASSERT_RESULT(bool, true, node->acceptCurrentState(1)); // force state drop
233  }
234  else {
235  prev_frame->push(node); // @@@ frames are pushed in reverted order (seems to be wrong)
236  }
237  }
238  }
239  }
240 
241  currFrame->accept_resources(frameData, common);
242  delete frameData;
243  frameData = currFrame->take_previous_frame_data();
244 
245  delete currFrame;
246  currFrame = prev_frame;
247  frameLevel --;
248 
249  delete common;
250 }
251 
252 bool AP_main::push_node(AP_tree_nlen *node, AP_STACK_MODE mode) {
258  bool pushed = false;
259  if (!currFrame) {
260  if (mode & SEQUENCE) node->unhash_sequence();
261  }
262  else {
263  if (frameLevel < node->last_remembered_frame()) {
264  cerr << "Main frame level=" << frameLevel << " node frame level=" << node->last_remembered_frame() << endl;
265  GBK_terminate("AP_main::push_node: main/node frame-level inconsistency");
266  }
267 
268  if (mode == ROOT) {
269  // test that it is really root what is pushed
270  ap_assert(!node->father);
271  ap_assert(node->is_root_node());
272 
273  if (frameData->root_pushed) {
274  // do not push root twice in same frame
275  mode = BOTH;
276  }
277  else {
278  frameData->root_pushed = true;
279 #if defined(CHECK_ROOT_POPS)
280  ap_assert(node == currFrame->root_at_create); // make sure the pushed root is the correct one
281 #endif
282  }
283  }
284 
285  if (node->rememberState(mode, frameLevel)) {
286  currFrame->push(node);
287  pushed = true;
288  }
289  if (mode == ROOT) {
290  // In AP_main::pop(), root-node has to be restored after everything else has been restored.
291  // Move node to bottom of stack now to ensure that.
292  currFrame->remove(node);
293  currFrame->shift(node);
294  }
295  }
296  return pushed;
297 }
298 
300  ap_assert(!agt && agt_); // do only once
301  agt = agt_;
302 }
303 
304 const char *AP_main::get_aliname() const {
305  return get_tree_root()->get_aliview()->get_aliname();
306 }
307 
308 #if defined(UNIT_TESTS)
309 void AP_main::remember_whole_tree() {
310  remember();
311  AP_tree_nlen *root = get_root_node();
312  push_node(root, ROOT);
313  ap_assert(!root->is_leaf());
314  root->get_leftson()->remember_subtree(this);
315  root->get_rightson()->remember_subtree(this);
316 }
317 #endif
GBDATA * GB_open(const char *path, const char *opent)
Definition: ad_load.cxx:1363
AP_STACK_MODE mode
Definition: AP_buffer.hxx:132
ELEM * pop()
Definition: AP_buffer.hxx:73
void accept()
Definition: AP_main.cxx:205
AP_tree_nlen * root_at_create
Definition: AP_buffer.hxx:281
size_t count_elements() const
Definition: AP_buffer.hxx:90
void push(ELEM *element)
Definition: AP_buffer.hxx:46
#define ASSERT_RESULT(Type, Expected, Expr)
Definition: arb_assert.h:336
void remember_user_state()
Definition: AP_main.cxx:27
STL namespace.
#define DOWNCAST(totype, expr)
Definition: downcast.h:141
BASE::const_iterator const_iterator
Definition: AP_buffer.hxx:44
bool push_node(AP_tree_nlen *node, AP_STACK_MODE)
Definition: AP_main.cxx:252
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
void revert_user_state()
Definition: AP_main.cxx:32
void GBK_terminate(const char *error) __ATTR__NORETURN
Definition: arb_msg.cxx:509
AP_STACK_MODE
Definition: AP_buffer.hxx:117
static void error(const char *msg)
Definition: mkptypes.cxx:96
Level get_level() const
void remember()
Definition: AP_main.cxx:50
#define ap_assert(cond)
GB_ERROR open(const char *db_server)
Definition: AP_main.cxx:20
HasLevelSmallerThan(Level level_)
Definition: AP_main.cxx:100
bool operator()(const NodeState *state) const
Definition: AP_main.cxx:101
bool has_node(AP_tree_nlen *node) const
Definition: AP_buffer.hxx:208
void revert()
Definition: AP_main.cxx:66
void aw_message(const char *msg)
Definition: AW_status.cxx:1142
#define NULp
Definition: cxxforward.h:116
Level frameNr
Definition: AP_buffer.hxx:131
void set_tree_root(AWT_graphic_parsimony *agt_)
Definition: AP_main.cxx:299
GBDATA * gb_main
Definition: adname.cxx:32
const char * get_aliname() const
Definition: AP_main.cxx:304
unsigned long Level
Definition: AP_buffer.hxx:126