diff --git a/nl-writer2/include/mp/nl-solver.h b/nl-writer2/include/mp/nl-solver.h index a4d85bc95..9032f2d2c 100644 --- a/nl-writer2/include/mp/nl-solver.h +++ b/nl-writer2/include/mp/nl-solver.h @@ -229,14 +229,15 @@ class NLSolver { bool ReadSolution(SOLHandler& solh); protected: - void Init(); - void Destroy(); + void InitAutoStub(); + void DestroyAutoStub(); mp::NLUtils& Utils() const { return *p_ut_; } private: mp::NLUtils utils_; mp::NLUtils* p_ut_ = nullptr; + std::string pathstr_; std::string filestub_; bool filestubCustom_ = false; NLW2_NLOptionsBasic_C nl_opts_; diff --git a/nl-writer2/include/mp/nl-solver.hpp b/nl-writer2/include/mp/nl-solver.hpp index da3abd704..1a3d14c59 100644 --- a/nl-writer2/include/mp/nl-solver.hpp +++ b/nl-writer2/include/mp/nl-solver.hpp @@ -29,7 +29,7 @@ namespace mp { template bool NLSolver::LoadModel(NLFeeder& nlf) { if (GetFileStub().empty()) - return (err_msg_="WriteNL error: provide filestub.", false); + InitAutoStub(); auto result = mp::WriteNLFile(GetFileStub(), nlf, Utils()); if (NLW2_WriteNL_OK != result.first) return (err_msg_ = "WriteNL error: " + result.second, false); diff --git a/nl-writer2/src/nl-solver.cc b/nl-writer2/src/nl-solver.cc index 49a4b9b2c..48a32d689 100644 --- a/nl-writer2/src/nl-solver.cc +++ b/nl-writer2/src/nl-solver.cc @@ -25,6 +25,14 @@ #include #include #include +#include +#include + +#if defined(_WIN32) || defined(_WIN64) + #include // _mktemp[_s] +#else + #include // mkdtemp +#endif #include "mp/nl-solver.hpp" #include "mp/nl-opcodes.h" @@ -519,24 +527,54 @@ double NLModel::ComputeObjValue(const double *x) const { } NLSolver::NLSolver() - : p_ut_(&utils_) { Init(); } + : p_ut_(&utils_) { } NLSolver::NLSolver(mp::NLUtils* put) - : p_ut_(put ? put : &utils_) { Init(); } + : p_ut_(put ? put : &utils_) { } -NLSolver::~NLSolver() { Destroy(); } +NLSolver::~NLSolver() { DestroyAutoStub(); } -void NLSolver::Init() { +void NLSolver::InitAutoStub() { // init file stub - char tmpn[L_tmpnam]; - tmpnam(tmpn); - filestub_ = tmpn; + std::random_device dev; + std::mt19937 prng(dev()); + std::uniform_int_distribution rand(0); + auto path = std::filesystem::temp_directory_path(); + path /= "nlw2_"; // via '/' + char rnds[64] = "rndhex"; + std::snprintf(rnds, sizeof(rnds)-1, "%lX", rand(prng)); + path += rnds; // no '/' + + path += "_XXXXXX"; + pathstr_ = path.string(); + +#if defined(_WIN32) || defined(_WIN64) + auto p1 = _mktemp((char*)pathstr_.c_str()); + assert(p1); + if (!std::filesystem::create_directory(pathstr_)) + Utils().myexit("Could not create temp dir '" + + pathstr_ + "'"); +#else + if (!mkdtemp((char*)pathstr_.c_str())) + Utils().myexit("Could not create a temp dir\n" + "from pattern '" + pathstr_ + "'"); +#endif + path = pathstr_; + // Plus filename + std::snprintf(rnds, sizeof(rnds)-1, "%lX", rand(prng)); + path /= rnds; + filestub_ = path.string(); } -void NLSolver::Destroy() { - // try & delete .nl - if (!filestubCustom_) - std::remove((filestub_ + ".nl").c_str()); +void NLSolver::DestroyAutoStub() { + // delete temp folder if created + if (pathstr_.size()) { + std::error_code ec; + std::filesystem::remove_all(pathstr_, ec); + if (ec) + Utils().log_warning("Failed to remove temp dir '%s': %s", + pathstr_.c_str(), ec.message().c_str()); + } } void NLSolver::SetFileStub(std::string stub) {