00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00028
00029
00030
00031
00032
00033
00034
00035 #include <coconut_config.h>
00036 #include <search_graph.h>
00037 #include <set>
00038
00039 #define DEBUG_SGRAPH_EXTRACT 0
00040
00041 #if DEBUG_SGRAPH_EXTRACT
00042 #include <print_set.h>
00043 #include <print_seq.h>
00044 #endif
00045
00046 using namespace vgtl;
00047
00048 namespace coco {
00049
00050 #include "sum_deltas.h"
00051
00052 class __sg_anc_visitor: public prepost_visitor<search_node*, bool>
00053 {
00054 private:
00055 std::set<search_node_id>& ancestors;
00056
00057 public:
00059 __sg_anc_visitor(std::set<search_node_id>& anc) : ancestors(anc) {}
00060
00062 ~__sg_anc_visitor() {}
00063
00065
00066 inline void vinit()
00067 {
00068
00069 }
00070
00071 inline void vcollect(return_value const &)
00072 {
00073
00074 throw api_exception(apiee_search_graph,
00075 "in __sg_anc_visitor::vcollect: do not know how to handle virtual nodes");
00076 }
00077
00078 inline return_value vvalue()
00079 {
00080
00081 return true;
00082 }
00083
00084 inline bool preorder(search_node* const& r)
00085 {
00086
00087 ancestors.insert(r->get_id());
00088 return true;
00089 }
00090
00091 inline bool postorder(search_node* const& r)
00092 {
00093
00094 return true;
00095 }
00096
00097 inline void collect(search_node* const&, return_value const &ancestor)
00098 {
00099
00100 }
00101
00102 inline return_value value()
00103 {
00104
00105 return true;
00106 }
00108 };
00109
00110 bool search_graph::possible_focus(const search_inspector& where,
00111 const std::list<search_focus>::const_iterator* not_this) const
00112 {
00113 bool ret(true);
00114
00115 if(!focus.empty())
00116 {
00117 std::set<search_node_id> ancestors_where;
00118 std::set<search_node_id> ancestors_existing;
00119 std::list<walker>::const_iterator i;
00120 std::set<search_node_id>::iterator anc_it;
00121
00122 recursive_walk_up(where, __sg_anc_visitor(ancestors_where));
00123 for(i = focus.begin(); i != focus.end(); ++i)
00124 {
00125 if(not_this && *not_this == i)
00126 continue;
00127 recursive_walk_up((search_inspector)*i,
00128 __sg_anc_visitor(ancestors_existing));
00129 anc_it = ancestors_where.find((**i)->get_id());
00130 if(anc_it != ancestors_where.end())
00131 {
00132 ret = false;
00133 break;
00134 }
00135 }
00136 if(ret)
00137 {
00138 anc_it = ancestors_existing.find((*where)->get_id());
00139 if(anc_it != ancestors_existing.end())
00140 ret = false;
00141 }
00142 }
00143 return ret;
00144 }
00145
00146 bool search_graph::possible_focus(const search_inspector& where,
00147 const search_focus& not_this) const
00148 {
00149 std::list<walker>::const_iterator i =
00150 find(focus.begin(), focus.end(), not_this);
00151 return possible_focus(where, i == focus.end() ? NULL : &i);
00152 }
00153
00154 search_focus& search_graph::new_focus(const search_inspector& where)
00155 {
00156 search_inspector where_copy = where;
00157 walker focus_to_add((node_type *) where_copy.node());
00158
00159 if(!possible_focus(where))
00160 throw api_exception(apiee_search_graph,
00161 "in search_graph :: new_focus : the inspected node cannot be focussed!");
00162 focus.push_front(focus_to_add);
00163 return focus.front();
00164 }
00165
00166 const search_focus& search_graph::get_focus(const search_inspector& where, bool& isNew)
00167 {
00168 search_inspector where_copy = where;
00169 walker focus_to_add((node_type *) where_copy.node());
00170
00171 std::list<walker>::const_iterator i =
00172 find(focus.begin(), focus.end(), focus_to_add);
00173 if (i != focus.end())
00174 {
00175 isNew = false;
00176 return *i;
00177 }
00178
00179 if(!possible_focus(where))
00180 throw api_exception(apiee_search_graph,
00181 "in search_graph :: new_focus : the inspected node cannot be focussed!");
00182 isNew = true;
00183 focus.push_front(focus_to_add);
00184 return focus.front();
00185 }
00186
00187 void search_graph::destroy_focus(const search_focus& where)
00188 {
00189 std::list<walker>::iterator i = find(focus.begin(), focus.end(), where);
00190 if(i == focus.end())
00191 throw api_exception(apiee_search_graph,
00192 "in search_graph :: destroy_focus (...) : the focus does not exist");
00193 focus.erase(i);
00194 }
00195
00196 search_focus& search_graph::set_focus(search_focus& focus_to_replace,
00197 const search_inspector& where)
00198 {
00199 if((search_inspector)focus_to_replace == where)
00200 return focus_to_replace;
00201
00202 std::list<walker>::iterator i =
00203 find(focus.begin(), focus.end(), focus_to_replace);
00204 if(i == focus.end())
00205 throw api_exception(apiee_search_graph,
00206 "in search_graph :: set_focus (...) : the focus does not exist");
00207 std::list<walker>::const_iterator i_cp(i);
00208 if(!possible_focus(where, &i_cp))
00209 throw api_exception(apiee_search_graph,
00210 "in search_graph :: set_focus : the inspected node cannot be focussed!");
00211
00212 search_inspector where_copy = where;
00213 *i = walker((node_type *) where_copy.node());
00214 return *i;
00215 }
00216
00217 search_inspector& search_graph::new_inspector(const search_inspector &
00218 inspector_to_add)
00219 {
00220 std::list<const_walker>::iterator i =
00221 find(inspector.begin(), inspector.end(), inspector_to_add);
00222 if(i != inspector.end())
00223 return *i;
00224 inspector.push_front(inspector_to_add);
00225 return inspector.front();
00226 }
00227
00228 void search_graph::destroy_inspector(const search_inspector &
00229 inspector_to_destroy)
00230 {
00231 std::list<const_walker>::iterator i =
00232 find(inspector.begin(), inspector.end(), inspector_to_destroy);
00233 if(i == inspector.end())
00234 throw api_exception(apiee_search_graph,
00235 "in search_graph :: destroy_inspector (...) : the inspector does not exist");
00236 inspector.erase(i);
00237 }
00238
00239 void search_graph::_extract_indirect(work_node& wnode,
00240 const search_inspector & from, const search_inspector & to) const
00241 {
00242
00243 std::list<delta_id> dels_t;
00244 copy(wnode.deltanew_it, wnode.deltas.end(), back_inserter(dels_t));
00245 wnode -= dels_t;
00246 if(wnode.dtable)
00247 for(std::list<delta_id>::iterator i = dels_t.begin(); i != dels_t.end(); ++i)
00248 wnode.dtable->remove(*i);
00249
00250 if(*from == *to)
00251 {
00252 return;
00253 }
00254 #if DEBUG_SGRAPH_EXTRACT
00255 std::cerr << "*****************************************" << std::endl <<
00256 "**** search_graph::_extract_indirect ****" << std::endl <<
00257 "*****************************************" << std::endl <<
00258 "wnode: " << wnode.get_id() << ", from: " << (*from)->get_id() <<
00259 ", to: " << (*to)->get_id() << std::endl <<
00260 "deltas: ";
00261 copy(wnode.deltas.begin(), wnode.deltanew_it, ostream_iterator<delta_id>(cerr,", "));
00262 std::cerr << " ;; ";
00263 copy(wnode.deltanew_it, wnode.deltas.end(), ostream_iterator<delta_id>(cerr,", "));
00264 std::cerr << std::endl;
00265 #endif
00266 dels_t.clear();
00267 std::set<search_node_id> to_parents;
00268 search_node *result = recursive_walk_up_if(to,
00269 sum_deltas(dels_t, to_parents, wnode.parents_in_graph));
00270 if(result == NULL)
00271 throw api_exception(apiee_search_graph,
00272 "in search_graph :: _extract_indirect (...) : no parent node found");
00273 #if DEBUG_SGRAPH_EXTRACT
00274 std::cerr << "dels_t: " << dels_t << std::endl;
00275 std::cerr << "to_parents: " << to_parents << std::endl;
00276 #endif
00277
00278 if(result->is_delta())
00279 {
00280 std::list<delta_id> dels_f;
00281 search_node_id psnid(result->get_id());
00282 std::set<search_node_id> from_parents;
00283 result = recursive_walk_up_if(from,
00284 sum_deltas(dels_f, from_parents, psnid));
00285 #if DEBUG_SGRAPH_EXTRACT
00286 std::cerr << "indirect:" << std::endl;
00287 std::cerr << "dels_f: " << dels_f << std::endl;
00288 std::cerr << "from_parents: " << from_parents << std::endl;
00289 #endif
00290 if(result == NULL)
00291 throw api_exception(apiee_search_graph,
00292 "in search_graph :: _extract_indirect (...) : this can't happen!");
00293 std::set<search_node_id> from_x_parents;
00294 std::list<delta_id> dels_x_f;
00295 full_node* fn(NULL);
00296 if(dels_f.size() > 0.1*wnode.get_model()->number_of_nodes())
00297 {
00298 fn = (full_node*)recursive_walk_up_if(get(psnid),
00299 sum_deltas(dels_x_f, from_x_parents));
00300 #if DEBUG_SGRAPH_EXTRACT
00301 std::cerr << "dels_x_f: " << dels_x_f << std::endl;
00302 std::cerr << "from_x_parents: " << from_x_parents << std::endl;
00303 #endif
00304 }
00305 if(fn && dels_f.size() > dels_x_f.size() + 0.1*fn->get_model()->number_of_nodes())
00306 {
00307 wnode = *fn;
00308 #if DEBUG_SGRAPH_EXTRACT
00309 std::cerr << "full get: " << dels_x_f << " ; " << dels_t << std::endl;
00310 #endif
00311 wnode += dels_x_f;
00312 wnode += dels_t;
00313 }
00314 else
00315 {
00316 #if DEBUG_SGRAPH_EXTRACT
00317 std::cerr << "move: -: " << dels_f << " ;+: " << dels_t << std::endl;
00318 #endif
00319 wnode -= dels_f;
00320 wnode += dels_t;
00321 }
00322 std::set<search_node_id>::iterator from_parents_c(from_parents.begin()),
00323 from_parents_e(from_parents.end());
00324 for(; from_parents_c != from_parents_e; ++from_parents_c)
00325 wnode.parents_in_graph.erase(*from_parents_c);
00326 wnode.parents_in_graph.insert(to_parents.begin(), to_parents.end());
00327 #if DEBUG_SGRAPH_EXTRACT
00328 std::cerr << "wnode.parents_in_graph: " << wnode.parents_in_graph << std::endl;
00329 #endif
00330 wnode._snr = (*to)->parent_relation();
00331 wnode._id = (*to)->get_id();
00332 wnode._rid = (*to)->get_rowid();
00333 wnode.deltanew_it = wnode.deltas.end();
00334 }
00335 else
00336 {
00337 #if DEBUG_SGRAPH_EXTRACT
00338 std::cerr << "direct:" << std::endl;
00339 #endif
00340 _extract_full(wnode, to, dels_t, to_parents, (full_node*)result);
00341 }
00342 }
00343
00344 void search_graph::_extract_full(work_node& wnode, const search_inspector & where,
00345 std::list<delta_id>& dels, std::set<search_node_id>& nds, full_node* fn) const
00346 {
00347 wnode = *fn;
00348 wnode += dels;
00349
00350 wnode.__vdbf = &(const_cast<search_graph*>(this))->get_viewdbase();
00351 wnode._snr = (*where)->parent_relation();
00352 wnode._id = (*where)->get_id();
00353 wnode._rid = (*where)->get_rowid();
00354 wnode.deltanew_it = wnode.deltas.end();
00355 wnode.parents_in_graph = nds;
00356 }
00357
00358 void search_graph::_extract(work_node& wnode, const search_inspector & where) const
00359 {
00360 search_inspector wnode_p(get(wnode.get_id()));
00361 if(wnode.__vdbf == &this->get_viewdbase() && wnode_p != ground())
00362
00363 _extract_indirect(wnode, wnode_p, where);
00364 else
00365 {
00366 std::list<delta_id> dels;
00367 wnode.parents_in_graph.clear();
00368 full_node *result = (full_node*)recursive_walk_up_if(where, sum_deltas(dels,
00369 wnode.parents_in_graph));
00370 if(result == NULL)
00371 throw api_exception(apiee_search_graph,
00372 "in search_graph :: extract (...) : no full node found");
00373
00374 _extract_full(wnode, where, dels, wnode.parents_in_graph, result);
00375 }
00376 }
00377
00378 void search_graph::extract(work_node& wnode, const search_inspector& where) const
00379 {
00380 std::list<const_walker>::const_iterator i =
00381 find(inspector.begin(), inspector.end(), where);
00382 if(i == inspector.end())
00383 throw api_exception(apiee_search_graph,
00384 "in search_graph :: extract (...) : the inspector does not exist");
00385
00386 _extract(wnode, where);
00387 wnode.set_globalinfo();
00388 }
00389
00390 void search_graph::extract(work_node& wnode, const search_focus& where) const
00391 {
00392 std::list<walker>::const_iterator i =
00393 find(focus.begin(), focus.end(), where);
00394 if(i == focus.end())
00395 throw api_exception(apiee_search_graph,
00396 "in search_graph :: extract (...) : the focus does not exist");
00397
00398 _extract(wnode, (search_inspector)where);
00399 wnode.set_globalinfo();
00400 }
00401
00402 work_node search_graph::extract(const search_inspector & where) const
00403 {
00404 std::list<const_walker>::const_iterator i =
00405 find(inspector.begin(), inspector.end(), where);
00406 if(i == inspector.end())
00407 throw api_exception(apiee_search_graph,
00408 "in search_graph :: extract (...) : the inspector does not exist");
00409
00410 std::list<delta_id> dels;
00411 std::set<search_node_id> nds;
00412 full_node *result = (full_node*)recursive_walk_up_if(where, sum_deltas(dels, nds));
00413 if(result == NULL)
00414 throw api_exception(apiee_search_graph,
00415 "in search_graph :: extract (...) : no full node found");
00416 work_node where_as_work_node(*result, std::list<delta_id>(),
00417 &(const_cast<search_graph*>(this))->get_viewdbase());
00418
00419 where_as_work_node += dels;
00420
00421 where_as_work_node._snr = (*where)->parent_relation();
00422 where_as_work_node._id = (*where)->get_id();
00423 where_as_work_node._rid = (*where)->get_rowid();
00424 where_as_work_node.deltanew_it = where_as_work_node.deltas.end();
00425 where_as_work_node.parents_in_graph = nds;
00426
00427 where_as_work_node.set_globalinfo();
00428 return where_as_work_node;
00429 }
00430
00431 work_node search_graph::extract(const search_focus & where) const
00432 {
00433 std::list<walker>::const_iterator i =
00434 find(focus.begin(), focus.end(), where);
00435 if(i == focus.end())
00436 throw api_exception(apiee_search_graph,
00437 "in search_graph :: extract (...) : the focus does not exist");
00438
00439 std::list<delta_id> dels;
00440 std::set<search_node_id> nds;
00441 full_node *result = (full_node*)recursive_walk_up_if(where, sum_deltas(dels, nds));
00442 if(result == NULL)
00443 throw api_exception(apiee_search_graph,
00444 "in search_graph :: extract (...) : no full node found");
00445 work_node where_as_work_node(*result, std::list<delta_id>(),
00446 &(const_cast<search_graph*>(this))->get_viewdbase());
00447
00448 where_as_work_node += dels;
00449
00450 where_as_work_node._snr = (*where)->parent_relation();
00451 where_as_work_node._id = (*where)->get_id();
00452 where_as_work_node._rid = (*where)->get_rowid();
00453 where_as_work_node.deltanew_it = where_as_work_node.deltas.end();
00454 where_as_work_node.parents_in_graph = nds;
00455
00456 where_as_work_node.set_globalinfo();
00457 return where_as_work_node;
00458 }
00459
00460 search_focus& search_graph::update_and_delete(work_node& wnode, search_focus& foc,
00461 const search_inspector& where, bool just_this,
00462 bool relaxation_kills)
00463 {
00464 search_inspector sinsp(foc);
00465 _extract_indirect(wnode, sinsp, where);
00466 if(!possible_focus(where, NULL))
00467 throw api_exception(apiee_search_graph,
00468 "in search_graph :: update_and_delete : the new node cannot be focussed after deleting the old!");
00469 if(just_this)
00470 remove(foc);
00471 else
00472 remove_upwards(foc, relaxation_kills);
00473 foc = new_focus(where);
00474 return foc;
00475 }
00476
00477 search_focus& search_graph::update(work_node& wnode, search_focus& foc,
00478 const search_inspector& where)
00479 {
00480 _extract_indirect(wnode, (search_inspector)foc, where);
00481 foc = set_focus(foc, where);
00482 return foc;
00483 }
00484
00485 search_inspector& search_graph::insert(const search_focus &where,
00486 const search_node &what)
00487 {
00488 search_focus protected_where(where);
00489 walker new_where =
00490 split(protected_where, protected_where.child_begin(), sky(),
00491 sky().parent_begin(), (search_node*) &what);
00492
00493 const_walker new_where_as_const_walker((node_type*) new_where.node());
00494
00495 __id_ref[what.get_id()] = new_where_as_const_walker;
00496 inspector.push_front(new_where_as_const_walker);
00497 return inspector.front();
00498 }
00499
00500
00501 search_inspector& search_graph::replace(search_focus& where,
00502 const search_node &what)
00503 {
00504 std::list<walker>::iterator i = find(focus.begin(), focus.end(), where);
00505 if(i == focus.end())
00506 throw api_exception(apiee_search_graph,
00507 "in search_graph :: replace (...) : the focus does not exist");
00508 if(what.is_delta())
00509 *where = (search_node*) new delta_node(*(delta_node*)&what);
00510 else
00511 *where = (search_node*) new full_node(*(full_node*)&what);
00512 inspector.push_front(const_walker((node_type*) where.node()));
00513 return inspector.front();
00514 }
00515
00516 void search_graph::_internal_remove(search_focus& where)
00517 {
00518 std::vector<search_node_id> _id_to_erase;
00519 std::list<vdbl::rowid> rli;
00520 vdbl::rowid rid;
00521 if((*where)->is_delta())
00522 {
00523 delta_node& where_as_delta = *(delta_node*) *where;
00524 if(!where.is_leaf())
00525 {
00526 for(walker::children_iterator c = where.child_begin();
00527 c != where.child_end(); ++c)
00528 if((*(where >> c))->is_delta())
00529 {
00530
00531 delta_node* c_as_delta = (delta_node*) *(where >> c);
00532
00533 std::vector<delta_id> delta_where_plus_delta_c;
00534 for(unsigned int i = 0; i < where_as_delta.n_deltas(); ++i)
00535 {
00536 db_deltas_to_remove.push_front(where_as_delta.get_delta_id(i));
00537 delta_where_plus_delta_c.push_back(db_deltas_to_remove.front());
00538 }
00539 for(unsigned int i = 0; i < c_as_delta->n_deltas(); ++i)
00540 {
00541 db_deltas_to_remove.push_front(c_as_delta->get_delta_id(i));
00542 delta_where_plus_delta_c.push_back(db_deltas_to_remove.front());
00543 }
00544 gptr<vdbl::database>* _xdb = c_as_delta->database();
00545 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00546 i != search_nodes_to_deallocate.end(); ++i)
00547 if(c_as_delta == *i)
00548 {
00549 search_nodes_to_deallocate.erase(i);
00550 break;
00551 }
00552 _id_to_erase.push_back(c_as_delta->get_id());
00553 rid = c_as_delta->get_rowid();
00554 if(rid != VDBL_MAXROWID)
00555 rli.push_back(rid);
00556 delete c_as_delta;
00557
00558 c_as_delta = new delta_node(get_node_id(), __dbuser,
00559 delta_where_plus_delta_c, ptr_ground,
00560 *_xdb);
00561 search_nodes_to_deallocate.push_front(c_as_delta);
00562 }
00563 }
00564 }
00565 else
00566 {
00567 full_node& where_as_full = *(full_node*) *where;
00568 if(!where.is_leaf())
00569 {
00570 for(walker::children_iterator c = where.child_begin();
00571 c != where.child_end(); ++c)
00572 if((*(where >> c))->is_delta())
00573 {
00574 delta_node * c_as_delta = (delta_node*) *(where >> c);
00575 work_node full_where_plus_delta_c(full_node_to_work_node
00576 (where_as_full, ptr_ground));
00577 for(unsigned int i = 0; i < c_as_delta->n_deltas(); ++i)
00578 full_where_plus_delta_c += c_as_delta->get_delta_id(i);
00579 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00580 i != search_nodes_to_deallocate.end(); ++i)
00581 if(c_as_delta == *i)
00582 {
00583 search_nodes_to_deallocate.erase(i);
00584 break;
00585 }
00586 _id_to_erase.push_back(c_as_delta->get_id());
00587 rid = c_as_delta->get_rowid();
00588 if(rid != VDBL_MAXROWID)
00589 rli.push_back(rid);
00590 delete c_as_delta;
00591
00592 *(where >> c) = new work_node(full_where_plus_delta_c);
00593 search_nodes_to_deallocate.push_front(*(where >> c));
00594 }
00595 }
00596 }
00597
00598
00599 if((*where)->parent_relation() == snr_split)
00600 {
00601 if(where.n_parents() > 1)
00602 throw api_exception(apiee_search_graph,
00603 "in search_graph :: remove (...) : a split has more than one parent");
00604 else
00605 {
00606 walker::parents_iterator p = where.parent_begin();
00607 walker parent_of_where = where << p;
00608 unsigned int num_of_splits(0);
00609 walker first_split;
00610 for(walker::children_iterator c = parent_of_where.child_begin();
00611 c != parent_of_where.child_end(); ++c)
00612 {
00613 walker child_of_parent_of_where = parent_of_where >> c;
00614 if(child_of_parent_of_where != where &&
00615 (*child_of_parent_of_where)->parent_relation() == snr_split)
00616 {
00617 if(num_of_splits == 0)
00618 first_split = child_of_parent_of_where;
00619 num_of_splits++;
00620 }
00621 }
00622 if(num_of_splits == 1)
00623 (*first_split)->_snr = snr_reduction;
00624 }
00625 }
00626
00627 _id_to_erase.push_back((*where)->get_id());
00628 rid = (*where)->get_rowid();
00629 if(rid != VDBL_MAXROWID)
00630 rli.push_back(rid);
00631 delete *where;
00632 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00633 i != search_nodes_to_deallocate.end(); ++i)
00634 if(*where == *i)
00635 {
00636 search_nodes_to_deallocate.erase(i);
00637 break;
00638 }
00639
00640 erase(where);
00641
00642 vdbl::standard_table* sntab =
00643 (vdbl::standard_table*)(**__dbase).get_table("search info", __dbuser);
00644 for(std::vector<search_node_id>::iterator si = _id_to_erase.begin();
00645 si != _id_to_erase.end(); ++si)
00646 __id_ref.erase(*si);
00647 if(sntab != NULL)
00648 {
00649 for(std::list<vdbl::rowid>::iterator __i = rli.begin(); __i != rli.end(); ++__i)
00650 sntab->remove(*__i);
00651 }
00652 return;
00653 }
00654
00655 void search_graph::remove(search_focus& where)
00656 {
00657 std::list<walker>::iterator flw = find(focus.begin(), focus.end(), where);
00658 if(flw == focus.end())
00659 throw api_exception(apiee_search_graph,
00660 "in search_graph :: remove (...) : the focus does not exist");
00661 if(where.n_parents() >= 2 && (*where)->parent_relation() != snr_glue)
00662 throw api_exception(apiee_search_graph,
00663 "in search_graph :: remove (...) : search_node has several ancestors");
00664 _internal_remove(where);
00665 focus.erase(flw);
00666 where = ground();
00667 }
00668
00669 search_focus& search_graph::promote(search_focus& where)
00670 {
00671 std::list<walker>::iterator i = find(focus.begin(), focus.end(), where);
00672 if(i == focus.end())
00673 throw api_exception(apiee_search_graph,
00674 "in search_graph :: promote (...) : the focus does not exist");
00675 if(where.n_parents() >= 2)
00676 throw api_exception(apiee_search_graph,
00677 "in search_graph :: promote (...) : search_node has several ancestors");
00678 walker p = where << where.parent_begin();
00679 std::vector<search_node_id> _id_to_erase;
00680
00681 if((*where)->is_delta())
00682 {
00683 delta_node *where_as_delta = (delta_node*) *where;
00684
00685 if((*p)->is_delta())
00686 {
00687 delta_node* p_as_delta = (delta_node*) *p;
00688
00689 std::vector<delta_id> delta_where_plus_delta_p;
00690 for(unsigned int i = 0; i < where_as_delta->n_deltas(); ++i)
00691 {
00692 db_deltas_to_remove.push_front(where_as_delta->get_delta_id(i));
00693 delta_where_plus_delta_p.push_back(db_deltas_to_remove.front());
00694 }
00695 for(unsigned int i = 0; i < p_as_delta->n_deltas(); ++i)
00696 {
00697 db_deltas_to_remove.push_front(p_as_delta->get_delta_id(i));
00698 delta_where_plus_delta_p.push_back(db_deltas_to_remove.front());
00699 }
00700 gptr<vdbl::database>* _xdb = p_as_delta->database();
00701 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00702 i != search_nodes_to_deallocate.end(); ++i)
00703 if(*p == *i)
00704 {
00705 search_nodes_to_deallocate.erase(i);
00706 break;
00707 }
00708 _id_to_erase.push_back((*p)->get_id());
00709 delete *p;
00710
00711 search_node_id sid = get_node_id();
00712 *p = new delta_node(sid, __dbuser, delta_where_plus_delta_p,
00713 ptr_ground, *_xdb);
00714 __id_ref[sid] = p;
00715 }
00716 else
00717 {
00718 full_node *p_as_full = (full_node*) *p;
00719 work_node full_p_plus_delta_where(full_node_to_work_node
00720 (*p_as_full, ptr_ground));
00721
00722 for(unsigned int i = 0; i < where_as_delta->n_deltas(); ++i)
00723 full_p_plus_delta_where += where_as_delta->get_delta_id(i);
00724 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00725 i != search_nodes_to_deallocate.end(); ++i)
00726 if(*p == *i)
00727 {
00728 search_nodes_to_deallocate.erase(i);
00729 break;
00730 }
00731 _id_to_erase.push_back((*p)->get_id());
00732 delete *p;
00733
00734 *p = new work_node(full_p_plus_delta_where);
00735 __id_ref[full_p_plus_delta_where.get_id()] = p;
00736 }
00737 search_nodes_to_deallocate.push_front(*p);
00738 }
00739 else
00740 {
00741 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00742 i != search_nodes_to_deallocate.end(); ++i)
00743 if(*p == *i)
00744 {
00745 search_nodes_to_deallocate.erase(i);
00746 break;
00747 }
00748 _id_to_erase.push_back((*p)->get_id());
00749 delete *p;
00750
00751 *p = *where;
00752 __id_ref[(*where)->get_id()] = p;
00753 }
00754 *i = p;
00755 for(std::list<search_node*>::iterator i=search_nodes_to_deallocate.begin();
00756 i != search_nodes_to_deallocate.end(); ++i)
00757 if(*where == *i)
00758 {
00759 search_nodes_to_deallocate.erase(i);
00760 break;
00761 }
00762 _id_to_erase.push_back((*where)->get_id());
00763 delete *where;
00764
00765 erase(where);
00766
00767 vdbl::standard_table* sntab =
00768 (vdbl::standard_table*)(**__dbase).get_table("search info", __dbuser);
00769 for(std::vector<search_node_id>::iterator si = _id_to_erase.begin();
00770 si != _id_to_erase.end(); ++si)
00771 __id_ref.erase(*si);
00772 if(sntab != NULL)
00773 {
00774 std::sort(_id_to_erase.begin(), _id_to_erase.end());
00775 std::list<vdbl::rowid> rli;
00776 vdbl::standard_table::row_const_iterator __r;
00777 std::vector<search_node_id>::iterator ub;
00778 search_node_id sni;
00779 vdbl::colid ci = sntab->get_col_id("_id");
00780 bool error;
00781
00782 for(__r = sntab->row_begin();
00783 __r != sntab->row_end() && !_id_to_erase.empty(); ++__r)
00784 {
00785 const vdbl::row& rw(sntab->get_row(*__r, error));
00786 if(error) continue;
00787 const vdbl::col& cl(rw.get_col(ci, error));
00788 if(error) continue;
00789 cl.get(sni);
00790 ub = upper_bound(_id_to_erase.begin(), _id_to_erase.end(), sni);
00791 if(*ub == sni)
00792 {
00793 rli.push_back(*__r);
00794 _id_to_erase.erase(ub);
00795 }
00796 }
00797 for(std::list<vdbl::rowid>::iterator __i = rli.begin(); __i != rli.end(); ++__i)
00798 sntab->remove(*__i);
00799 }
00800
00801 return *i;
00802 }
00803
00804 void search_graph::remove_upwards(search_focus& where, bool relaxation_kills)
00805 {
00806 std::list<walker>::iterator flwr = find(focus.begin(), focus.end(), where);
00807 if(flwr == focus.end())
00808 throw api_exception(apiee_search_graph,
00809 "in search_graph :: remove_upwards (...) : the focus does not exist");
00810 if(where.n_parents() >= 2 && (*where)->parent_relation() != snr_glue)
00811 throw api_exception(apiee_search_graph,
00812 "in search_graph :: remove_upwards (...) : search_node has several ancestors");
00813
00814 std::list<walker> to_be_erased;
00815 to_be_erased.push_front(*flwr);
00816
00817 for(std::list<walker>::iterator flw = to_be_erased.begin();
00818 flw != to_be_erased.end(); ++flw)
00819 {
00820 switch((**flw)->parent_relation())
00821 {
00822 case snr_root:
00823
00824 break;
00825 case snr_split:
00826
00827 break;
00828 case snr_relaxation:
00829 if(!relaxation_kills)
00830 break;
00831
00832 case snr_reduction:
00833 case snr_glue:
00834
00835 for(walker::parents_iterator p = (*flw).parent_begin();
00836 p != (*flw).parent_end(); ++p)
00837 to_be_erased.push_back((*flw) << p);
00838 break;
00839 case snr_worknode:
00840 case snr_virtual:
00841 throw api_exception(apiee_search_graph,
00842 "in search_graph :: remove_upwards (...) : search_node is unremovable!");
00843 break;
00844 default:
00845 throw api_exception(apiee_search_graph,
00846 "in search_graph :: remove_upwards (...) : search_node has unknown parent relation!");
00847 break;
00848 }
00849 _internal_remove(*flw);
00850 }
00851 focus.erase(flwr);
00852 where = ground();
00853 }
00854
00855 bool search_graph::add_deltas(const search_focus& where,
00856 const std::vector<delta_id>& vid)
00857 {
00858 std::list<walker>::iterator flw = find(focus.begin(), focus.end(), where);
00859 if(flw == focus.end())
00860 throw api_exception(apiee_search_graph,
00861 "in search_graph :: add_deltas (...) : the focus does not exist");
00862 if((*where)->is_delta())
00863 {
00864 ((delta_node*)*where)->add_deltas(vid.begin(), vid.end());
00865 return true;
00866 }
00867 else
00868 return false;
00869 }
00870
00871 bool search_graph::register_hook(const work_node_comp_hook& wnch)
00872 {
00873 work_node_comp_hook* wnc;
00874 std::list<work_node_comp_hook*>::iterator wci;
00875
00876 for(wci = wn_hooks.begin(); wci != wn_hooks.end(); ++wci)
00877 if((*wci)->name() == wnch.name())
00878 return false;
00879 wnc = new work_node_comp_hook(wnch);
00880 if(__dbase)
00881 {
00882 vdbl::standard_table* sntab =
00883 (vdbl::standard_table*) (**__dbase).get_table("search info", __dbuser);
00884 if(sntab == NULL)
00885 {
00886 if(!(**__dbase).create_table("search info", __dbuser))
00887 throw api_exception(apiee_search_graph,
00888 "Database error: could not create table 'search info'");
00889 else
00890 sntab =
00891 (vdbl::standard_table*)(**__dbase).get_table("search info", __dbuser);
00892 if(sntab)
00893 sntab->add_col("_id", vdbl::typed_col<search_node_id>(search_node_id()),
00894 vdbl::colflags());
00895 }
00896 if(sntab == NULL)
00897 throw api_exception(apiee_search_graph,
00898 "Database error: could not find table 'search info'");
00899 wnc->init_columns(*sntab);
00900 }
00901 wn_hooks.push_back(wnc);
00902 return true;
00903 }
00904
00905 bool search_graph::unregister_hook(const std::string& name)
00906 {
00907 std::list<work_node_comp_hook*>::iterator wci;
00908 for(wci = wn_hooks.begin(); wci != wn_hooks.end(); ++wci)
00909 if((*wci)->name() == name)
00910 {
00911 if(__dbase)
00912 {
00913 vdbl::standard_table* sntab =
00914 (vdbl::standard_table*)(**__dbase).get_table("search info", __dbuser);
00915 if(sntab != NULL)
00916 (*wci)->drop_columns(*sntab);
00917 }
00918 delete *wci;
00919 wn_hooks.erase(wci);
00920 return true;
00921 }
00922 return false;
00923 }
00924
00925 void search_graph::apply_hooks(const work_node& w, const search_node_id& id,
00926 vdbl::rowid& rid, std::list<delta>& add_ds,
00927 std::list<certificate>& add_cs)
00928 {
00929 dbt_row dbr("_id", id);
00930
00931 if(!__dbase) return;
00932 for(std::list<work_node_comp_hook*>::const_iterator __b = wn_hooks.begin();
00933 __b != wn_hooks.end(); ++__b)
00934 (**__b)(w, dbr, &add_ds, &add_cs);
00935
00936 vdbl::standard_table* sntab =
00937 (vdbl::standard_table*)(**__dbase).get_table("search info", __dbuser);
00938 if(sntab == NULL) return;
00939 if(rid != VDBL_MAXROWID)
00940 sntab->update_row(dbr.row(), rid);
00941 else
00942 sntab->insert_row(dbr.row(), rid);
00943 }
00944
00945 }