# # # patch "roster.cc" # from [ff3e7002de0ea5cded215d2f90e6f399386a793d] # to [7a8c3076fc56de12ee153e1b3f300b7291c80802] # # patch "roster.hh" # from [f79fe7c3e150abe91f2497421a71eacbd0145d60] # to [aaa305a2796511d77f586beaa64cad29eba054d7] # # patch "roster_delta.cc" # from [b9541d767d86bf64f86bfd531a3d2c6c751f3886] # to [c2d4643c1dac50ceb8aaefd9297d9f080952b45e] # ============================================================ --- roster.cc ff3e7002de0ea5cded215d2f90e6f399386a793d +++ roster.cc 7a8c3076fc56de12ee153e1b3f300b7291c80802 @@ -2391,23 +2391,59 @@ void //////////////////////////////////////////////////////////////////// void -push_marking(basic_io::stanza & st, +append_with_escaped_quotes(string & collection, string const & item) +{ + size_t mark = 0; + size_t cursor = item.find('"', mark); + while (cursor != string::npos) + { + collection.append(item, mark, cursor - mark); + collection.append(1, '\\'); + mark = cursor; + if (mark == item.size()) + { + cursor = string::npos; + } + else + { + cursor = item.find('"', mark + 1); + } + } + collection.append(item, mark, item.size() - mark + 1); +} + +void +push_marking(string & contents, bool is_file, - marking_t const & mark) + marking_t const & mark, + int symbol_length) { I(!null_id(mark.birth_revision)); - st.push_binary_pair(syms::birth, mark.birth_revision.inner()); + contents.append(symbol_length - 5, ' '); + contents.append("birth ["); + contents.append(encode_hexenc(mark.birth_revision.inner()(), origin::internal)); + contents.append("]\n"); + for (set::const_iterator i = mark.parent_name.begin(); i != mark.parent_name.end(); ++i) - st.push_binary_pair(syms::path_mark, i->inner()); + { + contents.append(symbol_length - 9, ' '); + contents.append("path_mark ["); + contents.append(encode_hexenc(i->inner()(), origin::internal)); + contents.append("]\n"); + } if (is_file) { for (set::const_iterator i = mark.file_content.begin(); i != mark.file_content.end(); ++i) - st.push_binary_pair(basic_io::syms::content_mark, i->inner()); + { + contents.append("content_mark [");// always the longest symbol + contents.append(encode_hexenc(i->inner()(), origin::internal)); + contents.append("]\n"); + } } else I(mark.file_content.empty()); @@ -2417,7 +2453,14 @@ push_marking(basic_io::stanza & st, { for (set::const_iterator j = i->second.begin(); j != i->second.end(); ++j) - st.push_binary_triple(syms::attr_mark, i->first(), j->inner()); + { + contents.append(symbol_length - 9, ' '); + contents.append("attr_mark \""); + append_with_escaped_quotes(contents, i->first()); + contents.append("\" ["); + contents.append(encode_hexenc(j->inner()(), origin::internal)); + contents.append("]\n"); + } } } @@ -2470,38 +2513,126 @@ void // processed more efficiently. void -roster_t::print_to(basic_io::printer & pr, +roster_t::print_to(data & dat, marking_map const & mm, bool print_local_parts) const { + string contents; I(has_root()); - { - basic_io::stanza st; - st.push_str_pair(basic_io::syms::format_version, "1"); - pr.print_stanza(st); - } + + // approximate byte counts + // a file is name + content (+ birth + path-mark + content-mark + ident) + // 2 sym + name + hash (+ 4 sym + 3 hash + 1 num) + // 24 + name + 43 (+48 + 129 + 10) = 67 + name (+ 187) = ~100 (+ 187) + // a dir is name (+ birth + path-mark + ident) + // 1 sym + name (+ 3 sym + 2 hash + 1 num) + // 12 + name (+ 36 + 86 + 10) = 12 + name (+ 132) = ~52 (+ 132) + // an attr is name/value (+ name/mark) + // 1 sym + 2 name (+ 1 sym + 1 name + 1 hash) + // 12 + 2 name (+ 12 + 43 + name) = ~40 (+ ~70) + // in the monotone tree, there are about 2% as many attrs as nodes + + if (print_local_parts) + { + contents.reserve(nodes.size() * (290 + 0.02 * 110) * 1.1); + } + else + { + contents.reserve(nodes.size() * (100 + 0.02 * 40) * 1.1); + } + + // symbols are: + // birth (all local) + // dormant_attr (any local) + // ident (all local) + // path_mark (all local) + // attr_mark (any local) + // dir (all dir) + // file (all file) + // content (all file) + // attr (any) + // content_mark (all local file) + + // local file : symbol length 12 + // local dir : symbol length 9 or 12 (if dormant_attr) + // public file : symbol length 7 + // public dir : symbol length 3 or 4 (if attr) + + contents += "format_version \"1\"\n"; + for (dfs_iter i(root_dir, true); !i.finished(); ++i) { + contents += "\n"; + node_t curr = *i; - basic_io::stanza st; - { - if (is_dir_t(curr)) - { - st.push_str_pair(basic_io::syms::dir, i.path()); - } - else - { - file_t ftmp = downcast_to_file_t(curr); - st.push_str_pair(basic_io::syms::file, i.path()); - st.push_binary_pair(basic_io::syms::content, ftmp->content.inner()); - } - } + int symbol_length = 0; + if (is_dir_t(curr)) + { + if (print_local_parts) + { + symbol_length = 9; + // unless we have a dormant attr + for (attr_map_t::const_iterator j = curr->attrs.begin(); + j != curr->attrs.end(); ++j) + { + if (!j->second.first) + { + symbol_length = 12; + break; + } + } + } + else + { + symbol_length = 3; + // unless we have a live attr + for (attr_map_t::const_iterator j = curr->attrs.begin(); + j != curr->attrs.end(); ++j) + { + if (j->second.first) + { + symbol_length = 4; + break; + } + } + } + contents.append(symbol_length - 3, ' '); + contents.append("dir \""); + append_with_escaped_quotes(contents, i.path()); + contents.append("\"\n"); + } + else + { + if (print_local_parts) + { + symbol_length = 12; + } + else + { + symbol_length = 7; + } + file_t ftmp = downcast_to_file_t(curr); + + contents.append(symbol_length - 4, ' '); + contents.append("file \""); + append_with_escaped_quotes(contents, i.path()); + contents.append("\"\n"); + + contents.append(symbol_length - 7, ' '); + contents.append("content ["); + contents.append(encode_hexenc(ftmp->content.inner()(), origin::internal)); + contents.append("]\n"); + } + if (print_local_parts) { I(curr->self != the_null_node); - st.push_str_pair(syms::ident, lexical_cast(curr->self)); + contents.append(symbol_length - 5, ' '); + contents.append("ident \""); + contents.append(lexical_cast(curr->self)); + contents.append("\"\n"); } // Push the non-dormant part of the attr map @@ -2511,7 +2642,13 @@ roster_t::print_to(basic_io::printer & p if (j->second.first) { // L(FL("printing attr %s : %s = %s") % fp % j->first % j->second); - st.push_str_triple(basic_io::syms::attr, j->first(), j->second.second()); + + contents.append(symbol_length - 4, ' '); + contents.append("attr \""); + append_with_escaped_quotes(contents, j->first()); + contents.append("\" \""); + append_with_escaped_quotes(contents, j->second.second()); + contents.append("\"\n"); } } @@ -2524,17 +2661,19 @@ roster_t::print_to(basic_io::printer & p if (!j->second.first) { I(j->second.second().empty()); - st.push_str_pair(syms::dormant_attr, j->first()); + + contents.append("dormant_attr \""); // always the longest sym + append_with_escaped_quotes(contents, j->first()); + contents.append("\"\n"); } } marking_map::const_iterator m = mm.find(curr->self); I(m != mm.end()); - push_marking(st, is_file_t(curr), m->second); + push_marking(contents, is_file_t(curr), m->second, symbol_length); } - - pr.print_stanza(st); } + dat = data(contents, origin::internal); } inline size_t @@ -2675,9 +2814,7 @@ write_roster_and_marking(roster_t const ros.check_sane_against(mm); else ros.check_sane(true); - basic_io::printer pr; - ros.print_to(pr, mm, print_local_parts); - dat = data(pr.buf, origin::internal); + ros.print_to(dat, mm, print_local_parts); } ============================================================ --- roster.hh f79fe7c3e150abe91f2497421a71eacbd0145d60 +++ roster.hh aaa305a2796511d77f586beaa64cad29eba054d7 @@ -224,7 +224,7 @@ public: // marking map void check_sane_against(marking_map const & marks, bool temp_nodes_ok=false) const; - void print_to(basic_io::printer & pr, + void print_to(data & dat, marking_map const & mm, bool print_local_parts) const; @@ -430,7 +430,12 @@ void calculate_ident(roster_t const & ro manifest_id & ident); // for roster_delta -void push_marking(basic_io::stanza & st, bool is_file, marking_t const & mark); + +void append_with_escaped_quotes(std::string & collection, + std::string const & item); +void push_marking(std::string & contents, + bool is_file, marking_t const & mark, + int symbol_length); void parse_marking(basic_io::parser & pa, marking_t & marking); // Parent maps are used in a number of places to keep track of all the ============================================================ --- roster_delta.cc b9541d767d86bf64f86bfd531a3d2c6c751f3886 +++ roster_delta.cc c2d4643c1dac50ceb8aaefd9297d9f080952b45e @@ -27,6 +27,7 @@ using std::make_pair; using boost::lexical_cast; using std::pair; using std::make_pair; +using std::string; namespace { @@ -272,92 +273,106 @@ namespace } void - push_nid(symbol const & sym, node_id nid, basic_io::stanza & st) + push_nid(symbol const & sym, node_id nid, string & contents, int symbol_length) { - st.push_str_pair(sym, lexical_cast(nid)); + contents.append(symbol_length - sym().size(), ' '); + contents.append(sym()); + contents.append(" \""); + contents.append(lexical_cast(nid)); + contents.append("\"\n"); } static void push_loc(pair const & loc, - basic_io::stanza & st) + string & contents, int symbol_length) { - st.push_str_triple(syms::location, - lexical_cast(loc.first), - loc.second()); + contents.append(symbol_length - 8, ' '); + contents.append("location \""); + contents.append(lexical_cast(loc.first)); + contents.append("\" \""); + append_with_escaped_quotes(contents, loc.second()); + contents.append("\"\n"); } void - print_roster_delta_t(basic_io::printer & printer, + print_roster_delta_t(data & dat, roster_delta_t & d) { + string contents; + for (roster_delta_t::nodes_deleted_t::const_iterator i = d.nodes_deleted.begin(); i != d.nodes_deleted.end(); ++i) { - basic_io::stanza st; - push_nid(syms::deleted, *i, st); - printer.print_stanza(st); + push_nid(syms::deleted, *i, contents, 7); + contents += "\n"; } for (roster_delta_t::nodes_renamed_t::const_iterator i = d.nodes_renamed.begin(); i != d.nodes_renamed.end(); ++i) { - basic_io::stanza st; - push_nid(syms::rename, i->first, st); - push_loc(i->second, st); - printer.print_stanza(st); + push_nid(syms::rename, i->first, contents, 8); + push_loc(i->second, contents, 8); + contents += "\n"; } for (roster_delta_t::dirs_added_t::const_iterator i = d.dirs_added.begin(); i != d.dirs_added.end(); ++i) { - basic_io::stanza st; - push_nid(syms::add_dir, i->second, st); - push_loc(i->first, st); - printer.print_stanza(st); + push_nid(syms::add_dir, i->second, contents, 8); + push_loc(i->first, contents, 8); + contents += "\n"; } for (roster_delta_t::files_added_t::const_iterator i = d.files_added.begin(); i != d.files_added.end(); ++i) { - basic_io::stanza st; - push_nid(syms::add_file, i->second.first, st); - push_loc(i->first, st); - st.push_binary_pair(syms::content, i->second.second.inner()); - printer.print_stanza(st); + push_nid(syms::add_file, i->second.first, contents, 8); + push_loc(i->first, contents, 8); + contents.append(" content ["); + contents.append(encode_hexenc(i->second.second.inner()(), origin::internal)); + contents.append("]\n\n"); } for (roster_delta_t::deltas_applied_t::const_iterator i = d.deltas_applied.begin(); i != d.deltas_applied.end(); ++i) { - basic_io::stanza st; - push_nid(syms::delta, i->first, st); - st.push_binary_pair(syms::content, i->second.inner()); - printer.print_stanza(st); + push_nid(syms::delta, i->first, contents, 7); + contents.append("content ["); + contents.append(encode_hexenc(i->second.inner()(), origin::internal)); + contents.append("]\n\n"); } for (roster_delta_t::attrs_cleared_t::const_iterator i = d.attrs_cleared.begin(); i != d.attrs_cleared.end(); ++i) { - basic_io::stanza st; - push_nid(syms::attr_cleared, i->first, st); - st.push_str_pair(syms::attr, i->second()); - printer.print_stanza(st); + push_nid(syms::attr_cleared, i->first, contents, 12); + contents.append(" attr \""); + append_with_escaped_quotes(contents, i->second()); + contents.append("\"\n\n"); } for (roster_delta_t::attrs_changed_t::const_iterator i = d.attrs_changed.begin(); i != d.attrs_changed.end(); ++i) { - basic_io::stanza st; - push_nid(syms::attr_changed, i->first, st); - st.push_str_pair(syms::attr, i->second.first()); - st.push_str_triple(syms::value, - lexical_cast(i->second.second.first), - i->second.second.second()); - printer.print_stanza(st); + push_nid(syms::attr_changed, i->first, contents, 12); + contents.append(" attr \""); + append_with_escaped_quotes(contents, i->second.first()); + contents.append("\"\n value \""); + contents.append(lexical_cast(i->second.second.first)); + contents.append("\" \""); + append_with_escaped_quotes(contents, i->second.second.second()); + contents.append("\"\n\n"); } for (roster_delta_t::markings_changed_t::const_iterator i = d.markings_changed.begin(); i != d.markings_changed.end(); ++i) { - basic_io::stanza st; - push_nid(syms::marking, i->first, st); - // ...this second argument is a bit odd... - push_marking(st, !i->second.file_content.empty(), i->second); - printer.print_stanza(st); + bool is_file = !i->second.file_content.empty(); + int symbol_length = (is_file ? 12 : 9); + push_nid(syms::marking, i->first, contents, symbol_length); + push_marking(contents, is_file, i->second, symbol_length); + contents.append("\n"); } + // I wouldn't think it should be possible to have empty contents here, + // but apparently it is. + if (!contents.empty()) + { + contents.erase(contents.size() - 1); // drop last extra trailing newline + } + dat = data(contents, origin::internal); } node_id @@ -476,9 +491,9 @@ delta_rosters(roster_t const & from, mar MM(to_markings); roster_delta_t d; make_roster_delta_t(from, from_markings, to, to_markings, d); - basic_io::printer printer; - print_roster_delta_t(printer, d); - del = roster_delta(printer.buf, origin::internal); + data dat; + print_roster_delta_t(dat, d); + del = roster_delta(dat(), origin::internal); } static