# # # patch "ChangeLog" # from [ce11cd3ab433ce9fe8c1645321267dc93865514e] # to [75b4a58f05b4c01f9386cd1952b9d08b52e9d06d] # # patch "annotate.cc" # from [5a0e7200fad7865dc1ce9b30aaa531d0f6f7b542] # to [50b054150a5d9cdc0902867573202c2adbddab50] # # patch "database.cc" # from [a65fbb52f8ad90194b9c195ee5e3c16e2113e5e9] # to [8fd5626b20edcf5ebcd042ad36d8f9b3202ead44] # # patch "database.hh" # from [90abb4ec87c1b090257a07d79be1c3e33d931a6a] # to [d3e1ec3863d5a86422a4fb4fad90925392c2437c] # # patch "roster_delta.cc" # from [66a0a455754209bea533db586769e37b9bd18ca3] # to [c78fd99ec874ac047c4c5b2581f8e974a1adf648] # # patch "roster_delta.hh" # from [25e389e2c42e9754480cb7f5e43157623eeaf1fa] # to [c469955ebc623dd5986883c7751a1010e530a963] # ============================================================ --- ChangeLog ce11cd3ab433ce9fe8c1645321267dc93865514e +++ ChangeLog 75b4a58f05b4c01f9386cd1952b9d08b52e9d06d @@ -1,3 +1,20 @@ +2007-02-02 Thomas Moschny + + * roster_delta.{cc|hh} + (get_markings_from_roster_delta, get_content_from_roster_delta): + New functions. Both try to extract node-specific information from + a single roster delta. + + * database.{cc|hh} (get_markings, get_file_content): New functions + using roster deltas to find the set of markings resp. the content + hash for a given node and revision id. + + * annotate.cc (do_annotate_node): Utilize the new methods. Store + the set of markings and the file content hash in the work_unit for + the corresponding revision, to avoid fetching the same information + twice. Don't fetch content hash or markings for marked ancestors, + as we can deduce that information from the descendants. + 2007-02-01 Matthew Gregan * sqlite/*: Import SQLite 3.3.12. ============================================================ --- annotate.cc 5a0e7200fad7865dc1ce9b30aaa531d0f6f7b542 +++ annotate.cc 50b054150a5d9cdc0902867573202c2adbddab50 @@ -160,12 +160,16 @@ struct annotate_node_work annotate_node_work(shared_ptr annotations_, shared_ptr lineage_, revision_id revision_, node_id fid_, - rev_height height_) + rev_height height_, + shared_ptr > content_marks_, + file_id content_) : annotations(annotations_), lineage(lineage_), revision(revision_), fid(fid_), - height(height_) + height(height_), + content_marks(content_marks_), + content(content_) {} shared_ptr annotations; @@ -173,6 +177,8 @@ struct annotate_node_work revision_id revision; node_id fid; rev_height height; + shared_ptr > content_marks; + file_id content; }; struct by_rev {}; @@ -662,6 +668,23 @@ annotate_lineage_mapping::set_copied_all } } +// fetches the list of file_content markings for the given revision_id and +// node_id +static void get_file_content_marks(app_state & app, + revision_id const & rev, + node_id const & fid, + set & content_marks) +{ + marking_t markings; + app.db.get_markings(rev, fid, markings); + + I(markings.file_content.size() != 0); + + content_marks.clear(); + content_marks.insert(markings.file_content.begin(), + markings.file_content.end()); +} + static void do_annotate_node (annotate_node_work const & work_unit, @@ -670,66 +693,60 @@ do_annotate_node { L(FL("do_annotate_node for node %s") % work_unit.revision); - roster_t roster; - marking_t marks; + shared_ptr > ancestors; - { - marking_map markmap; - app.db.get_roster(work_unit.revision, roster, markmap); - - map::const_iterator mmi = - markmap.find(work_unit.fid); - I(mmi != markmap.end()); - marks = mmi->second; - } - - I(marks.file_content.size() != 0); - - set parents; // fixme: rename - - if (marks.file_content.size() == 1 - && *(marks.file_content.begin()) == work_unit.revision) + bool marked = (work_unit.content_marks->size() == 1 + && *(work_unit.content_marks->begin()) == work_unit.revision); + + if (marked) { + ancestors = shared_ptr > (new set()); // this node is marked, need to inspect the parents - app.db.get_revision_parents(work_unit.revision, parents); + app.db.get_revision_parents(work_unit.revision, *ancestors); } else { - // jump directly to the marked ancestors - parents = marks.file_content; + ancestors = work_unit.content_marks; } size_t added_in_parent_count = 0; - for (set::const_iterator i = parents.begin(); - i != parents.end(); i++) + for (set::const_iterator i = ancestors->begin(); + i != ancestors->end(); i++) { revision_id parent_revision = *i; - roster_t parent_roster; L(FL("do_annotate_node processing edge from parent %s to child %s") % parent_revision % work_unit.revision); I(!(work_unit.revision == parent_revision)); - app.db.get_roster(parent_revision, parent_roster); - if (!parent_roster.has_node(work_unit.fid)) + file_id file_in_parent; + shared_ptr > parent_content_marks(new set()); + + if (marked) { - L(FL("file added in %s, continuing") % work_unit.revision); - added_in_parent_count++; - continue; + // we are marked, so we don't know much about the ancestor + app.db.get_file_content(parent_revision, work_unit.fid, file_in_parent); + if (null_id(file_in_parent)) + { + L(FL("file added in %s, continuing") % work_unit.revision); + added_in_parent_count++; + continue; + } + get_file_content_marks(app, parent_revision, work_unit.fid, *parent_content_marks); } - + else + { + // we know that this ancestor is marked + file_in_parent = work_unit.content; + parent_content_marks->insert(parent_revision); + } + // The node was live in the parent, so this represents a delta. - file_t file_in_child = - downcast_to_file_t(roster.get_node(work_unit.fid)); - - file_t file_in_parent = - downcast_to_file_t(parent_roster.get_node(work_unit.fid)); - shared_ptr parent_lineage; - if (file_in_parent->content == file_in_child->content) + if (file_in_parent == work_unit.content) { L(FL("parent file identical, " "set copied all mapped and copy lineage\n")); @@ -739,9 +756,9 @@ do_annotate_node else { file_data data; - app.db.get_file_version(file_in_parent->content, data); + app.db.get_file_version(file_in_parent, data); L(FL("building parent lineage for parent file %s") - % file_in_parent->content); + % file_in_parent); parent_lineage = work_unit.lineage->build_parent_lineage(work_unit.annotations, parent_revision, @@ -763,7 +780,9 @@ do_annotate_node parent_lineage, parent_revision, work_unit.fid, - parent_height); + parent_height, + parent_content_marks, + file_in_parent); work_units.insert(newunit); } @@ -777,7 +796,7 @@ do_annotate_node } } - if (added_in_parent_count == parents.size()) + if (added_in_parent_count == ancestors->size()) { work_unit.lineage->credit_mapped_lines(work_unit.annotations); } @@ -799,9 +818,13 @@ do_annotate (app_state &app, file_t file work_units work_units; { + // prepare the first work_unit rev_height height; app.db.get_rev_height(rid, height); - annotate_node_work workunit(acp, lineage, rid, file_node->self, height); + shared_ptr >content_marks(new set()); + get_file_content_marks(app, rid, file_node->self, *content_marks); + annotate_node_work workunit(acp, lineage, rid, file_node->self, height, + content_marks, file_node->content); work_units.insert(workunit); } ============================================================ --- database.cc a65fbb52f8ad90194b9c195ee5e3c16e2113e5e9 +++ database.cc 8fd5626b20edcf5ebcd042ad36d8f9b3202ead44 @@ -1395,6 +1395,130 @@ void }; void +database::get_markings(revision_id const & id, + node_id const & nid, + marking_t & markings) +{ + 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_markings_from_roster_delta(del, nid, markings); + 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_markings_from_roster_delta(del, nid, markings); + 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); + map::const_iterator mmi = + mm.find(nid); + I(mmi != mm.end()); + markings = mmi->second; + return; + } + target_rev = *p; + ++i; + } +} + +void +database::get_file_content(revision_id const & id, + node_id const & nid, + file_id & content) +{ + // the imaginary root revision doesn't have any file. + if (null_id(id)) + { + 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; + } +} + + +void database::get_roster_version(revision_id const & id, cached_roster & cr) { ============================================================ --- database.hh 90abb4ec87c1b090257a07d79be1c3e33d931a6a +++ database.hh d3e1ec3863d5a86422a4fb4fad90925392c2437c @@ -349,6 +349,15 @@ public: bool roster_version_exists(revision_id const & ident); void get_roster_ids(std::set & ids); + // using roster deltas + void get_markings(revision_id const & id, + node_id const & nid, + marking_t & markings); + + void get_file_content(revision_id const & id, + node_id const & nid, + file_id & content); + // // --== Keys ==-- // ============================================================ --- roster_delta.cc 66a0a455754209bea533db586769e37b9bd18ca3 +++ roster_delta.cc c78fd99ec874ac047c4c5b2581f8e974a1adf648 @@ -491,7 +491,62 @@ apply_roster_delta(roster_delta const & d.apply(roster, markings); } +// Extract the marking for one node from the roster delta, or return false +// if they are not contained in that delta +bool +get_markings_from_roster_delta(roster_delta const & del, + node_id const & nid, + marking_t & markings) +{ + // FIXME: factor out this block + basic_io::input_source src(del.inner()(), "roster_delta"); + basic_io::tokenizer tok(src); + basic_io::parser pars(tok); + roster_delta_t d; + parse_roster_delta_t(pars, d); + std::map::iterator i = d.markings_changed.find(nid); + if (i != d.markings_changed.end()) + { + markings = i->second; + return true; + } + else + { + return false; + } +} + +// Extract the content hash for one node from the roster delta. Return false +// if this delta doesn't contain information about this node. +bool +get_content_from_roster_delta(roster_delta const & del, + node_id const & nid, + file_id & content) +{ + // FIXME: factor out this block + basic_io::input_source src(del.inner()(), "roster_delta"); + basic_io::tokenizer tok(src); + basic_io::parser pars(tok); + roster_delta_t d; + parse_roster_delta_t(pars, d); + + std::map::const_iterator i = d.deltas_applied.find(nid); + if (i != d.deltas_applied.end()) + { + content = i->second; + return true; + } + + if (d.nodes_deleted.find(nid) != d.nodes_deleted.end()) + { + content = file_id(); + return true; + } + + return false; +} + #ifdef BUILD_UNIT_TESTS static void ============================================================ --- roster_delta.hh 25e389e2c42e9754480cb7f5e43157623eeaf1fa +++ roster_delta.hh c469955ebc623dd5986883c7751a1010e530a963 @@ -25,7 +25,16 @@ apply_roster_delta(roster_delta const & apply_roster_delta(roster_delta const & del, roster_t & roster, marking_map & markings); +bool +get_markings_from_roster_delta(roster_delta const & del, + node_id const & nid, + marking_t & markings); +bool +get_content_from_roster_delta(roster_delta const & del, + node_id const & nid, + file_id & content); + #ifdef BUILD_UNIT_TESTS // instead of having elaborate tests here, we just export a function, and then