# # # patch "annotate.cc" # from [60c185b0871f241d70edad4671fb5365e6cb4285] # to [d5d697b9f27b4aba4f0f90425023e35437083b83] # # patch "database.cc" # from [40233e632e2045e6f9327d9c0dfe51e93491236c] # to [e285e1178b0800d51ae0f17d75b5ee9b43f37b37] # # patch "database.hh" # from [30356b8eff24860141a9498fae5860298965106f] # to [d098635da9410b7c7ecd5a05ead436d51a54a1a3] # ============================================================ --- annotate.cc 60c185b0871f241d70edad4671fb5365e6cb4285 +++ annotate.cc d5d697b9f27b4aba4f0f90425023e35437083b83 @@ -186,6 +186,11 @@ struct by_rev {}; struct by_rev {}; +// instead of using a priority queue and a set to keep track of the already +// seen revisions, we use a multi index container. it stores work units is +// indexed by their revision and their revision's height, with the latter +// being the index used by default. usage of that data structure frees us +// from the burden of keeping two data structures in sync. typedef multi_index_container< annotate_node_work, indexed_by< @@ -681,7 +686,7 @@ static void get_file_content_marks(app_s marking_t markings; app.db.get_markings(rev, fid, markings); - I(markings.file_content.size() != 0); + I(!markings.file_content.empty()); content_marks.clear(); content_marks.insert(markings.file_content.begin(), @@ -700,6 +705,7 @@ do_annotate_node(annotate_node_work cons for (set::const_iterator i = work_unit.interesting_ancestors->begin(); i != work_unit.interesting_ancestors->end(); i++) { + // parent means parent in the annotate graph here revision_id parent_revision = *i; L(FL("do_annotate_node processing edge from parent %s to child %s") @@ -718,6 +724,7 @@ do_annotate_node(annotate_node_work cons { // we already added this parent, get the information from there file_in_parent = lmn->content; + // next two values are actually not used parents_interesting_ancestors = lmn->interesting_ancestors; parent_marked = lmn->marked; } ============================================================ --- database.cc 40233e632e2045e6f9327d9c0dfe51e93491236c +++ database.cc e285e1178b0800d51ae0f17d75b5ee9b43f37b37 @@ -1394,17 +1394,79 @@ struct roster_reconstruction_graph : pub } }; +struct database::extractor +{ + virtual bool look_at_delta(roster_delta const & del) = 0; + virtual void look_at_roster(roster_t const & roster, marking_map const & mm) = 0; + virtual ~extractor() {}; +}; + +struct database::markings_extractor : public database::extractor +{ +private: + node_id const & nid; + marking_t & markings; + +public: + markings_extractor(node_id const & _nid, marking_t & _markings) : + nid(_nid), markings(_markings) {} ; + + bool look_at_delta(roster_delta const & del) + { + return get_markings_from_roster_delta(del, nid, markings); + } + + void look_at_roster(roster_t const & roster, marking_map const & mm) + { + map::const_iterator mmi = + mm.find(nid); + I(mmi != mm.end()); + markings = mmi->second; + } +}; + +struct database::file_content_extractor : database::extractor +{ +private: + node_id const & nid; + file_id & content; + +public: + file_content_extractor(node_id const & _nid, file_id & _content) : + nid(_nid), content(_content) {} ; + + bool look_at_delta(roster_delta const & del) + { + return get_content_from_roster_delta(del, nid, content); + } + + void look_at_roster(roster_t const & roster, marking_map const & mm) + { + if (roster.has_node(nid)) + content = downcast_to_file_t(roster.get_node(nid))->content; + else + content = file_id(); + } +}; + void -database::get_markings(revision_id const & id, - node_id const & nid, - marking_t & markings) +database::extract_from_deltas(revision_id const & id, extractor & x) { reconstruction_path selected_path; { roster_reconstruction_graph graph(*this); { // we look at the nearest delta(s) first, without constructing the - // whole path, as this is rather expensive + // whole path, as that would be a rather expensive operation. + // + // the reason why this strategy is worth the effort is, that in most + // cases we are looking at the parent of a (content-)marked node, thus + // the information we are for is right there in the delta leading to + // this node. + // + // recording the deltas visited here in a set as to avoid inspecting + // them later seems to be of little value, as it imposes a cost here, + // but can seldom be exploited. set deltas; graph.get_next(id.inner()(), deltas); for (set::const_iterator i = deltas.begin(); @@ -1412,7 +1474,7 @@ database::get_markings(revision_id const { roster_delta del; get_roster_delta(id.inner()(), *i, del); - bool found = get_markings_from_roster_delta(del, nid, markings); + bool found = x.look_at_delta(del); if (found) return; } @@ -1431,7 +1493,7 @@ database::get_markings(revision_id const { roster_delta del; get_roster_delta(target_rev, *p, del); - bool found = get_markings_from_roster_delta(del, nid, markings); + bool found = x.look_at_delta(del); if (found) return; } @@ -1441,10 +1503,7 @@ database::get_markings(revision_id const roster_t roster; marking_map mm; get_roster_base(*p, roster, mm); - map::const_iterator mmi = - mm.find(nid); - I(mmi != mm.end()); - markings = mmi->second; + x.look_at_roster(roster, mm); return; } target_rev = *p; @@ -1453,6 +1512,15 @@ void } void +database::get_markings(revision_id const & id, + node_id const & nid, + marking_t & markings) +{ + markings_extractor x(nid, markings); + extract_from_deltas(id, x); +} + +void database::get_file_content(revision_id const & id, node_id const & nid, file_id & content) @@ -1463,61 +1531,10 @@ database::get_file_content(revision_id c content = file_id(); return; } - - reconstruction_path selected_path; - { - roster_reconstruction_graph graph(*this); - { - // we look at the nearest delta(s) first, without constructing the - // whole path, as this is rather expensive - set deltas; - graph.get_next(id.inner()(), deltas); - for (set::const_iterator i = deltas.begin(); - i != deltas.end(); ++i) - { - roster_delta del; - get_roster_delta(id.inner()(), *i, del); - bool found = get_content_from_roster_delta(del, nid, content); - if (found) - return; - } - } - get_reconstruction_path(id.inner()(), graph, selected_path); - } - - int path_length(selected_path.size()); - int i(0); - string target_rev; - - for (reconstruction_path::const_iterator p = selected_path.begin(); - p != selected_path.end(); ++p) - { - if (i > 0) - { - roster_delta del; - get_roster_delta(target_rev, *p, del); - bool found = get_content_from_roster_delta(del, nid, content); - if (found) - return; - } - if (i == path_length-1) - { - // last iteration, we have reached a roster base - roster_t roster; - marking_map mm; - get_roster_base(*p, roster, mm); - if (roster.has_node(nid)) - content = downcast_to_file_t(roster.get_node(nid))->content; - else - content = file_id(); - return; - } - target_rev = *p; - ++i; - } + file_content_extractor x(nid, content); + extract_from_deltas(id, x); } - void database::get_roster_version(revision_id const & id, cached_roster & cr) ============================================================ --- database.hh 30356b8eff24860141a9498fae5860298965106f +++ database.hh d098635da9410b7c7ecd5a05ead436d51a54a1a3 @@ -353,6 +353,11 @@ public: void get_file_content(revision_id const & id, node_id const & nid, file_id & content); +private: + struct extractor; + struct file_content_extractor; + struct markings_extractor; + void extract_from_deltas(revision_id const & id, extractor & x); // // --== Keys ==--