Skip to content
Permalink
Browse files

Merge pull request #13433 from aeslaughter/reset-copy-fix-13342

Avoid accumlation of supplied command line arguments
  • Loading branch information...
aeslaughter committed Jun 5, 2019
2 parents c84b154 + f8fdab5 commit b9bb03afe2668ad85db1a062674514abee60e5ef
@@ -49,11 +49,24 @@ class CommandLine
};

CommandLine(int argc, char * argv[]);
CommandLine(const CommandLine & other);
virtual ~CommandLine();

void addArguments(int argc, char * argv[]);
void addArgument(std::string);

/**
* Removes multiapp parameters not associated with the supplied name.
*
* When a sub-application is created the CommandLine object from the master application is
* copied and supplied to the sub-app. This method cleans up the copy so it is ready to
* be used for a sub-application by removing parameters that are not associated with the provided
* sub-application name.
*
* See MultiApp::createApp
*/
void initForMultiApp(const std::string &);

/**
* Return the raw argv arguments as a vector.
*/
@@ -114,7 +127,10 @@ class CommandLine
std::map<std::string, Option> _cli_options;

private:
/// indices of CLI args that have been marked as used
std::set<int> _used_hiti;

/// indices of CLI args that are HIT syntax parameters
std::set<int> _hiti;

/// Storage for the raw argv
@@ -175,4 +191,3 @@ CommandLine::search(const std::string & option_name, T & argument)
}
mooseError("Unrecognized option name");
}

@@ -146,6 +146,11 @@ class Parser : public ConsoleStreamInterface, public hit::Walker

std::vector<std::string> listValidParams(std::string & section_name);

/**
* Marks MOOSE hit syntax from supplied command-line arguments
*/
std::string hitCLIFilter(std::string appname, const std::vector<std::string> & argv);

protected:
/**
* Helper functions for setting parameters of arbitrary types - bodies are in the .C file
@@ -266,6 +271,5 @@ class Parser : public ConsoleStreamInterface, public hit::Walker
private:
std::string _errmsg;
std::string _warnmsg;
std::string hitCLIFilter(std::string appname, const std::vector<std::string> & argv);
void walkRaw(std::string fullpath, std::string nodepath, hit::Node * n);
};
@@ -245,7 +245,10 @@ MultiApp::initialSetup()
_app_type, getParam<std::string>("library_path"), getParam<std::string>("library_name"));

for (unsigned int i = 0; i < _my_num_apps; i++)
{
createApp(i, _global_time_offset);
_app.parser().hitCLIFilter(_apps[i]->name(), _app.commandLine()->getArguments());
}
}

void
@@ -609,7 +612,13 @@ MultiApp::createApp(unsigned int i, Real start_time)

InputParameters app_params = AppFactory::instance().getValidParams(_app_type);
app_params.set<FEProblemBase *>("_parent_fep") = &_fe_problem;
app_params.set<std::shared_ptr<CommandLine>>("_command_line") = _app.commandLine();

// Set the command line parameters with a copy of the main application command line parameters,
// the copy is required so that the addArgument command below doesn't accumulate more and more
// of the same cli_args, which is important when running in batch mode.
std::shared_ptr<CommandLine> app_cli = std::make_shared<CommandLine>(*_app.commandLine());
app_cli->initForMultiApp(full_name);
app_params.set<std::shared_ptr<CommandLine>>("_command_line") = app_cli;

if (_cli_args.size() > 0)
{
@@ -13,11 +13,23 @@
#include "MooseUtils.h"
#include "InputParameters.h"

// Contrib RE
#include "pcrecpp.h"

// C++ includes
#include <iomanip>

CommandLine::CommandLine(int argc, char * argv[]) { addArguments(argc, argv); }

CommandLine::CommandLine(const CommandLine & other)
: _cli_options(other._cli_options),
_used_hiti(other._used_hiti),
_hiti(other._hiti),
_argv(other._argv),
_args(other._args)
{
}

void
CommandLine::addArguments(int argc, char * argv[])
{
@@ -48,6 +60,43 @@ CommandLine::addArgument(std::string arg)

CommandLine::~CommandLine() {}

void
CommandLine::initForMultiApp(const std::string & subapp_full_name)
{
// Get the name and number for the current sub-application
std::string sub_name;
int sub_num = std::numeric_limits<int>::min(); // this initial value should never be used
pcrecpp::RE("(\\S*?)(\\d*)").FullMatch(subapp_full_name, &sub_name, &sub_num);

if (sub_num == std::numeric_limits<int>::min())
mooseError("The sub-application name '", subapp_full_name, "' must contain a number.");

// "remove" CLI args for other sub-applications; remove_if just moves items to the end, so
// an erase is needed to actually remove the items
auto new_end =
std::remove_if(_argv.begin(), _argv.end(), [&sub_name, sub_num](const std::string & arg) {
// Determine if the current command line argument ('arg') and extract the sub-application
// name and number. If 'arg' is not command line argument for sub-application then the regex
// match fails and the argument is retained.
std::string arg_sub_name;
int arg_sub_num = -1;
pcrecpp::RE("(\\S*?)(\\d*):").PartialMatch(arg, &arg_sub_name, &arg_sub_num);
if (!arg_sub_name.empty())
{
// The argument should be retained if names match and the current argument doesn't have
// a number or the supplied sub-application number and the current argument number match
bool keep = (sub_name == arg_sub_name && (arg_sub_num == -1 || arg_sub_num == sub_num));
return !keep;
}
return false;
});
_argv.erase(new_end, _argv.end());

// Clear hit CLI arguments, these will be populated after the sub-application is created
_hiti.clear();
_used_hiti.clear();
}

void
CommandLine::addCommandLineOptionsFromParams(InputParameters & params)
{
@@ -71,3 +71,35 @@ TEST(CommandLine, parse)
"astring anotherstring");
}
}

TEST(CommandLine, initForMultiApp)
{
int argc = 6;
const char * argv[6] = {
"--flag", "sub0:year=2011", "sub1:year=2013", "sub:month=1", "notsub:day=2", ":niner=9"};
{
CommandLine cl(argc, (char **)argv);

std::vector<std::string> gold = {
"--flag", "sub0:year=2011", "sub1:year=2013", "sub:month=1", "notsub:day=2", ":niner=9"};
EXPECT_EQ(cl.getArguments(), gold);

cl.initForMultiApp("sub0");
gold = {"--flag", "sub0:year=2011", "sub:month=1", ":niner=9"};
EXPECT_EQ(cl.getArguments(), gold);
}

{
CommandLine cl(argc, (char **)argv);
cl.initForMultiApp("sub1");
std::vector<std::string> gold = {"--flag", "sub1:year=2013", "sub:month=1", ":niner=9"};
EXPECT_EQ(cl.getArguments(), gold);
}

{
CommandLine cl(argc, (char **)argv);
cl.initForMultiApp("notsub0");
std::vector<std::string> gold = {"--flag", "notsub:day=2", ":niner=9"};
EXPECT_EQ(cl.getArguments(), gold);
}
}

0 comments on commit b9bb03a

Please sign in to comment.
You can’t perform that action at this time.