# # # patch "app_state.cc" # from [ffe7d555550ba0029a88e3e0fcfdfe99c1a8720b] # to [8b0780694d5c22c05ab679a92cdcdeda1cb52381] # # patch "database.cc" # from [c609818513960b330c4d833ba6abe267fa635c47] # to [e05fbe08e03862c48542a85603614e609c1421b4] # # patch "monotone.cc" # from [c1d774218a91a191fcd1894c3fc02c9aa0747dcf] # to [2c59dffd4d6d9d5c511828392247a163284b1d11] # # patch "mtn-sanity.cc" # from [245d3726f06c950455e311f45d076545a0f3e083] # to [99ff16995d5a2b8554320e012d8a5ed3c3593e85] # # patch "netsync.cc" # from [b162d327e4854e204ec02ef5f3fd0e0be2c42596] # to [4a3199e4aee2485231c03c8094233a2e9b02ece8] # # patch "netxx_pipe.cc" # from [66d4dcf236cc6c230626cec1ea10aa97b838543c] # to [4a4b34cf653e71569bb50194fc8d10c166b48025] # # patch "options_list.hh" # from [c232a5b2e9e84041361ba6a81689406db3110d39] # to [e1ae13e30c448ecfeec41cf0b5afd7ab1463d056] # # patch "paths.cc" # from [0b81dfd4a65442de417c635cd8f003994af44ee1] # to [3b49f7bc82b3c802ca1cbd482bbfc550a7499df0] # # patch "paths.hh" # from [5f2909f8cb250e4a5ddbb66eae949517c644d91f] # to [76413afe6f7f837a534418ae5cf9d0b39bce7c41] # # patch "restrictions.cc" # from [3b059a0327f0bea5958a1eecfb2bbe9a3c525e10] # to [5872ed61a24448574daefa2cb119d9fa129f6ac1] # # patch "sanity.cc" # from [8c2cb1ec66d4342731bb79f536f50fec2a9c9eca] # to [d81b4ce4f71d64a34f060990e79636019bc1dc37] # # patch "sanity.hh" # from [9b427a9911acfa147e536fab01cf20febf27778b] # to [c56eb62b0c077c6a79efc6eb86d663e7b8d7672b] # # patch "simplestring_xform.cc" # from [4d9df66d29c1e2b1ec4ef1717b271de71fd3d941] # to [9537d56180ced77a4c692399b935f08a02b05c1d] # # patch "tester.cc" # from [775277ecee57590d0124a8d04f94452668ca34e0] # to [96dde1189e56c66156cc0038e423b33d170957c6] # # patch "unix/get_system_flavour.cc" # from [de33a20261af04c652ce6b3b29b24fb37cbb0e8e] # to [adfea09a6109d5ea5ffcb48507077f7fb496b53f] # ============================================================ --- app_state.cc ffe7d555550ba0029a88e3e0fcfdfe99c1a8720b +++ app_state.cc 8b0780694d5c22c05ab679a92cdcdeda1cb52381 @@ -7,7 +7,6 @@ // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. -#include // for strtoul() #include #include @@ -60,16 +59,13 @@ app_state::allow_workspace() if (found_workspace) { - if (global_sanity.filename.empty()) - { - bookkeeping_path dump_path; - work.get_local_dump_path(dump_path); - L(FL("setting dump path to %s") % dump_path); - // The 'true' means that, e.g., if we're running checkout, - // then it's okay for dumps to go into our starting working - // dir's _MTN rather than the new workspace dir's _MTN. - global_sanity.filename = system_path(dump_path, false).as_external(); - } + bookkeeping_path dump_path; + work.get_local_dump_path(dump_path); + + // The 'false' means that, e.g., if we're running checkout, + // then it's okay for dumps to go into our starting working + // dir's _MTN rather than the new workspace dir's _MTN. + global_sanity.set_dump_path(system_path(dump_path, false).as_external()); } load_rcfiles(); } @@ -169,17 +165,14 @@ app_state::create_workspace(system_path work.enable_inodeprints(); found_workspace = true; - if (global_sanity.filename.empty()) - { - bookkeeping_path dump_path; - work.get_local_dump_path(dump_path); - L(FL("setting dump path to %s") % dump_path); - // The 'true' means that, e.g., if we're running checkout, - // then it's okay for dumps to go into our starting working - // dir's _MTN rather than the new workspace dir's _MTN. - global_sanity.filename = system_path(dump_path, false).as_external(); - } + bookkeeping_path dump_path; + work.get_local_dump_path(dump_path); + // The 'false' means that, e.g., if we're running checkout, + // then it's okay for dumps to go into our starting working + // dir's _MTN rather than the new workspace dir's _MTN. + global_sanity.set_dump_path(system_path(dump_path, false).as_external()); + load_rcfiles(); } ============================================================ --- database.cc c609818513960b330c4d833ba6abe267fa635c47 +++ database.cc e05fbe08e03862c48542a85603614e609c1421b4 @@ -766,13 +766,13 @@ database::fetch(results & res, I(params == int(query.args.size())); // profiling finds this logging to be quite expensive - if (global_sanity.debug) + if (global_sanity.debug_p()) L(FL("binding %d parameters for %s") % params % query.sql_cmd); for (int param = 1; param <= params; param++) { // profiling finds this logging to be quite expensive - if (global_sanity.debug) + if (global_sanity.debug_p()) { string log; switch (query.args[param-1].type) ============================================================ --- monotone.cc c1d774218a91a191fcd1894c3fc02c9aa0747dcf +++ monotone.cc 2c59dffd4d6d9d5c511828392247a163284b1d11 @@ -243,8 +243,9 @@ cpp_main(int argc, char ** argv) // if we didn't find one at this point. app.allow_workspace(); - if (!app.found_workspace && global_sanity.filename.empty()) - global_sanity.filename = (app.opts.conf_dir / "dump").as_external(); + if (!app.found_workspace) + global_sanity.set_dump_path((app.opts.conf_dir / "dump") + .as_external()); app.lua.hook_note_mtn_startup(args); ============================================================ --- mtn-sanity.cc 245d3726f06c950455e311f45d076545a0f3e083 +++ mtn-sanity.cc 99ff16995d5a2b8554320e012d8a5ed3c3593e85 @@ -15,11 +15,11 @@ mtn_sanity::initialize(int argc, char ** void mtn_sanity::initialize(int argc, char ** argv, char const * lc_all) { + this->sanity::initialize(argc, argv, lc_all); + std::string full_version_string; get_full_version(full_version_string); PERM_MM(full_version_string); - - this->sanity::initialize(argc, argv, lc_all); } void ============================================================ --- netsync.cc b162d327e4854e204ec02ef5f3fd0e0be2c42596 +++ netsync.cc 4a3199e4aee2485231c03c8094233a2e9b02ece8 @@ -2311,7 +2311,7 @@ build_stream_to_server(app_state & app, && app.lua.hook_get_netsync_connect_command(u, include_pattern, exclude_pattern, - global_sanity.debug, + global_sanity.debug_p(), argv)) { I(argv.size() > 0); ============================================================ --- netxx_pipe.cc 66d4dcf236cc6c230626cec1ea10aa97b838543c +++ netxx_pipe.cc 4a4b34cf653e71569bb50194fc8d10c166b48025 @@ -11,6 +11,7 @@ #include "sanity.hh" #include "platform.hh" #include +#include // for operator<< #ifdef WIN32 #include ============================================================ --- options_list.hh c232a5b2e9e84041361ba6a81689406db3110d39 +++ options_list.hh e1ae13e30c448ecfeec41cf0b5afd7ab1463d056 @@ -229,7 +229,7 @@ OPTION(globals, dump, true, "dump", gettext_noop("file to dump debugging log to, on failure")) #ifdef option_bodies { - global_sanity.filename = system_path(arg).as_external(); + global_sanity.set_dump_path(system_path(arg).as_external()); } #endif @@ -484,7 +484,7 @@ GOPT(ticker, "ticker", std::string, , #ifdef option_bodies { ticker = arg; - if (ticker == "none" || global_sanity.quiet) + if (ticker == "none" || global_sanity.quiet_p()) ui.set_tick_writer(new tick_write_nothing); else if (ticker == "dot") ui.set_tick_writer(new tick_write_dot); ============================================================ --- paths.cc 0b81dfd4a65442de417c635cd8f003994af44ee1 +++ paths.cc 3b49f7bc82b3c802ca1cbd482bbfc550a7499df0 @@ -86,13 +86,6 @@ static access_tracker worki // system_path's. static access_tracker working_root; -bookkeeping_path const bookkeeping_root("_MTN"); -path_component const bookkeeping_root_component("_MTN"); - -// this is a file_path because it does not conform to the invariant that -// bookkeeping paths always start with the _current_ bookkeeping root. -file_path const old_bookkeeping_root = file_path_internal("MT"); - void save_initial_path() { ============================================================ --- paths.hh 5f2909f8cb250e4a5ddbb66eae949517c644d91f +++ paths.hh 76413afe6f7f837a534418ae5cf9d0b39bce7c41 @@ -219,11 +219,19 @@ public: { return data < other.data; } }; -extern bookkeeping_path const bookkeeping_root; -extern path_component const bookkeeping_root_component; -// for migration -extern file_path const old_bookkeeping_root; +// these are #defines so that they will be constructed lazily, when used. +// This is actually necessary for correct behavior; the path constructors +// use sanity.hh assertions and therefore must not run before +// sanity::initialize is called. +// +// old_bookkeeping_root is a file_path because it does not conform to the +// invariant that bookkeeping paths always start with the _current_ +// bookkeeping root. +#define bookkeeping_root (bookkeeping_path("_MTN")) +#define bookkeeping_root_component (path_component("_MTN")) +#define old_bookkeeping_root (file_path_internal("MT")) + // this will always be an absolute path class system_path : public any_path { ============================================================ --- restrictions.cc 3b059a0327f0bea5958a1eecfb2bbe9a3c525e10 +++ restrictions.cc 5872ed61a24448574daefa2cb119d9fa129f6ac1 @@ -320,7 +320,7 @@ node_restriction::includes(roster_t cons } else { - if (global_sanity.debug) + if (global_sanity.debug_p()) { // printing this slows down "log ". L(FL("(debug) default exclude of nid %d path '%s'") ============================================================ --- sanity.cc 8c2cb1ec66d4342731bb79f536f50fec2a9c9eca +++ sanity.cc d81b4ce4f71d64a34f060990e79636019bc1dc37 @@ -17,6 +17,7 @@ #include #include +#include #include "constants.hh" #include "platform.hh" @@ -35,19 +36,36 @@ using boost::format; using boost::format; -// debugging / logging system +struct sanity::impl +{ + bool debug; + bool quiet; + bool reallyquiet; + boost::circular_buffer logbuf; + std::string filename; + std::string gasp_dump; + bool already_dumping; + std::vector musings; -sanity::sanity() : - debug(false), quiet(false), reallyquiet(false), logbuf(0xffff), - already_dumping(false) -{} + impl() : + debug(false), quiet(false), reallyquiet(false), logbuf(0xffff), + already_dumping(false) + {} +}; +// debugging / logging system + sanity::~sanity() -{} +{ + if (imp) + delete imp; +} void sanity::initialize(int argc, char ** argv, char const * lc_all) { + imp = new impl; + // set up some marked strings, so even if our logbuf overflows, we'll get // this data in a crash. This (and subclass overrides) are probably the // only place PERM_MM should ever be used. @@ -80,38 +98,43 @@ sanity::dump_buffer() void sanity::dump_buffer() { - if (!filename.empty()) + I(imp); + if (!imp->filename.empty()) { - ofstream out(filename.c_str()); + ofstream out(imp->filename.c_str()); if (out) { - copy(logbuf.begin(), logbuf.end(), ostream_iterator(out)); - copy(gasp_dump.begin(), gasp_dump.end(), ostream_iterator(out)); + copy(imp->logbuf.begin(), imp->logbuf.end(), + ostream_iterator(out)); + copy(imp->gasp_dump.begin(), imp->gasp_dump.end(), + ostream_iterator(out)); inform_message((FL("wrote debugging log to %s\n" "if reporting a bug, please include this file") - % filename).str()); + % imp->filename).str()); } else - inform_message((FL("failed to write debugging log to %s") % filename).str()); + inform_message((FL("failed to write debugging log to %s") + % imp->filename).str()); } else inform_message("discarding debug log, because I have nowhere to write it\n" - "(maybe you want --debug or --dump?)"); + "(maybe you want --debug or --dump?)"); } void sanity::set_debug() { - quiet = false; - reallyquiet = false; - debug = true; + I(imp); + imp->quiet = false; + imp->reallyquiet = false; + imp->debug = true; // it is possible that some pre-setting-of-debug data // accumulated in the log buffer (during earlier option processing) // so we will dump it now ostringstream oss; vector lines; - copy(logbuf.begin(), logbuf.end(), ostream_iterator(oss)); + copy(imp->logbuf.begin(), imp->logbuf.end(), ostream_iterator(oss)); split_into_lines(oss.str(), lines); for (vector::const_iterator i = lines.begin(); i != lines.end(); ++i) inform_log((*i) + "\n"); @@ -120,19 +143,32 @@ sanity::set_quiet() void sanity::set_quiet() { - debug = false; - quiet = true; - reallyquiet = false; + I(imp); + imp->debug = false; + imp->quiet = true; + imp->reallyquiet = false; } void sanity::set_reallyquiet() { - debug = false; - quiet = true; - reallyquiet = true; + I(imp); + imp->debug = false; + imp->quiet = true; + imp->reallyquiet = true; } +void +sanity::set_dump_path(std::string const & path) +{ + I(imp); + if (imp->filename.empty()) + { + L(FL("setting dump path to %s") % path); + imp->filename = path; + } +} + string sanity::do_format(format_base const & fmt, char const * file, int line) { @@ -150,11 +186,31 @@ sanity::do_format(format_base const & fm } } +bool +sanity::debug_p() +{ + I(imp); + return imp->debug; +} +bool +sanity::quiet_p() +{ + I(imp); + return imp->quiet; +} + +// These functions can be called before sanity::initialize() if there +// is a bug, and therefore must not use I() if imp is unavailable, as +// that will cause infinite recursion (invariant_failure calls log). + void sanity::log(plain_format const & fmt, char const * file, int line) { + if (!imp) + throw std::logic_error("sanity::log called before sanity::initialize"); + string str = do_format(fmt, file, line); if (str.size() > constants::log_line_sz) @@ -163,10 +219,10 @@ sanity::log(plain_format const & fmt, if (str.at(str.size() - 1) != '\n') str.at(str.size() - 1) = '\n'; } - copy(str.begin(), str.end(), back_inserter(logbuf)); + copy(str.begin(), str.end(), back_inserter(imp->logbuf)); if (str[str.size() - 1] != '\n') - logbuf.push_back('\n'); - if (debug) + imp->logbuf.push_back('\n'); + if (imp->debug) inform_log(str); } @@ -174,6 +230,9 @@ sanity::progress(i18n_format const & i18 sanity::progress(i18n_format const & i18nfmt, char const * file, int line) { + if (!imp) + throw std::logic_error("sanity::progress called before sanity::initialize"); + string str = do_format(i18nfmt, file, line); if (str.size() > constants::log_line_sz) @@ -182,10 +241,10 @@ sanity::progress(i18n_format const & i18 if (str.at(str.size() - 1) != '\n') str.at(str.size() - 1) = '\n'; } - copy(str.begin(), str.end(), back_inserter(logbuf)); + copy(str.begin(), str.end(), back_inserter(imp->logbuf)); if (str[str.size() - 1] != '\n') - logbuf.push_back('\n'); - if (! quiet) + imp->logbuf.push_back('\n'); + if (! imp->quiet) inform_message(str); } @@ -193,6 +252,9 @@ sanity::warning(i18n_format const & i18n sanity::warning(i18n_format const & i18nfmt, char const * file, int line) { + if (!imp) + throw std::logic_error("sanity::warning called before sanity::initialize"); + string str = do_format(i18nfmt, file, line); if (str.size() > constants::log_line_sz) @@ -202,10 +264,10 @@ sanity::warning(i18n_format const & i18n str.at(str.size() - 1) = '\n'; } string str2 = "warning: " + str; - copy(str2.begin(), str2.end(), back_inserter(logbuf)); + copy(str2.begin(), str2.end(), back_inserter(imp->logbuf)); if (str[str.size() - 1] != '\n') - logbuf.push_back('\n'); - if (! reallyquiet) + imp->logbuf.push_back('\n'); + if (! imp->reallyquiet) inform_warning(str); } @@ -216,7 +278,8 @@ sanity::naughty_failure(string const & e string message; log(FL("%s:%d: usage constraint '%s' violated") % file % line % expr, file.c_str(), line); - prefix_lines_with(_("misuse: "), do_format(explain, file.c_str(), line), message); + prefix_lines_with(_("misuse: "), do_format(explain, file.c_str(), line), + message); gasp(); throw informative_failure(message); } @@ -228,7 +291,8 @@ sanity::error_failure(string const & exp string message; log(FL("%s:%d: detected error '%s' violated") % file % line % expr, file.c_str(), line); - prefix_lines_with(_("error: "), do_format(explain, file.c_str(), line), message); + prefix_lines_with(_("error: "), do_format(explain, file.c_str(), line), + message); throw informative_failure(message); } @@ -260,20 +324,42 @@ void // Last gasp dumps void +sanity::push_musing(MusingI const *musing) +{ + I(imp); + if (!imp->already_dumping) + imp->musings.push_back(musing); +} + +void +sanity::pop_musing(MusingI const *musing) +{ + I(imp); + if (!imp->already_dumping) + { + I(imp->musings.back() == musing); + imp->musings.pop_back(); + } +} + + +void sanity::gasp() { - if (already_dumping) + if (!imp) + return; + if (imp->already_dumping) { L(FL("ignoring request to give last gasp; already in process of dumping")); return; } - already_dumping = true; - L(FL("saving current work set: %i items") % musings.size()); + imp->already_dumping = true; + L(FL("saving current work set: %i items") % imp->musings.size()); ostringstream out; - out << (F("Current work set: %i items") % musings.size()) + out << (F("Current work set: %i items") % imp->musings.size()) << '\n'; // final newline is kept out of the translation for (vector::const_iterator - i = musings.begin(); i != musings.end(); ++i) + i = imp->musings.begin(); i != imp->musings.end(); ++i) { string tmp; try @@ -294,31 +380,16 @@ sanity::gasp() L(FL("ignoring error trigged by saving work set to debug log")); } } - gasp_dump = out.str(); + imp->gasp_dump = out.str(); L(FL("finished saving work set")); - if (debug) + if (imp->debug) { inform_log("contents of work set:"); - inform_log(gasp_dump); + inform_log(imp->gasp_dump); } - already_dumping = false; + imp->already_dumping = false; } -MusingI::MusingI() -{ - if (!global_sanity.already_dumping) - global_sanity.musings.push_back(this); -} - -MusingI::~MusingI() -{ - if (!global_sanity.already_dumping) - { - I(global_sanity.musings.back() == this); - global_sanity.musings.pop_back(); - } -} - template <> void dump(string const & obj, string & out) { ============================================================ --- sanity.hh 9b427a9911acfa147e536fab01cf20febf27778b +++ sanity.hh c56eb62b0c077c6a79efc6eb86d663e7b8d7672b @@ -16,8 +16,8 @@ #include #include #include +#include -#include "boost/circular_buffer.hpp" #include "boost/current_function.hpp" #include "i18n.h" @@ -55,23 +55,24 @@ struct sanity { struct i18n_format; struct sanity { - sanity(); virtual ~sanity(); virtual void initialize(int, char **, char const *); void dump_buffer(); void set_debug(); void set_quiet(); void set_reallyquiet(); + // This takes a bare std::string because we don't want to expose vocab.hh + // or paths.hh here. + void set_dump_path(std::string const & path); - bool debug; - bool quiet; - bool reallyquiet; - boost::circular_buffer logbuf; - std::string filename; - std::string gasp_dump; - bool already_dumping; - std::vector musings; + // A couple of places need to look at the debug flag to avoid doing + // expensive logging if it's off. + bool debug_p(); + // ??? --quiet overrides any --ticker= setting if both are on the + // command line (and needs to look at this to do so). + bool quiet_p(); + void log(plain_format const & fmt, char const * file, int line); void progress(i18n_format const & fmt, @@ -89,7 +90,10 @@ struct sanity { unsigned long sz, unsigned long idx, std::string const & file, int line)); + void gasp(); + void push_musing(MusingI const *musing); + void pop_musing(MusingI const *musing); private: std::string do_format(format_base const & fmt, @@ -98,6 +102,9 @@ private: virtual void inform_message(std::string const &msg) = 0; virtual void inform_warning(std::string const &msg) = 0; virtual void inform_error(std::string const &msg) = 0; + + struct impl; + impl * imp; }; extern sanity & global_sanity; @@ -406,8 +413,8 @@ public: class MusingI { public: - MusingI(); - virtual ~MusingI(); + MusingI() { global_sanity.push_musing(this); } + virtual ~MusingI() { global_sanity.pop_musing(this); } virtual void gasp(std::string & out) const = 0; }; ============================================================ --- simplestring_xform.cc 4d9df66d29c1e2b1ec4ef1717b271de71fd3d941 +++ simplestring_xform.cc 9537d56180ced77a4c692399b935f08a02b05c1d @@ -1,8 +1,9 @@ #include "simplestring_xform.hh" #include "sanity.hh" #include "constants.hh" #include +#include using std::string; using std::vector; ============================================================ --- tester.cc 775277ecee57590d0124a8d04f94452668ca34e0 +++ tester.cc 96dde1189e56c66156cc0038e423b33d170957c6 @@ -491,6 +491,7 @@ int main(int argc, char **argv) int retcode = 2; lua_State *st = 0; try{ + global_sanity.initialize(argc, argv, "C"); // global_sanity.set_debug(); string testfile; string firstdir; ============================================================ --- unix/get_system_flavour.cc de33a20261af04c652ce6b3b29b24fb37cbb0e8e +++ unix/get_system_flavour.cc adfea09a6109d5ea5ffcb48507077f7fb496b53f @@ -5,6 +5,7 @@ #include #include "sanity.hh" +#include // for operator<< void get_system_flavour(std::string & ident) {